aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Zhao <jerryz123@berkeley.edu>2023-06-05 10:36:54 -0700
committerJerry Zhao <jerryz123@berkeley.edu>2023-06-20 12:23:47 -0700
commit6ae3783b08b86303836babcc7a8b473cf37b7c64 (patch)
tree4420c4c736f486566f96a6de72aaaa4f34e70a5a
parente5a61098733b34f8906e26827f94afdc9df277df (diff)
downloadriscv-isa-sim-6ae3783b08b86303836babcc7a8b473cf37b7c64.zip
riscv-isa-sim-6ae3783b08b86303836babcc7a8b473cf37b7c64.tar.gz
riscv-isa-sim-6ae3783b08b86303836babcc7a8b473cf37b7c64.tar.bz2
sim_t: Move dts device node construction/parsing to device_factories
-rw-r--r--riscv/dts.cc46
-rw-r--r--riscv/dts.h3
-rw-r--r--riscv/sim.cc82
3 files changed, 46 insertions, 85 deletions
diff --git a/riscv/dts.cc b/riscv/dts.cc
index bd1f4fe..4b8de9f 100644
--- a/riscv/dts.cc
+++ b/riscv/dts.cc
@@ -17,7 +17,8 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
const char* bootargs,
size_t pmpregions,
std::vector<processor_t*> procs,
- std::vector<std::pair<reg_t, mem_t*>> mems)
+ std::vector<std::pair<reg_t, mem_t*>> mems,
+ std::string device_nodes)
{
std::stringstream s;
s << std::dec <<
@@ -85,47 +86,8 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
" #size-cells = <2>;\n"
" compatible = \"ucbbar,spike-bare-soc\", \"simple-bus\";\n"
" ranges;\n"
- " clint@" << CLINT_BASE << " {\n"
- " compatible = \"riscv,clint0\";\n"
- " interrupts-extended = <" << std::dec;
- for (size_t i = 0; i < procs.size(); i++)
- s << "&CPU" << i << "_intc 3 &CPU" << i << "_intc 7 ";
- reg_t clintbs = CLINT_BASE;
- reg_t clintsz = CLINT_SIZE;
- s << std::hex << ">;\n"
- " reg = <0x" << (clintbs >> 32) << " 0x" << (clintbs & (uint32_t)-1) <<
- " 0x" << (clintsz >> 32) << " 0x" << (clintsz & (uint32_t)-1) << ">;\n"
- " };\n"
- " PLIC: plic@" << PLIC_BASE << " {\n"
- " compatible = \"riscv,plic0\";\n"
- " #address-cells = <2>;\n"
- " interrupts-extended = <" << std::dec;
- for (size_t i = 0; i < procs.size(); i++)
- s << "&CPU" << i << "_intc 11 &CPU" << i << "_intc 9 ";
- reg_t plicbs = PLIC_BASE;
- reg_t plicsz = PLIC_SIZE;
- s << std::hex << ">;\n"
- " reg = <0x" << (plicbs >> 32) << " 0x" << (plicbs & (uint32_t)-1) <<
- " 0x" << (plicsz >> 32) << " 0x" << (plicsz & (uint32_t)-1) << ">;\n"
- " riscv,ndev = <0x" << PLIC_NDEV << ">;\n"
- " riscv,max-priority = <0x" << ((1U << PLIC_PRIO_BITS) - 1) << ">;\n"
- " #interrupt-cells = <1>;\n"
- " interrupt-controller;\n"
- " };\n"
- " SERIAL0: ns16550@" << NS16550_BASE << " {\n"
- " compatible = \"ns16550a\";\n"
- " clock-frequency = <" << std::dec << (cpu_hz/insns_per_rtc_tick) << ">;\n"
- " interrupt-parent = <&PLIC>;\n"
- " interrupts = <" << std::dec << NS16550_INTERRUPT_ID;
- reg_t ns16550bs = NS16550_BASE;
- reg_t ns16550sz = NS16550_SIZE;
- s << std::hex << ">;\n"
- " reg = <0x" << (ns16550bs >> 32) << " 0x" << (ns16550bs & (uint32_t)-1) <<
- " 0x" << (ns16550sz >> 32) << " 0x" << (ns16550sz & (uint32_t)-1) << ">;\n"
- " reg-shift = <0x" << NS16550_REG_SHIFT << ">;\n"
- " reg-io-width = <0x" << NS16550_REG_IO_WIDTH << ">;\n"
- " };\n"
- " };\n"
+ << device_nodes
+ << " };\n"
" htif {\n"
" compatible = \"ucb,htif0\";\n"
" };\n"
diff --git a/riscv/dts.h b/riscv/dts.h
index 2b7404e..d365502 100644
--- a/riscv/dts.h
+++ b/riscv/dts.h
@@ -12,7 +12,8 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
const char* bootargs,
size_t pmpregions,
std::vector<processor_t*> procs,
- std::vector<std::pair<reg_t, mem_t*>> mems);
+ std::vector<std::pair<reg_t, mem_t*>> mems,
+ std::string device_nodes);
std::string dts_compile(const std::string& dts);
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