From c1273bcbaf659f5bb54fb85e1292b21d70503bc4 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Sun, 31 May 2015 18:28:53 -0700 Subject: [PATCH] Use single, shared real-time counter This required disentangling INSTRET/CYCLE from TIME. --- riscv/processor.cc | 73 +++++++++++++++++++++++++--------------------- riscv/processor.h | 7 +++-- riscv/sim.cc | 6 ++-- riscv/sim.h | 2 ++ 4 files changed, 50 insertions(+), 38 deletions(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index 6368c8f..cf6790a 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -202,18 +202,13 @@ static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch) return npc; } -static void update_timer(state_t* state, size_t instret) +void processor_t::check_timer() { - uint64_t count0 = (uint64_t)(uint32_t)state->mtime; - state->mtime += instret; - uint64_t before = count0 - state->stimecmp; - if (int64_t(before ^ (before + instret)) < 0) - state->mip |= MIP_STIP; -} - -static size_t next_timer(state_t* state) -{ - return state->stimecmp - (uint32_t)state->mtime; + // this assumes the rtc doesn't change asynchronously during step(), + if (state.stimecmp >= (uint32_t)state.prev_rtc + && state.stimecmp < (uint32_t)sim->rtc) + state.mip |= MIP_STIP; + state.prev_rtc = sim->rtc; } void processor_t::step(size_t n) @@ -224,7 +219,6 @@ void processor_t::step(size_t n) if (unlikely(!run || !n)) return; - n = std::min(n, next_timer(&state) | 1U); #define maybe_serialize() \ if (unlikely(pc == PC_SERIALIZE)) { \ @@ -235,6 +229,7 @@ void processor_t::step(size_t n) try { + check_timer(); take_interrupt(); if (unlikely(debug)) @@ -280,7 +275,7 @@ void processor_t::step(size_t n) take_trap(t, pc); } - update_timer(&state, instret); + state.minstret += instret; // tail-recurse if we didn't execute as many instructions as we'd hoped if (instret < n) @@ -371,29 +366,35 @@ void processor_t::set_csr(int which, reg_t val) break; case CSR_MTIME: case CSR_STIMEW: - state.mtime = val; + // this implementation ignores writes to MTIME break; case CSR_MTIMEH: case CSR_STIMEHW: + // this implementation ignores writes to MTIME + break; + case CSR_TIMEW: + val -= sim->rtc; if (xlen == 32) - state.mtime = (uint32_t)val | (state.mtime >> 32 << 32); + state.sutime_delta = (uint32_t)val | (state.sutime_delta >> 32 << 32); else - state.mtime = val; + state.sutime_delta = val; + break; + case CSR_TIMEHW: + val = ((val << 32) - sim->rtc) >> 32; + state.sutime_delta = (val << 32) | (uint32_t)state.sutime_delta; break; case CSR_CYCLEW: - case CSR_TIMEW: case CSR_INSTRETW: - val -= state.mtime; + val -= state.minstret; if (xlen == 32) - state.sutime_delta = (uint32_t)val | (state.sutime_delta >> 32 << 32); + state.suinstret_delta = (uint32_t)val | (state.suinstret_delta >> 32 << 32); else - state.sutime_delta = val; + state.suinstret_delta = val; break; case CSR_CYCLEHW: - case CSR_TIMEHW: case CSR_INSTRETHW: - val -= state.mtime; - state.sutime_delta = (val << 32) | (uint32_t)state.sutime_delta; + val = ((val << 32) - state.minstret) >> 32; + state.suinstret_delta = (val << 32) | (uint32_t)state.suinstret_delta; break; case CSR_MSTATUS: { if ((val ^ state.mstatus) & (MSTATUS_VM | MSTATUS_PRV | MSTATUS_PRV1 | MSTATUS_MPRV)) @@ -496,29 +497,33 @@ reg_t processor_t::get_csr(int which) break; return (state.fflags << FSR_AEXC_SHIFT) | (state.frm << FSR_RD_SHIFT); case CSR_MTIME: + case CSR_STIME: case CSR_STIMEW: - return state.mtime; + return sim->rtc; case CSR_MTIMEH: + case CSR_STIMEH: case CSR_STIMEHW: - return state.mtime >> 32; - case CSR_CYCLE: + return sim->rtc >> 32; case CSR_TIME: - case CSR_INSTRET: - case CSR_STIME: - case CSR_CYCLEW: case CSR_TIMEW: + return sim->rtc + state.sutime_delta; + case CSR_CYCLE: + case CSR_CYCLEW: + case CSR_INSTRET: case CSR_INSTRETW: - return state.mtime + state.sutime_delta; - case CSR_CYCLEH: + return state.minstret + state.suinstret_delta; case CSR_TIMEH: + case CSR_TIMEHW: + if (xlen == 64) + break; + return (sim->rtc + state.sutime_delta) >> 32; + case CSR_CYCLEH: case CSR_INSTRETH: - case CSR_STIMEH: case CSR_CYCLEHW: - case CSR_TIMEHW: case CSR_INSTRETHW: if (xlen == 64) break; - return (state.mtime + state.sutime_delta) >> 32; + return (state.minstret + state.suinstret_delta) >> 32; case CSR_SSTATUS: { reg_t ss = 0; ss = set_field(ss, SSTATUS_IE, get_field(state.mstatus, MSTATUS_IE)); diff --git a/riscv/processor.h b/riscv/processor.h index 1d497d0..134c0a1 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -45,7 +45,7 @@ struct state_t reg_t mbadaddr; reg_t mscratch; reg_t mcause; - reg_t mtime; + reg_t minstret; reg_t mie; reg_t mip; reg_t sepc; @@ -55,12 +55,14 @@ struct state_t reg_t sptbr; reg_t scause; reg_t sutime_delta; + reg_t suinstret_delta; reg_t tohost; reg_t fromhost; - bool serialized; // whether timer CSRs are in a well-defined state + reg_t prev_rtc; uint32_t stimecmp; uint32_t fflags; uint32_t frm; + bool serialized; // whether timer CSRs are in a well-defined state reg_t load_reservation; @@ -118,6 +120,7 @@ private: std::vector opcode_store; std::map pc_histogram; + void check_timer(); void take_interrupt(); // take a trap if any interrupts are pending void take_trap(trap_t& t, reg_t epc); // take an exception void disasm(insn_t insn); // disassemble and print an instruction diff --git a/riscv/sim.cc b/riscv/sim.cc index 0fdd829..eb31f12 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -21,7 +21,7 @@ static void handle_signal(int sig) sim_t::sim_t(const char* isa, size_t nprocs, size_t mem_mb, const std::vector& args) : htif(new htif_isasim_t(this, args)), procs(std::max(nprocs, size_t(1))), - current_step(0), current_proc(0), debug(false) + rtc(0), current_step(0), current_proc(0), debug(false) { signal(SIGINT, &handle_signal); // allocate target machine's memory, shrinking it as necessary @@ -93,8 +93,10 @@ void sim_t::step(size_t n) { current_step = 0; procs[current_proc]->yield_load_reservation(); - if (++current_proc == procs.size()) + if (++current_proc == procs.size()) { current_proc = 0; + rtc += INTERLEAVE / INSNS_PER_RTC_TICK; + } htif->tick(); } diff --git a/riscv/sim.h b/riscv/sim.h index ca1ad6f..6615ab0 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -47,6 +47,8 @@ private: 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; -- 2.30.2