aboutsummaryrefslogtreecommitdiff
path: root/ci-tests
diff options
context:
space:
mode:
authorAlexander Romanov <alexander.romanov@syntacore.com>2024-03-05 09:42:52 +0300
committerAlexander Romanov <alexander.romanov@syntacore.com>2024-03-07 11:51:53 +0300
commit7da36db7c1369ce0ba039c1984c5c7c21da1101b (patch)
tree694361f3efe4b258c8ad386bd9f22bab275830a6 /ci-tests
parent8d239ff376d3614af554630aa5e7ae6c5d7f010e (diff)
downloadriscv-isa-sim-7da36db7c1369ce0ba039c1984c5c7c21da1101b.zip
riscv-isa-sim-7da36db7c1369ce0ba039c1984c5c7c21da1101b.tar.gz
riscv-isa-sim-7da36db7c1369ce0ba039c1984c5c7c21da1101b.tar.bz2
workaround to support custom extensions that use standard prefixes
RISC-V ISA states (21.1): "A standard-compatible global encoding can also use standard prefixes for non-standard extensions if the associated standard extensions are not included in the global encoding." Currently all the instructions (either from standard or custom extensions) are all being inserted into a single std::vector which is then being sorted. An instruction matching process performs linear search on that vector. The problem is that when a custom extension uses the same opcode as standard one (i.e. match and mask are equal to the standard counterparts) it is undefined which instruction will be picked. That is because in std::sort "The order of equal elements is not guaranteed to be preserved". That being said it is impossible to define custom extension (via customext) that would use the prefix of a disabled standard extension. In this change I separate custom and standard extensions in two separate std::vector's. By default we report an error if they have common elements (There're an additional processor_t constructor's argument that skips this check). If this error is disabled during instruction matching we first trying to find it among custom instructions. If it has been found the search is stopped and custom instruction is executed, otherwise we look for it among standard instructions. Overall this change does not completely fix the problem but at least makes it possible to use the feature of RISC-V ISA.
Diffstat (limited to 'ci-tests')
-rwxr-xr-xci-tests/create-ci-binary-tarball10
-rw-r--r--ci-tests/dummy-slliuw.c8
-rw-r--r--ci-tests/test-customext.cc90
-rwxr-xr-xci-tests/test-spike5
-rw-r--r--ci-tests/testlib.c11
5 files changed, 117 insertions, 7 deletions
diff --git a/ci-tests/create-ci-binary-tarball b/ci-tests/create-ci-binary-tarball
index b4fa545..abc9ee0 100755
--- a/ci-tests/create-ci-binary-tarball
+++ b/ci-tests/create-ci-binary-tarball
@@ -12,9 +12,13 @@ mkdir -p build/hello && cd "$_"
riscv64-unknown-elf-gcc -O2 -o hello `git rev-parse --show-toplevel`/ci-tests/hello.c
cd -
+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 -
+
mv build/pk/pk .
mv build/hello/hello .
+mv build/dummy-slliuw/dummy-slliuw .
+tar -cf spike-ci.tar pk hello dummy-slliuw
-tar -cf spike-ci.tar pk hello
-
-rm pk hello
+rm pk hello dummy-slliuw
diff --git a/ci-tests/dummy-slliuw.c b/ci-tests/dummy-slliuw.c
new file mode 100644
index 0000000..05b7a40
--- /dev/null
+++ b/ci-tests/dummy-slliuw.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+
+int main() {
+ // as if slli.uw zero, t1, 3
+ asm(".4byte 0x0833101b");
+ printf("Executed successfully\n");
+ return 0;
+}
diff --git a/ci-tests/test-customext.cc b/ci-tests/test-customext.cc
new file mode 100644
index 0000000..5ef6c4f
--- /dev/null
+++ b/ci-tests/test-customext.cc
@@ -0,0 +1,90 @@
+#include <riscv/extension.h>
+#include <riscv/sim.h>
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const { return xpr_name[insn.rd()]; }
+} xrd;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const { return xpr_name[insn.rs1()]; }
+} xrs1;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const { return xpr_name[insn.rs2()]; }
+} xrs2;
+
+struct : public arg_t {
+ std::string to_string(insn_t insn) const {
+ return std::to_string((int)insn.shamt());
+ }
+} shamt;
+
+static reg_t do_nop4([[maybe_unused]] processor_t *p,
+ [[maybe_unused]] insn_t insn, reg_t pc) {
+ return pc + 4;
+}
+
+// dummy extension that uses the same prefix as standard zba extension
+struct xslliuw_dummy_t : public extension_t {
+ const char *name() { return "dummyslliuw"; }
+
+ xslliuw_dummy_t() {}
+
+ std::vector<insn_desc_t> get_instructions() {
+ std::vector<insn_desc_t> insns;
+ insns.push_back(insn_desc_t{MATCH_SLLI_UW, MASK_SLLI_UW, do_nop4, do_nop4,
+ do_nop4, do_nop4, do_nop4, do_nop4, do_nop4,
+ do_nop4});
+ return insns;
+ }
+
+ std::vector<disasm_insn_t *> get_disasms() {
+ std::vector<disasm_insn_t *> insns;
+ insns.push_back(new disasm_insn_t("dummy_slliuw", MATCH_SLLI_UW,
+ MASK_SLLI_UW, {&xrd, &xrs1, &shamt}));
+ return insns;
+ }
+};
+
+REGISTER_EXTENSION(dummyslliuw, []() { return new xslliuw_dummy_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_xdummyslliuw";
+ std::vector<device_factory_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();
+}
diff --git a/ci-tests/test-spike b/ci-tests/test-spike
index 725ac64..0540739 100755
--- a/ci-tests/test-spike
+++ b/ci-tests/test-spike
@@ -14,4 +14,7 @@ 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++17 -I../install/include -L../install/lib $DIR/testlib.c -lriscv -o test-libriscv
-LD_LIBRARY_PATH=../install/lib ./test-libriscv | grep "Hello, world! Pi is approximately 3.141588."
+g++ -std=c++17 -I../install/include -L../install/lib $DIR/test-customext.cc -lriscv -o test-customext
+
+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"
diff --git a/ci-tests/testlib.c b/ci-tests/testlib.c
index 5e39c1b..9cdbe07 100644
--- a/ci-tests/testlib.c
+++ b/ci-tests/testlib.c
@@ -12,11 +12,16 @@ static std::vector<std::pair<reg_t, abstract_mem_t*>> make_mems(const std::vecto
return mems;
}
-int main()
-{
+int main(int argc, char **argv) {
cfg_t cfg;
std::vector<device_factory_t*> plugin_devices;
- std::vector<std::string> htif_args {"pk", "hello"};
+
+ 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;
std::vector<std::pair<reg_t, abstract_mem_t*>> mems =
make_mems(cfg.mem_layout);