From: Andrew Waterman Date: Tue, 25 Nov 2014 21:39:53 +0000 (-0800) Subject: Factor out the dummy RoCC accelerator X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=590417bec978bfc3fbf35d303760494395eb65b2;p=riscv-isa-sim.git Factor out the dummy RoCC accelerator --- diff --git a/config.h.in b/config.h.in index 42d4d22..12aeebd 100644 --- a/config.h.in +++ b/config.h.in @@ -1,5 +1,8 @@ /* config.h.in. Generated from configure.ac by autoheader. */ +/* Define if subproject MCPPBS_SPROJ_NORM is enabled */ +#undef DUMMY_ROCC_ENABLED + /* Define to 1 if you have the `dl' library (-ldl). */ #undef HAVE_LIBDL diff --git a/configure b/configure index abddde5..e98db52 100755 --- a/configure +++ b/configure @@ -4301,6 +4301,51 @@ $as_echo "#define HWACHA_ENABLED /**/" >>confdefs.h + # Add subproject to our running list + + subprojects="$subprojects dummy_rocc" + + # Process the subproject appropriately. If enabled add it to the + # $enabled_subprojects running shell variable, set a + # SUBPROJECT_ENABLED C define, and include the appropriate + # 'subproject.ac'. + + + { $as_echo "$as_me:${as_lineno-$LINENO}: configuring default subproject : dummy_rocc" >&5 +$as_echo "$as_me: configuring default subproject : dummy_rocc" >&6;} + ac_config_files="$ac_config_files dummy_rocc.mk:dummy_rocc/dummy_rocc.mk.in" + + enable_dummy_rocc_sproj="yes" + subprojects_enabled="$subprojects_enabled dummy_rocc" + +$as_echo "#define DUMMY_ROCC_ENABLED /**/" >>confdefs.h + + + + + + + # Determine if this is a required or an optional subproject + + + + # Determine if there is a group with the same name + + + + # Create variations of the subproject name suitable for use as a CPP + # enabled define, a shell enabled variable, and a shell function + + + + + + + + + + + # Add subproject to our running list subprojects="$subprojects softfloat" @@ -5147,6 +5192,7 @@ do case $ac_config_target in "riscv.mk") CONFIG_FILES="$CONFIG_FILES riscv.mk:riscv/riscv.mk.in" ;; "hwacha.mk") CONFIG_FILES="$CONFIG_FILES hwacha.mk:hwacha/hwacha.mk.in" ;; + "dummy_rocc.mk") CONFIG_FILES="$CONFIG_FILES dummy_rocc.mk:dummy_rocc/dummy_rocc.mk.in" ;; "softfloat.mk") CONFIG_FILES="$CONFIG_FILES softfloat.mk:softfloat/softfloat.mk.in" ;; "spike.mk") CONFIG_FILES="$CONFIG_FILES spike.mk:spike/spike.mk.in" ;; "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; diff --git a/configure.ac b/configure.ac index d6fb7e5..89d4dcf 100644 --- a/configure.ac +++ b/configure.ac @@ -82,7 +82,7 @@ AC_SUBST([CXXFLAGS],["-Wall -Wno-unused -O2 -std=c++11"]) # The '*' suffix indicates an optional subproject. The '**' suffix # indicates an optional subproject which is also the name of a group. -MCPPBS_SUBPROJECTS([ riscv, hwacha, softfloat, spike ]) +MCPPBS_SUBPROJECTS([ riscv, hwacha, dummy_rocc, softfloat, spike ]) #------------------------------------------------------------------------- # MCPPBS subproject groups diff --git a/dummy_rocc/dummy_rocc.ac b/dummy_rocc/dummy_rocc.ac new file mode 100644 index 0000000..e69de29 diff --git a/dummy_rocc/dummy_rocc.cc b/dummy_rocc/dummy_rocc.cc new file mode 100644 index 0000000..85ab7aa --- /dev/null +++ b/dummy_rocc/dummy_rocc.cc @@ -0,0 +1,47 @@ +#include "rocc.h" +#include "mmu.h" +#include + +class dummy_rocc_t : public rocc_t +{ + public: + const char* name() { return "dummy_rocc"; } + + reg_t custom0(rocc_insn_t insn, reg_t xs1, reg_t xs2) + { + reg_t prev_acc = acc[insn.rs2]; + + if (insn.rs2 >= num_acc) + illegal_instruction(); + + switch (insn.funct) + { + case 0: // acc <- xs1 + acc[insn.rs2] = xs1; + break; + case 1: // xd <- acc (the only real work is the return statement below) + break; + case 2: // acc[rs2] <- Mem[xs1] + acc[insn.rs2] = p->get_mmu()->load_uint64(xs1); + break; + case 3: // acc[rs2] <- accX + xs1 + acc[insn.rs2] += xs1; + break; + default: + illegal_instruction(); + } + + return prev_acc; // in all cases, xd <- previous value of acc[rs2] + } + + dummy_rocc_t() + { + memset(acc, 0, sizeof(acc)); + } + + private: + static const int num_acc = 4; + reg_t acc[num_acc]; +}; + +REGISTER_EXTENSION(dummy_rocc, []() { return new dummy_rocc_t; }) diff --git a/dummy_rocc/dummy_rocc.mk.in b/dummy_rocc/dummy_rocc.mk.in new file mode 100644 index 0000000..298b9f9 --- /dev/null +++ b/dummy_rocc/dummy_rocc.mk.in @@ -0,0 +1,7 @@ +dummy_rocc_subproject_deps = \ + spike \ + riscv \ + softfloat \ + +dummy_rocc_srcs = \ + dummy_rocc.cc \ diff --git a/dummy_rocc/dummy_rocc_test.c b/dummy_rocc/dummy_rocc_test.c new file mode 100644 index 0000000..94de8c0 --- /dev/null +++ b/dummy_rocc/dummy_rocc_test.c @@ -0,0 +1,29 @@ +// The following is a RISC-V program to test the functionality of the +// dummy RoCC accelerator. +// Compile with riscv64-unknown-elf-gcc dummy_rocc_test.c +// Run with spike --extension=dummy_rocc pk a.out + +#include +#include +#include + +int main() { + uint64_t x = 123, y = 456, z = 0; + // load x into accumulator 2 (funct=0) + asm volatile ("custom0 x0, %0, 2, 0" : : "r"(x)); + // read it back into z (funct=1) to verify it + asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z)); + assert(z == x); + // accumulate 456 into it (funct=3) + asm volatile ("custom0 x0, %0, 2, 3" : : "r"(y)); + // verify it + asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z)); + assert(z == x+y); + // do it all again, but initialize acc2 via memory this time (funct=2) + asm volatile ("custom0 x0, %0, 2, 2" : : "r"(&x)); + asm volatile ("custom0 x0, %0, 2, 3" : : "r"(y)); + asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z)); + assert(z == x+y); + + printf("success!\n"); +} diff --git a/hwacha/hwacha.cc b/hwacha/hwacha.cc index 1a89d73..fdd215e 100644 --- a/hwacha/hwacha.cc +++ b/hwacha/hwacha.cc @@ -4,6 +4,8 @@ #include "trap.h" #include +REGISTER_EXTENSION(hwacha, []() { return new hwacha_t; }) + void ct_state_t::reset() { nxpr = 32; diff --git a/hwacha/hwacha.mk.in b/hwacha/hwacha.mk.in index b4f375e..3624879 100644 --- a/hwacha/hwacha.mk.in +++ b/hwacha/hwacha.mk.in @@ -1,4 +1,5 @@ hwacha_subproject_deps = \ + spike \ riscv \ softfloat \ diff --git a/riscv/dummy-rocc-test.c b/riscv/dummy-rocc-test.c deleted file mode 100644 index ce48179..0000000 --- a/riscv/dummy-rocc-test.c +++ /dev/null @@ -1,29 +0,0 @@ -// The following is a RISC-V program to test the functionality of the -// dummy RoCC accelerator. -// Compile with riscv-gcc dummy-rocc-test.c -// Run with spike --extension=dummy pk a.out - -#include -#include -#include - -int main() { - uint64_t x = 123, y = 456, z = 0; - // load x into accumulator 2 (funct=0) - asm volatile ("custom0 x0, %0, 2, 0" : : "r"(x)); - // read it back into z (funct=1) to verify it - asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z)); - assert(z == x); - // accumulate 456 into it (funct=3) - asm volatile ("custom0 x0, %0, 2, 3" : : "r"(y)); - // verify it - asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z)); - assert(z == x+y); - // do it all again, but initialize acc2 via memory this time (funct=2) - asm volatile ("custom0 x0, %0, 2, 2" : : "r"(&x)); - asm volatile ("custom0 x0, %0, 2, 3" : : "r"(y)); - asm volatile ("custom0 %0, x0, 2, 1" : "=r"(z)); - assert(z == x+y); - - printf("success!\n"); -} diff --git a/riscv/dummy-rocc.h b/riscv/dummy-rocc.h deleted file mode 100644 index 75e0722..0000000 --- a/riscv/dummy-rocc.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _RISCV_DUMMY_ROCC_H -#define _RISCV_DUMMY_ROCC_H - -#include "rocc.h" -#include "mmu.h" - -class dummy_rocc_t : public rocc_t -{ - public: - const char* name() { return "dummy"; } - - reg_t custom0(rocc_insn_t insn, reg_t xs1, reg_t xs2) - { - reg_t prev_acc = acc[insn.rs2]; - - if (insn.rs2 > num_acc) - illegal_instruction(); - - switch (insn.funct) - { - case 0: // acc <- xs1 - acc[insn.rs2] = xs1; - break; - case 1: // xd <- acc (the only real work is the return statement below) - break; - case 2: // acc[rs2] <- Mem[xs1] - acc[insn.rs2] = p->get_mmu()->load_uint64(xs1); - break; - case 3: // acc[rs2] <- accX + xs1 - acc[insn.rs2] += xs1; - break; - default: - illegal_instruction(); - } - - return prev_acc; // in all cases, xd <- previous value of acc[rs2] - } - - void reset() - { - for(int i = 0; i < num_acc; i++) acc[i] = 0; - } - - private: - static const int num_acc = 4; - reg_t acc[num_acc]; -}; - -#endif diff --git a/riscv/extension.h b/riscv/extension.h index cce8345..f73a5a8 100644 --- a/riscv/extension.h +++ b/riscv/extension.h @@ -3,8 +3,6 @@ #include "processor.h" #include "disasm.h" -#include -#include #include #include @@ -27,11 +25,12 @@ class extension_t void clear_interrupt(); }; -std::map>& extensions(); +std::function find_extension(const char* name); +void register_extension(const char* name, std::function f); #define REGISTER_EXTENSION(name, constructor) \ class register_##name { \ - public: register_##name() { extensions()[#name] = constructor; } \ + public: register_##name() { register_extension(#name, constructor); } \ }; static register_##name dummy_##name; #endif diff --git a/riscv/riscv-dis.cc b/riscv/riscv-dis.cc deleted file mode 100644 index 19d579d..0000000 --- a/riscv/riscv-dis.cc +++ /dev/null @@ -1,54 +0,0 @@ -// See LICENSE for license details. - -// This little program finds occurrences of strings like -// DASM(ffabc013) -// in its input, then replaces them with the disassembly -// enclosed hexadecimal number, interpreted as a RISC-V -// instruction. - -#include "disasm.h" -#include "extension.h" -#include -#include -#include -#include -using namespace std; - -int main(int argc, char** argv) -{ - string s; - disassembler_t d; - - std::function extension; - option_parser_t parser; - parser.option(0, "extension", 1, [&](const char* s){ - if (!extensions().count(s)) - fprintf(stderr, "unknown extension %s!\n", s), exit(-1); - extension = extensions()[s]; - - for (auto disasm_insn : extension()->get_disasms()) - d.add_insn(disasm_insn); - }); - - while (getline(cin, s)) - { - for (size_t start = 0; (start = s.find("DASM(", start)) != string::npos; ) - { - size_t end = s.find(')', start); - if (end == string::npos) - break; - - size_t numstart = start + strlen("DASM("); - uint32_t n = strtoul(&s[numstart], NULL, 16); - - string dis = d.disassemble(*(insn_t*)&n); - - s = s.substr(0, start) + dis + s.substr(end+1); - start += dis.length(); - } - - cout << s << '\n'; - } - - return 0; -} diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index c5a9055..0d5869d 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -19,7 +19,6 @@ riscv_hdrs = \ memtracer.h \ extension.h \ rocc.h \ - dummy-rocc.h \ insn_template.h \ mulhi.h \ diff --git a/spike/extensions.cc b/spike/extensions.cc index 0d22a95..315621f 100644 --- a/spike/extensions.cc +++ b/spike/extensions.cc @@ -1,14 +1,35 @@ #include "extension.h" -#include "hwacha.h" -#include "dummy-rocc.h" +#include +#include +#include -REGISTER_EXTENSION(dummy, []() { return new dummy_rocc_t; }) -REGISTER_EXTENSION(hwacha, []() { return new hwacha_t; }) - -// Static constructors want to make use of the extensions map, so we -// access it through a function call to guarantee initialization order. -std::map>& extensions() +static std::map>& extensions() { static std::map> v; return v; } + +void register_extension(const char* name, std::function f) +{ + extensions()[name] = f; +} + +std::function find_extension(const char* name) +{ + if (!extensions().count(name)) { + // try to find extension xyz by loading libxyz.so + std::string libname = std::string("lib") + name + ".so"; + if (!dlopen(libname.c_str(), RTLD_LAZY)) { + fprintf(stderr, "couldn't find extension '%s' (or library '%s')\n", + name, libname.c_str()); + exit(-1); + } + if (!extensions().count(name)) { + fprintf(stderr, "couldn't find extension '%s' in shared library '%s'\n", + name, libname.c_str()); + exit(-1); + } + } + + return extensions()[name]; +} diff --git a/spike/riscv-dis.cc b/spike/riscv-dis.cc new file mode 100644 index 0000000..89c4b74 --- /dev/null +++ b/spike/riscv-dis.cc @@ -0,0 +1,47 @@ +// See LICENSE for license details. + +// This little program finds occurrences of strings like +// DASM(ffabc013) +// in its input, then replaces them with the disassembly +// enclosed hexadecimal number, interpreted as a RISC-V +// instruction. + +#include "disasm.h" +#include "extension.h" +#include +#include +#include +#include +using namespace std; + +int main(int argc, char** argv) +{ + string s; + disassembler_t d; + + std::function extension; + option_parser_t parser; + parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);}); + + while (getline(cin, s)) + { + for (size_t start = 0; (start = s.find("DASM(", start)) != string::npos; ) + { + size_t end = s.find(')', start); + if (end == string::npos) + break; + + size_t numstart = start + strlen("DASM("); + uint32_t n = strtoul(&s[numstart], NULL, 16); + + string dis = d.disassemble(*(insn_t*)&n); + + s = s.substr(0, start) + dis + s.substr(end+1); + start += dis.length(); + } + + cout << s << '\n'; + } + + return 0; +} diff --git a/spike/spike.cc b/spike/spike.cc index 5c8901c..ab5cea5 100644 --- a/spike/spike.cc +++ b/spike/spike.cc @@ -51,11 +51,7 @@ int main(int argc, char** argv) parser.option(0, "ic", 1, [&](const char* s){ic.reset(new icache_sim_t(s));}); parser.option(0, "dc", 1, [&](const char* s){dc.reset(new dcache_sim_t(s));}); parser.option(0, "l2", 1, [&](const char* s){l2.reset(cache_sim_t::construct(s, "L2$"));}); - parser.option(0, "extension", 1, [&](const char* s){ - if (!extensions().count(s)) - fprintf(stderr, "unknown extension %s!\n", s), exit(-1); - extension = extensions()[s]; - }); + parser.option(0, "extension", 1, [&](const char* s){extension = find_extension(s);}); parser.option(0, "extlib", 1, [&](const char *s){ void *lib = dlopen(s, RTLD_NOW | RTLD_GLOBAL); if (lib == NULL) { diff --git a/spike/spike.mk.in b/spike/spike.mk.in index 7534e86..280fa6c 100644 --- a/spike/spike.mk.in +++ b/spike/spike.mk.in @@ -1,7 +1,6 @@ spike_subproject_deps = \ - softfloat \ riscv \ - hwacha \ + softfloat \ spike_install_prog_srcs = \ spike.cc \