Browse Source

Move much closer to new platform-M memory map

Reset vector is at 0x1000; below that is reserved for debug
Memory is at 0x80000000
pull/40/merge
Andrew Waterman 10 years ago
parent
commit
b593e6df7a
  1. 9
      riscv/encoding.h
  2. 24
      riscv/htif.cc
  3. 1
      riscv/interactive.cc
  4. 33
      riscv/mmu.cc
  5. 16
      riscv/mmu.h
  6. 9
      riscv/processor.cc
  7. 1
      riscv/processor.h
  8. 40
      riscv/sim.cc
  9. 12
      riscv/sim.h
  10. 1
      spike_main/spike.cc

9
riscv/encoding.h

@ -67,9 +67,12 @@
#define IRQ_COP 12 #define IRQ_COP 12
#define IRQ_HOST 13 #define IRQ_HOST 13
#define DEFAULT_RSTVEC 0x0 #define DEFAULT_RSTVEC 0x1000
#define DEFAULT_NMIVEC 0x4 #define DEFAULT_NMIVEC 0x1004
#define DEFAULT_MTVEC 0x8 #define CFGSTRING_ADDR 0x100C
#define DEFAULT_MTVEC 0x1010
#define IO_BASE 0x40000000
#define MEM_BASE 0x80000000
// page table entry (PTE) fields // page table entry (PTE) fields
#define PTE_V 0x001 // Valid #define PTE_V 0x001 // Valid

24
riscv/htif.cc

@ -2,6 +2,7 @@
#include "htif.h" #include "htif.h"
#include "sim.h" #include "sim.h"
#include "mmu.h"
#include "encoding.h" #include "encoding.h"
#include <unistd.h> #include <unistd.h>
#include <stdexcept> #include <stdexcept>
@ -46,17 +47,30 @@ void htif_isasim_t::tick_once()
send(&ack, sizeof(ack)); send(&ack, sizeof(ack));
uint64_t buf[hdr.data_size]; uint64_t buf[hdr.data_size];
for (size_t i = 0; i < hdr.data_size; i++) for (size_t i = 0; i < hdr.data_size; i++) {
buf[i] = sim->debug_mmu->load_uint64((hdr.addr+i)*HTIF_DATA_ALIGN); reg_t addr = (hdr.addr + i) * HTIF_DATA_ALIGN;
try {
buf[i] = sim->debug_mmu->load_uint64(addr);
} catch (trap_load_access_fault& e) {
fprintf(stderr, "HTIF: attempt to read from illegal address 0x%" PRIx64 "\n", addr);
exit(-1);
}
}
send(buf, hdr.data_size * sizeof(buf[0])); send(buf, hdr.data_size * sizeof(buf[0]));
break; break;
} }
case HTIF_CMD_WRITE_MEM: case HTIF_CMD_WRITE_MEM:
{ {
const uint64_t* buf = (const uint64_t*)p.get_payload(); const uint64_t* buf = (const uint64_t*)p.get_payload();
for (size_t i = 0; i < hdr.data_size; i++) for (size_t i = 0; i < hdr.data_size; i++) {
sim->debug_mmu->store_uint64((hdr.addr+i)*HTIF_DATA_ALIGN, buf[i]); reg_t addr = (hdr.addr + i) * HTIF_DATA_ALIGN;
try {
sim->debug_mmu->store_uint64(addr, buf[i]);
} catch (trap_load_access_fault& e) {
fprintf(stderr, "HTIF: attempt to write to illegal address 0x%" PRIx64 "\n", addr);
exit(-1);
}
}
packet_header_t ack(HTIF_CMD_ACK, seqno, 0, 0); packet_header_t ack(HTIF_CMD_ACK, seqno, 0, 0);
send(&ack, sizeof(ack)); send(&ack, sizeof(ack));
break; break;

1
riscv/interactive.cc

@ -3,6 +3,7 @@
#include "decode.h" #include "decode.h"
#include "disasm.h" #include "disasm.h"
#include "sim.h" #include "sim.h"
#include "mmu.h"
#include "htif.h" #include "htif.h"
#include <sys/mman.h> #include <sys/mman.h>
#include <termios.h> #include <termios.h>

33
riscv/mmu.cc

@ -4,8 +4,8 @@
#include "sim.h" #include "sim.h"
#include "processor.h" #include "processor.h"
mmu_t::mmu_t(char* _mem, size_t _memsz) mmu_t::mmu_t(sim_t* sim, processor_t* proc)
: mem(_mem), memsz(_memsz), proc(NULL) : sim(sim), proc(proc)
{ {
flush_tlb(); flush_tlb();
} }
@ -54,23 +54,26 @@ reg_t mmu_t::translate(reg_t addr, access_type type)
const uint16_t* mmu_t::fetch_slow_path(reg_t addr) const uint16_t* mmu_t::fetch_slow_path(reg_t addr)
{ {
reg_t paddr = translate(addr, FETCH); reg_t paddr = translate(addr, FETCH);
if (paddr < memsz) if (sim->addr_is_mem(paddr)) {
refill_tlb(addr, paddr, FETCH); refill_tlb(addr, paddr, FETCH);
else return (const uint16_t*)sim->addr_to_mem(paddr);
throw trap_instruction_access_fault(addr); } else {
return (const uint16_t*)(mem + paddr); if (!sim->mmio_load(paddr, sizeof fetch_temp, (uint8_t*)&fetch_temp))
throw trap_instruction_access_fault(addr);
return &fetch_temp;
}
} }
void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes) void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes)
{ {
reg_t paddr = translate(addr, LOAD); reg_t paddr = translate(addr, LOAD);
if (paddr < memsz) { if (sim->addr_is_mem(paddr)) {
memcpy(bytes, mem + paddr, len); memcpy(bytes, sim->addr_to_mem(paddr), len);
if (tracer.interested_in_range(paddr, paddr + PGSIZE, LOAD)) if (tracer.interested_in_range(paddr, paddr + PGSIZE, LOAD))
tracer.trace(paddr, len, LOAD); tracer.trace(paddr, len, LOAD);
else else
refill_tlb(addr, paddr, LOAD); refill_tlb(addr, paddr, LOAD);
} else if (!proc || !proc->sim->mmio_load(paddr, len, bytes)) { } else if (!sim->mmio_load(paddr, len, bytes)) {
throw trap_load_access_fault(addr); throw trap_load_access_fault(addr);
} }
} }
@ -78,13 +81,13 @@ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes)
void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes) void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes)
{ {
reg_t paddr = translate(addr, STORE); reg_t paddr = translate(addr, STORE);
if (paddr < memsz) { if (sim->addr_is_mem(paddr)) {
memcpy(mem + paddr, bytes, len); memcpy(sim->addr_to_mem(paddr), bytes, len);
if (tracer.interested_in_range(paddr, paddr + PGSIZE, STORE)) if (tracer.interested_in_range(paddr, paddr + PGSIZE, STORE))
tracer.trace(paddr, len, STORE); tracer.trace(paddr, len, STORE);
else else
refill_tlb(addr, paddr, STORE); refill_tlb(addr, paddr, STORE);
} else if (!proc || !proc->sim->mmio_store(paddr, len, bytes)) { } else if (!sim->mmio_store(paddr, len, bytes)) {
throw trap_store_access_fault(addr); throw trap_store_access_fault(addr);
} }
} }
@ -102,7 +105,7 @@ void mmu_t::refill_tlb(reg_t vaddr, reg_t paddr, access_type type)
else if (type == STORE) tlb_store_tag[idx] = expected_tag; else if (type == STORE) tlb_store_tag[idx] = expected_tag;
else tlb_load_tag[idx] = expected_tag; else tlb_load_tag[idx] = expected_tag;
tlb_data[idx] = mem + paddr - vaddr; tlb_data[idx] = sim->addr_to_mem(paddr) - vaddr;
} }
reg_t mmu_t::walk(reg_t addr, access_type type, bool supervisor, bool pum) reg_t mmu_t::walk(reg_t addr, access_type type, bool supervisor, bool pum)
@ -130,10 +133,10 @@ reg_t mmu_t::walk(reg_t addr, access_type type, bool supervisor, bool pum)
// check that physical address of PTE is legal // check that physical address of PTE is legal
reg_t pte_addr = base + idx * ptesize; reg_t pte_addr = base + idx * ptesize;
if (pte_addr >= memsz) if (!sim->addr_is_mem(pte_addr))
break; break;
void* ppte = mem + pte_addr; void* ppte = sim->addr_to_mem(pte_addr);
reg_t pte = ptesize == 4 ? *(uint32_t*)ppte : *(uint64_t*)ppte; reg_t pte = ptesize == 4 ? *(uint32_t*)ppte : *(uint64_t*)ppte;
reg_t ppn = pte >> PTE_PPN_SHIFT; reg_t ppn = pte >> PTE_PPN_SHIFT;

16
riscv/mmu.h

@ -7,6 +7,7 @@
#include "trap.h" #include "trap.h"
#include "common.h" #include "common.h"
#include "config.h" #include "config.h"
#include "sim.h"
#include "processor.h" #include "processor.h"
#include "memtracer.h" #include "memtracer.h"
#include <stdlib.h> #include <stdlib.h>
@ -33,7 +34,7 @@ struct icache_entry_t {
class mmu_t class mmu_t
{ {
public: public:
mmu_t(char* _mem, size_t _memsz); mmu_t(sim_t* sim, processor_t* proc);
~mmu_t(); ~mmu_t();
// template for functions that load an aligned value from memory // template for functions that load an aligned value from memory
@ -93,10 +94,7 @@ public:
int length = insn_length(insn); int length = insn_length(insn);
if (likely(length == 4)) { if (likely(length == 4)) {
if (likely(addr % PGSIZE < PGSIZE-2)) insn |= (insn_bits_t)*(const int16_t*)translate_insn_addr(addr + 2) << 16;
insn |= (insn_bits_t)*(const int16_t*)(iaddr + 1) << 16;
else
insn |= (insn_bits_t)*(const int16_t*)translate_insn_addr(addr + 2) << 16;
} else if (length == 2) { } else if (length == 2) {
insn = (int16_t)insn; insn = (int16_t)insn;
} else if (length == 6) { } else if (length == 6) {
@ -113,7 +111,7 @@ public:
entry->tag = addr; entry->tag = addr;
entry->data = fetch; entry->data = fetch;
reg_t paddr = (const char*)iaddr - mem; reg_t paddr = sim->mem_to_addr((char*)iaddr);
if (tracer.interested_in_range(paddr, paddr + 1, FETCH)) { if (tracer.interested_in_range(paddr, paddr + 1, FETCH)) {
entry->tag = -1; entry->tag = -1;
tracer.trace(paddr, length, FETCH); tracer.trace(paddr, length, FETCH);
@ -134,18 +132,16 @@ public:
return access_icache(addr)->data; return access_icache(addr)->data;
} }
void set_processor(processor_t* p) { proc = p; flush_tlb(); }
void flush_tlb(); void flush_tlb();
void flush_icache(); void flush_icache();
void register_memtracer(memtracer_t*); void register_memtracer(memtracer_t*);
private: private:
char* mem; sim_t* sim;
size_t memsz;
processor_t* proc; processor_t* proc;
memtracer_list_t tracer; memtracer_list_t tracer;
uint16_t fetch_temp;
// implement an instruction cache for simulator performance // implement an instruction cache for simulator performance
icache_entry_t icache[ICACHE_ENTRIES]; icache_entry_t icache[ICACHE_ENTRIES];

9
riscv/processor.cc

@ -5,6 +5,7 @@
#include "common.h" #include "common.h"
#include "config.h" #include "config.h"
#include "sim.h" #include "sim.h"
#include "mmu.h"
#include "htif.h" #include "htif.h"
#include "disasm.h" #include "disasm.h"
#include <cinttypes> #include <cinttypes>
@ -25,8 +26,7 @@ processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id)
{ {
parse_isa_string(isa); parse_isa_string(isa);
mmu = new mmu_t(sim->mem, sim->memsz); mmu = new mmu_t(sim, this);
mmu->set_processor(this);
reset(true); reset(true);
@ -217,7 +217,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
set_csr(CSR_MSTATUS, s); set_csr(CSR_MSTATUS, s);
set_privilege(PRV_S); set_privilege(PRV_S);
} else { } else {
state.pc = DEFAULT_MTVEC; state.pc = state.mtvec;
state.mcause = t.cause(); state.mcause = t.cause();
state.mepc = epc; state.mepc = epc;
if (t.has_badaddr()) if (t.has_badaddr())
@ -344,6 +344,7 @@ void processor_t::set_csr(int which, reg_t val)
case CSR_SCAUSE: state.scause = val; break; case CSR_SCAUSE: state.scause = val; break;
case CSR_SBADADDR: state.sbadaddr = val; break; case CSR_SBADADDR: state.sbadaddr = val; break;
case CSR_MEPC: state.mepc = val; break; case CSR_MEPC: state.mepc = val; break;
case CSR_MTVEC: state.mtvec = val >> 2 << 2; break;
case CSR_MSCRATCH: state.mscratch = val; break; case CSR_MSCRATCH: state.mscratch = val; break;
case CSR_MCAUSE: state.mcause = val; break; case CSR_MCAUSE: state.mcause = val; break;
case CSR_MBADADDR: state.mbadaddr = val; break; case CSR_MBADADDR: state.mbadaddr = val; break;
@ -441,7 +442,7 @@ reg_t processor_t::get_csr(int which)
case CSR_MIMPID: return 0; case CSR_MIMPID: return 0;
case CSR_MVENDORID: return 0; case CSR_MVENDORID: return 0;
case CSR_MHARTID: return id; case CSR_MHARTID: return id;
case CSR_MTVEC: return DEFAULT_MTVEC; case CSR_MTVEC: return state.mtvec;
case CSR_MEDELEG: return state.medeleg; case CSR_MEDELEG: return state.medeleg;
case CSR_MIDELEG: return state.mideleg; case CSR_MIDELEG: return state.mideleg;
case CSR_MTOHOST: case CSR_MTOHOST:

1
riscv/processor.h

@ -46,6 +46,7 @@ struct state_t
reg_t mepc; reg_t mepc;
reg_t mbadaddr; reg_t mbadaddr;
reg_t mscratch; reg_t mscratch;
reg_t mtvec;
reg_t mcause; reg_t mcause;
reg_t minstret; reg_t minstret;
reg_t mie; reg_t mie;

40
riscv/sim.cc

@ -1,6 +1,7 @@
// See LICENSE for license details. // See LICENSE for license details.
#include "sim.h" #include "sim.h"
#include "mmu.h"
#include "htif.h" #include "htif.h"
#include <map> #include <map>
#include <iostream> #include <iostream>
@ -40,7 +41,7 @@ sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb,
fprintf(stderr, "warning: only got %lu bytes of target mem (wanted %lu)\n", fprintf(stderr, "warning: only got %lu bytes of target mem (wanted %lu)\n",
(unsigned long)memsz, (unsigned long)memsz0); (unsigned long)memsz, (unsigned long)memsz0);
debug_mmu = new mmu_t(mem, memsz); debug_mmu = new mmu_t(this, NULL);
for (size_t i = 0; i < procs.size(); i++) for (size_t i = 0; i < procs.size(); i++)
procs[i] = new processor_t(isa, this, i); procs[i] = new processor_t(isa, this, i);
@ -158,13 +159,20 @@ bool sim_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes)
void sim_t::make_config_string() void sim_t::make_config_string()
{ {
size_t csr_size = NCSR * 16 /* RV128 */; reg_t rtc_addr = IO_BASE;
size_t device_tree_addr = memsz;
size_t cpu_addr = memsz + csr_size;
reg_t rtc_addr = memsz;
bus.add_device(rtc_addr, rtc.get()); bus.add_device(rtc_addr, rtc.get());
config_string_addr = rtc_addr + rtc->size();
uint32_t reset_vec[8] = {
0x297 + MEM_BASE - DEFAULT_RSTVEC, // reset vector
0x00028067, // jump straight to MEM_BASE
0x00000000, // reserved
0, // pointer to configuration string
0, 0, 0, 0 // trap vector
};
config_string_addr = DEFAULT_RSTVEC + sizeof(reset_vec);
reset_vec[3] = config_string_addr;
std::vector<char> rom((char*)reset_vec, (char*)reset_vec + sizeof(reset_vec));
std::stringstream s; std::stringstream s;
s << std::hex << s << std::hex <<
@ -177,8 +185,8 @@ void sim_t::make_config_string()
"};\n" "};\n"
"ram {\n" "ram {\n"
" 0 {\n" " 0 {\n"
" addr 0;\n" " addr 0x" << MEM_BASE << ";\n"
" size 0x" << memsz << ";\n" " size 0x" << (MEM_BASE + memsz) << ";\n"
" };\n" " };\n"
"};\n" "};\n"
"core {\n"; "core {\n";
@ -187,19 +195,15 @@ void sim_t::make_config_string()
" " << i << " {\n" " " << i << " {\n"
" " << "0 {\n" << // hart 0 on core i " " << "0 {\n" << // hart 0 on core i
" isa " << procs[i]->isa_string << ";\n" " isa " << procs[i]->isa_string << ";\n"
" addr 0x" << cpu_addr << ";\n"
" timecmp 0x" << (rtc_addr + 8*(1+i)) << ";\n" " timecmp 0x" << (rtc_addr + 8*(1+i)) << ";\n"
" };\n" " };\n"
" };\n"; " };\n";
bus.add_device(cpu_addr, procs[i]);
cpu_addr += csr_size;
} }
s << "};\n"; s << "};\n";
std::string str = s.str(); config_string = s.str();
std::vector<char> vec(str.begin(), str.end()); rom.insert(rom.end(), config_string.begin(), config_string.end());
vec.push_back(0); rom.push_back(0);
assert(vec.size() <= csr_size); boot_rom.reset(new rom_device_t(rom));
config_string.reset(new rom_device_t(vec)); bus.add_device(DEFAULT_RSTVEC, boot_rom.get());
bus.add_device(config_string_addr, config_string.get());
} }

12
riscv/sim.h

@ -7,10 +7,10 @@
#include <string> #include <string>
#include <memory> #include <memory>
#include "processor.h" #include "processor.h"
#include "mmu.h"
#include "devices.h" #include "devices.h"
class htif_isasim_t; class htif_isasim_t;
class mmu_t;
// this class encapsulates the processors and memory in a RISC-V machine. // this class encapsulates the processors and memory in a RISC-V machine.
class sim_t class sim_t
@ -29,7 +29,7 @@ public:
void set_histogram(bool value); void set_histogram(bool value);
void set_procs_debug(bool value); void set_procs_debug(bool value);
htif_isasim_t* get_htif() { return htif.get(); } htif_isasim_t* get_htif() { return htif.get(); }
const char* get_config_string() { return &config_string->contents()[0]; } const char* get_config_string() { return config_string.c_str(); }
// returns the number of processors in this simulator // returns the number of processors in this simulator
size_t num_cores() { return procs.size(); } size_t num_cores() { return procs.size(); }
@ -44,7 +44,8 @@ private:
size_t memsz; // memory size in bytes size_t memsz; // memory size in bytes
mmu_t* debug_mmu; // debug port into main memory mmu_t* debug_mmu; // debug port into main memory
std::vector<processor_t*> procs; std::vector<processor_t*> procs;
std::unique_ptr<rom_device_t> config_string; std::string config_string;
std::unique_ptr<rom_device_t> boot_rom;
std::unique_ptr<rtc_t> rtc; std::unique_ptr<rtc_t> rtc;
reg_t config_string_addr; reg_t config_string_addr;
bus_t bus; bus_t bus;
@ -60,6 +61,11 @@ private:
bool histogram_enabled; // provide a histogram of PCs bool histogram_enabled; // provide a histogram of PCs
// memory-mapped I/O routines // memory-mapped I/O routines
bool addr_is_mem(reg_t addr) {
return addr >= MEM_BASE && addr < MEM_BASE + memsz;
}
char* addr_to_mem(reg_t addr) { return mem + addr - MEM_BASE; }
reg_t mem_to_addr(char* x) { return x - mem + MEM_BASE; }
bool mmio_load(reg_t addr, size_t len, uint8_t* bytes); bool mmio_load(reg_t addr, size_t len, uint8_t* bytes);
bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes); bool mmio_store(reg_t addr, size_t len, const uint8_t* bytes);
void make_config_string(); void make_config_string();

1
spike_main/spike.cc

@ -1,6 +1,7 @@
// See LICENSE for license details. // See LICENSE for license details.
#include "sim.h" #include "sim.h"
#include "mmu.h"
#include "htif.h" #include "htif.h"
#include "cachesim.h" #include "cachesim.h"
#include "extension.h" #include "extension.h"

Loading…
Cancel
Save