This assignment is already implemented in the current version of Vortex. If you would like to work on a version that does not already contain prefetch logic, checkout commit 456f1df. A Vagrant VM with this version is located here and instructions to set up this VM are located here.
In this assignment, you will learn how to add a new instruction by using intrinsics and extending the pipeline. You will add a software prefetch instruction. You will first add the new instruction to Sim-X, a functional simulator of Vortex, before implementing it in the pipeline using RTL programming. Since software prefetch is an instruction that is not currently supported by the RISC-V toolchain, you will first have to insert the new instruction using assembly code.
You will begin by inserting the instruction in /Vortex/runtime/include/vx_intrinsics.h using assembly code.
-
0x6bis the opcode for instructions not defined by RISC-V. -
5is the identifier for the instruction. Identifiers 0-4 have already been used. The purpose of an instruction identifier is to distinguish software prefetch from the tmc, wspawn, split, join and bar instructions (which all use the same opcode). -
The software prefetch instruction takes only one argument: the load address.
Following the pattern of how the other Vortex RISC-V instructions are implemented, decode the opcode for software prefetch in /Vortex/sim/simX/decode.cpp.
For now, all we want to do is print the prefetch address when the instruction is executed in /Vortex/sim/simX/execute.cpp. We are not worried about the details of the implementation yet since our goal for now is to simply understand how a new instruction is added.
rsdatacontains the prefetch address. Since the prefetch intrinsic uses only one register for the address, we usersdata[0]to get the prefetch address and we print the address in the case statement.
As mentioned before, the opcode for Vortex RISC-V instructions is 0x6b and is defined in /Vortex/hw/rtl/VX_define.vh. The instruction identifier 5 for software prefetch has also been defined here.
In /Vortex/hw/rtl/VX_decode.sv, you will need to add a case for the identifier 5.
- Software prefetch executes in the LSU
- The immediate field which contains the address needs to be sign extended to 32 bits
- Software prefetch is designed to mimic a load instruction while ignoring the load responce. Hence, the rd register is not used.
You need to add a tag to /Vortex/hw/rtl/interfaces/VX_lsu_req_if.sv to distinguish a software prefetch from a load.
You will need to modify the value of this tag in Vortex/hw/rtl/VX_instr_demux.sv since you want to set the tag before the instruction reaches the LSU unit.
- the prefetch tag has to replicate the decode logic of a load instruction.
- For a load, the
req_wbsignal is 0. - For a load, the most significant bit of op_type is 0.
We mimic the behavior of a load my modifying the req_wb signal in /Vortex/hw/rtl/VX_lsu_unit.sv. We make the cache response invalid if it comes from a prefetch request.
-
A test to check the working of the fence instruction has already been developed in /Vortex/tests/regression/fence.
-
Duplicate this folder, rename it to prefetch, and modify the PROJECT=fence line inside the Makefile to PROJECT=prefetch
-
Inside the for loop in kernel.c, add the following line:
for (uint32_t i = 0; i < count ; ++i) { ... vx_prefetch(src0_ptr + offset + i); }
-
Compile the modified prefetch kernel. You should see a new opcode in the kernel body of kernel.dump
800000b0: 0007506b 0x7506b -
0x7506bis the opcode for prefetch. Prefetch can be distinguished from the other instructions since it doesn't have an assembly syntax.
./ci/blackbox.sh --driver=simx --cores=4 --app=prefetch./ci/blackbox.sh --driver=rtlsim --cores=4 --app=prefetch --debug