Virtual Memory Support

This commit is contained in:
Jaewon Lee 2024-06-16 19:05:38 -04:00
parent 62673b4b72
commit 862997fc94
6 changed files with 275 additions and 192 deletions

View file

@ -172,7 +172,15 @@
`define IO_BASE_ADDR 64'h000000040 `define IO_BASE_ADDR 64'h000000040
`endif `endif
`else `ifndef PAGE_TABLE_BASE_ADDR
`define PAGE_TABLE_BASE_ADDR 64'h1F0000000
`endif
`ifndef PAGE_TABLE_SIZE
`define PAGE_TABLE_SIZE 4096
`endif
`else # XLEN_32
`ifndef STACK_BASE_ADDR `ifndef STACK_BASE_ADDR
`define STACK_BASE_ADDR 32'hFFFF0000 `define STACK_BASE_ADDR 32'hFFFF0000
@ -190,6 +198,14 @@
`define IO_BASE_ADDR 32'h00000040 `define IO_BASE_ADDR 32'h00000040
`endif `endif
`ifndef PAGE_TABLE_BASE_ADDR
`define PAGE_TABLE_BASE_ADDR 32'hF0000000
`endif
`ifndef PAGE_TABLE_SIZE
`define PAGE_TABLE_SIZE 4096
`endif
`endif `endif
`define IO_END_ADDR `USER_BASE_ADDR `define IO_END_ADDR `USER_BASE_ADDR
@ -266,13 +282,17 @@
`ifndef PTE_SIZE `ifndef PTE_SIZE
`ifdef XLEN_32 `ifdef XLEN_32
`define PTE_SIZE 4 `define PTE_SIZE 4
`define NUM_PTE_ENTRY 1024
`else `else
`ifdef XLEN_64 `ifdef XLEN_64
`define PTE_SIZE 8 `define PTE_SIZE 8
`define NUM_PTE_ENTRY 1024
`else `else
`define PTE_SIZE 8 `define PTE_SIZE 8
`define NUM_PTE_ENTRY 1024
`endif `endif
`endif `endif
`define PT_SIZE (PTE_SIZE * NUM_PTE_ENTRY)
`endif `endif
`ifndef TLB_SIZE `ifndef TLB_SIZE

View file

@ -83,17 +83,18 @@ bool bit(uint64_t addr, uint8_t idx)
class vx_device { class vx_device {
public: public:
vx_device() vx_device()
: arch_(NUM_THREADS, NUM_WARPS, NUM_CORES) : arch_(NUM_THREADS, NUM_WARPS, NUM_CORES)
, ram_(0, RAM_PAGE_SIZE) #ifdef VM_ENABLE
, processor_(arch_) , ram_(0, RAM_PAGE_SIZE<<11)
, global_mem_(ALLOC_BASE_ADDR, #else
GLOBAL_MEM_SIZE - ALLOC_BASE_ADDR, , ram_(0, RAM_PAGE_SIZE)
RAM_PAGE_SIZE, #endif
CACHE_BLOCK_SIZE) , processor_(arch_)
{ , global_mem_(ALLOC_BASE_ADDR, GLOBAL_MEM_SIZE - ALLOC_BASE_ADDR, RAM_PAGE_SIZE, CACHE_BLOCK_SIZE)
// attach memory module {
processor_.attach_ram(&ram_); // attach memory module
processor_.attach_ram(&ram_);
#ifdef VM_ENABLE #ifdef VM_ENABLE
//Set //Set
set_processor_satp(VM_ADDR_MODE); set_processor_satp(VM_ADDR_MODE);
@ -101,6 +102,9 @@ public:
} }
~vx_device() { ~vx_device() {
#ifdef VM_ENABLE
this->mem_free(PAGE_TABLE_BASE_ADDR); // Right position?
#endif
if (future_.valid()) { if (future_.valid()) {
future_.wait(); future_.wait();
} }
@ -147,66 +151,90 @@ public:
} }
#ifdef VM_ENABLE #ifdef VM_ENABLE
// VM SUPPORT // virtual to phycial mapping
uint64_t map_local_mem(uint64_t size, uint64_t* dev_pAddr) uint64_t map_p2v(uint64_t pAddr)
{ {
bool no_trans = false; return pAddr + 0xf000000;
std::cout << __PRETTY_FUNCTION__ << std::endl; }
// std::cout << "startup addr: 0x" << std::hex << STARTUP_ADDR << std::endl; bool need_trans(uint64_t dev_pAddr)
std::cout << "Input device physical addr: 0x" << std::hex << *dev_pAddr<< std::endl; {
std::cout << "bit mode: " << std::dec << XLEN << std::endl; // Check if the this is the BARE mode
bool isBAREMode = (get_mode() == VA_MODE::BARE);
// Check if the address is reserved
bool isReserved = (dev_pAddr >= PAGE_TABLE_BASE_ADDR);
// Check if the address falls within the startup address range
bool isStartAddress = (STARTUP_ADDR <= dev_pAddr) && (dev_pAddr <= (STARTUP_ADDR + 0x40000));
// Print the boolean results for debugging purposes
// printf("%p, %u, %u\n", (void *)dev_pAddr, isReserved, isStartAddress);
// Return true if the address needs translation (i.e., it's not reserved and not a start address)
return (!isBAREMode && !isReserved && !isStartAddress);
}
uint64_t phy_to_virt_map(uint64_t size, uint64_t* dev_pAddr, uint32_t flags)
{
// DBGPRINT("====%s====\n", __PRETTY_FUNCTION__);
DBGPRINT("(size = 0x%lx, dev_pAddr= 0x%lx, flags = 0x%x)\n", size, *dev_pAddr, flags);
DBGPRINT("bit mode: %d\n", XLEN);
// if (*dev_pAddr == STARTUP_ADDR || *dev_pAddr == 0x7FFFF000) { // if (*dev_pAddr == STARTUP_ADDR || *dev_pAddr == 0x7FFFF000) {
if (*dev_pAddr >= 0xF0000000 )
no_trans = true;
}
if (get_mode() == VA_MODE::BARE || no_trans == true) if (!need_trans(*dev_pAddr))
{ {
std::cout << "No Translation is needed." << std::endl; DBGPRINT("Translation is not needed.\n");
return 0; return 0;
} }
uint64_t init_pAddr = *dev_pAddr; uint64_t init_pAddr = *dev_pAddr;
uint64_t init_vAddr = *dev_pAddr + 0xf000000; // vpn will change, but we want to return the vpn of the beginning of the virtual allocation uint64_t init_vAddr = map_p2v(init_pAddr);
uint64_t ppn = 0, vpn = 0 ; uint64_t ppn = 0, vpn = 0 ;
//dev_pAddr can be of size greater than a page, but we have to map and update //dev_pAddr can be of size greater than a page, but we have to map and update
//page tables on a page table granularity. So divide the allocation into pages. //page tables on a page table granularity. So divide the allocation into pages.
bool is_start = false;
for (ppn = (*dev_pAddr) >> 12; ppn < ((*dev_pAddr) >> 12) + (size/RAM_PAGE_SIZE) + 1; ppn++) for (ppn = (*dev_pAddr) >> 12; ppn < ((*dev_pAddr) >> 12) + (size/RAM_PAGE_SIZE) + 1; ppn++)
{ {
vpn = map_p2v(ppn << 12) >> 12;
if (is_start == false) {
DBGPRINT("**Search vpn in page table:0x%lx\n", vpn);
is_start = true;
}
else {
DBGPRINT("Next vpn: 0x%lx\n",vpn);
}
//Currently a 1-1 mapping is used, this can be changed here to support different //Currently a 1-1 mapping is used, this can be changed here to support different
//mapping schemes //mapping schemes
vpn = ppn + (0xf000000 >> 12);
//If ppn to vpn mapping doesnt exist. //If ppn to vpn mapping doesnt exist.
if (addr_mapping.find(vpn) == addr_mapping.end()) if (addr_mapping.find(vpn) == addr_mapping.end())
{ {
//Create mapping. //Create mapping.
update_page_table(ppn, vpn); update_page_table(ppn, vpn, flags);
addr_mapping[vpn] = ppn; addr_mapping[vpn] = ppn;
} }
} }
DBGPRINT("Mapped virtual addr: 0x%lx to physical addr: %lx\n", init_vAddr, init_pAddr);
std::cout << "Mapped virtual addr: " << init_vAddr << " to physical addr: " << init_pAddr << std::endl; // Sanity check
// sanity check
uint64_t pAddr = page_table_walk(init_vAddr); uint64_t pAddr = page_table_walk(init_vAddr);
if (pAddr != init_pAddr) if (pAddr != init_pAddr)
{ {
std::cout << "ERROR" << pAddr << "and" << init_pAddr << " is not the same" <<std::endl; assert(pAddr == init_pAddr && "ERROR: translated virtual Addresses are not the same with physical Address");
} }
*dev_pAddr = init_vAddr; // commit vpn to be returned to host *dev_pAddr = init_vAddr; // commit vpn to be returned to host
std::cout << "Translated device virtual addr: 0x" << std::hex << *dev_pAddr<< std::endl; DBGPRINT("Translated device virtual addr: 0x%lx\n", *dev_pAddr);
return 0; return 0;
} }
#endif #endif
int mem_alloc(uint64_t size, int flags, uint64_t* dev_addr) { int mem_alloc(uint64_t size, int flags, uint64_t* dev_addr) {
std::cout << __PRETTY_FUNCTION__ << std::endl;
uint64_t addr; uint64_t addr;
DBGPRINT("mem_alloc size: 0x%lx\n",size);
CHECK_ERR(global_mem_.allocate(size, &addr), { CHECK_ERR(global_mem_.allocate(size, &addr), {
return err; return err;
}); });
@ -217,25 +245,36 @@ public:
*dev_addr = addr; *dev_addr = addr;
#ifdef VM_ENABLE #ifdef VM_ENABLE
// VM address translation // VM address translation
map_local_mem(size, dev_addr); phy_to_virt_map(size, dev_addr,flags);
#endif #endif
return 0; return 0;
} }
int mem_reserve(uint64_t dev_addr, uint64_t size, int flags) { int mem_reserve(uint64_t dev_addr, uint64_t size, int flags) {
CHECK_ERR(global_mem_.reserve(dev_addr, size), { CHECK_ERR(global_mem_.reserve(dev_addr, size), {
return err; return err;
}); });
CHECK_ERR(this->mem_access(dev_addr, size, flags), { DBGPRINT("mem_reserve: addr: 0x%lx, size: 0x%lx\n",dev_addr, size);
global_mem_.release(dev_addr); CHECK_ERR(this->mem_access(dev_addr, size, flags), {
return err; global_mem_.release(dev_addr);
}); return err;
return 0; });
} #ifdef VM_ENABLE
uint64_t paddr = dev_addr;
phy_to_virt_map(size, &paddr, flags);
#endif
return 0;
}
int mem_free(uint64_t dev_addr) { int mem_free(uint64_t dev_addr) {
return global_mem_.release(dev_addr); #ifdef VM_ENABLE
} uint64_t pAddr = page_table_walk(dev_addr);
// VM address translation
return global_mem_.release(pAddr);
#else
return global_mem_.release(dev_addr);
#endif
}
int mem_access(uint64_t dev_addr, uint64_t size, int flags) { int mem_access(uint64_t dev_addr, uint64_t size, int flags) {
uint64_t asize = aligned_size(size, CACHE_BLOCK_SIZE); uint64_t asize = aligned_size(size, CACHE_BLOCK_SIZE);
@ -255,17 +294,13 @@ public:
} }
int upload(uint64_t dest_addr, const void* src, uint64_t size) { int upload(uint64_t dest_addr, const void* src, uint64_t size) {
std::cout << __PRETTY_FUNCTION__ << std::endl; // DBGPRINT("====%s====\n", __PRETTY_FUNCTION__);
uint64_t asize = aligned_size(size, CACHE_BLOCK_SIZE); uint64_t asize = aligned_size(size, CACHE_BLOCK_SIZE);
if (dest_addr + asize > GLOBAL_MEM_SIZE) if (dest_addr + asize > GLOBAL_MEM_SIZE)
return -1; return -1;
#ifdef VM_ENABLE #ifdef VM_ENABLE
uint64_t pAddr = page_table_walk(dest_addr); uint64_t pAddr = page_table_walk(dest_addr);
std::cout << "== Upload data to vAddr = 0x" << std::hex <<dest_addr << ", pAddr=0x" << pAddr << "."<< std::endl; DBGPRINT("Upload data to vAddr = 0x%lx (pAddr=0x%lx)\n", dest_addr, pAddr);
if (get_mode() != VA_MODE::BARE)
std::cout << "uploading to 0x" << dest_addr << "(VA)" << std::endl;
else
std::cout << "uploading to 0x" << dest_addr << std::endl;
#endif #endif
@ -287,7 +322,7 @@ public:
return -1; return -1;
#ifdef VM_ENABLE #ifdef VM_ENABLE
uint64_t pAddr = page_table_walk(src_addr); uint64_t pAddr = page_table_walk(src_addr);
std::cout << "== Download data to vAddr = 0x" << std::hex <<src_addr<< ", pAddr=0x" << pAddr << "."<< std::endl; DBGPRINT("Download data to vAddr = 0x%lx (pAddr=0x%lx)\n", src_addr, pAddr);
#endif #endif
ram_.enable_acl(false); ram_.enable_acl(false);
@ -372,12 +407,17 @@ public:
/* VM Management */ /* VM Management */
void set_processor_satp(VA_MODE mode) void set_processor_satp(VA_MODE mode)
{ {
// DBGPRINT("====%s====\n", __PRETTY_FUNCTION__);
uint32_t satp; uint32_t satp;
if (mode == VA_MODE::BARE) if (mode == VA_MODE::BARE)
{
DBGPRINT("VA_MODE = BARE MODE");
satp = 0; satp = 0;
}
else if (mode == VA_MODE::SV32) else if (mode == VA_MODE::SV32)
{ {
satp = (alloc_first_level_page_table() >> 12) | 0x80000000; satp = (alloc_2nd_level_page_table() >> 12) | 0x80000000;
DBGPRINT("VA_MODE = SV32 MODE(satp = 0x%x)\n",satp);
} }
processor_.set_satp(satp); processor_.set_satp(satp);
} }
@ -387,52 +427,62 @@ public:
// return processor_.get_satp(); // return processor_.get_satp();
return processor_.get_satp() & 0x003fffff; return processor_.get_satp() & 0x003fffff;
} }
uint64_t get_pte_address(uint64_t base_page, uint64_t vpn)
{
return (base_page << 12) + (vpn * PTE_SIZE);
}
VA_MODE get_mode() VA_MODE get_mode()
{ {
return processor_.get_satp() & 0x80000000 ? VA_MODE::SV32 : VA_MODE::BARE; return processor_.get_satp() & 0x80000000 ? VA_MODE::SV32 : VA_MODE::BARE;
} }
void update_page_table(uint64_t ppn, uint64_t vpn) { void update_page_table(uint64_t ppn, uint64_t vpn, uint32_t flag) {
std::cout << __PRETTY_FUNCTION__ << std::endl; // DBGPRINT("====%s====\n", __PRETTY_FUNCTION__);
std::cout << "mapping vpn: " << std::hex << vpn << " to ppn:" << ppn << std::endl; DBGPRINT("Mapping vpn 0x%05lx to ppn 0x%05lx(flags = %u)\n", vpn, ppn,flag);
assert((((ppn>> 20) == 0) && ((vpn >> 20) == 0)) && "Upper 12 bits are not zero!");
//Updating page table with the following mapping of (vAddr) to (pAddr). //Updating page table with the following mapping of (vAddr) to (pAddr).
// uint32_t page_bit_shift = log2ceil(PTE_SIZE*NUM_PTE_ENTRY); // uint32_t page_bit_shift = log2ceil(PTE_SIZE*NUM_PTE_ENTRY);
uint32_t page_bit_shift = 12; uint64_t ppn_1 = 0, pte_addr = 0, pte_bytes = 0;
uint64_t ppn_1, pte_addr, pte_bytes;
uint64_t vpn_1 = bits(vpn, 10, 19); uint64_t vpn_1 = bits(vpn, 10, 19);
uint64_t vpn_0 = bits(vpn, 0, 9); uint64_t vpn_0 = bits(vpn, 0, 9);
//Read first level PTE. //Read first level PTE.
pte_addr = (get_ptbr() << 12) + (vpn_1 * PTE_SIZE); DBGPRINT("Start second-level page table\n");
pte_addr = get_pte_address(get_ptbr(), vpn_1);
pte_bytes = read_pte(pte_addr); pte_bytes = read_pte(pte_addr);
std::cout << "[PTE] addr 0x" << std::hex << pte_addr << ", PTE 0x" << std::hex << pte_bytes << std::endl; DBGPRINT("[PTE] addr 0x%lx, PTE 0x%lx\n", pte_addr, pte_bytes);
ppn_1 = (pte_bytes >> 10);
if ( bit(pte_bytes, 0) && ((pte_bytes & 0xFFFFFFFF) != 0xbaadf00d)) if ( bit(pte_bytes, 0) && ((pte_bytes & 0xFFFFFFFF) != 0xbaadf00d))
{ {
//If valid bit set, proceed to next level using new ppn form PTE. //If valid bit set, proceed to next level using new ppn form PTE.
std::cout << "PTE valid, continuing the walk..." << std::endl; DBGPRINT("PTE valid (ppn 0x%lx), continuing the walk...\n",ppn_1);
ppn_1 = (pte_bytes >> 10);
} }
else else
{ {
//If valid bit not set, allocate a second level page table //If valid bit not set, allocate a second level page table
// in device memory and store ppn in PTE. Set rwx = 000 in PTE // in device memory and store ppn in PTE. Set rwx = 000 in PTE
//to indicate this is a pointer to the next level of the page table. //to indicate this is a pointer to the next level of the page table.
std::cout << "PTE invalid, get second page table..." << std::endl; DBGPRINT("PTE Invalid (ppn 0x%lx), continuing the walk...\n",ppn_1);
ppn_1 = (alloc_second_level_page_table() >> 12); ppn_1 = (alloc_1st_level_page_table(vpn_1) >> 12);
pte_bytes = ((ppn_1 << 10) | 0b0000000001) ; pte_bytes = ((ppn_1 << 10) | 0b0000000001) ;
assert((pte_addr>> 32) == 0 && "Upper 32 bits are not zero!");
write_pte(pte_addr, pte_bytes); write_pte(pte_addr, pte_bytes);
// if (pte_bytes != read_pte(pte_addr))
// DBGPRINT("Read/write values are different!\n");
} }
DBGPRINT("Move to first-level page table\n");
//Read second level PTE. //Read second level PTE.
pte_addr = (ppn_1 << page_bit_shift) + (vpn_0 * PTE_SIZE); pte_addr = get_pte_address(ppn_1, vpn_0);
pte_bytes = read_pte(pte_addr); pte_bytes = read_pte(pte_addr);
std::cout << "got pte: " << std::hex << pte_bytes << std::endl;
if ( bit(pte_bytes, 0) && ((pte_bytes & 0xFFFFFFFF) != 0xbaadf00d)) if ( bit(pte_bytes, 0) && ((pte_bytes & 0xFFFFFFFF) != 0xbaadf00d))
{ {
std::cout << "ERROR, shouldn't be here" << std::endl; DBGPRINT("ERROR, shouldn't be here\n");
exit(1);
//If valid bit is set, then the page is already allocated. //If valid bit is set, then the page is already allocated.
//Should not reach this point, a sanity check. //Should not reach this point, a sanity check.
} }
@ -442,87 +492,62 @@ public:
//to indicate this is a leaf PTE and has the stated permissions. //to indicate this is a leaf PTE and has the stated permissions.
pte_bytes = ( (ppn << 10) | 0b0000001111) ; pte_bytes = ( (ppn << 10) | 0b0000001111) ;
write_pte(pte_addr, pte_bytes); write_pte(pte_addr, pte_bytes);
if (pte_bytes != read_pte(pte_addr))
//If super paging is enabled. DBGPRINT("Read/write values are different!\n");
/*
if (SUPER_PAGING)
{
//Check if this second level Page Table can be promoted to a super page. Brute force
//method is used to iterate over all PTE entries of the table and check if they have
//their valid bit set.
bool superpage = true;
for(int i = 0; i < 1024; i++)
{
pte_addr = (ppn_1 << 12) + (i * PTE_SIZE);
pte_bytes = read_pte(pte_addr);
if (!bit(pte_bytes, 0) && ((pte_bytes & 0xFFFFFFFF) != 0xbaadf00d))
{
superpage = false;
break;
}
}
if (superpage)
{
//This can be promoted to a super page. Set root PTE to the first PTE of the
//second level. This is because the first PTE of the second level already has the
//correct PPN1, PPN0 set to zero and correct access bits.
pte_addr = (ppn_1 << 12);
pte_bytes = read_pte(pte_addr);
pte_addr = (get_ptbr() << 12) + (vpn_1 * PTE_SIZE);
write_pte(pte_addr, pte_bytes);
}
}
*/
} }
} }
uint64_t page_table_walk(uint64_t vAddr_bits) uint64_t page_table_walk(uint64_t vAddr_bits)
{ {
// DBGPRINT("====%s====\n", __PRETTY_FUNCTION__);
std::cout << "PTW on vAddr: 0x" << std::hex << vAddr_bits << std::endl; DBGPRINT("PTW on vAddr: 0x%lx\n", vAddr_bits);
if (!need_trans(vAddr_bits))
{
DBGPRINT("Translation is not needed.\n");
return vAddr_bits;
}
uint64_t LEVELS = 2; uint64_t LEVELS = 2;
vAddr_SV32_t vAddr(vAddr_bits); vAddr_SV32_t vAddr(vAddr_bits);
uint64_t pte_addr, pte_bytes; uint64_t pte_addr, pte_bytes;
uint64_t pt_ba = get_ptbr() << 12; uint64_t pt_ba = get_ptbr() << 12;
//Get base page table. //Get base page table.
for ( i = LEVELS-1 ; i >= 0 ; i--) for ( int i = LEVELS-1 ; i >= 0 ; i--)
{ {
//Read PTE. //Read PTE.
pte_addr = pt_ba+vAddr.vpn[i]*PTE_SIZE; pte_addr = pt_ba+vAddr.vpn[i]*PTE_SIZE;
std::cout << "reading PTE from RAM addr 0x" << std::hex << (pte_addr) << std::endl;
pte_bytes = read_pte(pte_addr); pte_bytes = read_pte(pte_addr);
pte_bytes &= 0x00000000FFFFFFFF; // Only for 32 bit
PTE_SV32_t pte(pte_bytes); PTE_SV32_t pte(pte_bytes);
std::cout << "got pte: " << std::hex << pte_bytes << std::endl; DBGPRINT("pte_bytes = 0x%lx, pte flags = %u)\n", pte.ppn , pte.flags);
//Check if it has invalid flag bits. //Check if it has invalid flag bits.
if ( (pte.v == 0) | ( (pte.r == 0) & (pte.w == 1) ) ) if ( (pte.v == 0) | ( (pte.r == 0) & (pte.w == 1) ) )
{ {
std::cout << "Error on vAddr 0x" << std::hex << vAddr_bits << std::endl; std::string msg= "Page Fault : Attempted to access invalid entry. Entry: 0x";
throw Page_Fault_Exception("Page Fault : Attempted to access invalid entry. Entry: 0x"); throw Page_Fault_Exception(msg);
} }
if ( (pte.r == 0) & (pte.w == 0) & (pte.x == 0)) if ( (pte.r == 0) & (pte.w == 0) & (pte.x == 0))
{ {
//Not a leaf node as rwx == 000 //Not a leaf node as rwx == 000
if (i == 0) if (i == 0)
{
throw Page_Fault_Exception("Page Fault : No leaf node found."); throw Page_Fault_Exception("Page Fault : No leaf node found.");
}
else else
{ {
//Continue on to next level. //Continue on to next level.
pt_ba = (pte_bytes >> 10 ) << 12; pt_ba = pte.ppn << 12;
std::cout << "next pt_ba: " << pt_ba << std::endl; DBGPRINT("next pt_ba: %p\n", (void *)pt_ba);
} }
} }
else else
{ {
//Leaf node found, finished walking. //Leaf node found, finished walking.
pt_ba = (pte_bytes >> 10 ) << 12; pt_ba = pte.ppn << 12;
std::cout << "Found PPN 0 = 0x" << pt_ba << std::endl; DBGPRINT("Found PT_Base_Address [%d] = %lx\n", i, pt_ba);
break; break;
} }
@ -535,35 +560,35 @@ public:
{ {
throw Page_Fault_Exception("Page Fault : TYPE LOAD, Incorrect permissions."); throw Page_Fault_Exception("Page Fault : TYPE LOAD, Incorrect permissions.");
} }
//Regular page.
uint64_t paddr = pt_ba << 12 + vAddr.pgoff; uint64_t paddr = pt_ba + vAddr.pgoff;
return paddr return paddr;
} }
uint64_t alloc_first_level_page_table() { uint64_t alloc_2nd_level_page_table() {
uint64_t addr=0xF0000000; // DBGPRINT("====%s====\n", __PRETTY_FUNCTION__);
uint64_t size=1<<23; uint64_t addr=PAGE_TABLE_BASE_ADDR;
uint64_t size=1<<23; // 8MB !!!FIXME!!!
CHECK_ERR(this->mem_reserve(addr, size, VX_MEM_READ_WRITE), { CHECK_ERR(this->mem_reserve(addr, size, VX_MEM_READ_WRITE), {
return err; return err;
}); });
// global_mem_.allocate(RAM_PAGE_SIZE, &addr); init_page_table(addr);
std::cout << "address of page table 0x" << std::hex << addr << std::endl;
init_page_table(addr,size);
return addr; return addr;
} }
uint64_t alloc_second_level_page_table(uint64_t vpn_1) { uint64_t alloc_1st_level_page_table(uint64_t vpn_1) {
uint64_t addr = 0xF0000000 + PTE_SIZE * NUM_PTE_ENTRY*(1+vpn_1) // DBGPRINT("====%s====\n", __PRETTY_FUNCTION__);
std::cout << "address of page table 0x" << std::hex << addr << std::endl; uint64_t addr = PAGE_TABLE_BASE_ADDR + PTE_SIZE * NUM_PTE_ENTRY*(1+vpn_1);
init_page_table(addr);
return addr; return addr;
} }
void init_page_table(uint64_t addr, uint64_t size) { void init_page_table(uint64_t addr) {
// uint64_t asize = aligned_size(RAM_PAGE_SIZE, CACHE_BLOCK_SIZE); // DBGPRINT("====%s====\n", __PRETTY_FUNCTION__);
uint64_t asize = aligned_size(size, CACHE_BLOCK_SIZE); DBGPRINT("int_page_table (addr=0x%lx)\n", addr);
uint64_t asize = aligned_size(RAM_PAGE_SIZE, CACHE_BLOCK_SIZE);
// uint64_t asize = aligned_size(size, CACHE_BLOCK_SIZE);
uint8_t *src = new uint8_t[RAM_PAGE_SIZE]; uint8_t *src = new uint8_t[RAM_PAGE_SIZE];
for (uint64_t i = 0; i < RAM_PAGE_SIZE; ++i) { for (uint64_t i = 0; i < RAM_PAGE_SIZE; ++i) {
// src[i] = (value >> (i << 3)) & 0xff;
src[i] = 0; src[i] = 0;
} }
ram_.enable_acl(false); ram_.enable_acl(false);
@ -574,14 +599,14 @@ public:
// void read_page_table(uint64_t addr) { // void read_page_table(uint64_t addr) {
// uint8_t *dest = new uint8_t[RAM_PAGE_SIZE]; // uint8_t *dest = new uint8_t[RAM_PAGE_SIZE];
// download(dest, addr, RAM_PAGE_SIZE); // download(dest, addr, RAM_PAGE_SIZE);
// printf("VXDRV: download %d bytes from 0x%x\n", RAM_PAGE_SIZE, addr); // DBGPRINT("VXDRV: download %d bytes from 0x%x\n", RAM_PAGE_SIZE, addr);
// for (int i = 0; i < RAM_PAGE_SIZE; i += 4) { // for (int i = 0; i < RAM_PAGE_SIZE; i += 4) {
// printf("mem-read: 0x%x -> 0x%x\n", addr + i, *(uint64_t*)((uint8_t*)dest + i)); // DBGPRINT("mem-read: 0x%x -> 0x%x\n", addr + i, *(uint64_t*)((uint8_t*)dest + i));
// } // }
// } // }
void write_pte(uint64_t addr, uint64_t value = 0xbaadf00d) { void write_pte(uint64_t addr, uint64_t value = 0xbaadf00d) {
std::cout << "writing pte 0x" << std::hex << value << " to pAddr: 0x" << std::hex << addr << std::endl; DBGPRINT("[Write_pte] writing pte 0x%lx to pAddr: 0x%lx\n", value, addr);
uint8_t *src = new uint8_t[PTE_SIZE]; uint8_t *src = new uint8_t[PTE_SIZE];
for (uint64_t i = 0; i < PTE_SIZE; ++i) { for (uint64_t i = 0; i < PTE_SIZE; ++i) {
src[i] = (value >> (i << 3)) & 0xff; src[i] = (value >> (i << 3)) & 0xff;
@ -596,15 +621,17 @@ public:
uint8_t *dest = new uint8_t[PTE_SIZE]; uint8_t *dest = new uint8_t[PTE_SIZE];
uint64_t mask = 0; uint64_t mask = 0;
if (XLEN == 32) if (XLEN == 32)
mask = 0xFFFFFFFF; mask = 0x00000000FFFFFFFF;
else if (XLEN == 64) else if (XLEN == 64)
mask = 0xFFFFFFFFFFFFFFFF; mask = 0xFFFFFFFFFFFFFFFF;
else else
assert(0, "XLEN is not either 32 or 64") assert(0 && "XLEN is not either 32 or 64");
std::cout << "[read_pte] reading PTE from RAM addr 0x" << std::hex << addr << std::endl;
ram_.read((uint8_t*)dest, addr, PTE_SIZE); ram_.read((uint8_t*)dest, addr, PTE_SIZE);
return (*(uint64_t*)((uint8_t*)dest)) & mask; uint64_t ret = (*(uint64_t*)((uint8_t*)dest)) & mask;
DBGPRINT("[read_pte] reading PTE 0x%lx from RAM addr 0x%lx\n", ret, addr);
return ret;
} }
#endif // JAEWON #endif // JAEWON

View file

@ -115,6 +115,7 @@ void MemoryUnit::ADecoder::map(uint64_t start, uint64_t end, MemDevice &md) {
} }
void MemoryUnit::ADecoder::read(void* data, uint64_t addr, uint64_t size) { void MemoryUnit::ADecoder::read(void* data, uint64_t addr, uint64_t size) {
// printf("====%s (addr= 0x%lx, size= 0x%lx) ====\n", __PRETTY_FUNCTION__,addr,size);
mem_accessor_t ma; mem_accessor_t ma;
if (!this->lookup(addr, size, &ma)) { if (!this->lookup(addr, size, &ma)) {
std::cout << "lookup of 0x" << std::hex << addr << " failed.\n"; std::cout << "lookup of 0x" << std::hex << addr << " failed.\n";
@ -124,6 +125,7 @@ void MemoryUnit::ADecoder::read(void* data, uint64_t addr, uint64_t size) {
} }
void MemoryUnit::ADecoder::write(const void* data, uint64_t addr, uint64_t size) { void MemoryUnit::ADecoder::write(const void* data, uint64_t addr, uint64_t size) {
// printf("====%s====\n", __PRETTY_FUNCTION__);
mem_accessor_t ma; mem_accessor_t ma;
if (!this->lookup(addr, size, &ma)) { if (!this->lookup(addr, size, &ma)) {
std::cout << "lookup of 0x" << std::hex << addr << " failed.\n"; std::cout << "lookup of 0x" << std::hex << addr << " failed.\n";
@ -158,6 +160,7 @@ void MemoryUnit::attach(MemDevice &m, uint64_t start, uint64_t end) {
#ifdef VM_ENABLE #ifdef VM_ENABLE
std::pair<bool, uint64_t> MemoryUnit::tlbLookup(uint64_t vAddr, ACCESS_TYPE type, uint64_t* size_bits) { std::pair<bool, uint64_t> MemoryUnit::tlbLookup(uint64_t vAddr, ACCESS_TYPE type, uint64_t* size_bits) {
// printf("====%s====\n", __PRETTY_FUNCTION__);
//Find entry while accounting for different sizes. //Find entry while accounting for different sizes.
for (auto entry : tlb_) for (auto entry : tlb_)
@ -220,7 +223,7 @@ std::pair<bool, uint64_t> MemoryUnit::tlbLookup(uint64_t vAddr, ACCESS_TYPE type
return std::make_pair(false, 0); return std::make_pair(false, 0);
} }
} }
#endif //JAEWON #else
MemoryUnit::TLBEntry MemoryUnit::tlbLookup(uint64_t vAddr, uint32_t flagMask) { MemoryUnit::TLBEntry MemoryUnit::tlbLookup(uint64_t vAddr, uint32_t flagMask) {
auto iter = tlb_.find(vAddr / pageSize_); auto iter = tlb_.find(vAddr / pageSize_);
if (iter != tlb_.end()) { if (iter != tlb_.end()) {
@ -244,52 +247,62 @@ uint64_t MemoryUnit::toPhyAddr(uint64_t addr, uint32_t flagMask) {
} }
return pAddr; return pAddr;
} }
#endif
#ifdef VM_ENABLE #ifdef VM_ENABLE
void MemoryUnit::read(void* data, uint64_t addr, uint64_t size, ACCESS_TYPE type) { void MemoryUnit::read(void* data, uint64_t addr, uint32_t size, ACCESS_TYPE type) {
// printf("====%s====\n", __PRETTY_FUNCTION__);
uint64_t pAddr; uint64_t pAddr;
if (this->mode == VA_MODE::BARE) { pAddr = vAddr_to_pAddr(addr, type);
pAddr = addr;
} else {
pAddr = vAddr_to_pAddr(addr, type);
}
return decoder_.read(data, pAddr, size); return decoder_.read(data, pAddr, size);
} }
#else #else
void MemoryUnit::read(void* data, uint64_t addr, uint64_t size, bool sup) { void MemoryUnit::read(void* data, uint64_t addr, uint32_t size, bool sup) {
uint64_t pAddr = this->toPhyAddr(addr, sup ? 8 : 1); uint64_t pAddr = this->toPhyAddr(addr, sup ? 8 : 1);
return decoder_.read(data, pAddr, size); return decoder_.read(data, pAddr, size);
} }
#endif #endif
#ifdef VM_ENABLE #ifdef VM_ENABLE
void MemoryUnit::write(const void* data, uint64_t addr, uint64_t size, ACCESS_TYPE type) { void MemoryUnit::write(const void* data, uint64_t addr, uint32_t size, ACCESS_TYPE type) {
// printf("====%s====\n", __PRETTY_FUNCTION__);
uint64_t pAddr; uint64_t pAddr;
if ( (this->mode == VA_MODE::BARE) | (addr >= IO_BASE_ADDR) ) { pAddr = vAddr_to_pAddr(addr, type);
pAddr = addr;
} else {
pAddr = vAddr_to_pAddr(addr, type);
}
decoder_.write(data, pAddr, size); decoder_.write(data, pAddr, size);
amo_reservation_.valid = false; amo_reservation_.valid = false;
} }
#else #else
void MemoryUnit::write(const void* data, uint64_t addr, uint64_t size, bool sup) { void MemoryUnit::write(const void* data, uint64_t addr, uint32_t size, bool sup) {
uint64_t pAddr = this->toPhyAddr(addr, sup ? 16 : 1); uint64_t pAddr = this->toPhyAddr(addr, sup ? 16 : 1);
decoder_.write(data, pAddr, size); decoder_.write(data, pAddr, size);
amo_reservation_.valid = false; amo_reservation_.valid = false;
} }
#endif #endif
#ifdef VM_ENABLE
void MemoryUnit::amo_reserve(uint64_t addr) {
uint64_t pAddr = this->vAddr_to_pAddr(addr,ACCESS_TYPE::LOAD);
amo_reservation_.addr = pAddr;
amo_reservation_.valid = true;
}
#else
void MemoryUnit::amo_reserve(uint64_t addr) { void MemoryUnit::amo_reserve(uint64_t addr) {
uint64_t pAddr = this->toPhyAddr(addr, 1); uint64_t pAddr = this->toPhyAddr(addr, 1);
amo_reservation_.addr = pAddr; amo_reservation_.addr = pAddr;
amo_reservation_.valid = true; amo_reservation_.valid = true;
} }
#endif
#ifdef VM_ENABLE
bool MemoryUnit::amo_check(uint64_t addr) {
uint64_t pAddr = this->vAddr_to_pAddr(addr, ACCESS_TYPE::LOAD);
return amo_reservation_.valid && (amo_reservation_.addr == pAddr);
}
#else
bool MemoryUnit::amo_check(uint64_t addr) { bool MemoryUnit::amo_check(uint64_t addr) {
uint64_t pAddr = this->toPhyAddr(addr, 1); uint64_t pAddr = this->toPhyAddr(addr, 1);
return amo_reservation_.valid && (amo_reservation_.addr == pAddr); return amo_reservation_.valid && (amo_reservation_.addr == pAddr);
} }
#endif
#ifdef VM_ENABLE #ifdef VM_ENABLE
@ -465,6 +478,7 @@ uint8_t *RAM::get(uint64_t address) const {
} }
void RAM::read(void* data, uint64_t addr, uint64_t size) { void RAM::read(void* data, uint64_t addr, uint64_t size) {
// printf("====%s (addr= 0x%lx, size= 0x%lx) ====\n", __PRETTY_FUNCTION__,addr,size);
if (check_acl_ && acl_mngr_.check(addr, size, 0x1) == false) { if (check_acl_ && acl_mngr_.check(addr, size, 0x1) == false) {
throw BadAddress(); throw BadAddress();
} }
@ -577,15 +591,41 @@ void RAM::loadHexImage(const char* filename) {
} }
#ifdef VM_ENABLE #ifdef VM_ENABLE
bool MemoryUnit::need_trans(uint64_t dev_pAddr)
{
// Check if the this is the BARE mode
bool isBAREMode = (this->mode == VA_MODE::BARE);
// Check if the address is reserved
bool isReserved = (dev_pAddr >= PAGE_TABLE_BASE_ADDR);
// Check if the address falls within the startup address range
bool isStartAddress = (STARTUP_ADDR <= dev_pAddr) && (dev_pAddr < (STARTUP_ADDR + 0x40000));
// Print the boolean results for debugging purposes
// printf("0x%lx, %u, %u, %u \n", dev_pAddr,isBAREMode, isReserved, isStartAddress);
// Return true if the address needs translation (i.e., it's not reserved and not a start address)
return (!isBAREMode && !isReserved && !isStartAddress);
}
uint64_t MemoryUnit::vAddr_to_pAddr(uint64_t vAddr, ACCESS_TYPE type) uint64_t MemoryUnit::vAddr_to_pAddr(uint64_t vAddr, ACCESS_TYPE type)
{ {
uint64_t pfn; uint64_t pfn;
uint64_t size_bits; uint64_t size_bits;
// printf("====%s====\n", __PRETTY_FUNCTION__);
// printf("vaddr = 0x%lx, type = 0x%u\n",vAddr,type);
if (!need_trans(vAddr))
{
// printf("Translation is not needed.\n");
return vAddr;
}
//First lookup TLB. //First lookup TLB.
std::pair<bool, uint64_t> tlb_access = tlbLookup(vAddr, type, &size_bits); std::pair<bool, uint64_t> tlb_access = tlbLookup(vAddr, type, &size_bits);
if (tlb_access.first) if (tlb_access.first)
{ {
// printf("Found pfn %lx in TLB\n",tlb_access.second);
pfn = tlb_access.second; pfn = tlb_access.second;
TLB_HIT++; TLB_HIT++;
} }
@ -596,33 +636,37 @@ uint64_t MemoryUnit::vAddr_to_pAddr(uint64_t vAddr, ACCESS_TYPE type)
pfn = ptw_access.first; TLB_MISS++; PTW++; pfn = ptw_access.first; TLB_MISS++; PTW++;
unique_translations.insert(vAddr>>size_bits); unique_translations.insert(vAddr>>size_bits);
PERF_UNIQUE_PTW = unique_translations.size(); PERF_UNIQUE_PTW = unique_translations.size();
} }
//Construct final address using pfn and offset. //Construct final address using pfn and offset.
std::cout << "[MemoryUnit] translated vAddr: 0x" << std::hex << vAddr << " to pAddr: 0x" << std::hex << ((pfn << size_bits) + (vAddr & ((1 << size_bits) - 1))) << std::endl; // std::cout << "[MemoryUnit] translated vAddr: 0x" << std::hex << vAddr << " to pAddr: 0x" << std::hex << ((pfn << size_bits) + (vAddr & ((1 << size_bits) - 1))) << std::endl;
return (pfn << size_bits) + (vAddr & ((1 << size_bits) - 1)); return (pfn << size_bits) + (vAddr & ((1 << size_bits) - 1));
} }
std::pair<uint64_t, uint8_t> MemoryUnit::page_table_walk(uint64_t vAddr_bits, ACCESS_TYPE type, uint64_t* size_bits) std::pair<uint64_t, uint8_t> MemoryUnit::page_table_walk(uint64_t vAddr_bits, ACCESS_TYPE type, uint64_t* size_bits)
{ {
// printf("====%s====\n", __PRETTY_FUNCTION__);
// printf("vaddr = 0x%lx, type = %u, size_bits %lu\n", vAddr_bits, type, *size_bits);
uint64_t LEVELS = 2; uint64_t LEVELS = 2;
vAddr_SV32_t vAddr(vAddr_bits); vAddr_SV32_t vAddr(vAddr_bits);
uint64_t pte_bytes; uint64_t pte_bytes = 0;
//Get base page table. //Get base page table.
uint64_t a = this->ptbr << 12; uint64_t pt_ba = this->ptbr << 12;
int i = LEVELS - 1; int i = LEVELS - 1;
while(true) while(true)
{ {
//Read PTE. //Read PTE.
decoder_.read(&pte_bytes, a+vAddr.vpn[i]*PTE_SIZE, sizeof(uint64_t)); decoder_.read(&pte_bytes, pt_ba+vAddr.vpn[i]*PTE_SIZE, PTE_SIZE);
PTE_SV32_t pte(pte_bytes); PTE_SV32_t pte(pte_bytes);
//Check if it has invalid flag bits. //Check if it has invalid flag bits.
if ( (pte.v == 0) | ( (pte.r == 0) & (pte.w == 1) ) ) if ( (pte.v == 0) | ( (pte.r == 0) & (pte.w == 1) ) )
{ {
printf("Error: PTE FLAGS=0x%x\n",pte.flags);
throw Page_Fault_Exception("Page Fault : Attempted to access invalid entry."); throw Page_Fault_Exception("Page Fault : Attempted to access invalid entry.");
} }
@ -632,18 +676,19 @@ std::pair<uint64_t, uint8_t> MemoryUnit::page_table_walk(uint64_t vAddr_bits, AC
i--; i--;
if (i < 0) if (i < 0)
{ {
printf("Error: PTE FLAGS=0x%x\n",pte.flags);
throw Page_Fault_Exception("Page Fault : No leaf node found."); throw Page_Fault_Exception("Page Fault : No leaf node found.");
} }
else else
{ {
//Continue on to next level. //Continue on to next level.
a = (pte_bytes >> 10 ) << 12; pt_ba = (pte_bytes >> 10 ) << 12;
} }
} }
else else
{ {
//Leaf node found, finished walking. //Leaf node found, finished walking.
a = (pte_bytes >> 10 ) << 12; pt_ba = (pte_bytes >> 10 ) << 12;
break; break;
} }
} }
@ -653,40 +698,21 @@ std::pair<uint64_t, uint8_t> MemoryUnit::page_table_walk(uint64_t vAddr_bits, AC
//Check RWX permissions according to access type. //Check RWX permissions according to access type.
if ( (type == ACCESS_TYPE::FETCH) & ((pte.r == 0) | (pte.x == 0)) ) if ( (type == ACCESS_TYPE::FETCH) & ((pte.r == 0) | (pte.x == 0)) )
{ {
printf("Error: PTE FLAGS=0x%x\n",pte.flags);
throw Page_Fault_Exception("Page Fault : TYPE FETCH, Incorrect permissions."); throw Page_Fault_Exception("Page Fault : TYPE FETCH, Incorrect permissions.");
} }
else if ( (type == ACCESS_TYPE::LOAD) & (pte.r == 0) ) else if ( (type == ACCESS_TYPE::LOAD) & (pte.r == 0) )
{ {
printf("Error: PTE FLAGS=0x%x\n",pte.flags);
throw Page_Fault_Exception("Page Fault : TYPE LOAD, Incorrect permissions."); throw Page_Fault_Exception("Page Fault : TYPE LOAD, Incorrect permissions.");
} }
else if ( (type == ACCESS_TYPE::STORE) & (pte.w == 0) ) else if ( (type == ACCESS_TYPE::STORE) & (pte.w == 0) )
{ {
printf("Error: PTE FLAGS=0x%x\n",pte.flags);
throw Page_Fault_Exception("Page Fault : TYPE STORE, Incorrect permissions."); throw Page_Fault_Exception("Page Fault : TYPE STORE, Incorrect permissions.");
} }
*size_bits = 12;
uint64_t pfn; uint64_t pfn = pt_ba >> *size_bits;
if (i > 0)
{
//It is a super page.
if (pte.ppn[0] != 0)
{
//Misss aligned super page.
throw Page_Fault_Exception("Page Fault : Miss Aligned Super Page.");
}
else
{
//Valid super page.
pfn = pte.ppn[1];
*size_bits = 22;
}
}
else
{
//Regular page.
*size_bits = 12;
pfn = a >> 12;
}
return std::make_pair(pfn, pte_bytes & 0xff); return std::make_pair(pfn, pte_bytes & 0xff);
} }

View file

@ -116,17 +116,21 @@ public:
// ACCESS_TYPE access_type; // ACCESS_TYPE access_type;
}; };
#ifdef VM_ENABLE
MemoryUnit(uint64_t pageSize = PAGE_TABLE_SIZE);
#else
MemoryUnit(uint64_t pageSize = 0); MemoryUnit(uint64_t pageSize = 0);
#endif
void attach(MemDevice &m, uint64_t start, uint64_t end); void attach(MemDevice &m, uint64_t start, uint64_t end);
#ifdef VM_ENABLE #ifdef VM_ENABLE
void read(void* data, uint64_t addr, uint64_t size, ACCESS_TYPE type = ACCESS_TYPE::LOAD); void read(void* data, uint64_t addr, uint32_t size, ACCESS_TYPE type = ACCESS_TYPE::LOAD);
void write(const void* data, uint64_t addr, uint64_t size, ACCESS_TYPE type = ACCESS_TYPE::STORE); void write(const void* data, uint64_t addr, uint32_t size, ACCESS_TYPE type = ACCESS_TYPE::STORE);
#else #else
void read(void* data, uint64_t addr, uint64_t size, bool sup); void read(void* data, uint64_t addr, uint32_t size, bool sup);
void write(const void* data, uint64_t addr, uint64_t size, bool sup); void write(const void* data, uint64_t addr, uint32_t size, bool sup);
#endif #endif
void amo_reserve(uint64_t addr); void amo_reserve(uint64_t addr);
@ -220,14 +224,16 @@ private:
#ifdef VM_ENABLE #ifdef VM_ENABLE
std::pair<bool, uint64_t> tlbLookup(uint64_t vAddr, ACCESS_TYPE type, uint64_t* size_bits); std::pair<bool, uint64_t> tlbLookup(uint64_t vAddr, ACCESS_TYPE type, uint64_t* size_bits);
bool need_trans(uint64_t dev_pAddr);
uint64_t vAddr_to_pAddr(uint64_t vAddr, ACCESS_TYPE type); 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); std::pair<uint64_t, uint8_t> page_table_walk(uint64_t vAddr_bits, ACCESS_TYPE type, uint64_t* size_bits);
#else
uint64_t toPhyAddr(uint64_t vAddr, uint32_t flagMask);
TLBEntry tlbLookup(uint64_t vAddr, uint32_t flagMask);
#endif #endif
TLBEntry tlbLookup(uint64_t vAddr, uint32_t flagMask);
uint64_t toPhyAddr(uint64_t vAddr, uint32_t flagMask);
std::unordered_map<uint64_t, TLBEntry> tlb_; std::unordered_map<uint64_t, TLBEntry> tlb_;
uint64_t pageSize_; uint64_t pageSize_;
@ -328,7 +334,7 @@ class PTE_SV32_t
} }
public: public:
uint64_t ppn[2]; uint64_t ppn;
uint32_t rsw; uint32_t rsw;
uint32_t flags; uint32_t flags;
bool d, a, g, u, x, w, r, v; bool d, a, g, u, x, w, r, v;
@ -337,8 +343,7 @@ class PTE_SV32_t
assert((address>> 32) == 0 && "Upper 32 bits are not zero!"); assert((address>> 32) == 0 && "Upper 32 bits are not zero!");
flags = bits(address,0,7); flags = bits(address,0,7);
rsw = bits(address,8,9); rsw = bits(address,8,9);
ppn[0] = bits(address,10,19); ppn = bits(address,10,31);
ppn[1] = bits(address,20,31);
d = bit(7); d = bit(7);
a = bit(6); a = bit(6);
@ -348,6 +353,7 @@ class PTE_SV32_t
w = bit(2); w = bit(2);
r = bit(1); r = bit(1);
v = bit(0); v = bit(0);
// printf("ppn = 0x%lx, flags= 0x%x, rsw= 0x%x\n",ppn,flags,rsw);
} }
}; };
@ -374,6 +380,7 @@ class vAddr_SV32_t
vpn[0] = bits(address,12,21); vpn[0] = bits(address,12,21);
vpn[1] = bits(address,22,31); vpn[1] = bits(address,22,31);
pgoff = bits(address,0,11); pgoff = bits(address,0,11);
// printf("vpn[0] = 0x%lx, vpn[1] = 0x%lx, pgoff = 0x%lx\n",vpn[0],vpn[1],pgoff);
} }
}; };
#endif #endif

View file

@ -270,6 +270,8 @@ bool Emulator::barrier(uint32_t bar_id, uint32_t count, uint32_t wid) {
#ifdef VM_ENABLE #ifdef VM_ENABLE
void Emulator::icache_read(void *data, uint64_t addr, uint32_t size) { void Emulator::icache_read(void *data, uint64_t addr, uint32_t size) {
DPH(3, "*** icache_read 0x" << std::hex << addr << ", size = 0x " << size);
try try
{ {
mmu_.read(data, addr, size, ACCESS_TYPE::LOAD); mmu_.read(data, addr, size, ACCESS_TYPE::LOAD);
@ -288,6 +290,7 @@ void Emulator::icache_read(void *data, uint64_t addr, uint32_t size) {
#ifdef VM_ENABLE #ifdef VM_ENABLE
void Emulator::set_satp(uint32_t satp) { void Emulator::set_satp(uint32_t satp) {
DPH(3, "set satp 0x" << std::hex << satp << " in emulator module\n");
set_csr(VX_CSR_SATP,satp,0,0); set_csr(VX_CSR_SATP,satp,0,0);
} }
#endif #endif
@ -327,6 +330,7 @@ void Emulator::dcache_read(void *data, uint64_t addr, uint32_t size) {
#ifdef VM_ENABLE #ifdef VM_ENABLE
void Emulator::dcache_write(const void* data, uint64_t addr, uint32_t size) { void Emulator::dcache_write(const void* data, uint64_t addr, uint32_t size) {
DP(1, "*** dcache_write 0x" << std::hex << addr << ", size = 0x " << size);
auto type = get_addr_type(addr); auto type = get_addr_type(addr);
if (addr >= uint64_t(IO_COUT_ADDR) if (addr >= uint64_t(IO_COUT_ADDR)
&& addr < (uint64_t(IO_COUT_ADDR) + IO_COUT_SIZE)) { && addr < (uint64_t(IO_COUT_ADDR) + IO_COUT_SIZE)) {

View file

@ -157,7 +157,6 @@ uint32_t Processor::get_satp() {
} }
void Processor::set_satp(uint32_t satp) { void Processor::set_satp(uint32_t satp) {
std::cout << "set SATP: 0x" << std::hex << this->satp << std::endl;
impl_->set_satp(satp); impl_->set_satp(satp);
this->satp = satp; this->satp = satp;
} }