diff options
-rw-r--r-- | riscv/dts.cc | 46 | ||||
-rw-r--r-- | riscv/dts.h | 3 | ||||
-rw-r--r-- | riscv/sim.cc | 82 |
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 |