aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2015-05-31 18:28:53 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2015-05-31 18:29:45 -0700
commitc1273bcbaf659f5bb54fb85e1292b21d70503bc4 (patch)
treef6b49e61986ce67bf17dffdee13771a7e7f0d46d /riscv
parent1f9205c93b3541b5c2ae19d4a6250aab70977e5f (diff)
downloadriscv-isa-sim-c1273bcbaf659f5bb54fb85e1292b21d70503bc4.zip
riscv-isa-sim-c1273bcbaf659f5bb54fb85e1292b21d70503bc4.tar.gz
riscv-isa-sim-c1273bcbaf659f5bb54fb85e1292b21d70503bc4.tar.bz2
Use single, shared real-time counter
This required disentangling INSTRET/CYCLE from TIME.
Diffstat (limited to 'riscv')
-rw-r--r--riscv/processor.cc73
-rw-r--r--riscv/processor.h7
-rw-r--r--riscv/sim.cc6
-rw-r--r--riscv/sim.h2
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<insn_desc_t> opcode_store;
std::map<size_t,size_t> 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<std::string>& 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;