expand MemoryUnit class defs and add some tlb-related functions

This commit is contained in:
Hanran Wu 2024-06-05 16:11:51 -04:00 committed by Jaewon Lee
parent cf3f2d4f6f
commit 2b426693f5
3 changed files with 181 additions and 7 deletions

View file

@ -14,6 +14,22 @@
`ifndef VX_CONFIG_VH
`define VX_CONFIG_VH
`ifndef VM_ADDR_MODE
`define VM_ADDR_MODE SV32
`endif
`ifndef PTE_SIZE
`define PTE_SIZE 8
`endif
`ifndef TLB_SIZE
`define TLB_SIZE 32
`endif
`ifndef SUPER_PAGING
`define SUPER_PAGING false
`endif
`ifndef MIN
`define MIN(x, y) (((x) < (y)) ? (x) : (y))
`endif

View file

@ -17,9 +17,22 @@
#include <fstream>
#include <assert.h>
#include "util.h"
#include <VX_config.h>
#include <bitset>
using namespace vortex;
uint64_t bits(uint64_t addr, uint8_t s_idx, uint8_t e_idx)
{
return (addr >> s_idx) & ((1 << (e_idx - s_idx + 1)) - 1);
}
bool bit(uint64_t addr, uint8_t idx)
{
return (addr) & (1 << idx);
}
RamMemDevice::RamMemDevice(const char *filename, uint32_t wordSize)
: wordSize_(wordSize) {
std::ifstream input(filename);
@ -158,12 +171,12 @@ uint64_t MemoryUnit::toPhyAddr(uint64_t addr, uint32_t flagMask) {
return pAddr;
}
void MemoryUnit::read(void* data, uint64_t addr, uint64_t size, bool sup) {
void MemoryUnit::read(void* data, uint64_t addr, uint64_t size, bool sup, ACCESS_TYPE type) {
uint64_t pAddr = this->toPhyAddr(addr, sup ? 8 : 1);
return decoder_.read(data, pAddr, size);
}
void MemoryUnit::write(const void* data, uint64_t addr, uint64_t size, bool sup) {
void MemoryUnit::write(const void* data, uint64_t addr, uint64_t size, bool sup, ACCESS_TYPE type) {
uint64_t pAddr = this->toPhyAddr(addr, sup ? 16 : 1);
decoder_.write(data, pAddr, size);
amo_reservation_.valid = false;
@ -179,10 +192,34 @@ bool MemoryUnit::amo_check(uint64_t addr) {
uint64_t pAddr = this->toPhyAddr(addr, 1);
return amo_reservation_.valid && (amo_reservation_.addr == pAddr);
}
void MemoryUnit::tlbAdd(uint64_t virt, uint64_t phys, uint32_t flags) {
tlb_[virt / pageSize_] = TLBEntry(phys / pageSize_, flags);
}
void MemoryUnit::tlbAdd(uint64_t virt, uint64_t phys, uint32_t flags, uint64_t size_bits) {
// HW: evict TLB by Most Recently Used
if (tlb_.size() == TLB_SIZE - 1) {
for (auto& entry : tlb_)
{
entry.second.mru_bit = false;
}
} else if (tlb_.size() == TLB_SIZE) {
uint64_t del;
for (auto entry : tlb_) {
if (!entry.second.mru_bit)
{
del = entry.first;
break;
}
}
tlb_.erase(tlb_.find(del));
TLB_EVICT++;
}
tlb_[virt / pageSize_] = TLBEntry(phys / pageSize_, flags, size_bits);
}
void MemoryUnit::tlbRm(uint64_t va) {
if (tlb_.find(va / pageSize_) != tlb_.end())
tlb_.erase(tlb_.find(va / pageSize_));

View file

@ -18,8 +18,22 @@
#include <map>
#include <unordered_map>
#include <cstdint>
#include <unordered_set>
#include <stdexcept>
namespace vortex {
enum VA_MODE {
BARE,
SV32
};
enum ACCESS_TYPE {
LOAD,
STORE,
FETCH
};
struct BadAddress {};
struct OutOfRange {};
@ -73,31 +87,39 @@ public:
class MemoryUnit {
public:
// HW: Expand PageFault struct to contain access_type info for debug purposes
struct PageFault {
PageFault(uint64_t a, bool nf)
: faultAddr(a)
, notFound(nf)
, access_type(ACCESS_TYPE::LOAD)
{}
uint64_t faultAddr;
bool notFound;
uint64_t faultAddr;
bool notFound;
ACCESS_TYPE access_type;
};
MemoryUnit(uint64_t pageSize = 0);
void attach(MemDevice &m, uint64_t start, uint64_t end);
void read(void* data, uint64_t addr, uint64_t size, bool sup);
void write(const void* data, uint64_t addr, uint64_t size, bool sup);
void read(void* data, uint64_t addr, uint64_t size, bool sup, ACCESS_TYPE type = ACCESS_TYPE::LOAD);
void write(const void* data, uint64_t addr, uint64_t size, bool sup, ACCESS_TYPE type = ACCESS_TYPE::LOAD);
void amo_reserve(uint64_t addr);
bool amo_check(uint64_t addr);
void tlbAdd(uint64_t virt, uint64_t phys, uint32_t flags);
void tlbAdd(uint64_t virt, uint64_t phys, uint32_t flags, uint64_t size_bits);
void tlbRm(uint64_t vaddr);
void tlbFlush() {
tlb_.clear();
}
uint32_t get_satp();
void set_satp(uint32_t satp);
private:
struct amo_reservation_t {
@ -137,11 +159,41 @@ private:
TLBEntry(uint32_t pfn, uint32_t flags)
: pfn(pfn)
, flags(flags)
{}
, mru_bit(true)
{};
TLBEntry(uint32_t pfn, uint32_t flags, uint64_t size_bits)
: pfn(pfn)
, flags(flags)
, mru_bit(true)
, size_bits (size_bits)
{
d = bit(7);
a = bit(6);
g = bit(5);
u = bit(4);
x = bit(3);
w = bit(2);
r = bit(1);
v = bit(0);
}
bool bit(uint8_t idx)
{
return (flags) & (1 << idx);
}
uint32_t pfn;
bool d, a, g, u, x, w, r, v;
bool mru_bit;
uint64_t size_bits;
uint32_t flags;
};
std::pair<bool, uint64_t> tlbLookup(uint64_t vAddr, ACCESS_TYPE type, uint64_t* size_bits);
uint64_t vAddr_to_pAddr(uint64_t vAddr, ACCESS_TYPE type);
std::pair<uint64_t, uint8_t> page_table_walk(uint64_t vAddr_bits, ACCESS_TYPE type, uint64_t* size_bits);
TLBEntry tlbLookup(uint64_t vAddr, uint32_t flagMask);
uint64_t toPhyAddr(uint64_t vAddr, uint32_t flagMask);
@ -151,6 +203,13 @@ private:
ADecoder decoder_;
bool enableVM_;
uint32_t satp;
VA_MODE mode;
uint32_t ptbr;
std::unordered_set<uint64_t> unique_translations;
uint64_t TLB_HIT, TLB_MISS, TLB_EVICT, PTW, PERF_UNIQUE_PTW;
amo_reservation_t amo_reservation_;
};
@ -219,4 +278,66 @@ private:
bool check_acl_;
};
class PTE_SV32_t
{
private:
uint64_t address;
uint64_t bits(uint64_t addr, uint8_t s_idx, uint8_t e_idx)
{
return (addr >> s_idx) & ((1 << (e_idx - s_idx + 1)) - 1);
}
bool bit(uint8_t idx)
{
return (address) & (1 << idx);
}
public:
uint64_t ppn[2];
uint32_t rsw;
uint32_t flags;
bool d, a, g, u, x, w, r, v;
PTE_SV32_t(uint64_t address) : address(address)
{
flags = bits(address,0,7);
rsw = bits(address,8,9);
ppn[0] = bits(address,10,19);
ppn[1] = bits(address,20,31);
d = bit(7);
a = bit(6);
g = bit(5);
u = bit(4);
x = bit(3);
w = bit(2);
r = bit(1);
v = bit(0);
}
};
class vAddr_SV32_t
{
private:
uint64_t address;
uint64_t bits(uint64_t addr, uint8_t s_idx, uint8_t e_idx)
{
return (addr >> s_idx) & ((1 << (e_idx - s_idx + 1)) - 1);
}
bool bit(uint64_t addr, uint8_t idx)
{
return (addr) & (1 << idx);
}
public:
uint64_t vpn[2];
uint64_t pgoff;
vAddr_SV32_t(uint64_t address) : address(address)
{
vpn[0] = bits(address,12,21);
vpn[1] = bits(address,22,31);
pgoff = bits(address,0,11);
}
};
} // namespace vortex