Move much closer to new platform-M memory map
authorAndrew Waterman <waterman@cs.berkeley.edu>
Fri, 29 Apr 2016 20:48:56 +0000 (13:48 -0700)
committerAndrew Waterman <waterman@cs.berkeley.edu>
Fri, 29 Apr 2016 20:48:56 +0000 (13:48 -0700)
Reset vector is at 0x1000; below that is reserved for debug
Memory is at 0x80000000

riscv/encoding.h
riscv/htif.cc
riscv/interactive.cc
riscv/mmu.cc
riscv/mmu.h
riscv/processor.cc
riscv/processor.h
riscv/sim.cc
riscv/sim.h
spike_main/spike.cc

index b219309f26707f618159ecfd68821f071a8ab3c3..56a13c30f2141dd26ece517a45e0ac38351e779e 100644 (file)
 #define IRQ_COP      12
 #define IRQ_HOST     13
 
-#define DEFAULT_RSTVEC 0x0
-#define DEFAULT_NMIVEC 0x4
-#define DEFAULT_MTVEC  0x8
+#define DEFAULT_RSTVEC 0x1000
+#define DEFAULT_NMIVEC 0x1004
+#define CFGSTRING_ADDR 0x100C
+#define DEFAULT_MTVEC  0x1010
+#define IO_BASE  0x40000000
+#define MEM_BASE 0x80000000
 
 // page table entry (PTE) fields
 #define PTE_V     0x001 // Valid
index 14f6381ec74cc50049cc0a604dc7821f4625d8f1..4a462ecbdc8387723c548373b4f2d4c1db3b68e7 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "htif.h"
 #include "sim.h"
+#include "mmu.h"
 #include "encoding.h"
 #include <unistd.h>
 #include <stdexcept>
@@ -46,17 +47,30 @@ void htif_isasim_t::tick_once()
       send(&ack, sizeof(ack));
 
       uint64_t buf[hdr.data_size];
-      for (size_t i = 0; i < hdr.data_size; i++)
-        buf[i] = sim->debug_mmu->load_uint64((hdr.addr+i)*HTIF_DATA_ALIGN);
+      for (size_t i = 0; i < hdr.data_size; i++) {
+        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]));
       break;
     }
     case HTIF_CMD_WRITE_MEM:
     {
       const uint64_t* buf = (const uint64_t*)p.get_payload();
-      for (size_t i = 0; i < hdr.data_size; i++)
-        sim->debug_mmu->store_uint64((hdr.addr+i)*HTIF_DATA_ALIGN, buf[i]);
-
+      for (size_t i = 0; i < hdr.data_size; 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);
       send(&ack, sizeof(ack));
       break;
index 8e22c02c01d7089b7b18923eb771cb0472f94d4b..69f2461d69be40f5f497858df583b88358085910 100644 (file)
@@ -3,6 +3,7 @@
 #include "decode.h"
 #include "disasm.h"
 #include "sim.h"
+#include "mmu.h"
 #include "htif.h"
 #include <sys/mman.h>
 #include <termios.h>
index 45457d9833296794611ad1b61a092b15735e9863..0113443cfa4a83d92265ec7e91dccb5404212fd0 100644 (file)
@@ -4,8 +4,8 @@
 #include "sim.h"
 #include "processor.h"
 
-mmu_t::mmu_t(char* _mem, size_t _memsz)
- : mem(_mem), memsz(_memsz), proc(NULL)
+mmu_t::mmu_t(sim_t* sim, processor_t* proc)
+ : sim(sim), proc(proc)
 {
   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)
 {
   reg_t paddr = translate(addr, FETCH);
-  if (paddr < memsz)
+  if (sim->addr_is_mem(paddr)) {
     refill_tlb(addr, paddr, FETCH);
-  else
-    throw trap_instruction_access_fault(addr);
-  return (const uint16_t*)(mem + paddr);
+    return (const uint16_t*)sim->addr_to_mem(paddr);
+  } else {
+    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)
 {
   reg_t paddr = translate(addr, LOAD);
-  if (paddr < memsz) {
-    memcpy(bytes, mem + paddr, len);
+  if (sim->addr_is_mem(paddr)) {
+    memcpy(bytes, sim->addr_to_mem(paddr), len);
     if (tracer.interested_in_range(paddr, paddr + PGSIZE, LOAD))
       tracer.trace(paddr, len, LOAD);
     else
       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);
   }
 }
@@ -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)
 {
   reg_t paddr = translate(addr, STORE);
-  if (paddr < memsz) {
-    memcpy(mem + paddr, bytes, len);
+  if (sim->addr_is_mem(paddr)) {
+    memcpy(sim->addr_to_mem(paddr), bytes, len);
     if (tracer.interested_in_range(paddr, paddr + PGSIZE, STORE))
       tracer.trace(paddr, len, STORE);
     else
       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);
   }
 }
@@ -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 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)
@@ -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
     reg_t pte_addr = base + idx * ptesize;
-    if (pte_addr >= memsz)
+    if (!sim->addr_is_mem(pte_addr))
       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 ppn = pte >> PTE_PPN_SHIFT;
 
index b9948c53e05e52e8b6d317febdb2cd7aa3a66b3a..b6aa2cab91e87179fa90f0d6652769c9fd34f135 100644 (file)
@@ -7,6 +7,7 @@
 #include "trap.h"
 #include "common.h"
 #include "config.h"
+#include "sim.h"
 #include "processor.h"
 #include "memtracer.h"
 #include <stdlib.h>
@@ -33,7 +34,7 @@ struct icache_entry_t {
 class mmu_t
 {
 public:
-  mmu_t(char* _mem, size_t _memsz);
+  mmu_t(sim_t* sim, processor_t* proc);
   ~mmu_t();
 
   // template for functions that load an aligned value from memory
@@ -93,10 +94,7 @@ public:
     int length = insn_length(insn);
 
     if (likely(length == 4)) {
-      if (likely(addr % PGSIZE < PGSIZE-2))
-        insn |= (insn_bits_t)*(const int16_t*)(iaddr + 1) << 16;
-      else
-        insn |= (insn_bits_t)*(const int16_t*)translate_insn_addr(addr + 2) << 16;
+      insn |= (insn_bits_t)*(const int16_t*)translate_insn_addr(addr + 2) << 16;
     } else if (length == 2) {
       insn = (int16_t)insn;
     } else if (length == 6) {
@@ -113,7 +111,7 @@ public:
     entry->tag = addr;
     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)) {
       entry->tag = -1;
       tracer.trace(paddr, length, FETCH);
@@ -134,18 +132,16 @@ public:
     return access_icache(addr)->data;
   }
 
-  void set_processor(processor_t* p) { proc = p; flush_tlb(); }
-
   void flush_tlb();
   void flush_icache();
 
   void register_memtracer(memtracer_t*);
 
 private:
-  char* mem;
-  size_t memsz;
+  sim_t* sim;
   processor_t* proc;
   memtracer_list_t tracer;
+  uint16_t fetch_temp;
 
   // implement an instruction cache for simulator performance
   icache_entry_t icache[ICACHE_ENTRIES];
index b932034e9a6415ba8079490565a78ccff2c9be1d..d5825af9930d6b98aef6036afb3eab6427821b0b 100644 (file)
@@ -5,6 +5,7 @@
 #include "common.h"
 #include "config.h"
 #include "sim.h"
+#include "mmu.h"
 #include "htif.h"
 #include "disasm.h"
 #include <cinttypes>
@@ -25,8 +26,7 @@ processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id)
 {
   parse_isa_string(isa);
 
-  mmu = new mmu_t(sim->mem, sim->memsz);
-  mmu->set_processor(this);
+  mmu = new mmu_t(sim, this);
 
   reset(true);
 
@@ -217,7 +217,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
     set_csr(CSR_MSTATUS, s);
     set_privilege(PRV_S);
   } else {
-    state.pc = DEFAULT_MTVEC;
+    state.pc = state.mtvec;
     state.mcause = t.cause();
     state.mepc = epc;
     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_SBADADDR: state.sbadaddr = 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_MCAUSE: state.mcause = 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_MVENDORID: return 0;
     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_MIDELEG: return state.mideleg;
     case CSR_MTOHOST:
index 5557e5afad3bceede99d44735142e9bd6793df6b..9b48cc20890249418c665e8b2389d3add367f779 100644 (file)
@@ -46,6 +46,7 @@ struct state_t
   reg_t mepc;
   reg_t mbadaddr;
   reg_t mscratch;
+  reg_t mtvec;
   reg_t mcause;
   reg_t minstret;
   reg_t mie;
index b45c51ee8f43d16af0955b1d46b322413bb2a6ce..7f80e6f958e345fc5faa057baa22f7a4f6dad3d0 100644 (file)
@@ -1,6 +1,7 @@
 // See LICENSE for license details.
 
 #include "sim.h"
+#include "mmu.h"
 #include "htif.h"
 #include <map>
 #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",
             (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++)
     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()
 {
-  size_t csr_size = NCSR * 16 /* RV128 */;
-  size_t device_tree_addr = memsz;
-  size_t cpu_addr = memsz + csr_size;
-
-  reg_t rtc_addr = memsz;
+  reg_t rtc_addr = IO_BASE;
   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;
   s << std::hex <<
@@ -177,8 +185,8 @@ void sim_t::make_config_string()
         "};\n"
         "ram {\n"
         "  0 {\n"
-        "    addr 0;\n"
-        "    size 0x" << memsz << ";\n"
+        "    addr 0x" << MEM_BASE << ";\n"
+        "    size 0x" << (MEM_BASE + memsz) << ";\n"
         "  };\n"
         "};\n"
         "core {\n";
@@ -187,19 +195,15 @@ void sim_t::make_config_string()
         "  " << i << " {\n"
         "    " << "0 {\n" << // hart 0 on core i
         "      isa " << procs[i]->isa_string << ";\n"
-        "      addr 0x" << cpu_addr << ";\n"
         "      timecmp 0x" << (rtc_addr + 8*(1+i)) << ";\n"
         "    };\n"
         "  };\n";
-    bus.add_device(cpu_addr, procs[i]);
-    cpu_addr += csr_size;
   }
   s <<  "};\n";
 
-  std::string str = s.str();
-  std::vector<char> vec(str.begin(), str.end());
-  vec.push_back(0);
-  assert(vec.size() <= csr_size);
-  config_string.reset(new rom_device_t(vec));
-  bus.add_device(config_string_addr, config_string.get());
+  config_string = s.str();
+  rom.insert(rom.end(), config_string.begin(), config_string.end());
+  rom.push_back(0);
+  boot_rom.reset(new rom_device_t(rom));
+  bus.add_device(DEFAULT_RSTVEC, boot_rom.get());
 }
index d8f39e2e73ed9e7637bf55834dc303d00a2cf1ae..01025ed990158a4a6a14212446c365fbe346a7ad 100644 (file)
@@ -7,10 +7,10 @@
 #include <string>
 #include <memory>
 #include "processor.h"
-#include "mmu.h"
 #include "devices.h"
 
 class htif_isasim_t;
+class mmu_t;
 
 // this class encapsulates the processors and memory in a RISC-V machine.
 class sim_t
@@ -29,7 +29,7 @@ public:
   void set_histogram(bool value);
   void set_procs_debug(bool value);
   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
   size_t num_cores() { return procs.size(); }
@@ -44,7 +44,8 @@ private:
   size_t memsz; // memory size in bytes
   mmu_t* debug_mmu;  // debug port into main memory
   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;
   reg_t config_string_addr;
   bus_t bus;
@@ -60,6 +61,11 @@ private:
   bool histogram_enabled; // provide a histogram of PCs
 
   // 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_store(reg_t addr, size_t len, const uint8_t* bytes);
   void make_config_string();
index 6ca7beb2c4353e3b315d30eb25d97af9aa97bd6f..2f885182cfd0e0d2f3658b32a719817619413061 100644 (file)
@@ -1,6 +1,7 @@
 // See LICENSE for license details.
 
 #include "sim.h"
+#include "mmu.h"
 #include "htif.h"
 #include "cachesim.h"
 #include "extension.h"