blob: 62cbf60f70a45edc84524ce8b7102fa2710fc03e [file] [log] [blame] [view]
# OpenTitan RISCV Vector Simulation in Renode
Follow setups in this document to build and run the following examples:
1. [OpenTitan Hello World Basic Example](#opentitan-hello-world-basic-example)
2. [OpenTitan Hello World Vector Sim Examples](#opentitan-hello-world-vector-sim-example)
Keep an eye on the file below for new build targets as they become available:
```
$ROOTDIR/build/opentitan_sw.mk
```
## OpenTitan Hello World Basic Example
These instructions guide through setting up and running a test of OpenTitan with a bare-bones Renode
robot-test-script.
### Sync and set up environment
```
repo sync
source ./build/setup.sh
```
### Build tools
```
m tools
```
### Build OpenTitan helloworld Demo
```
m opentitan_sw_bootrom
```
```
m opentitan_sw_helloworld
```
### Start OpenTitan Renode Script
```
renode -e "i @sim/config/shodan_secure.resc; start"
```
### Run `shodan_bootrom.robot` Robot-Test-Script
```
cd "${ROOTDIR}/sim/tests"
./test.sh shodan_bootrom.robot
```
Note: since we build Renode from source, we are to use Renode's provided `test.sh` instead of
`renode-test` for running robot test scripts.
[More details in Renode's documentation](https://renode.readthedocs.io/en/latest/introduction/testing.html#running-the-robot-test-script)
### View Results of the Tests
Results of the robot-test-script will be found in the following files:
```
$ROOTDIR/out/host/renode/tests/report.html
$ROOTDIR/out/host/renode/tests/robot_output.xml
$ROOTDIR/out/host/renode/tests/log.html
```
The `report.html` will share the results of each test.
One can utilize `robot_output.xml` for scripts/programs which may want to parse
and act on results.
## OpenTitan Hello World Vector Sim Example
How to run the HelloVector example and how to modify or add a new vector OpCode for Renode simulation.
1. [Run OpenTitan HelloVector Renode Demo](#run-opentitan-hellovector-renode-demo)
2. [Modify Vector OpCode Behavior and Simulate](#modify-vector-opcode-behavior-and-simulate)
3. [Add New Vector OpCode and Simulate](#add-new-vector-opcode-and-simulate)
### Run OpenTitan HelloVector Renode Demo
#### Sync and set up environment
```
repo sync
source ./build/setup.sh
```
#### Build tools
```
m tools
```
#### Build OpenTitan HelloVector Demo
```
m shodan_test_sw_bootrom
m shodan_test_sw_hellovector
```
#### Start OpenTitan-HelloVector Renode Script
```
renode -e "i @sim/config/shodan_hellovector.resc; start"
```
### Modify Vector OpCode Behavior and Simulate
To modify the functionality of an opcode, we will be modifying the following files:
`$ROOTDIR/sim/renode/src/Infrastructure/src/Emulator/Cores/tlib/arch/riscv/translate.c`
`$ROOTDIR/sim/renode/src/Infrastructure/src/Emulator/Cores/tlib/arch/riscv/instmap.h`
#### Add new opcode in `instmap.h`'s enum
To add a new opcode, create a new entry in `instmap.h`:
```
enum {
OPC_RISC_VADD_IVV = OPC_RISC_V_ARITH_IVV | (0x0 << 26),
OPC_RISC_VSUB_IVV = OPC_RISC_V_ARITH_IVV | (0x2 << 26),
OPC_RISC_VMINU_IVV = OPC_RISC_V_ARITH_IVV | (0x4 << 26),
YOUR_OPC_HERE = OPC_RISC_V_ARITH_IVV | (0x8 << 26),
```
#### Add `switch...case` entry and definition into `translate.c`
Open `translate.c` and look for the following function (which will be around line 1450):
```
static void gen_v_arith_ivv(DisasContext *dc, uint32_t opc, int vd, int vs1, int vs2) {
tlib_printf(LOG_LEVEL_ERROR, "V_ARITH_IVV");
```
In this function there will be a `switch case`.
Add an entry here for your new opcode, and fill out the behavior with tcg-lang.
```
switch (opc) {
case YOUR_OPC_HERE:
tlib_printf(LOG_LEVEL_ERROR, "OpCode Not Yet Defined");
break;
```
[Link to TCG Documentation for Reference](https://wiki.qemu.org/Documentation/TCG)
#### Rebuild Renode
```
m renode_clean
m renode
```
#### Add OpCode Test into `hello_vector.c`
Wrap the assembly within an `__asm__` block and add to `hello_vector.c`:
```
$ROOTDIR/hw/opentitan/sw_shodan/device/examples/hello_vector/hello_vector.c
```
#### Rebuild `shodan_test_sw_hellovector` target
If `hello_vector.c` was modified, run the following to rebuild the `shodan_test_sw_hellovector` target:
```
m shodan_test_sw_hellovector
```
#### Run Renode Script:
```
renode -e "i @sim/config/shodan_hellovector.resc; start"
```
#### Quicklinks to Relevant Files for OpCode Modification/Testing:
- `$ROOTDIR/build/shodan_test_sw.mk` -- build file for `hellovector` example
- `$ROOTDIR/sim/config/shodan_hellovector.resc` -- renode script which loads ELFs into memory
- `$ROOTDIR/hw/opentitan/sw_shodan/device/examples/hello_vector/hello_vector.c` -- add assembly here (in `__asm__` blocks) for simulation
- `$ROOTDIR/sim/renode/src/Infrastructure/src/Emulator/Cores/tlib/arch/riscv/translate.c` -- where to add or modify opcode behavior
- `$ROOTDIR/sim/renode/src/Infrastructure/src/Emulator/Cores/tlib/arch/riscv/instmap.h` -- where to add numerical opcode definitions
### Add New Vector OpCode and Simulate
To add a new vector opcode, we will be modifying the following toolchain files:
- `$ROOTDIR/toolchain/riscv-binutils/include/opcode/riscv-opc.h`
- `$ROOTDIR/toolchain/riscv-binutils/opcodes/riscv-opc.c`
And also these files for defining the behavior in simulation:
- `$ROOTDIR/sim/renode/src/Infrastructure/src/Emulator/Cores/tlib/arch/riscv/translate.c`
- `$ROOTDIR/sim/renode/src/Infrastructure/src/Emulator/Cores/tlib/arch/riscv/instmap.h`
#### Step 1: Obtain the RiscV OpCode Repo
Clone the [RiscV OpCode Support Repo](https://github.com/riscv/riscv-opcodes)
#### Step 2: Add Vector Opcode definition to `opcodes-rvv` file:
`cd` into the `riscv-opcodes` folder, add the instruction to the `opcodes-rvv` file:
Example for `vrgatherei16.vv`, add the following line to `opcodes-rvv`:
```
vrgatherei16.vv 31..26=0x0e vm vs2 vs1 14..12=0x0 vd 6..0=0x57
```
(Note the function6 opcode `0x0e` was determined in this case with the [RiscV Vector OpCode Table](https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc));
#### Step 3: Utilize the contained python script `parse_opcodes` to generate `MASK` and `MATCH` codes for the new instruction
Use the `parse_opcodes` script within the `riscv-opcodes` repo to create `MATCH`
and `MASK` macros for the new operation.
Example:
```
python3 parse_opcodes opcodes-rvv > temp_opc.h
```
This will yield these lines within the output `temp_opc.h` file:
```
#define MATCH_VRGATHEREI16VV 0x38000057
#define MASK_VRGATHEREI16VV 0xfc00707f
```
#### Step 4: Add these two lines to the `riscv-opc.h` file located at:
Place the above two macros in a reasonable location within the `riscv-opc.h`
file.
This file is located:
- `$ROOTDIR/toolchain/riscv-binutils/include/opcode/riscv-opc.h`
#### Step 5: Add an entry to the RVV Opcode Struct in the `riscv-opc.c` file:
Take care in spelling in the assembly instruction name (in this example `vrgatherei16.vv`)
as well as spelling in the mask and match names (in this example `MATCH_VRGATHEREI16VV` and `MASK_VRGATHEREI16VV`):
```
{"vrgatherei16.vv",0, INSN_CLASS_V, "Vd,Vt,VsVm", MATCH_VRGATHEREI16VV, MASK_VRGATHEREI16VV, match_vd_neq_vs1_neq_vs2_neq_vm, 0},
```
#### Step 6: Rebuild Relevant RiscV Toolchain
Will need to rebuild the gnu-toolchain to implement the changes:
```
m clean
m tools
```
#### Step 7: Add new opcode in `instmap.h`'s enum
Now we need to define the behavior in the Renode simulator.
For Renode to interpret this new opcode, create a new entry in `instmap.h`:
Note to use the `function6` opc in hex:
```
OPC_RISC_VXOR_IVV = OPC_RISC_V_ARITH_IVV | (0xB << 26),
OPC_RISC_VRGATHER_IVV = OPC_RISC_V_ARITH_IVV | (0xC << 26),
OPC_RISC_VRGATHEREI16_IVV = OPC_RISC_V_ARITH_IVV | (0xE << 26),
```
See the [RiscV Vector OpCode Table](https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc) for guidance.
#### Step 8: Define behavior within the `switch...case` within the `translate.c` file
For example, we can provide means for testing this function with 8 bit elements
of a 512 bit register length (i.e. SEW=8, VLEN=512, LMUL=1)
```
case OPC_RISC_VRGATHEREI16_IVV:
tlib_printf(LOG_LEVEL_ERROR, "VRGATHEREI16_IVV");
for (int i = 0; i < 64; ++i) {
vreg.e8[vd][i] = (vreg.e8[vs1][i] > VLMAX)? 0 : vreg.e8[vs2][vreg.e8[vs1][i]];
}
break;
```
`translate.c` file is located:
- `$ROOTDIR/sim/renode/src/Infrastructure/src/Emulator/Cores/tlib/arch/riscv/translate.c`
#### Step 9: Rebuild Renode
```
m renode_clean
m renode
```
Note: Care to look out for errors or warnings which may halt compilation (our make
will halt compilation if there are any unused values for example).
#### Step 10: Add opcode test to `hello_vector.c`
```
LOG_INFO("trying vrgatherei16");
__asm__ volatile("vrgatherei16.vv v0, v1, v2");
```
#### Step 11: Build OpenTitan HelloVector Demo
```
m shodan_test_sw_bootrom
m shodan_test_sw_hellovector
```
#### Step 12: Run Renode Script
```
renode -e "i @sim/config/shodan_hellovector.resc; start"
```
#### Quicklinks Specific for Creating/Defining new OpCodes:
- [RiscV OpCode Support Repo](https://github.com/riscv/riscv-opcodes) -- tools for adding new instructions and creating new opcodes
Toolchain Side:
- `$ROOTDIR/toolchain/riscv-binutils/include/opcode/riscv-opc.h` -- where to add new opcode definitions
- `$ROOTDIR/toolchain/riscv-binutils/opcodes/riscv-opc.c`-- gnu riscv-opcode struct definitions (also needs modification)
Renode Simulation Side:
- `$ROOTDIR/sim/renode/src/Infrastructure/src/Emulator/Cores/tlib/arch/riscv/translate.c` -- where to add or modify renode opcode sim behavior
- `$ROOTDIR/sim/renode/src/Infrastructure/src/Emulator/Cores/tlib/arch/riscv/instmap.h` -- where to add new opcodes for renode to simulate
## General References
- [RiscV v0.9 Vector Extension Draft](https://github.com/riscv/riscv-v-spec/releases/tag/0.9)
- [RiscV Vector OpCode Table](https://github.com/riscv/riscv-v-spec/blob/master/inst-table.adoc)