aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorJerry Zhao <jerryz123@berkeley.edu>2023-06-06 11:53:02 -0700
committerJerry Zhao <jerryz123@berkeley.edu>2023-06-20 12:23:47 -0700
commit186c619fb38f02d0b18514a2f8399cd8248e1dcc (patch)
treebb1f2b5cf2c2047df66d6935facda892568bb01d /riscv
parent701029d28b0e73f98a36869ef9317c49f0dc2949 (diff)
downloadspike-186c619fb38f02d0b18514a2f8399cd8248e1dcc.zip
spike-186c619fb38f02d0b18514a2f8399cd8248e1dcc.tar.gz
spike-186c619fb38f02d0b18514a2f8399cd8248e1dcc.tar.bz2
devices: Switch plugin device interface to use device_factory_t
Plugins should now implement and register a device_factory_t to configure how that device should be parsed from a FDT, and an optional default DTS string. This drops support for command-line flag-based device configuration
Diffstat (limited to 'riscv')
-rw-r--r--riscv/abstract_device.h11
-rw-r--r--riscv/devices.cc46
-rw-r--r--riscv/devices.h14
-rw-r--r--riscv/mmio_plugin.h91
-rw-r--r--riscv/riscv.mk.in1
-rw-r--r--riscv/sim.cc10
-rw-r--r--riscv/sim.h2
7 files changed, 22 insertions, 153 deletions
diff --git a/riscv/abstract_device.h b/riscv/abstract_device.h
index 90e2b24..c5c6415 100644
--- a/riscv/abstract_device.h
+++ b/riscv/abstract_device.h
@@ -6,6 +6,8 @@
#include <cstdint>
#include <cstddef>
#include <string>
+#include <map>
+#include <stdexcept>
class sim_t;
@@ -26,9 +28,18 @@ public:
virtual ~device_factory_t() {}
};
+// Type for holding all registered MMIO plugins by name.
+using mmio_device_map_t = std::map<std::string, const device_factory_t*>;
+
+mmio_device_map_t& mmio_device_map();
+
#define REGISTER_DEVICE(name, parse, generate) \
class name##_factory_t : public device_factory_t { \
public: \
+ name##_factory_t() { \
+ std::string str(#name); \
+ if (!mmio_device_map().emplace(str, this).second) throw std::runtime_error("Plugin \"" + str + "\" already registered"); \
+ }; \
name##_t* parse_from_fdt(const void* fdt, const sim_t* sim, reg_t* base) const override { return parse(fdt, sim, base); } \
std::string generate_dts(const sim_t* sim) const override { return generate(sim); } \
}; const device_factory_t *name##_factory = new name##_factory_t();
diff --git a/riscv/devices.cc b/riscv/devices.cc
index 81b232d..2c06f78 100644
--- a/riscv/devices.cc
+++ b/riscv/devices.cc
@@ -2,6 +2,12 @@
#include "mmu.h"
#include <stdexcept>
+mmio_device_map_t& mmio_device_map()
+{
+ static mmio_device_map_t device_map;
+ return device_map;
+}
+
void bus_t::add_device(reg_t addr, abstract_device_t* dev)
{
// Searching devices via lower_bound/upper_bound
@@ -51,46 +57,6 @@ std::pair<reg_t, abstract_device_t*> bus_t::find_device(reg_t addr)
return std::make_pair(it->first, it->second);
}
-// Type for holding all registered MMIO plugins by name.
-using mmio_plugin_map_t = std::map<std::string, mmio_plugin_t>;
-
-// Simple singleton instance of an mmio_plugin_map_t.
-static mmio_plugin_map_t& mmio_plugin_map()
-{
- static mmio_plugin_map_t instance;
- return instance;
-}
-
-void register_mmio_plugin(const char* name_cstr,
- const mmio_plugin_t* mmio_plugin)
-{
- std::string name(name_cstr);
- if (!mmio_plugin_map().emplace(name, *mmio_plugin).second) {
- throw std::runtime_error("Plugin \"" + name + "\" already registered!");
- }
-}
-
-mmio_plugin_device_t::mmio_plugin_device_t(const std::string& name,
- const std::string& args)
- : plugin(mmio_plugin_map().at(name)), user_data((*plugin.alloc)(args.c_str()))
-{
-}
-
-mmio_plugin_device_t::~mmio_plugin_device_t()
-{
- (*plugin.dealloc)(user_data);
-}
-
-bool mmio_plugin_device_t::load(reg_t addr, size_t len, uint8_t* bytes)
-{
- return (*plugin.load)(user_data, addr, len, bytes);
-}
-
-bool mmio_plugin_device_t::store(reg_t addr, size_t len, const uint8_t* bytes)
-{
- return (*plugin.store)(user_data, addr, len, bytes);
-}
-
mem_t::mem_t(reg_t size)
: sz(size)
{
diff --git a/riscv/devices.h b/riscv/devices.h
index 11cc347..b752a21 100644
--- a/riscv/devices.h
+++ b/riscv/devices.h
@@ -2,7 +2,6 @@
#define _RISCV_DEVICES_H
#include "decode.h"
-#include "mmio_plugin.h"
#include "abstract_device.h"
#include "abstract_interrupt_controller.h"
#include "platform.h"
@@ -157,19 +156,6 @@ class ns16550_t : public abstract_device_t {
static const int MAX_BACKOFF = 16;
};
-class mmio_plugin_device_t : public abstract_device_t {
- public:
- mmio_plugin_device_t(const std::string& name, const std::string& args);
- virtual ~mmio_plugin_device_t() override;
-
- virtual bool load(reg_t addr, size_t len, uint8_t* bytes) override;
- virtual bool store(reg_t addr, size_t len, const uint8_t* bytes) override;
-
- private:
- mmio_plugin_t plugin;
- void* user_data;
-};
-
template<typename T>
void write_little_endian_reg(T* word, reg_t addr, size_t len, const uint8_t* bytes)
{
diff --git a/riscv/mmio_plugin.h b/riscv/mmio_plugin.h
deleted file mode 100644
index f14470b..0000000
--- a/riscv/mmio_plugin.h
+++ /dev/null
@@ -1,91 +0,0 @@
-#ifndef _RISCV_MMIO_PLUGIN_H
-#define _RISCV_MMIO_PLUGIN_H
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-typedef uint64_t reg_t;
-
-typedef struct {
- // Allocate user data for an instance of the plugin. The parameter is a simple
- // c-string containing arguments used to construct the plugin. It returns a
- // void* to the allocated data.
- void* (*alloc)(const char*);
-
- // Load a memory address of the MMIO plugin. The parameters are the user_data
- // (void*), memory offset (reg_t), number of bytes to load (size_t), and the
- // buffer into which the loaded data should be written (uint8_t*). Return true
- // if the load is successful and false otherwise.
- bool (*load)(void*, reg_t, size_t, uint8_t*);
-
- // Store some bytes to a memory address of the MMIO plugin. The parameters are
- // the user_data (void*), memory offset (reg_t), number of bytes to store
- // (size_t), and the buffer containing the data to be stored (const uint8_t*).
- // Return true if the store is successful and false otherwise.
- bool (*store)(void*, reg_t, size_t, const uint8_t*);
-
- // Deallocate the data allocated during the call to alloc. The parameter is a
- // pointer to the user data allocated during the call to alloc.
- void (*dealloc)(void*);
-} mmio_plugin_t;
-
-// Register an mmio plugin with the application. This should be called by
-// plugins as part of their loading process.
-extern void register_mmio_plugin(const char* name_cstr,
- const mmio_plugin_t* mmio_plugin);
-
-#ifdef __cplusplus
-}
-
-#include <string>
-
-// Wrapper around the C plugin API that makes registering a C++ class with
-// correctly formed constructor, load, and store functions easier. The template
-// type should be the type that implements the MMIO plugin interface. Simply
-// make a global mmio_plugin_registration_t and your plugin should register
-// itself with the application when it is loaded because the
-// mmio_plugin_registration_t constructor will be called.
-template <typename T>
-struct mmio_plugin_registration_t
-{
- static void* alloc(const char* args)
- {
- return reinterpret_cast<void*>(new T(std::string(args)));
- }
-
- static bool load(void* self, reg_t addr, size_t len, uint8_t* bytes)
- {
- return reinterpret_cast<T*>(self)->load(addr, len, bytes);
- }
-
- static bool store(void* self, reg_t addr, size_t len, const uint8_t* bytes)
- {
- return reinterpret_cast<T*>(self)->store(addr, len, bytes);
- }
-
- static void dealloc(void* self)
- {
- delete reinterpret_cast<T*>(self);
- }
-
- mmio_plugin_registration_t(const std::string& name)
- {
- mmio_plugin_t plugin = {
- mmio_plugin_registration_t<T>::alloc,
- mmio_plugin_registration_t<T>::load,
- mmio_plugin_registration_t<T>::store,
- mmio_plugin_registration_t<T>::dealloc,
- };
-
- register_mmio_plugin(name.c_str(), &plugin);
- }
-};
-#endif // __cplusplus
-
-#endif
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
index d82df45..1ad8b23 100644
--- a/riscv/riscv.mk.in
+++ b/riscv/riscv.mk.in
@@ -35,7 +35,6 @@ riscv_install_hdrs = \
isa_parser.h \
log_file.h \
memtracer.h \
- mmio_plugin.h \
mmu.h \
platform.h \
processor.h \
diff --git a/riscv/sim.cc b/riscv/sim.cc
index 50dc4f6..0c5a7fb 100644
--- a/riscv/sim.cc
+++ b/riscv/sim.cc
@@ -38,7 +38,7 @@ 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,
+ std::vector<const device_factory_t*> plugin_device_factories,
const std::vector<std::string>& args,
const debug_module_config_t &dm_config,
const char *log_path,
@@ -69,11 +69,6 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
for (auto& x : mems)
bus.add_device(x.first, x.second);
- for (auto& x : plugin_devices) {
- bus.add_device(x.first, x.second.get());
- devices.push_back(x.second);
- }
-
debug_module.add_device(&bus);
socketif = NULL;
@@ -124,6 +119,9 @@ sim_t::sim_t(const cfg_t *cfg, bool halted,
clint_factory, // clint must be element 0
plic_factory, // plic must be element 1
ns16550_factory};
+ device_factories.insert(device_factories.end(),
+ plugin_device_factories.begin(),
+ plugin_device_factories.end());
// Load dtb_file if provided, otherwise self-generate a dts/dtb
if (dtb_file) {
diff --git a/riscv/sim.h b/riscv/sim.h
index 1cb0658..a3445db 100644
--- a/riscv/sim.h
+++ b/riscv/sim.h
@@ -27,7 +27,7 @@ class sim_t : public htif_t, public simif_t
public:
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,
+ std::vector<const device_factory_t*> plugin_device_factories,
const std::vector<std::string>& args,
const debug_module_config_t &dm_config, const char *log_path,
bool dtb_enabled, const char *dtb_file,