From 0c3af3d73a28c0fc57eac535b2a28f45134b556b Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 12 Nov 2015 17:51:46 -0800 Subject: [PATCH] Generate device tree for target machine --- riscv/decode.h | 1 + riscv/devices.cc | 40 +++++++++++++ riscv/devices.h | 34 +++++++++++ riscv/devicetree.h | 142 +++++++++++++++++++++++++++++++++++++++++++++ riscv/encoding.h | 78 ++++++++++++++++++++++++- riscv/mmu.cc | 4 +- riscv/processor.cc | 72 +++++++++++++++-------- riscv/processor.h | 10 +++- riscv/riscv.mk.in | 1 + riscv/sim.cc | 55 +++++++++++++++--- riscv/sim.h | 7 ++- 11 files changed, 404 insertions(+), 40 deletions(-) create mode 100644 riscv/devices.cc create mode 100644 riscv/devices.h create mode 100644 riscv/devicetree.h diff --git a/riscv/decode.h b/riscv/decode.h index a9713f4..5be6398 100644 --- a/riscv/decode.h +++ b/riscv/decode.h @@ -21,6 +21,7 @@ typedef uint64_t freg_t; const int NXPR = 32; const int NFPR = 32; +const int NCSR = 4096; #define X_RA 1 #define X_SP 2 diff --git a/riscv/devices.cc b/riscv/devices.cc new file mode 100644 index 0000000..25e39e0 --- /dev/null +++ b/riscv/devices.cc @@ -0,0 +1,40 @@ +#include "devices.h" + +void bus_t::add_device(reg_t addr, abstract_device_t* dev) +{ + devices[-addr] = dev; +} + +bool bus_t::load(reg_t addr, size_t len, uint8_t* bytes) +{ + auto it = devices.lower_bound(-addr); + if (it == devices.end()) + return false; + return it->second->load(addr - -it->first, len, bytes); +} + +bool bus_t::store(reg_t addr, size_t len, const uint8_t* bytes) +{ + auto it = devices.lower_bound(-addr); + if (it == devices.end()) + return false; + return it->second->store(addr - -it->first, len, bytes); +} + +rom_device_t::rom_device_t(std::vector data) + : data(data) +{ +} + +bool rom_device_t::load(reg_t addr, size_t len, uint8_t* bytes) +{ + if (addr + len > data.size()) + return false; + memcpy(bytes, &data[addr], len); + return true; +} + +bool rom_device_t::store(reg_t addr, size_t len, const uint8_t* bytes) +{ + return false; +} diff --git a/riscv/devices.h b/riscv/devices.h new file mode 100644 index 0000000..558ecc7 --- /dev/null +++ b/riscv/devices.h @@ -0,0 +1,34 @@ +#ifndef _RISCV_DEVICES_H +#define _RISCV_DEVICES_H + +#include "decode.h" +#include +#include + +class abstract_device_t { + public: + virtual bool load(reg_t addr, size_t len, uint8_t* bytes) = 0; + virtual bool store(reg_t addr, size_t len, const uint8_t* bytes) = 0; + virtual ~abstract_device_t() {} +}; + +class bus_t : public abstract_device_t { + public: + bool load(reg_t addr, size_t len, uint8_t* bytes); + bool store(reg_t addr, size_t len, const uint8_t* bytes); + void add_device(reg_t addr, abstract_device_t* dev); + + private: + std::map devices; +}; + +class rom_device_t : public abstract_device_t { + public: + rom_device_t(std::vector data); + bool load(reg_t addr, size_t len, uint8_t* bytes); + bool store(reg_t addr, size_t len, const uint8_t* bytes); + private: + std::vector data; +}; + +#endif diff --git a/riscv/devicetree.h b/riscv/devicetree.h new file mode 100644 index 0000000..5d4a871 --- /dev/null +++ b/riscv/devicetree.h @@ -0,0 +1,142 @@ +// See LICENSE for license details. + +#ifndef _RISCV_DEVICETREE_H +#define _RISCV_DEVICETREE_H + +#include +#include +#include +#include +#include +#include + +#define FDT_MAGIC 0xd00dfeedU +#define FDT_VERSION 17 +#define FDT_COMP_VERSION 16 +#define FDT_BEGIN_NODE 1 +#define FDT_END_NODE 2 +#define FDT_PROP 3 +#define FDT_END 9 + +struct fdt_header { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +}; + +struct fdt_reserve_entry { + uint64_t address; + uint64_t size; +}; + +struct string_table { + std::map strings; + std::vector data; + + size_t add(std::string s) { + if (!strings.count(s)) { + strings[s] = data.size(); + data.insert(data.end(), s.begin(), s.end()); + data.push_back(0); + } + return strings[s]; + } +}; + +struct device_tree { + device_tree() { + memset(rsvmap, 0, sizeof(rsvmap)); + } + + void begin_node(std::string s) { + std::vector name = s2v(s); + sblock.push_back(FDT_BEGIN_NODE); + sblock.insert(sblock.end(), name.begin(), name.end()); + } + + void end_node() { + sblock.push_back(FDT_END_NODE); + } + + std::vector finalize() { + sblock.push_back(FDT_END); + + struct fdt_header h; + h.size_dt_struct = sblock.size() * sizeof(sblock[0]); + h.size_dt_strings = strings.data.size(); + h.magic = FDT_MAGIC; + h.off_rsvmap = sizeof(h); + h.off_dt_struct = h.off_rsvmap + sizeof(rsvmap); + h.off_dt_strings = h.off_dt_struct + h.size_dt_struct; + h.totalsize = h.off_dt_strings + h.size_dt_strings; + h.version = FDT_VERSION; + h.last_comp_version = FDT_COMP_VERSION; + h.boot_cpuid_phys = 0; + + for (uint32_t* p = &h.magic; p < &h.magic + sizeof(h)/sizeof(uint32_t); p++) + *p = htonl(*p); + for (uint32_t& p : sblock) + p = htonl(p); + + std::vector res; + res.insert(res.end(), (char*)&h, (char*)&h + sizeof(h)); + res.insert(res.end(), (char*)&rsvmap, (char*)&rsvmap + sizeof(rsvmap)); + res.insert(res.end(), (char*)&sblock[0], + (char*)&sblock[0] + sblock.size() * sizeof(sblock[0])); + res.insert(res.end(), strings.data.begin(), strings.data.end()); + return res; + } + + void add_prop(std::string name, uint32_t data) + { + add_prop(name, std::vector(1, data), sizeof(data)); + } + + void add_reg(std::vector values) + { + std::vector v; + for (auto x : values) { + v.push_back(x >> 32); + v.push_back(x); + } + add_prop("reg", v, v.size() * sizeof(v[0])); + } + + void add_prop(std::string name, std::string data) + { + add_prop(name, s2v(data), data.size()+1); + } + + private: + struct string_table strings; + std::vector sblock; + struct fdt_reserve_entry rsvmap[1]; + + std::vector s2v(std::string data) { + std::vector v(data.begin(), data.end()); + do { + v.push_back(0); + } while (v.size() % 4); + + std::vector words; + for (size_t i = 0; i < v.size(); i += 4) + words.push_back((v[i] << 24) | (v[i+1] << 16) | (v[i+2] << 8) | v[i+3]); + return words; + } + + void add_prop(std::string name, std::vector data, size_t len) { + sblock.push_back(FDT_PROP); + sblock.push_back(len); + sblock.push_back(strings.add(name)); + sblock.insert(sblock.end(), data.begin(), data.end()); + } +}; + +#endif diff --git a/riscv/encoding.h b/riscv/encoding.h index 7303a2b..e9a495f 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -567,6 +567,54 @@ #define MASK_C_SWSP 0xe003 #define MATCH_C_FSWSP 0xe002 #define MASK_C_FSWSP 0xe003 +#define MATCH_CUSTOM0 0xb +#define MASK_CUSTOM0 0x707f +#define MATCH_CUSTOM0_RS1 0x200b +#define MASK_CUSTOM0_RS1 0x707f +#define MATCH_CUSTOM0_RS1_RS2 0x300b +#define MASK_CUSTOM0_RS1_RS2 0x707f +#define MATCH_CUSTOM0_RD 0x400b +#define MASK_CUSTOM0_RD 0x707f +#define MATCH_CUSTOM0_RD_RS1 0x600b +#define MASK_CUSTOM0_RD_RS1 0x707f +#define MATCH_CUSTOM0_RD_RS1_RS2 0x700b +#define MASK_CUSTOM0_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM1 0x2b +#define MASK_CUSTOM1 0x707f +#define MATCH_CUSTOM1_RS1 0x202b +#define MASK_CUSTOM1_RS1 0x707f +#define MATCH_CUSTOM1_RS1_RS2 0x302b +#define MASK_CUSTOM1_RS1_RS2 0x707f +#define MATCH_CUSTOM1_RD 0x402b +#define MASK_CUSTOM1_RD 0x707f +#define MATCH_CUSTOM1_RD_RS1 0x602b +#define MASK_CUSTOM1_RD_RS1 0x707f +#define MATCH_CUSTOM1_RD_RS1_RS2 0x702b +#define MASK_CUSTOM1_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM2 0x5b +#define MASK_CUSTOM2 0x707f +#define MATCH_CUSTOM2_RS1 0x205b +#define MASK_CUSTOM2_RS1 0x707f +#define MATCH_CUSTOM2_RS1_RS2 0x305b +#define MASK_CUSTOM2_RS1_RS2 0x707f +#define MATCH_CUSTOM2_RD 0x405b +#define MASK_CUSTOM2_RD 0x707f +#define MATCH_CUSTOM2_RD_RS1 0x605b +#define MASK_CUSTOM2_RD_RS1 0x707f +#define MATCH_CUSTOM2_RD_RS1_RS2 0x705b +#define MASK_CUSTOM2_RD_RS1_RS2 0x707f +#define MATCH_CUSTOM3 0x7b +#define MASK_CUSTOM3 0x707f +#define MATCH_CUSTOM3_RS1 0x207b +#define MASK_CUSTOM3_RS1 0x707f +#define MATCH_CUSTOM3_RS1_RS2 0x307b +#define MASK_CUSTOM3_RS1_RS2 0x707f +#define MATCH_CUSTOM3_RD 0x407b +#define MASK_CUSTOM3_RD 0x707f +#define MATCH_CUSTOM3_RD_RS1 0x607b +#define MASK_CUSTOM3_RD_RS1 0x707f +#define MATCH_CUSTOM3_RD_RS1_RS2 0x707b +#define MASK_CUSTOM3_RD_RS1_RS2 0x707f #define CSR_FFLAGS 0x1 #define CSR_FRM 0x2 #define CSR_FCSR 0x3 @@ -622,7 +670,8 @@ #define CSR_MTOHOST 0x780 #define CSR_MFROMHOST 0x781 #define CSR_MRESET 0x782 -#define CSR_SEND_IPI 0x783 +#define CSR_MIPI 0x783 +#define CSR_MIOBASE 0x784 #define CSR_CYCLEH 0xc80 #define CSR_TIMEH 0xc81 #define CSR_INSTRETH 0xc82 @@ -851,6 +900,30 @@ DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD) DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP) DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP) DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP) +DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0) +DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1) +DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2) +DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD) +DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1) +DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2) +DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1) +DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1) +DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2) +DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD) +DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1) +DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2) +DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2) +DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1) +DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2) +DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD) +DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1) +DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2) +DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3) +DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1) +DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2) +DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD) +DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1) +DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2) #endif #ifdef DECLARE_CSR DECLARE_CSR(fflags, CSR_FFLAGS) @@ -908,7 +981,8 @@ DECLARE_CSR(mhartid, CSR_MHARTID) DECLARE_CSR(mtohost, CSR_MTOHOST) DECLARE_CSR(mfromhost, CSR_MFROMHOST) DECLARE_CSR(mreset, CSR_MRESET) -DECLARE_CSR(send_ipi, CSR_SEND_IPI) +DECLARE_CSR(mipi, CSR_MIPI) +DECLARE_CSR(miobase, CSR_MIOBASE) DECLARE_CSR(cycleh, CSR_CYCLEH) DECLARE_CSR(timeh, CSR_TIMEH) DECLARE_CSR(instreth, CSR_INSTRETH) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index a8b1675..4558b1e 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -64,7 +64,7 @@ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes) tracer.trace(paddr, len, LOAD); else refill_tlb(addr, paddr, LOAD); - } else if (!proc || !proc->sim->mmio_load(addr, len, bytes)) { + } else if (!proc || !proc->sim->mmio_load(paddr, len, bytes)) { throw trap_load_access_fault(addr); } } @@ -78,7 +78,7 @@ void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes) tracer.trace(paddr, len, STORE); else refill_tlb(addr, paddr, STORE); - } else if (!proc || !proc->sim->mmio_store(addr, len, bytes)) { + } else if (!proc || !proc->sim->mmio_store(paddr, len, bytes)) { throw trap_store_access_fault(addr); } } diff --git a/riscv/processor.cc b/riscv/processor.cc index 37b77c5..3206ed0 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -54,52 +54,56 @@ static void bad_isa_string(const char* isa) abort(); } -void processor_t::parse_isa_string(const char* isa) +void processor_t::parse_isa_string(const char* str) { - const char* p = isa; - const char* all_subsets = "IMAFDC"; - std::string tmp; + std::string lowercase, tmp; + for (const char *r = str; *r; r++) + lowercase += std::tolower(*r); + + const char* p = lowercase.c_str(); + const char* all_subsets = "imafdc"; max_xlen = 64; cpuid = reg_t(2) << 62; - if (strncmp(p, "RV32", 4) == 0) + if (strncmp(p, "rv32", 4) == 0) max_xlen = 32, cpuid = 0, p += 4; - else if (strncmp(p, "RV64", 4) == 0) + else if (strncmp(p, "rv64", 4) == 0) p += 4; - else if (strncmp(p, "RV", 2) == 0) + else if (strncmp(p, "rv", 2) == 0) p += 2; if (!*p) { p = all_subsets; - } else if (*p == 'G') { // treat "G" as "IMAFD" - tmp = std::string("IMAFD") + (p+1); + } else if (*p == 'g') { // treat "G" as "IMAFD" + tmp = std::string("imafd") + (p+1); p = &tmp[0]; - } else if (*p != 'I') { - bad_isa_string(isa); + } else if (*p != 'i') { + bad_isa_string(str); } - cpuid |= 1L << ('S' - 'A'); // advertise support for supervisor mode + isa = "rv" + std::to_string(max_xlen) + p; + cpuid |= 1L << ('s' - 'a'); // advertise support for supervisor mode while (*p) { - cpuid |= 1L << (*p - 'A'); + cpuid |= 1L << (*p - 'a'); if (auto next = strchr(all_subsets, *p)) { all_subsets = next + 1; p++; - } else if (*p == 'X') { + } else if (*p == 'x') { const char* ext = p+1, *end = ext; while (islower(*end)) end++; register_extension(find_extension(std::string(ext, end - ext).c_str())()); p = end; } else { - bad_isa_string(isa); + bad_isa_string(str); } } if (supports_extension('D') && !supports_extension('F')) - bad_isa_string(isa); + bad_isa_string(str); } void state_t::reset() @@ -219,11 +223,6 @@ void processor_t::take_trap(trap_t& t, reg_t epc) t.side_effects(&state); // might set badvaddr etc. } -void processor_t::deliver_ipi() -{ - state.mip |= MIP_MSIP; -} - void processor_t::disasm(insn_t insn) { uint64_t bits = insn.bits() & ((1ULL << (8 * insn_length(insn.bits()))) - 1); @@ -329,6 +328,10 @@ void processor_t::set_csr(int which, reg_t val) state.mip = (state.mip & ~mask) | (val & mask); break; } + case CSR_MIPI: { + state.mip |= MIP_MSIP; + break; + } case CSR_MIE: { reg_t mask = MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP; state.mie = (state.mie & ~mask) | (val & mask); @@ -366,7 +369,6 @@ void processor_t::set_csr(int which, reg_t val) state.mip &= ~MIP_MTIP; state.mtimecmp = val; break; - case CSR_SEND_IPI: sim->send_ipi(val); break; case CSR_MTOHOST: if (state.tohost == 0) state.tohost = val; @@ -448,6 +450,7 @@ reg_t processor_t::get_csr(int which) case CSR_SSCRATCH: return state.sscratch; case CSR_MSTATUS: return state.mstatus; case CSR_MIP: return state.mip; + case CSR_MIPI: return 0; case CSR_MIE: return state.mie; case CSR_MEPC: return state.mepc; case CSR_MSCRATCH: return state.mscratch; @@ -465,7 +468,7 @@ reg_t processor_t::get_csr(int which) case CSR_MFROMHOST: sim->get_htif()->tick(); // not necessary, but faster return state.fromhost; - case CSR_SEND_IPI: return 0; + case CSR_MIOBASE: return sim->memsz; case CSR_UARCH0: case CSR_UARCH1: case CSR_UARCH2: @@ -569,3 +572,26 @@ void processor_t::register_base_instructions() register_insn({0, 0, &illegal_instruction, &illegal_instruction}); build_opcode_map(); } + +bool processor_t::load(reg_t addr, size_t len, uint8_t* bytes) +{ + try { + auto res = get_csr(addr / (max_xlen / 8)); + memcpy(bytes, &res, len); + return true; + } catch (trap_illegal_instruction& t) { + return false; + } +} + +bool processor_t::store(reg_t addr, size_t len, const uint8_t* bytes) +{ + try { + reg_t value = 0; + memcpy(&value, bytes, len); + set_csr(addr / (max_xlen / 8), value); + return true; + } catch (trap_illegal_instruction& t) { + return false; + } +} diff --git a/riscv/processor.h b/riscv/processor.h index fe0a121..b9564d6 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -4,6 +4,7 @@ #include "decode.h" #include "config.h" +#include "devices.h" #include #include #include @@ -72,7 +73,7 @@ struct state_t }; // this class represents one processor in a RISC-V machine. -class processor_t +class processor_t : public abstract_device_t { public: processor_t(const char* isa, sim_t* sim, uint32_t id); @@ -82,7 +83,6 @@ public: void set_histogram(bool value); void reset(bool value); void step(size_t n); // run for n cycles - void deliver_ipi(); // register an interprocessor interrupt bool running() { return run; } void set_csr(int which, reg_t val); void raise_interrupt(reg_t which); @@ -91,6 +91,7 @@ public: state_t* get_state() { return &state; } extension_t* get_extension() { return ext; } bool supports_extension(unsigned char ext) { + if (ext >= 'a' && ext <= 'z') ext += 'A' - 'a'; return ext >= 'A' && ext <= 'Z' && ((cpuid >> (ext - 'A')) & 1); } void push_privilege_stack(); @@ -101,6 +102,10 @@ public: void register_insn(insn_desc_t); void register_extension(extension_t*); + // MMIO slave interface + bool load(reg_t addr, size_t len, uint8_t* bytes); + bool store(reg_t addr, size_t len, const uint8_t* bytes); + private: sim_t* sim; mmu_t* mmu; // main memory is always accessed via the mmu @@ -111,6 +116,7 @@ private: uint32_t id; int max_xlen; int xlen; + std::string isa; bool run; // !reset bool debug; bool histogram_enabled; diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index af4f047..7d71fb5 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -40,6 +40,7 @@ riscv_srcs = \ extensions.cc \ rocc.cc \ regnames.cc \ + devices.cc \ $(riscv_gen_srcs) \ riscv_test_srcs = diff --git a/riscv/sim.cc b/riscv/sim.cc index f7ff11d..67b655e 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -2,6 +2,7 @@ #include "sim.h" #include "htif.h" +#include "devicetree.h" #include #include #include @@ -43,6 +44,8 @@ sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, for (size_t i = 0; i < procs.size(); i++) procs[i] = new processor_t(isa, this, i); + + make_device_tree(); } sim_t::~sim_t() @@ -53,12 +56,6 @@ sim_t::~sim_t() free(mem); } -void sim_t::send_ipi(reg_t who) -{ - if (who < procs.size()) - procs[who]->deliver_ipi(); -} - reg_t sim_t::get_scr(int which) { switch (which) @@ -146,10 +143,52 @@ void sim_t::set_procs_debug(bool value) bool sim_t::mmio_load(reg_t addr, size_t len, uint8_t* bytes) { - return false; + if (addr + len < addr) + return false; + return bus.load(addr, len, bytes); } bool sim_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes) { - return false; + if (addr + len < addr) + return false; + return bus.store(addr, len, bytes); +} + +void sim_t::make_device_tree() +{ + char buf[32]; + size_t max_devtree_size = procs.size() * 4096; // sloppy upper bound + size_t cpu_size = NCSR * procs[0]->max_xlen / 8; + reg_t cpu_addr = memsz + max_devtree_size; + + device_tree dt; + dt.begin_node(""); + dt.add_prop("#address-cells", 2); + dt.add_prop("#size-cells", 2); + dt.add_prop("model", "Spike"); + dt.begin_node("memory@0"); + dt.add_prop("device_type", "memory"); + dt.add_reg({0, memsz}); + dt.end_node(); + dt.begin_node("cpus"); + dt.add_prop("#address-cells", 2); + dt.add_prop("#size-cells", 2); + for (size_t i = 0; i < procs.size(); i++) { + sprintf(buf, "cpu@%" PRIx64, cpu_addr); + dt.begin_node(buf); + dt.add_prop("device_type", "cpu"); + dt.add_prop("compatible", "riscv"); + dt.add_prop("isa", procs[i]->isa); + dt.add_reg({cpu_addr}); + dt.end_node(); + + bus.add_device(cpu_addr, procs[i]); + cpu_addr += cpu_size; + } + dt.end_node(); + dt.end_node(); + + devicetree.reset(new rom_device_t(dt.finalize())); + bus.add_device(memsz, devicetree.get()); } diff --git a/riscv/sim.h b/riscv/sim.h index 636190e..6ef2c82 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -8,6 +8,7 @@ #include #include "processor.h" #include "mmu.h" +#include "devices.h" class htif_isasim_t; @@ -29,9 +30,6 @@ public: void set_procs_debug(bool value); htif_isasim_t* get_htif() { return htif.get(); } - // deliver an IPI to a specific processor - void send_ipi(reg_t who); - // returns the number of processors in this simulator size_t num_cores() { return procs.size(); } processor_t* get_core(size_t i) { return procs.at(i); } @@ -45,6 +43,8 @@ private: size_t memsz; // memory size in bytes mmu_t* debug_mmu; // debug port into main memory std::vector procs; + std::unique_ptr devicetree; + bus_t bus; processor_t* get_core(const std::string& i); void step(size_t n); // step through simulation @@ -60,6 +60,7 @@ private: // memory-mapped I/O routines 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); + void make_device_tree(); // presents a prompt for introspection into the simulation void interactive(); -- 2.30.2