Browse Source

Use single, shared real-time counter

This required disentangling INSTRET/CYCLE from TIME.
pull/23/head
Andrew Waterman 11 years ago
parent
commit
c1273bcbaf
  1. 73
      riscv/processor.cc
  2. 7
      riscv/processor.h
  3. 6
      riscv/sim.cc
  4. 2
      riscv/sim.h

73
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));

7
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

6
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();
}

2
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;

Loading…
Cancel
Save