Skip to content

Commit

Permalink
feat: add possibility for custom CSRs
Browse files Browse the repository at this point in the history
Currently in riscv-isa-sim there's no way to make a custom extension
that adds new CSRs. This simple patch makes it possible via new
virtual function in extension_t class.
  • Loading branch information
arrv-sc committed Nov 7, 2024
1 parent fd0a927 commit 6037eed
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 0 deletions.
4 changes: 4 additions & 0 deletions ci-tests/create-ci-binary-tarball
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ mkdir -p build/dummy-slliuw && cd "$_"
riscv64-unknown-elf-gcc -O2 -o dummy-slliuw `git rev-parse --show-toplevel`/ci-tests/dummy-slliuw.c
cd -

mkdir -p build/dummycsr && cd "$_"
riscv64-unknown-elf-gcc -O2 -o customcsr `git rev-parse --show-toplevel`/ci-tests/customcsr.c
cd -

mv build/pk/pk .
mv build/hello/hello .
mv build/dummy-slliuw/dummy-slliuw .
Expand Down
81 changes: 81 additions & 0 deletions ci-tests/custom-csr.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include <riscv/extension.h>
#include <riscv/sim.h>


class dummycsr_t: public csr_t {
public:
dummycsr_t(processor_t *proc, const reg_t addr): csr_t(proc, addr) {}

reg_t read() const noexcept override {
return 42;
}

void verify_permissions(insn_t insn, bool write) const override {}

protected:
bool unlogged_write(const reg_t val) noexcept override {
return true;
}
};

// dummy extension with dummy CSRs. Nice.
struct xdummycsr_t : public extension_t {
const char *name() { return "dummycsr"; }

xdummycsr_t() {}

std::vector<insn_desc_t> get_instructions() override {
return {};
}

std::vector<disasm_insn_t *> get_disasms() override {
return {};
}

std::vector<csr_t_p> get_csrs(processor_t &proc) const override {
return {std::make_shared<dummycsr_t>(&proc, /*Addr*/ 0xfff)};
}
};

REGISTER_EXTENSION(dummycsr, []() { return new xdummycsr_t; })

// Copied from spike main.
// TODO: This should really be provided in libriscv
static std::vector<std::pair<reg_t, abstract_mem_t *>>
make_mems(const std::vector<mem_cfg_t> &layout) {
std::vector<std::pair<reg_t, abstract_mem_t *>> mems;
mems.reserve(layout.size());
for (const auto &cfg : layout) {
mems.push_back(std::make_pair(cfg.get_base(), new mem_t(cfg.get_size())));
}
return mems;
}

int main(int argc, char **argv) {
cfg_t cfg;
cfg.isa = "RV64IMAFDCV_Zicsr_xdummycsr";
std::vector<device_factory_sargs_t> plugin_devices;
if (argc != 3) {
std::cerr << "Error: invalid arguments\n";
exit(1);
}
std::vector<std::string> htif_args{argv[1] /* pk */, argv[2] /* executable */};
debug_module_config_t dm_config = {.progbufsize = 2,
.max_sba_data_width = 0,
.require_authentication = false,
.abstract_rti = 0,
.support_hasel = true,
.support_abstract_csr_access = true,
.support_abstract_fpr_access = true,
.support_haltgroups = true,
.support_impebreak = true};
std::vector<std::pair<reg_t, abstract_mem_t *>> mems =
make_mems(cfg.mem_layout);
sim_t sim(&cfg, false, mems, plugin_devices, htif_args, dm_config,
nullptr, // log_path
true, // dtb_enabled
nullptr, // dtb_file
false, // socket_enabled
nullptr); // cmd_file
sim.run();
}
12 changes: 12 additions & 0 deletions ci-tests/customcsr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <stdio.h>

int main() {
int x = 1;
// dummycsr
asm("csrr %0, 0xfff" : "=r"(x));
if (x == 42)
printf("Executed successfully\n");
else
printf("FAIL. Got value: %d instead of 42\n", x);
return 0;
}
2 changes: 2 additions & 0 deletions ci-tests/test-spike
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ time ../install/bin/spike --isa=rv64gc pk hello | grep "Hello, world! Pi is app
# check that including sim.h in an external project works
g++ -std=c++2a -I../install/include -L../install/lib $DIR/testlib.cc -lriscv -o test-libriscv
g++ -std=c++2a -I../install/include -L../install/lib $DIR/test-customext.cc -lriscv -o test-customext
g++ -std=c++2a -I../install/include -L../install/lib $DIR/custom-csr.cc -lriscv -o test-custom-csr

# check that all installed headers are functional
g++ -std=c++2a -I../install/include -L../install/lib $DIR/testlib.cc -lriscv -o /dev/null -include ../install-hdrs-list.h

LD_LIBRARY_PATH=../install/lib ./test-libriscv pk hello| grep "Hello, world! Pi is approximately 3.141588."
LD_LIBRARY_PATH=../install/lib ./test-customext pk dummy-slliuw | grep "Executed successfully"
LD_LIBRARY_PATH=../install/lib ./test-custom-csr pk customcsr | grep "Executed successfully"
1 change: 1 addition & 0 deletions riscv/extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class extension_t
public:
virtual std::vector<insn_desc_t> get_instructions() = 0;
virtual std::vector<disasm_insn_t*> get_disasms() = 0;
virtual std::vector<csr_t_p> get_csrs ([[maybe_unused]] processor_t &proc) const { return {}; };
virtual const char* name() = 0;
virtual void reset() {};
virtual void set_debug(bool UNUSED value) {}
Expand Down
2 changes: 2 additions & 0 deletions riscv/processor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,8 @@ void processor_t::register_extension(extension_t *x) {
fprintf(stderr, "extensions must have unique names (got two named \"%s\"!)\n", x->name());
abort();
}
for (auto &csr: x->get_csrs(*this))
state.add_csr(csr->address, csr);
x->set_processor(this);
}

Expand Down

0 comments on commit 6037eed

Please sign in to comment.