1 // See LICENSE for license details.
15 processor_t::processor_t(sim_t
* _sim
, mmu_t
* _mmu
, uint32_t _id
)
16 : sim(*_sim
), mmu(*_mmu
), id(_id
), opcode_bits(0), utidx(0)
19 mmu
.set_processor(this);
21 #define DECLARE_INSN(name, match, mask) \
22 register_insn(match, mask, (insn_func_t)&processor_t::rv32_##name, (insn_func_t)&processor_t::rv64_##name);
26 // create microthreads
27 for (int i
=0; i
<MAX_UTS
; i
++)
28 uts
[i
] = new processor_t(&sim
, &mmu
, id
, i
);
31 processor_t::processor_t(sim_t
* _sim
, mmu_t
* _mmu
, uint32_t _id
,
33 : sim(*_sim
), mmu(*_mmu
), id(_id
)
36 set_pcr(PCR_SR
, SR_U64
| SR_EF
| SR_EV
);
39 // microthreads don't possess their own microthreads
40 for (int i
=0; i
<MAX_UTS
; i
++)
44 processor_t::~processor_t()
48 void processor_t::reset(bool value
)
54 // the ISA guarantees on boot that the PC is 0x2000 and the the processor
55 // is in supervisor mode, and in 64-bit mode, if supported, with traps
56 // and virtual memory disabled.
58 set_pcr(PCR_SR
, SR_S
| SR_S64
| SR_IM
);
61 // the following state is undefined upon boot-up,
62 // but we zero it for determinism
88 void processor_t::set_fsr(uint32_t val
)
90 fsr
= val
& ~FSR_ZERO
; // clear FSR bits that read as zero
93 void processor_t::vcfg()
95 if (nxpr_use
+ nfpr_use
< 2)
96 vlmax
= nxfpr_bank
* vecbanks_count
;
98 vlmax
= (nxfpr_bank
/ (nxpr_use
+ nfpr_use
- 1)) * vecbanks_count
;
100 vlmax
= std::min(vlmax
, MAX_UTS
);
103 void processor_t::setvl(int vlapp
)
105 vl
= std::min(vlmax
, vlapp
);
108 void processor_t::take_interrupt()
110 uint32_t interrupts
= (sr
& SR_IP
) >> SR_IP_SHIFT
;
111 interrupts
&= (sr
& SR_IM
) >> SR_IM_SHIFT
;
113 if(interrupts
&& (sr
& SR_ET
))
114 for(int i
= 0; ; i
++, interrupts
>>= 1)
116 throw interrupt_t(i
);
119 void processor_t::step(size_t n
, bool noisy
)
132 // execute_insn fetches and executes one instruction
133 #define execute_insn(noisy) \
135 mmu_t::insn_fetch_t fetch = _mmu.load_insn(npc); \
136 if(noisy) disasm(fetch.insn, npc); \
137 npc = fetch.func(this, fetch.insn, npc); \
141 if(noisy
) for( ; i
< n
; i
++) // print out instructions as we go
145 // unrolled for speed
146 for( ; n
> 3 && i
< n
-3; i
+=4)
159 // an exception occurred in the target processor
164 take_trap((1ULL << (8*sizeof(reg_t
)-1)) + t
.i
, noisy
);
166 catch(vt_command_t cmd
)
168 // this microthread has finished
169 assert(cmd
== vt_command_stop
);
174 // update timer and possibly register a timer interrupt
175 uint32_t old_count
= count
;
177 if(old_count
< compare
&& uint64_t(old_count
) + i
>= compare
)
178 set_interrupt(IRQ_TIMER
, true);
181 void processor_t::take_trap(reg_t t
, bool noisy
)
186 fprintf(stderr
, "core %3d: interrupt %d, epc 0x%016" PRIx64
"\n",
189 fprintf(stderr
, "core %3d: trap %s, epc 0x%016" PRIx64
"\n",
190 id
, trap_name(trap_t(t
)), pc
);
193 // switch to supervisor, set previous supervisor bit, disable traps
194 set_pcr(PCR_SR
, (((sr
& ~SR_ET
) | SR_S
) & ~SR_PS
) | ((sr
& SR_S
) ? SR_PS
: 0));
198 badvaddr
= mmu
.get_badvaddr();
201 void processor_t::deliver_ipi()
204 set_pcr(PCR_CLR_IPI
, 1);
207 void processor_t::disasm(insn_t insn
, reg_t pc
)
209 // the disassembler is stateless, so we share it
210 static disassembler disasm
;
211 fprintf(stderr
, "core %3d: 0x%016" PRIx64
" (0x%08" PRIxFAST32
") %s\n",
212 id
, pc
, insn
.bits
, disasm
.disassemble(insn
).c_str());
215 void processor_t::set_pcr(int which
, reg_t val
)
220 sr
= (val
& ~SR_IP
) | (sr
& SR_IP
);
221 #ifndef RISCV_ENABLE_64BIT
222 sr
&= ~(SR_S64
| SR_U64
);
224 #ifndef RISCV_ENABLE_FPU
227 #ifndef RISCV_ENABLE_RVC
230 #ifndef RISCV_ENABLE_VEC
246 set_interrupt(IRQ_TIMER
, false);
256 set_interrupt(IRQ_IPI
, val
& 1);
269 set_interrupt(IRQ_HOST
, val
!= 0);
275 reg_t
processor_t::get_pcr(int which
)
294 return mmu
.get_ptbr();
311 void processor_t::set_interrupt(int which
, bool on
)
313 uint32_t mask
= (1 << (which
+ SR_IP_SHIFT
)) & SR_IP
;
320 insn_func_t
processor_t::decode_insn(insn_t insn
)
322 bool rv64
= (sr
& SR_S
) ? (sr
& SR_S64
) : (sr
& SR_U64
);
324 auto key
= insn
.bits
& ((1L << opcode_bits
)-1);
325 auto it
= opcode_map
.find(key
);
326 for (auto it
= opcode_map
.find(key
); it
!= opcode_map
.end() && it
->first
== key
; ++it
)
327 if ((insn
.bits
& it
->second
.mask
) == it
->second
.match
)
328 return rv64
? it
->second
.rv64
: it
->second
.rv32
;
330 return &processor_t::illegal_instruction
;
333 reg_t
processor_t::illegal_instruction(insn_t insn
, reg_t pc
)
335 throw trap_illegal_instruction
;
338 void processor_t::register_insn(uint32_t match
, uint32_t mask
, insn_func_t rv32
, insn_func_t rv64
)
341 if (opcode_bits
== 0 || (mask
& ((1L << opcode_bits
)-1)) != ((1L << opcode_bits
)-1))
344 while ((mask
& ((1L << (x
+1))-1)) == ((1L << (x
+1))-1) &&
345 (opcode_bits
== 0 || x
<= opcode_bits
))
349 decltype(opcode_map
) new_map
;
350 for (auto it
= opcode_map
.begin(); it
!= opcode_map
.end(); ++it
)
351 new_map
.insert(std::make_pair(it
->second
.match
& ((1L<<x
)-1), it
->second
));
352 opcode_map
= new_map
;
355 opcode_map
.insert(std::make_pair(match
& ((1L<<opcode_bits
)-1),
356 (opcode_map_entry_t
){match
, mask
, rv32
, rv64
}));