| # Create Springbok Vector Unit Test |
| |
| * [Step 0: Repo Sync and Build Prequisites](#step-0:-repo-sync-and-build-prequisites) |
| * [Step 1: Select Instruction and Update Tracker](#step-1:-select-instruction-and-update-tracker) |
| * [Step 2: Create operation definition in `${ROOTDIR}/sw/vec/softrvv/include`](#step-2:-create-operation-definition-in-`${rootdir}/sw/vec/softrvv/include`) |
| * [Step 3: Add the header to softrvv.h](#step-3:-add-the-header-to-softrvv.h) |
| * [Step 4: Add main test entry within the CMakeLists.txt](#step-4:-add-main-test-entry-within-the-cmakelists.txt) |
| * [Step 5: Create subtest](#step-5:-create-subtest) |
| * [Add brief softrvv test](#add-brief-softrvv-test) |
| * [Add this smaller test to a 2nd Cmake file](#add-this-smaller-test-to-a-2nd-cmake-file) |
| * [Step 6.1: Build and Run Elf with Renode/Qemu](#step-6.1:-build-and-run-elf-with-renode/qemu) |
| * [Run Elf with Renode](#run-elf-with-renode) |
| * [Run Elf with Qemu](#run-elf-with-qemu) |
| * [Step 6.2 (Optional): Debug Elf with Renode/Qemu and gdb](#step-6.2-(optional):-debug-elf-with-renode/qemu-and-gdb) |
| * [Step 6.3 (Optional): Object dump with binutils](#step-6.3-(optional):-object-dump-with-binutils) |
| * [Step 7: Build and Run CTests](#step-7:-build-and-run-ctests) |
| * [Step 8 (optional): view generated code](#step-8-(optional):-view-generated-code) |
| * [Step 9: Mark Tests as Passing](#step-9:-mark-tests-as-passing) |
| * [Step 10: Git Commit](#step-10:-git-commit) |
| |
| ## Step 0: Repo Sync and Build Prequisites |
| |
| ```sh |
| repo sync |
| m renode_clean renode |
| m qemu_clean qemu |
| ``` |
| |
| ## Step 1: Select Instruction and Update Tracker |
| |
| Go to the following spreadsheet and write or select one's name under the `DRI - Unit Test`. |
| |
| [Select Instructions Here](https://docs.google.com/spreadsheets/d/1MVh0eQjdKkPiBOCXysfuLWWkFiL3gWzqvk-xA8-1rNg/edit#gid=1311575874) |
| |
| Now you've signed up to develop a unit test for this vector instruction :) |
| |
| |
| Side Note: The following pivot table is very useful for quickly scanning through the instructions available: |
| [DRI Pivot Table](https://docs.google.com/spreadsheets/d/1MVh0eQjdKkPiBOCXysfuLWWkFiL3gWzqvk-xA8-1rNg/edit#gid=1165644093) |
| |
| ## Step 2: Create operation definition in `${ROOTDIR}/sw/vec/softrvv/include` |
| |
| Add definition of the operation as a file `softrvv_<op>h.h` in the following folder, where `<op>` is your operation (e.g. `vadd`, `vor`, `vmerge`, etc...): |
| |
| ```sh |
| ${ROOTDIR}/sw/vec/softrvv/include |
| ``` |
| |
| This test will contain the definition of the operation (e.g. `vadd` operation below): |
| |
| ```cpp |
| template <typename T> |
| void vadd_vi(T *dest, T *src1, T src2, int32_t avl) { |
| for (int32_t idx = 0; idx < avl; idx++) { |
| dest[idx] = src1[idx] + src2; |
| } |
| } |
| |
| ``` |
| |
| See [softrvv_vadd.h](https://spacebeaker.googlesource.com/shodan/sw/vec/+/refs/heads/master/softrvv/include/softrvv_vadd.h) for a reference. |
| |
| ## Step 3: Add the header to softrvv.h |
| |
| Add the header file as an includes in the `softrvv.h`: |
| |
| ```cpp |
| #include "softrvv_vadd.h" |
| ``` |
| |
| ` softrvv.h ` is in the `${ROOTDIR}/sw/vec/softrvv/include` directory. |
| |
| |
| |
| ## Step 4: Add main test entry within the CMakeLists.txt |
| |
| |
| `cd` into the following folder, and edit the `CMakeLists.txt` file there |
| |
| ```sh |
| ${ROOTDIR}/sw/vec/tests/CMakeLists.txt |
| ``` |
| |
| Add an entry there with the opcode formats relavant to the operation: |
| |
| ```cmake |
| vec_cc_generated_test( |
| NAME |
| vadd |
| OPFMT |
| OPIVV |
| OPIVX |
| OPIVI |
| LINKOPTS |
| -Xlinker --defsym=__itcm_length__=200K |
| ) |
| ``` |
| |
| Note: this operation uses OPIVV, OPIVX, and OPIVI formats. |
| |
| A range of tests will be be autogenerated for each one of the OPFMT's added. |
| |
| The Mako templates for each OPFMT test can be found at `${ROOTDIR}/sw/vec/tests/templates`. |
| |
| Note on `__itcm_length__`: keeping this number low for each test helps our overall performance, most tests are good with 128K, some might need a little more memory (`ctest` will let you know if you need to add more here). |
| |
| ## Step 5: Create subtest |
| |
| Please also add a small manual test the new softvv instruction. |
| Steps delineated as follows: |
| |
| ### Add brief softrvv test |
| |
| ```sh |
| cd ${ROOTDIR}/sw/vec/softrvv/tests |
| ``` |
| |
| Then add a test-file named `softrvv_<op>_test.cpp`. |
| |
| See other files in the same folder as references. |
| |
| In this test-file you'll define a few simple test cases to run on the defined functions: |
| |
| See for example this VV test from [softrvv_vadd_test.cpp](https://spacebeaker.googlesource.com/shodan/sw/vec/+/refs/heads/master/softrvv/tests/softrvv_vadd_test.cpp): |
| |
| ```cpp |
| uint32_t src1[] = {1, 2, 3, 4, 5}; |
| uint32_t src2[] = {1, 2, 3, 4, 5}; |
| |
| uint32_t ref_vv[] = {2, 4, 6, 8, 10}; |
| |
| TEST_F(SoftRvvVaddTest, VV) { |
| softrvv::vadd_vv<uint32_t>(dest, src1, src2, AVL_CONST); |
| ASSERT_EQ(memcmp(dest, ref_vv, sizeof(dest)), 0); |
| } |
| ``` |
| |
| ### Add this smaller test to a 2nd Cmake file |
| |
| Edit another CMakeLists.txt file (path below): |
| |
| ```sh |
| ${ROOTDIR}/sw/vec/softrvv/tests/CMakeLists.txt |
| ``` |
| |
| Add the subtest just created: |
| |
| ```cmake |
| vec_cc_test( |
| NAME |
| softrvv_vadd |
| SRCS |
| softrvv_vadd_test.cpp |
| DEPS |
| softrvv |
| LINKOPTS |
| -Xlinker --defsym=__itcm_length__=128K |
| ``` |
| |
| ## Step 6.1: Build and Run Elf with Renode/Qemu |
| |
| `cd` into the root directory (`cd $ROOTDIR`), and build the elf with: |
| |
| ```sh |
| m springbok |
| ``` |
| |
| ### Run Elf with Renode |
| |
| From the root directory, run `sim_springbok` |
| |
| ```sh |
| sim_springbok ./out/springbok/tests/vadd_test.elf |
| ``` |
| |
| This will run the single elf, and if there is an error, can give useful |
| information, such as the PC and MTVAL associated with any illegal instruction. |
| |
| ### Run Elf with Qemu |
| |
| From the root directory, run `qemu_sim_springbok` |
| |
| ```sh |
| qemu_sim_springbok ./out/springbok/tests/vadd_test.elf |
| ``` |
| |
| ## Step 6.2 (Optional): Debug Elf with Renode/Qemu and gdb |
| |
| To debug an elf, open two console sessions in the `$ROOTDIR`, in one run start a simulator |
| (either `sim_springbok` or `qemu_sim_springbok`): |
| |
| Start Renode simulation: |
| ```sh |
| sim_springbok ./out/springbok/tests/vadd_test.elf debug |
| ``` |
| Alternatively, start Qemu simulation: |
| |
| ```sh |
| qemu_sim_springbok ./out/springbok/tests/vadd_test.elf -s -S |
| ``` |
| |
| Now, in the other console session run the following command to start a gdb session: |
| |
| ```sh |
| cache/toolchain/bin/riscv32-unknown-elf-gdb -ex "target remote :3333" out/springbok/tests/vadd_test.elf |
| ``` |
| |
| Note: To run GDB with the Qemu simulation, use |
| |
| ```sh |
| cache/toolchain/bin/riscv32-unknown-elf-gdb -ex "target remote :1234" out/springbok/tests/vadd_test.elf |
| ``` |
| |
| First, in the Renode session, type `start`. |
| |
| Then, in the gdb session, type the following, |
| |
| ```sh |
| layout split |
| b main |
| ``` |
| |
| and step through as usual with GDB. |
| |
| ## Step 6.3 (Optional): Object dump with binutils |
| |
| Sadly, gdb cannot presently decode RVV machine code into assembly instructions. |
| |
| However, the objdump __is__ able to decode the RVV machine code into assembly. |
| To do this, obtain the program counter for the RVV machine code in question, then perform an objdump. |
| |
| Run this on the elf (while in the `$ROOTDIR`): |
| ```sh |
| cache/toolchain_iree_rv32imf/bin/riscv32-unknown-elf-objdump -d out/springbok/tests/vadd_test.elf | less |
| ``` |
| |
| Then search for the PC for any instruction of interest. |
| |
| ## Step 7: Build and Run CTests |
| |
| CTests must be run from the `${ROOTDIR}/out/springbok` directory. |
| |
| `cd ${ROOTDIR}/out/springbok` |
| |
| Next, using Regex in the quoted section, select Qemu, Renode, and/or other operations |
| to include in a test run: |
| |
| ```sh |
| m springbok && ctest --verbose -R ".*vadd.*" --gtest_color=yes |
| ``` |
| |
| ## Step 8 (optional): view generated code |
| |
| Code for the main test was autogenerated, however by `cd`'ing into the following directory, one can inspect the generated code. |
| |
| ```sh |
| ${ROOTDIR}/out/springbok/tests/generated/ |
| ``` |
| |
| ## Step 9: Mark Tests as Passing |
| |
| Note: at minimum, one's test should be expected to pass in Qemu. Since Renode vec support is WIP, a unit test failing may indicate problem in the Renode implementation. |
| |
| On the [unit test tracker](https://docs.google.com/spreadsheets/d/1MVh0eQjdKkPiBOCXysfuLWWkFiL3gWzqvk-xA8-1rNg/edit#gid=1311575874): |
| |
| 1. Mark whether the unit test passes in Qemu |
| 2. Mark whether the unit test passes in Renode |
| 3. Mark the instruction "Springbok Unit Test" as "implemented" |
| |
| ## Step 10: Git Commit |
| |
| At this point there are two commitable chunks: |
| |
| 1. operation definition, softrvv.h change, and CMakeLists.txt entry. |
| 2. the manual test and its CMakeLists.txt entry |
| |
| These may be added as either one CL, or two CL's separating these two contributions. |