12 processor_t::processor_t(sim_t
* _sim
, char* _mem
, size_t _memsz
)
13 : sim(_sim
), mmu(_mem
,_memsz
)
15 initialize_dispatch_table();
16 // a few assumptions about endianness, including freg_t union
17 static_assert(BYTE_ORDER
== LITTLE_ENDIAN
);
18 static_assert(sizeof(freg_t
) == 8);
19 static_assert(sizeof(reg_t
) == 8);
21 static_assert(sizeof(insn_t
) == 4);
22 static_assert(sizeof(uint128_t
) == 16 && sizeof(int128_t
) == 16);
32 processor_t::~processor_t()
39 itlbsim
->print_stats();
47 dtlbsim
->print_stats();
51 void processor_t::init(uint32_t _id
, icsim_t
* default_icache
,
52 icsim_t
* default_dcache
)
56 for (int i
=0; i
<MAX_UTS
; i
++)
58 uts
[i
] = new processor_t(sim
, mmu
.mem
, mmu
.memsz
);
60 uts
[i
]->set_sr(uts
[i
]->sr
| SR_EF
);
61 uts
[i
]->set_sr(uts
[i
]->sr
| SR_EV
);
65 #ifdef RISCV_ENABLE_ICSIM
66 icsim
= new icsim_t(*default_icache
);
68 itlbsim
= new icsim_t(1, 8, 4096, "ITLB");
69 mmu
.set_itlbsim(itlbsim
);
71 #ifdef RISCV_ENABLE_ICSIM
72 dcsim
= new icsim_t(*default_dcache
);
74 dtlbsim
= new icsim_t(1, 8, 4096, "DTLB");
75 mmu
.set_dtlbsim(dtlbsim
);
79 void processor_t::reset()
83 memset(XPR
,0,sizeof(XPR
));
84 memset(FPR
,0,sizeof(FPR
));
98 set_sr(SR_S
| SR_SX
); // SX ignored if 64b mode not supported
110 for (int i
=0; i
<MAX_UTS
; i
++)
114 void processor_t::set_sr(uint32_t val
)
117 #ifndef RISCV_ENABLE_64BIT
118 sr
&= ~(SR_SX
| SR_UX
);
120 #ifndef RISCV_ENABLE_FPU
123 #ifndef RISCV_ENABLE_RVC
126 #ifndef RISCV_ENABLE_VEC
130 mmu
.set_vm_enabled(sr
& SR_VM
);
131 mmu
.set_supervisor(sr
& SR_S
);
134 xprlen
= ((sr
& SR_S
) ? (sr
& SR_SX
) : (sr
& SR_UX
)) ? 64 : 32;
137 void processor_t::set_fsr(uint32_t val
)
139 fsr
= val
& ~FSR_ZERO
;
142 void processor_t::vcfg()
144 if (nxpr_use
+ nfpr_use
< 2)
145 vlmax
= nxfpr_bank
* vecbanks_count
;
147 vlmax
= (nxfpr_bank
/ (nxpr_use
+ nfpr_use
- 1)) * vecbanks_count
;
149 vlmax
= std::min(vlmax
, MAX_UTS
);
152 void processor_t::setvl(int vlapp
)
154 vl
= std::min(vlmax
, vlapp
);
157 void processor_t::take_interrupt()
159 uint32_t interrupts
= (cause
& CAUSE_IP
) >> CAUSE_IP_SHIFT
;
160 interrupts
&= (sr
& SR_IM
) >> SR_IM_SHIFT
;
162 if(interrupts
&& (sr
& SR_ET
))
163 throw trap_interrupt
;
166 void processor_t::step(size_t n
, bool noisy
)
176 #define execute_insn(noisy) \
177 do { insn_t insn = mmu.load_insn(pc, sr & SR_EC); \
178 if(noisy) disasm(insn,pc); \
179 pc = dispatch_table[insn.bits % DISPATCH_TABLE_SIZE](this, insn, pc); \
180 XPR[0] = 0; } while(0)
182 if(noisy
) for( ; i
< n
; i
++)
186 for( ; n
> 3 && i
< n
-3; i
+=4)
204 catch(vt_command_t cmd
)
207 if (cmd
== vt_command_stop
)
218 typeof(count
) old_count
= count
;
219 typeof(count
) max_count
= -1;
221 if(old_count
< compare
&& (count
>= compare
|| old_count
> max_count
-i
))
222 cause
|= 1 << (TIMER_IRQ
+CAUSE_IP_SHIFT
);
225 void processor_t::take_trap(trap_t t
, bool noisy
)
227 demand(t
< NUM_TRAPS
, "internal error: bad trap number %d", int(t
));
228 demand(sr
& SR_ET
, "error mode on core %d!\ntrap %s, pc 0x%016llx",
229 id
, trap_name(t
), (unsigned long long)pc
);
231 printf("core %3d: trap %s, pc 0x%016llx\n",
232 id
, trap_name(t
), (unsigned long long)pc
);
234 set_sr((((sr
& ~SR_ET
) | SR_S
) & ~SR_PS
) | ((sr
& SR_S
) ? SR_PS
: 0));
235 cause
= (cause
& ~CAUSE_EXCCODE
) | (t
<< CAUSE_EXCCODE_SHIFT
);
238 badvaddr
= mmu
.get_badvaddr();
241 void processor_t::deliver_ipi()
243 cause
|= 1 << (IPI_IRQ
+CAUSE_IP_SHIFT
);
247 void processor_t::disasm(insn_t insn
, reg_t pc
)
249 printf("core %3d: 0x%016llx (0x%08x) ",id
,(unsigned long long)pc
,insn
.bits
);
251 #ifdef RISCV_HAVE_LIBOPCODES
252 disassemble_info info
;
253 INIT_DISASSEMBLE_INFO(info
, stdout
, fprintf
);
254 info
.flavour
= bfd_target_unknown_flavour
;
255 info
.arch
= bfd_arch_mips
;
256 info
.mach
= 101; // XXX bfd_mach_mips_riscv requires modified bfd.h
257 info
.endian
= BFD_ENDIAN_LITTLE
;
258 info
.buffer
= (bfd_byte
*)&insn
;
259 info
.buffer_length
= sizeof(insn
);
260 info
.buffer_vma
= pc
;
262 int ret
= print_insn_little_mips(pc
, &info
);
263 demand(ret
== insn_length(insn
.bits
), "disasm bug!");
270 // if the lower log2(DISPATCH_TABLE_SIZE) bits of an instruction
271 // uniquely identify that instruction, the dispatch table points
272 // directly to that insn_func. otherwise, we search the short
273 // list of instructions that match.
275 insn_func_t
processor_t::dispatch_table
[DISPATCH_TABLE_SIZE
];
283 static std::vector
<insn_chain_t
> dispatch_chain
[DISPATCH_TABLE_SIZE
];
285 reg_t
processor_t::dispatch(insn_t insn
, reg_t pc
)
287 size_t idx
= insn
.bits
% DISPATCH_TABLE_SIZE
;
288 for(size_t i
= 0; i
< dispatch_chain
[idx
].size(); i
++)
290 insn_chain_t
& c
= dispatch_chain
[idx
][i
];
291 if((insn
.bits
& c
.mask
) == c
.opcode
)
292 return c
.func(this, insn
, pc
);
294 throw trap_illegal_instruction
;
297 void processor_t::initialize_dispatch_table()
299 if(dispatch_table
[0] != NULL
)
302 for(size_t i
= 0; i
< DISPATCH_TABLE_SIZE
; i
++)
304 #define DECLARE_INSN(name, opcode, mask) \
305 if((i & (mask)) == ((opcode) & (mask) & (DISPATCH_TABLE_SIZE-1))) \
306 dispatch_chain[i].push_back( \
307 (insn_chain_t){&processor_t::insn_func_ ## name, opcode, mask});
312 for(size_t i
= 0; i
< DISPATCH_TABLE_SIZE
; i
++)
314 if(dispatch_chain
[i
].size() == 1)
315 dispatch_table
[i
] = dispatch_chain
[i
][0].func
;
317 dispatch_table
[i
] = &processor_t::dispatch
;