aboutsummaryrefslogtreecommitdiff
path: root/riscv/sim.cc
diff options
context:
space:
mode:
Diffstat (limited to 'riscv/sim.cc')
-rw-r--r--riscv/sim.cc82
1 files changed, 40 insertions, 42 deletions
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 10e86be..3283e5c 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -32,6 +32,10 @@ static void handle_signal(int sig)
const size_t sim_t::INTERLEAVE;
+extern device_factory_t* clint_factory;
+extern device_factory_t* plic_factory;
+extern device_factory_t* ns16550_factory;
+
sim_t::sim_t(const cfg_t *cfg, bool halted,
std::vector<std::pair<reg_t, mem_t*>> mems,
std::vector<std::pair<reg_t, std::shared_ptr<abstract_device_t>>> plugin_devices,
@@ -90,9 +94,9 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
#ifndef RISCV_ENABLE_DUAL_ENDIAN
if (cfg->endianness != endianness_little) {
fputs("Big-endian support has not been prroperly enabled; "
- "please rebuild the riscv-isa-sim project using "
- "\"configure --enable-dual-endian\".\n",
- stderr);
+ "please rebuild the riscv-isa-sim project using "
+ "\"configure --enable-dual-endian\".\n",
+ stderr);
abort();
}
#endif
@@ -108,6 +112,19 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
// When running without using a dtb, skip the fdt-based configuration steps
if (!dtb_enabled) return;
+ // Only make a CLINT (Core-Local INTerrupt controller) and PLIC (Platform-
+ // Level-Interrupt-Controller) if they are specified in the device tree
+ // configuration.
+ //
+ // This isn't *quite* as general as we could get (because you might have one
+ // that's not bus-accessible), but it should handle the normal use cases. In
+ // particular, the default device tree configuration that you get without
+ // setting the dtb_file argument has one.
+ std::vector<device_factory_t*> device_factories = {
+ clint_factory, // clint must be element 0
+ plic_factory, // plic must be element 1
+ ns16550_factory};
+
// Load dtb_file if provided, otherwise self-generate a dts/dtb
if (dtb_file) {
std::ifstream fin(dtb_file, std::ios::binary);
@@ -117,13 +134,16 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
}
std::stringstream strstream;
strstream << fin.rdbuf();
-
dtb = strstream.str();
} else {
std::pair<reg_t, reg_t> initrd_bounds = cfg->initrd_bounds();
+ std::string device_nodes;
+ for (device_factory_t *factory : device_factories)
+ device_nodes.append(factory->generate_dts(this));
dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ,
initrd_bounds.first, initrd_bounds.second,
- cfg->bootargs(), cfg->pmpregions, procs, mems);
+ cfg->bootargs(), cfg->pmpregions, procs, mems,
+ device_nodes);
dtb = dts_compile(dts);
}
@@ -141,43 +161,21 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
void *fdt = (void *)dtb.c_str();
- // Only make a CLINT (Core-Local INTerrupt controller) if one is specified in
- // the device tree configuration.
- //
- // This isn't *quite* as general as we could get (because you might have one
- // that's not bus-accessible), but it should handle the normal use cases. In
- // particular, the default device tree configuration that you get without
- // setting the dtb_file argument has one.
- reg_t clint_base;
- if (fdt_parse_clint(fdt, &clint_base, "riscv,clint0") == 0) {
- clint.reset(new clint_t(this, CPU_HZ / INSNS_PER_RTC_TICK, cfg->real_time_clint()));
- bus.add_device(clint_base, clint.get());
- devices.push_back(clint);
- }
-
- // pointer to wired interrupt controller
- abstract_interrupt_controller_t *intctrl = NULL;
-
- // create plic
- reg_t plic_base;
- uint32_t plic_ndev;
- if (fdt_parse_plic(fdt, &plic_base, &plic_ndev, "riscv,plic0") == 0) {
- plic.reset(new plic_t(this, plic_ndev));
- bus.add_device(plic_base, plic.get());
- devices.push_back(plic);
- intctrl = plic.get();
- }
-
- // create ns16550
- reg_t ns16550_base;
- uint32_t ns16550_shift, ns16550_io_width;
- if (fdt_parse_ns16550(fdt, &ns16550_base,
- &ns16550_shift, &ns16550_io_width, "ns16550a") == 0) {
- assert(intctrl);
- std::shared_ptr<ns16550_t> ns16550(new ns16550_t(intctrl, NS16550_INTERRUPT_ID,
- ns16550_shift, ns16550_io_width));
- bus.add_device(ns16550_base, ns16550.get());
- devices.push_back(ns16550);
+ for (size_t i = 0; i < device_factories.size(); i++) {
+ device_factory_t *factory = device_factories[i];
+ reg_t device_base = 0;
+ abstract_device_t* device = factory->parse_from_fdt(fdt, this, &device_base);
+ if (device) {
+ assert(device_base);
+ bus.add_device(device_base, device);
+ std::shared_ptr<abstract_device_t> dev_ptr(device);
+ devices.push_back(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