|
|
|
@ -46,10 +46,8 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, |
|
|
|
bool socket_enabled, |
|
|
|
FILE *cmd_file) // needed for command line option --cmd
|
|
|
|
: htif_t(args), |
|
|
|
isa(cfg->isa, cfg->priv), |
|
|
|
cfg(cfg), |
|
|
|
mems(mems), |
|
|
|
procs(std::max(cfg->nprocs(), size_t(1))), |
|
|
|
dtb_enabled(dtb_enabled), |
|
|
|
log_file(log_path), |
|
|
|
cmd_file(cmd_file), |
|
|
|
@ -98,14 +96,16 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, |
|
|
|
|
|
|
|
debug_mmu = new mmu_t(this, cfg->endianness, NULL); |
|
|
|
|
|
|
|
for (size_t i = 0; i < cfg->nprocs(); i++) { |
|
|
|
procs[i] = new processor_t(&isa, cfg, this, cfg->hartids[i], halted, |
|
|
|
log_file.get(), sout_); |
|
|
|
harts[cfg->hartids[i]] = procs[i]; |
|
|
|
} |
|
|
|
|
|
|
|
// When running without using a dtb, skip the fdt-based configuration steps
|
|
|
|
if (!dtb_enabled) return; |
|
|
|
if (!dtb_enabled) { |
|
|
|
for (size_t i = 0; i < cfg->nprocs(); i++) { |
|
|
|
procs.push_back(new processor_t(cfg->isa, cfg->priv, |
|
|
|
cfg, this, cfg->hartids[i], halted, |
|
|
|
log_file.get(), sout_)); |
|
|
|
harts[cfg->hartids[i]] = procs[i]; |
|
|
|
return; |
|
|
|
} |
|
|
|
} // otherwise, generate the procs by parsing the DTS
|
|
|
|
|
|
|
|
// Only make a CLINT (Core-Local INTerrupt controller) and PLIC (Platform-
|
|
|
|
// Level-Interrupt-Controller) if they are specified in the device tree
|
|
|
|
@ -133,6 +133,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, |
|
|
|
std::stringstream strstream; |
|
|
|
strstream << fin.rdbuf(); |
|
|
|
dtb = strstream.str(); |
|
|
|
dts = dtc_compile(dtb, "dtb", "dts"); |
|
|
|
} else { |
|
|
|
std::pair<reg_t, reg_t> initrd_bounds = cfg->initrd_bounds; |
|
|
|
std::string device_nodes; |
|
|
|
@ -141,11 +142,8 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, |
|
|
|
const std::vector<std::string>& sargs = factory_sargs.second; |
|
|
|
device_nodes.append(factory->generate_dts(this, sargs)); |
|
|
|
} |
|
|
|
dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, |
|
|
|
initrd_bounds.first, initrd_bounds.second, |
|
|
|
cfg->bootargs, cfg->pmpregions, cfg->pmpgranularity, |
|
|
|
procs, mems, device_nodes); |
|
|
|
dtb = dts_compile(dts); |
|
|
|
dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, cfg, mems, device_nodes); |
|
|
|
dtb = dtc_compile(dts, "dts", "dtb"); |
|
|
|
} |
|
|
|
|
|
|
|
int fdt_code = fdt_check_header(dtb.c_str()); |
|
|
|
@ -162,24 +160,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, |
|
|
|
|
|
|
|
void *fdt = (void *)dtb.c_str(); |
|
|
|
|
|
|
|
for (size_t i = 0; i < device_factories.size(); i++) { |
|
|
|
const device_factory_t* factory = device_factories[i].first; |
|
|
|
const std::vector<std::string>& sargs = device_factories[i].second; |
|
|
|
reg_t device_base = 0; |
|
|
|
abstract_device_t* device = factory->parse_from_fdt(fdt, this, &device_base, sargs); |
|
|
|
if (device) { |
|
|
|
assert(device_base); |
|
|
|
std::shared_ptr<abstract_device_t> dev_ptr(device); |
|
|
|
add_device(device_base, dev_ptr); |
|
|
|
|
|
|
|
if (i == 0) // clint_factory
|
|
|
|
clint = std::static_pointer_cast<clint_t>(dev_ptr); |
|
|
|
else if (i == 1) // plic_factory
|
|
|
|
plic = std::static_pointer_cast<plic_t>(dev_ptr); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//per core attribute
|
|
|
|
// per core attribute
|
|
|
|
int cpu_offset = 0, cpu_map_offset, rc; |
|
|
|
size_t cpu_idx = 0; |
|
|
|
cpu_offset = fdt_get_offset(fdt, "/cpus"); |
|
|
|
@ -193,10 +174,33 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, |
|
|
|
if (!(cpu_map_offset < 0) && cpu_offset == cpu_map_offset) |
|
|
|
continue; |
|
|
|
|
|
|
|
if (cpu_idx >= nprocs()) |
|
|
|
break; |
|
|
|
if (cpu_idx != procs.size()) { |
|
|
|
std::cerr << "Spike only supports contiguous CPU IDs in the DTS" << std::endl; |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
|
|
|
|
//handle pmp
|
|
|
|
// handle isa string
|
|
|
|
const char* isa_str; |
|
|
|
rc = fdt_parse_isa(fdt, cpu_offset, &isa_str); |
|
|
|
if (rc != 0) { |
|
|
|
std::cerr << "core (" << cpu_idx << ") has an invalid or missing 'riscv,isa'\n"; |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
|
|
|
|
// handle hartid
|
|
|
|
uint32_t hartid; |
|
|
|
rc = fdt_parse_hartid(fdt, cpu_offset, &hartid); |
|
|
|
if (rc != 0) { |
|
|
|
std::cerr << "core (" << cpu_idx << ") has an invalid or missing `reg` (hartid)\n"; |
|
|
|
exit(1); |
|
|
|
} |
|
|
|
|
|
|
|
procs.push_back(new processor_t(isa_str, DEFAULT_PRIV, |
|
|
|
cfg, this, hartid, halted, |
|
|
|
log_file.get(), sout_)); |
|
|
|
harts[hartid] = procs[cpu_idx]; |
|
|
|
|
|
|
|
// handle pmp
|
|
|
|
reg_t pmp_num, pmp_granularity; |
|
|
|
if (fdt_parse_pmp_num(fdt, cpu_offset, &pmp_num) != 0) |
|
|
|
pmp_num = 0; |
|
|
|
@ -206,7 +210,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, |
|
|
|
procs[cpu_idx]->set_pmp_granularity(pmp_granularity); |
|
|
|
} |
|
|
|
|
|
|
|
//handle mmu-type
|
|
|
|
// handle mmu-type
|
|
|
|
const char *mmu_type; |
|
|
|
rc = fdt_parse_mmu_type(fdt, cpu_offset, &mmu_type); |
|
|
|
if (rc == 0) { |
|
|
|
@ -220,7 +224,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, |
|
|
|
} else if (strncmp(mmu_type, "riscv,sv57", strlen("riscv,sv57")) == 0) { |
|
|
|
procs[cpu_idx]->set_mmu_capability(IMPL_MMU_SV57); |
|
|
|
} else if (strncmp(mmu_type, "riscv,sbare", strlen("riscv,sbare")) == 0) { |
|
|
|
//has been set in the beginning
|
|
|
|
// has been set in the beginning
|
|
|
|
} else { |
|
|
|
std::cerr << "core (" |
|
|
|
<< cpu_idx |
|
|
|
@ -235,12 +239,22 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, |
|
|
|
cpu_idx++; |
|
|
|
} |
|
|
|
|
|
|
|
if (cpu_idx != nprocs()) { |
|
|
|
std::cerr << "core number in dts (" |
|
|
|
<< cpu_idx |
|
|
|
<< ") doesn't match it in command line (" |
|
|
|
<< nprocs() << ").\n"; |
|
|
|
exit(1); |
|
|
|
// must be located after procs/harts are set (devices might use sim_t get_* member functions)
|
|
|
|
for (size_t i = 0; i < device_factories.size(); i++) { |
|
|
|
const device_factory_t* factory = device_factories[i].first; |
|
|
|
const std::vector<std::string>& sargs = device_factories[i].second; |
|
|
|
reg_t device_base = 0; |
|
|
|
abstract_device_t* device = factory->parse_from_fdt(fdt, this, &device_base, sargs); |
|
|
|
if (device) { |
|
|
|
assert(device_base); |
|
|
|
std::shared_ptr<abstract_device_t> dev_ptr(device); |
|
|
|
add_device(device_base, dev_ptr); |
|
|
|
|
|
|
|
if (i == 0) // clint_factory
|
|
|
|
clint = std::static_pointer_cast<clint_t>(dev_ptr); |
|
|
|
else if (i == 1) // plic_factory
|
|
|
|
plic = std::static_pointer_cast<plic_t>(dev_ptr); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -256,7 +270,7 @@ int sim_t::run() |
|
|
|
if (!debug && log) |
|
|
|
set_procs_debug(true); |
|
|
|
|
|
|
|
htif_t::set_expected_xlen(isa.get_max_xlen()); |
|
|
|
htif_t::set_expected_xlen(harts[0]->get_isa().get_max_xlen()); |
|
|
|
|
|
|
|
// htif_t::run() will repeatedly call back into sim_t::idle(), each
|
|
|
|
// invocation of which will advance target time
|
|
|
|
|