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; \
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);
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);
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)
#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);
}
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;
case CSR_SCYCLE:
case CSR_STIME:
case CSR_SINSTRET:
- serialize();
return state.scount;
case CSR_CYCLEH:
case CSR_TIMEH:
case CSR_SINSTRETH:
if (xlen == 64)
break;
- serialize();
return state.scount >> 32;
case CSR_SSTATUS:
{
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;
bool run; // !reset
bool debug;
bool histogram_enabled;
- bool serialized;
std::vector<insn_desc_t> instructions;
std::vector<insn_desc_t*> opcode_map;
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