aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2015-03-26 00:28:10 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2015-03-26 19:26:32 -0700
commit180554d8f20e6ed5d90790579b85535c890ebc68 (patch)
treef7ab03177e697be2264bc0ab2a5ca2bf546eedfb /riscv
parent41fa048e935d6e95d50dcb8bb463658b7a4d718e (diff)
downloadspike-180554d8f20e6ed5d90790579b85535c890ebc68.zip
spike-180554d8f20e6ed5d90790579b85535c890ebc68.tar.gz
spike-180554d8f20e6ed5d90790579b85535c890ebc68.tar.bz2
Serialize counters without throwing C++ exceptions
Ideally, a similar mechanism will apply to target machine exceptions.
Diffstat (limited to 'riscv')
-rw-r--r--riscv/decode.h4
-rw-r--r--riscv/processor.cc42
-rw-r--r--riscv/processor.h3
3 files changed, 27 insertions, 22 deletions
diff --git a/riscv/decode.h b/riscv/decode.h
index 4ad4549..72efcd9 100644
--- a/riscv/decode.h
+++ b/riscv/decode.h
@@ -159,7 +159,11 @@ private:
npc = sext_xlen(x); \
} while(0)
+#define PC_SERIALIZE 3 /* sentinel value indicating simulator pipeline flush */
+
#define validate_csr(which, write) ({ \
+ if (!STATE.serialized) return PC_SERIALIZE; \
+ STATE.serialized = false; \
unsigned my_priv = get_field(STATE.mstatus, MSTATUS_PRV); \
unsigned csr_priv = get_field((which), 0x300); \
unsigned csr_read_only = get_field((which), 0xC00) == 3; \
diff --git a/riscv/processor.cc b/riscv/processor.cc
index 0ff5578..afae1ce 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -21,7 +21,7 @@
processor_t::processor_t(sim_t* _sim, mmu_t* _mmu, uint32_t _id)
: sim(_sim), mmu(_mmu), ext(NULL), disassembler(new disassembler_t),
- id(_id), run(false), debug(false), serialized(false)
+ id(_id), run(false), debug(false)
{
reset(true);
mmu->set_processor(this);
@@ -86,16 +86,6 @@ void processor_t::reset(bool value)
ext->reset(); // reset the extension
}
-struct serialize_t {};
-
-void processor_t::serialize()
-{
- if (serialized)
- serialized = false;
- else
- serialized = true, throw serialize_t();
-}
-
void processor_t::raise_interrupt(reg_t which)
{
throw trap_t(((reg_t)1 << 63) | which);
@@ -183,17 +173,28 @@ void processor_t::step(size_t n)
return;
n = std::min(n, next_timer(&state) | 1U);
+ #define maybe_serialize() \
+ if (unlikely(pc == PC_SERIALIZE)) { \
+ pc = state.pc; \
+ state.serialized = true; \
+ continue; \
+ }
+
try
{
take_interrupt();
if (unlikely(debug))
{
- while (instret++ < n)
+ while (instret < n)
{
insn_fetch_t fetch = mmu->load_insn(pc);
- disasm(fetch.insn);
- state.pc = pc = execute_insn(this, pc, fetch);
+ if (!state.serialized)
+ disasm(fetch.insn);
+ pc = execute_insn(this, pc, fetch);
+ maybe_serialize();
+ instret++;
+ state.pc = pc;
}
}
else while (instret < n)
@@ -204,22 +205,26 @@ void processor_t::step(size_t n)
#define ICACHE_ACCESS(idx) { \
insn_fetch_t fetch = ic_entry->data; \
ic_entry++; \
- state.pc = pc = execute_insn(this, pc, fetch); \
- instret++; \
+ pc = execute_insn(this, pc, fetch); \
if (idx == mmu_t::ICACHE_ENTRIES-1) break; \
if (unlikely(ic_entry->tag != pc)) break; \
+ instret++; \
+ state.pc = pc; \
}
switch (idx) {
#include "icache.h"
}
+
+ maybe_serialize();
+ instret++;
+ state.pc = pc;
}
}
catch(trap_t& t)
{
state.pc = take_trap(t, pc);
}
- catch(serialize_t& s) {}
update_timer(&state, instret);
}
@@ -388,7 +393,6 @@ void processor_t::set_csr(int which, reg_t val)
case CSR_SEPC: state.sepc = val; break;
case CSR_STVEC: state.stvec = val & ~3; break;
case CSR_STIMECMP:
- serialize();
state.stip = false;
state.stimecmp = val;
break;
@@ -426,7 +430,6 @@ reg_t processor_t::get_csr(int which)
case CSR_SCYCLE:
case CSR_STIME:
case CSR_SINSTRET:
- serialize();
return state.scount;
case CSR_CYCLEH:
case CSR_TIMEH:
@@ -436,7 +439,6 @@ reg_t processor_t::get_csr(int which)
case CSR_SINSTRETH:
if (xlen == 64)
break;
- serialize();
return state.scount >> 32;
case CSR_SSTATUS:
{
diff --git a/riscv/processor.h b/riscv/processor.h
index 4189fea..e9d9c4f 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -55,6 +55,7 @@ struct state_t
reg_t fromhost;
reg_t scount;
bool stip;
+ bool serialized; // whether timer CSRs are in a well-defined state
uint32_t stimecmp;
uint32_t fflags;
uint32_t frm;
@@ -104,7 +105,6 @@ private:
bool run; // !reset
bool debug;
bool histogram_enabled;
- bool serialized;
std::vector<insn_desc_t> instructions;
std::vector<insn_desc_t*> opcode_map;
@@ -112,7 +112,6 @@ private:
std::map<size_t,size_t> pc_histogram;
void take_interrupt(); // take a trap if any interrupts are pending
- void serialize(); // collapse into defined architectural state
reg_t take_trap(trap_t& t, reg_t epc); // take an exception
void disasm(insn_t insn); // disassemble and print an instruction