11 processor_t::processor_t(sim_t
* _sim
, mmu_t
* _mmu
, uint32_t _id
)
12 : sim(*_sim
), mmu(*_mmu
), id(_id
), utidx(0)
16 // create microthreads
17 for (int i
=0; i
<MAX_UTS
; i
++)
18 uts
[i
] = new processor_t(&sim
, &mmu
, id
, i
);
21 processor_t::processor_t(sim_t
* _sim
, mmu_t
* _mmu
, uint32_t _id
,
23 : sim(*_sim
), mmu(*_mmu
), id(_id
), utidx(_utidx
)
26 set_sr(sr
| SR_EF
| SR_EV
);
28 // microthreads don't possess their own microthreads
29 for (int i
=0; i
<MAX_UTS
; i
++)
33 processor_t::~processor_t()
37 void processor_t::reset()
41 // the ISA guarantees on boot that the PC is 0x2000 and the the processor
42 // is in supervisor mode, and in 64-bit mode, if supported, with traps
43 // and virtual memory disabled. we accomplish this by setting EVEC to
44 // 0x2000 and *enabling* traps, then sending the core an IPI.
45 set_sr(SR_S
| SR_SX
| SR_ET
| SR_IM
);
48 // the following state is undefined upon boot-up,
49 // but we zero it for determinism
50 memset(XPR
,0,sizeof(XPR
));
51 memset(FPR
,0,sizeof(FPR
));
75 void processor_t::set_sr(uint32_t val
)
77 sr
= val
& ~SR_ZERO
; // clear SR bits that read as zero
79 #ifndef RISCV_ENABLE_64BIT
80 sr
&= ~(SR_SX
| SR_UX
); // SX=UX=0 for RV32 implementations
82 #ifndef RISCV_ENABLE_FPU
85 #ifndef RISCV_ENABLE_RVC
88 #ifndef RISCV_ENABLE_VEC
92 // update MMU state and flush TLB
93 mmu
.set_vm_enabled(sr
& SR_VM
);
94 mmu
.set_supervisor(sr
& SR_S
);
97 // set the fixed-point register length
98 xprlen
= ((sr
& SR_S
) ? (sr
& SR_SX
) : (sr
& SR_UX
)) ? 64 : 32;
101 void processor_t::set_fsr(uint32_t val
)
103 fsr
= val
& ~FSR_ZERO
; // clear FSR bits that read as zero
106 void processor_t::vcfg()
108 if (nxpr_use
+ nfpr_use
< 2)
109 vlmax
= nxfpr_bank
* vecbanks_count
;
111 vlmax
= (nxfpr_bank
/ (nxpr_use
+ nfpr_use
- 1)) * vecbanks_count
;
113 vlmax
= std::min(vlmax
, MAX_UTS
);
116 void processor_t::setvl(int vlapp
)
118 vl
= std::min(vlmax
, vlapp
);
121 void processor_t::take_interrupt()
123 uint32_t interrupts
= interrupts_pending
;
124 interrupts
&= (sr
& SR_IM
) >> SR_IM_SHIFT
;
126 if(interrupts
&& (sr
& SR_ET
))
127 for(int i
= 0; ; i
++, interrupts
>>= 1)
129 throw (trap_t
)(trap_irq0
+ i
);
132 void processor_t::step(size_t n
, bool noisy
)
147 // execute_insn fetches and executes one instruction
148 #define execute_insn(noisy) \
150 insn = _mmu.load_insn(npc, sr & SR_EC, &func); \
151 if(noisy) disasm(insn,pc); \
152 npc = func(this, insn, npc); \
156 if(noisy
) for( ; i
< n
; i
++) // print out instructions as we go
160 // unrolled for speed
161 for( ; n
> 3 && i
< n
-3; i
+=4)
176 // an exception occurred in the target processor
180 catch(vt_command_t cmd
)
182 // this microthread has finished
184 assert(cmd
== vt_command_stop
);
196 // update timer and possibly register a timer interrupt
197 uint32_t old_count
= count
;
199 if(old_count
< compare
&& uint64_t(old_count
) + i
>= compare
)
200 interrupts_pending
|= 1 << TIMER_IRQ
;
203 void processor_t::take_trap(trap_t t
, bool noisy
)
206 printf("core %3d: trap %s, pc 0x%016llx\n",
207 id
, trap_name(t
), (unsigned long long)pc
);
209 // switch to supervisor, set previous supervisor bit, disable traps
210 set_sr((((sr
& ~SR_ET
) | SR_S
) & ~SR_PS
) | ((sr
& SR_S
) ? SR_PS
: 0));
214 badvaddr
= mmu
.get_badvaddr();
217 void processor_t::deliver_ipi()
219 interrupts_pending
|= 1 << IPI_IRQ
;
223 void processor_t::disasm(insn_t insn
, reg_t pc
)
225 // the disassembler is stateless, so we share it
226 static disassembler disasm
;
227 printf("core %3d: 0x%016llx (0x%08x) %s\n", id
, (unsigned long long)pc
,
228 insn
.bits
, disasm
.disassemble(insn
).c_str());