return false;
return it->second->store(addr - -it->first, len, bytes);
}
-
-rom_device_t::rom_device_t(std::vector<char> 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;
-}
#include <map>
#include <vector>
+class processor_t;
+
class abstract_device_t {
public:
virtual bool load(reg_t addr, size_t len, uint8_t* bytes) = 0;
rom_device_t(std::vector<char> data);
bool load(reg_t addr, size_t len, uint8_t* bytes);
bool store(reg_t addr, size_t len, const uint8_t* bytes);
+ const std::vector<char>& contents() { return data; }
private:
std::vector<char> data;
};
+class rtc_t : public abstract_device_t {
+ public:
+ rtc_t(std::vector<processor_t*>&);
+ bool load(reg_t addr, size_t len, uint8_t* bytes);
+ bool store(reg_t addr, size_t len, const uint8_t* bytes);
+ size_t size() { return regs.size() * sizeof(regs[0]); }
+ void increment(reg_t inc);
+ private:
+ std::vector<processor_t*>& procs;
+ std::vector<uint64_t> regs;
+ uint64_t time() { return regs[0]; }
+};
+
#endif
#define CSR_MIDELEG 0x303
#define CSR_MIE 0x304
#define CSR_MTVEC 0x305
-#define CSR_MTIMECMP 0x321
#define CSR_MSCRATCH 0x340
#define CSR_MEPC 0x341
#define CSR_MCAUSE 0x342
#define CSR_MSTIME_DELTA 0x705
#define CSR_MSINSTRET_DELTA 0x706
#define CSR_MCYCLE 0xf00
-#define CSR_MTIME 0xf01
#define CSR_MINSTRET 0xf02
#define CSR_MISA 0xf10
#define CSR_MVENDORID 0xf11
#define CSR_CYCLEH 0xc80
#define CSR_TIMEH 0xc81
#define CSR_INSTRETH 0xc82
-#define CSR_MTIMECMPH 0x361
#define CSR_MUCYCLE_DELTAH 0x780
#define CSR_MUTIME_DELTAH 0x781
#define CSR_MUINSTRET_DELTAH 0x782
#define CSR_MSTIME_DELTAH 0x785
#define CSR_MSINSTRET_DELTAH 0x786
#define CSR_MCYCLEH 0xf80
-#define CSR_MTIMEH 0xf81
#define CSR_MINSTRETH 0xf82
#define CAUSE_MISALIGNED_FETCH 0x0
#define CAUSE_FAULT_FETCH 0x1
DECLARE_CSR(mideleg, CSR_MIDELEG)
DECLARE_CSR(mie, CSR_MIE)
DECLARE_CSR(mtvec, CSR_MTVEC)
-DECLARE_CSR(mtimecmp, CSR_MTIMECMP)
DECLARE_CSR(mscratch, CSR_MSCRATCH)
DECLARE_CSR(mepc, CSR_MEPC)
DECLARE_CSR(mcause, CSR_MCAUSE)
DECLARE_CSR(mstime_delta, CSR_MSTIME_DELTA)
DECLARE_CSR(msinstret_delta, CSR_MSINSTRET_DELTA)
DECLARE_CSR(mcycle, CSR_MCYCLE)
-DECLARE_CSR(mtime, CSR_MTIME)
DECLARE_CSR(minstret, CSR_MINSTRET)
DECLARE_CSR(misa, CSR_MISA)
DECLARE_CSR(mvendorid, CSR_MVENDORID)
DECLARE_CSR(cycleh, CSR_CYCLEH)
DECLARE_CSR(timeh, CSR_TIMEH)
DECLARE_CSR(instreth, CSR_INSTRETH)
-DECLARE_CSR(mtimecmph, CSR_MTIMECMPH)
DECLARE_CSR(mucycle_deltah, CSR_MUCYCLE_DELTAH)
DECLARE_CSR(mutime_deltah, CSR_MUTIME_DELTAH)
DECLARE_CSR(muinstret_deltah, CSR_MUINSTRET_DELTAH)
DECLARE_CSR(mstime_deltah, CSR_MSTIME_DELTAH)
DECLARE_CSR(msinstret_deltah, CSR_MSINSTRET_DELTAH)
DECLARE_CSR(mcycleh, CSR_MCYCLEH)
-DECLARE_CSR(mtimeh, CSR_MTIMEH)
DECLARE_CSR(minstreth, CSR_MINSTRETH)
#endif
#ifdef DECLARE_CAUSE
void processor_t::take_interrupt()
{
- check_timer();
-
reg_t pending_interrupts = state.mip & state.mie;
reg_t mie = get_field(state.mstatus, MSTATUS_MIE);
raise_interrupt(ctz(enabled_interrupts));
}
-void processor_t::check_timer()
-{
- if (sim->rtc >= state.mtimecmp)
- state.mip |= MIP_MTIP;
-}
-
static bool validate_priv(reg_t priv)
{
return priv == PRV_U || priv == PRV_S || priv == PRV_M;
case CSR_MSCRATCH: state.mscratch = val; break;
case CSR_MCAUSE: state.mcause = val; break;
case CSR_MBADADDR: state.mbadaddr = val; break;
- case CSR_MTIMECMP:
- state.mip &= ~MIP_MTIP;
- state.mtimecmp = val;
- break;
case CSR_MTOHOST:
if (state.tohost == 0)
state.tohost = val;
case CSR_MSCYCLE_DELTAH: if (xlen > 32) break; else return 0;
case CSR_MSTIME_DELTAH: if (xlen > 32) break; else return 0;
case CSR_MSINSTRET_DELTAH: if (xlen > 32) break; else return 0;
- case CSR_MTIME: return sim->rtc;
case CSR_MCYCLE: return state.minstret;
case CSR_MINSTRET: return state.minstret;
- case CSR_MTIMEH: if (xlen > 32) break; else return sim->rtc >> 32;
case CSR_MCYCLEH: if (xlen > 32) break; else return state.minstret >> 32;
case CSR_MINSTRETH: if (xlen > 32) break; else return state.minstret >> 32;
case CSR_SSTATUS: {
case CSR_MSCRATCH: return state.mscratch;
case CSR_MCAUSE: return state.mcause;
case CSR_MBADADDR: return state.mbadaddr;
- case CSR_MTIMECMP: return state.mtimecmp;
case CSR_MISA: return isa;
case CSR_MARCHID: return 0;
case CSR_MIMPID: return 0;
case CSR_MFROMHOST:
sim->get_htif()->tick(); // not necessary, but faster
return state.fromhost;
- case CSR_MCFGADDR: return sim->memsz;
+ case CSR_MCFGADDR: return sim->config_string_addr;
}
throw trap_illegal_instruction();
}
reg_t mstatus;
reg_t mepc;
reg_t mbadaddr;
- reg_t mtimecmp;
reg_t mscratch;
reg_t mcause;
reg_t minstret;
friend class sim_t;
friend class mmu_t;
+ friend class rtc_t;
friend class extension_t;
void parse_isa_string(const char* isa);
rocc.cc \
regnames.cc \
devices.cc \
+ rom.cc \
+ rtc.cc \
$(riscv_gen_srcs) \
riscv_test_srcs =
--- /dev/null
+#include "devices.h"
+
+rom_device_t::rom_device_t(std::vector<char> 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;
+}
--- /dev/null
+#include "devices.h"
+#include "processor.h"
+
+rtc_t::rtc_t(std::vector<processor_t*>& procs)
+ : procs(procs), regs(1 + procs.size())
+{
+}
+
+bool rtc_t::load(reg_t addr, size_t len, uint8_t* bytes)
+{
+ if (addr + len > size())
+ return false;
+ memcpy(bytes, (uint8_t*)®s[0] + addr, len);
+ return true;
+}
+
+bool rtc_t::store(reg_t addr, size_t len, const uint8_t* bytes)
+{
+ if (addr + len > size() || addr < 8)
+ return false;
+ memcpy((uint8_t*)®s[0] + addr, bytes, len);
+ increment(0);
+ return true;
+}
+
+void rtc_t::increment(reg_t inc)
+{
+ regs[0] += inc;
+ for (size_t i = 0; i < procs.size(); i++) {
+ procs[i]->state.mip &= ~MIP_MTIP;
+ if (regs[0] >= regs[1+i])
+ procs[i]->state.mip |= MIP_MTIP;
+ }
+}
sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb,
const std::vector<std::string>& args)
: htif(new htif_isasim_t(this, args)), procs(std::max(nprocs, size_t(1))),
- rtc(0), current_step(0), current_proc(0), debug(false)
+ current_step(0), current_proc(0), debug(false)
{
signal(SIGINT, &handle_signal);
// allocate target machine's memory, shrinking it as necessary
for (size_t i = 0; i < procs.size(); i++)
procs[i] = new processor_t(isa, this, i);
+ rtc.reset(new rtc_t(procs));
make_config_string();
}
procs[current_proc]->yield_load_reservation();
if (++current_proc == procs.size()) {
current_proc = 0;
- rtc += INTERLEAVE / INSNS_PER_RTC_TICK;
+ rtc->increment(INTERLEAVE / INSNS_PER_RTC_TICK);
}
htif->tick();
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());
+ config_string_addr = rtc_addr + rtc->size();
+
std::stringstream s;
s << std::hex <<
"platform {\n"
" vendor ucb;\n"
" arch spike;\n"
"};\n"
+ "rtc {\n"
+ " addr 0x" << rtc_addr << ";\n"
+ "};\n"
"ram {\n"
" 0 {\n"
" addr 0;\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]);
vec.push_back(0);
assert(vec.size() <= csr_size);
config_string.reset(new rom_device_t(vec));
- bus.add_device(memsz, config_string.get());
+ bus.add_device(config_string_addr, config_string.get());
}
mmu_t* debug_mmu; // debug port into main memory
std::vector<processor_t*> procs;
std::unique_ptr<rom_device_t> config_string;
+ std::unique_ptr<rtc_t> rtc;
+ reg_t config_string_addr;
bus_t bus;
processor_t* get_core(const std::string& i);
void step(size_t n); // step through simulation
static const size_t INTERLEAVE = 5000;
static const size_t INSNS_PER_RTC_TICK = 100; // 10 MHz clock for 1 BIPS core
- reg_t rtc;
size_t current_step;
size_t current_proc;
bool debug;
#include <sstream>
#include <stdlib.h>
-
struct : public arg_t {
std::string to_string(insn_t insn) const {
return std::to_string((int)insn.i_imm()) + '(' + xpr_name[insn.rs1()] + ')';