├── README.md ├── bram.sv ├── bram_altsyncram.sv ├── clarvi.sv ├── clarvi_avalon.sv ├── clarvi_debug.sv ├── clarvi_hw.tcl ├── info for developers.md ├── riscv.svh ├── sim.sv ├── sim.tcl ├── software ├── Makefile ├── link.ld ├── readme.md ├── src │ ├── init.s │ └── main.c └── txt2hex.py ├── test-compile.tcl ├── test.tcl ├── tests-all.sh ├── tests-all.tcl └── tests ├── Makefile ├── env ├── b │ └── riscv_test.h └── encoding.h ├── link.ld └── txt2hex.py /README.md: -------------------------------------------------------------------------------- 1 | # Clarvi 2 | 3 | A simple RISC-V implementation in SystemVerilog. Intended to be clear and understandable for teaching purposes, while maintaining good performance. 4 | 5 | This is an RV32I core. It provides a minimum implementation of the v1.9 RISC-V privileged specification, including full support for interrupts and exceptions. 6 | Only machine mode is implemented, and there is only partial support for catching invalid instructions. 7 | There is also support for the full v2.1 user-level specification. 8 | 9 | It passes all RV32I user-level tests, and the relevant RV32I machine-mode tests (but not those which assume support for user mode, virtual memory etc). 10 | 11 | There are minor deviations from the privileged specification: 12 | - On a branch to an invalid or misaligned address, an exception is only raised on the subsequent fetch, so any side effects of the branch (e.g. for JALR) are maintained. 13 | The specification is ambiguous on this matter, which causes the `ma_fetch` test to fail. 14 | - Misaligned loads and stores are not supported. 15 | - The `timecmp` register is implemented as a CSR rather than being memory mapped - its address can be found in `riscv.svh`. 16 | - The `dscratch` register is adopted as means of producing debug output. 17 | 18 | It is possible to disable machine mode by undefining `MACHINE_MODE`. This removes support for all privileged instructions, interrupts, exceptions and handling of illegal instructions, but provides a reasonable frequency increase. 19 | 20 | The processor has a 6-stage pipeline, which is similar to the classic RISC pipeline, with a few differences: 21 | - The intruction fetch is 2-stage, to accomodate on-chip memory with a fixed 1 cycle latency 22 | - Loads and Stores are initiated in the Execute stage, while load results are aligned in the Memory Align stage 23 | - Jumps are computed in the Execute stage, meaning a 3-cycle penalty for any taken branch. 24 | 25 | 26 | ## Memory Requirements 27 | 28 | The core has a generic memory interface, with separate instruction and data ports. These could be connected to the same or different memories. Be sure to configure the `ADDR_WIDTH` parameters appropriately for the amount of memory attached - accesses beyond this address width will raise access faults. Note that this is the **word** address width. All memory bus addresses are word not byte addresses. 29 | 30 | The included `clarvi_avalon` component is a wrapper which exposes an Altera Avalon MM interface. The core supports a main memory with variable latency, allowing for both the `wait` and `readdatavalid` signals as specified by the Avalon MM interface. 31 | 32 | To attach instruction memory with a latency longer than 1 cycle, a wrapper component should be created which uses the core's `wait` signal to stall it when memory access will have a latency of more than 1 cycle. The `wait` signal is expected to behave like the Avalon MM `waitrequest` signal. 33 | 34 | 35 | ## Performance 36 | 37 | On a Cyclone V board using on-chip BRAM as memory, 100 to 150Mhz can be achieved depending on the amount of RAM and whether machine mode is enabled. 38 | 39 | CPI is as follows: 40 | 41 | - 4: Branch taken 42 | - 2: Load followed by dependent instruction 43 | - 1: All other instructions 44 | 45 | Average CPI is therefore roughly 1.5, depending on how branch-heavy the code is. 46 | 47 | 48 | ## What's in the box 49 | 50 | This repository includes the following: 51 | 52 | ### Main source files 53 | 54 | - The CPU source code is in `clarvi.sv`. It includes `riscv.svh` which contains various struct, enumeration and constant definitions. 55 | - Testbench code is in `sim.sv`. It relies upon the included `bram` testbench component which provides a mockup of a dual-port on-chip memory. 56 | 57 | ### Software and Tests 58 | 59 | A makefile, linker script and `init` program is provided. Software is built into a `.mem.txt` file supported by ModelSim, and a `.mem.hex` file which is an Intel HEX format memory image, supported by Altera Quartus/Qsys. 60 | 61 | To simulate the processor in ModelSim, run the command `do sim.tcl `. 62 | 63 | If you want to see a full instruction trace, run `do sim.tcl TRACE`. 64 | 65 | The RISC-V test suite can be run by building the tests with the makefile provided in the tests directory. 66 | You may have to correct the path to your `riscv-tests` repository location in the makefile. 67 | 68 | Also included is a 'b' (bare) test environment, needed to run the tests with machine mode disabled, and a custom linker script. 69 | 70 | There are scripts provided to run the tests using ModelSim: 71 | - `./tests-all.sh` runs all tests 72 | - `./tests-all.sh ` runs all tests with the given environment. For instance `./tests-all.sh b` runs all tests configured for machine mode disabled 73 | - Inside modelsim, an individual test can be run with the command `do test.tcl `. 74 | 75 | The tests may also be run in hardware. To help identify when a test ends and its result, the test result register (x28) is exposed on a debug port. 76 | -------------------------------------------------------------------------------- /bram.sv: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright (c) 2016, Robert Eady 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | *******************************************************************************/ 25 | 26 | 27 | `timescale 1ns/10ps 28 | 29 | module dual_port_bram #( 30 | parameter INIT_FILE = "mem.hex", 31 | parameter ADDRESS_WIDTH = 12, 32 | parameter BYTE_WIDTH = 8, 33 | parameter BYTES_PER_WORD = 4 34 | )( 35 | input logic clock, 36 | input logic reset, 37 | 38 | input logic [ADDRESS_WIDTH-1:0] avs_a_address, 39 | input logic [BYTES_PER_WORD-1:0] avs_a_byteenable, 40 | input logic avs_a_read, 41 | output logic [BYTES_PER_WORD-1:0][BYTE_WIDTH-1:0] avs_a_readdata, 42 | input logic avs_a_write, 43 | input logic [BYTES_PER_WORD-1:0][BYTE_WIDTH-1:0] avs_a_writedata, 44 | 45 | input logic [ADDRESS_WIDTH-1:0] avs_b_address, 46 | input logic [BYTES_PER_WORD-1:0] avs_b_byteenable, 47 | input logic avs_b_read, 48 | output logic [BYTES_PER_WORD-1:0][BYTE_WIDTH-1:0] avs_b_readdata, 49 | input logic avs_b_write, 50 | input logic [BYTES_PER_WORD-1:0][BYTE_WIDTH-1:0] avs_b_writedata 51 | ); 52 | 53 | // model the RAM with an array of 2D arrays, each representing one word 54 | logic [BYTES_PER_WORD-1:0][BYTE_WIDTH-1:0] memory [1 << ADDRESS_WIDTH]; 55 | initial $readmemh(INIT_FILE, memory); 56 | 57 | // port A 58 | always_ff @(posedge clock) begin 59 | if (avs_a_write) 60 | for (int i = 0; i < BYTES_PER_WORD; i++) 61 | if (avs_a_byteenable[i]) 62 | memory[avs_a_address][i] <= avs_a_writedata[i]; 63 | if (avs_a_read) 64 | avs_a_readdata <= memory[avs_a_address]; 65 | end 66 | 67 | // port B 68 | always_ff @(posedge clock) begin 69 | if (avs_b_write) 70 | for (int i = 0; i < BYTES_PER_WORD; i++) 71 | if (avs_b_byteenable[i]) 72 | memory[avs_b_address][i] <= avs_b_writedata[i]; 73 | if (avs_b_read) 74 | avs_b_readdata <= memory[avs_b_address]; 75 | end 76 | 77 | endmodule 78 | -------------------------------------------------------------------------------- /bram_altsyncram.sv: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright (c) 2016, Robert Eady 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | *******************************************************************************/ 25 | 26 | 27 | `timescale 1ns/10ps 28 | 29 | module dual_port_bram_altsyncram #( 30 | parameter INIT_FILE = "mem.hex", 31 | parameter ADDRESS_WIDTH = 12, 32 | parameter BYTE_WIDTH = 8, 33 | parameter BYTES_PER_WORD = 4 34 | )( 35 | input logic clock, 36 | input logic reset, 37 | 38 | input logic [ADDRESS_WIDTH-1:0] avs_a_address, 39 | input logic [BYTES_PER_WORD-1:0] avs_a_byteenable, 40 | input logic avs_a_read, 41 | output logic [BYTES_PER_WORD-1:0][BYTE_WIDTH-1:0] avs_a_readdata, 42 | input logic avs_a_write, 43 | input logic [BYTES_PER_WORD-1:0][BYTE_WIDTH-1:0] avs_a_writedata, 44 | 45 | input logic [ADDRESS_WIDTH-1:0] avs_b_address, 46 | input logic [BYTES_PER_WORD-1:0] avs_b_byteenable, 47 | input logic avs_b_read, 48 | output logic [BYTES_PER_WORD-1:0][BYTE_WIDTH-1:0] avs_b_readdata, 49 | input logic avs_b_write, 50 | input logic [BYTES_PER_WORD-1:0][BYTE_WIDTH-1:0] avs_b_writedata 51 | ); 52 | 53 | altsyncram #( 54 | .operation_mode ("BIDIR_DUAL_PORT"), 55 | .width_a (BYTE_WIDTH * BYTES_PER_WORD), 56 | .width_b (BYTE_WIDTH * BYTES_PER_WORD), 57 | .widthad_a (ADDRESS_WIDTH), 58 | .widthad_b (ADDRESS_WIDTH), 59 | .outdata_reg_a ("UNREGISTERED"), 60 | .outdata_reg_b ("UNREGISTERED"), 61 | .width_byteena_a (BYTES_PER_WORD), 62 | .width_byteena_b (BYTES_PER_WORD), 63 | .byte_size (BYTE_WIDTH), 64 | .init_file (INIT_FILE), 65 | .address_reg_b ("CLOCK0"), 66 | .byteena_reg_b ("CLOCK0"), 67 | .indata_reg_b ("CLOCK0"), 68 | .rdcontrol_reg_b ("CLOCK0"), 69 | .wrcontrol_wraddress_reg_b ("CLOCK0"), 70 | .intended_device_family ("Cyclone V") 71 | ) altsyncram_component ( 72 | .clock0 (clock), 73 | .address_a (avs_a_address), 74 | .address_b (avs_b_address), 75 | .rden_a (avs_a_read), 76 | .rden_b (avs_b_read), 77 | .q_a (avs_a_readdata), 78 | .q_b (avs_b_readdata), 79 | .byteena_a (avs_a_byteenable), 80 | .byteena_b (avs_b_byteenable), 81 | .wren_a (avs_a_write), 82 | .wren_b (avs_b_write), 83 | .data_a (avs_a_writedata), 84 | .data_b (avs_b_writedata), 85 | .aclr0 (1'b0), 86 | .aclr1 (1'b0), 87 | .addressstall_a (1'b0), 88 | .addressstall_b (1'b0), 89 | .clock1 (1'b1), 90 | .clocken0 (1'b1), 91 | .clocken1 (1'b1), 92 | .clocken2 (1'b1), 93 | .clocken3 (1'b1), 94 | .eccstatus () 95 | ); 96 | 97 | endmodule 98 | -------------------------------------------------------------------------------- /clarvi.sv: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright (c) 2016, Robert Eady 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | *******************************************************************************/ 25 | 26 | /******************************************************************************* 27 | 28 | The processor has a 6 stage pipeline, with pipeline registers between stages. 29 | Instruction fetch takes two cycles. 30 | 31 | Note that memory accesses are submitted in the execute stage and loaded values 32 | aligned in the memory align stage. Branches are performed in the execute stage. 33 | 34 | There are forwarding paths from the output of the execute, memory align and 35 | write back stages into the end of the decode stage. 36 | 37 | IF/DE DE/EX EX/MA MA/WB 38 | Instruction Fetch --> Decode --> Execute --> Memory Align --> Write Back 39 | ^-----------/---------------/---------------/ 40 | 41 | List of abbreviations/conventions: 42 | 43 | instr: instruction if: instruction fetch 44 | pc: program counter de: decode 45 | imm: immediate value ex: execute 46 | rd: destination register alu: arithmetic logic unit 47 | rs1: source register 1 wb: write back 48 | rs2: source register 2 49 | avm: avalon master (memory interface) 50 | inr: interrupt receiver 51 | 52 | Pipeline register values are prefixed according to the stages they fall between, 53 | e.g. de_ex_instr is a DE/EX pipeline register storing the decoded instruction. 54 | 55 | Combination signals are prefixed with the stage they are used in, 56 | e.g. ex_result is output of the ALU in the execute stage. 57 | 58 | The core only supports single cycle latency instruction memory. 59 | Main memory can have arbitrary (>= 1 cycle) latency. 60 | 61 | *******************************************************************************/ 62 | 63 | `include "riscv.svh" 64 | 65 | `define MACHINE_MODE // enable support for machine mode instructions, interrupts and exceptions 66 | `define DEBUG // enable debug outputs 67 | `ifdef MODEL_TECH 68 | `define SIMULATION // enable simulation features 69 | // `define TRACE // enable full instruction tracing in simulation. 70 | `endif 71 | 72 | `timescale 1ns/10ps 73 | 74 | module clarvi #( 75 | parameter DATA_ADDR_WIDTH = 14, 76 | parameter INSTR_ADDR_WIDTH = 14, 77 | parameter INITIAL_PC = 0, 78 | parameter DEFAULT_TRAP_VECTOR = 0 79 | )( 80 | input logic clock, 81 | input logic reset, 82 | 83 | // data memory port (read/write) 84 | output logic [DATA_ADDR_WIDTH-1:0] main_address, 85 | output logic [3:0] main_byte_enable, 86 | output logic main_read_enable, 87 | input logic [31:0] main_read_data, 88 | input logic main_read_data_valid, 89 | output logic main_write_enable, 90 | output logic [31:0] main_write_data, 91 | input logic main_wait, 92 | 93 | // instruction memory port (read-only) 94 | output logic [INSTR_ADDR_WIDTH-1:0] instr_address, 95 | output logic instr_read_enable, 96 | input logic [31:0] instr_read_data, 97 | input logic instr_wait, 98 | 99 | // external interrupt signal, active high 100 | input logic inr_irq, 101 | 102 | // debug ports 103 | output logic [31:0] debug_register28, 104 | output logic [31:0] debug_scratch, 105 | output logic [31:0] debug_pc 106 | ); 107 | 108 | localparam TRACE = 1; 109 | 110 | logic [31:0] registers [1:31]; // register file - register zero is hardcoded to 0 when fetching 111 | 112 | logic [63:0] instret = '0; // number of instructions retired (completed) 113 | logic [63:0] cycles = '0; // cycle counter 114 | always_ff @(posedge clock) cycles <= reset ? 0 : cycles + 1; 115 | 116 | // Some CSRs (Control and Status Registers) 117 | mstatus_t mstatus = '0; // status 118 | mie_t mie = '0; // interrupts enabled 119 | mip_t mip; // interrupts pending 120 | logic [31:0] dscratch; // debug scratch register, used for debug output 121 | logic [31:0] mtvec = DEFAULT_TRAP_VECTOR; // trap handler address 122 | 123 | // traps caused by the instruction being fetched or executed 124 | logic interrupt, if_exception, ex_exception, ex_mem_address_error; 125 | 126 | logic main_read_pending = 0; //whether we have sent a memory read which has not yet been replied to 127 | 128 | // buffer to hold the last valid main memory read response: valid is set iff this data has not yet been used by MA 129 | logic[31:0] main_read_data_buffer; 130 | logic main_read_data_buffer_valid = 0; 131 | 132 | // Stage invalidation flags 133 | logic if_invalid = 1; 134 | logic if_de_invalid = 1; 135 | logic de_ex_invalid = 1; 136 | logic ex_ma_invalid = 1; 137 | logic ma_wb_invalid = 1; 138 | 139 | logic stall_for_memory_wait; // stall everything when main memory or instruction memory isn't ready for load/store/IF 140 | logic stall_for_load_dep; // stall IF, DE and repeat EX for a load followed by dependent instruction 141 | logic stall_for_memory_pending; //stall IF, DE and EX when a read request is late being answered 142 | 143 | // distribute stall signals to each stage: 144 | logic stall_if; 145 | logic stall_de; 146 | logic stall_ex; 147 | logic stall_ma; 148 | logic stall_wb; 149 | 150 | always_comb begin 151 | stall_if = stall_for_memory_wait || stall_for_memory_pending || stall_for_load_dep; 152 | stall_de = stall_for_memory_wait || stall_for_memory_pending || stall_for_load_dep; 153 | stall_ex = stall_for_memory_wait || stall_for_memory_pending; 154 | stall_ma = stall_for_memory_wait; 155 | stall_wb = stall_for_memory_wait; 156 | end 157 | 158 | // === Instruction Fetch =================================================== 159 | 160 | logic [31:0] pc = INITIAL_PC; 161 | logic [31:0] if_pc, if_de_pc, if_de_instr, instr_read_data_buffer; 162 | logic if_stall_on_prev; 163 | 164 | always_comb begin 165 | // PC is byte-addressed but our instruction memory is word-addressed 166 | instr_address = pc[INSTR_ADDR_WIDTH+1:2]; 167 | // read the next instruction on every cycle 168 | instr_read_enable = '1; 169 | end 170 | 171 | always_ff @(posedge clock) begin 172 | // buffer the last instruction read before a stall. 173 | if_stall_on_prev <= stall_if; 174 | if (!if_stall_on_prev) 175 | instr_read_data_buffer <= instr_read_data; 176 | 177 | if (!stall_if) begin 178 | // if there was a stall on the last cycle, we read from the instruction buffer not the bus. 179 | // this allows the PC to 'catch up' on the next cycle. 180 | if_de_instr <= if_stall_on_prev ? instr_read_data_buffer : instr_read_data; 181 | if_pc <= pc; 182 | if_de_pc <= if_pc; 183 | end 184 | end 185 | 186 | // === Decode ============================================================== 187 | 188 | logic [31:0] de_rs1_fetched, de_rs2_fetched; 189 | logic [31:0] de_rs1_forward, de_rs2_forward; // forwarding logic appears later 190 | instr_t de_instr, de_ex_instr; 191 | logic [31:0] de_ex_rs1_value, de_ex_rs2_value; 192 | 193 | always_comb begin 194 | de_instr = decode_instr(if_de_instr, if_de_pc); 195 | 196 | // register fetch 197 | de_rs1_fetched = fetch(de_instr.rs1); 198 | de_rs2_fetched = fetch(de_instr.rs2); 199 | 200 | // if the next instruction is a load and this instruction is dependent on its result, 201 | // stall for one cycle since the result won't be ready yet - unless the load raises an exception. 202 | stall_for_load_dep = !if_de_invalid && !de_ex_invalid && de_ex_instr.memory_read && !ex_mem_address_error 203 | && (de_instr.rs1 == de_ex_instr.rd && de_instr.rs1_used 204 | || de_instr.rs2 == de_ex_instr.rd && de_instr.rs2_used); 205 | 206 | // ignore waitrequest unless we are actually reading/writing memory, 207 | // because the bus is allowed to hold waitrequest high while idle. 208 | stall_for_memory_wait = (instr_wait && instr_read_enable) 209 | || (main_wait && (main_read_enable || main_write_enable)); 210 | 211 | stall_for_memory_pending = main_read_pending && !main_read_data_buffer_valid && !main_read_data_valid; 212 | 213 | end 214 | 215 | always_ff @(posedge clock) begin 216 | if (!stall_de) begin 217 | de_ex_instr <= de_instr; 218 | // if the value isn't forwarded, these take the register fetch results. 219 | de_ex_rs1_value <= de_rs1_forward; 220 | de_ex_rs2_value <= de_rs2_forward; 221 | end 222 | end 223 | 224 | // === Execute ============================================================= 225 | 226 | instr_t ex_ma_instr; 227 | logic [31:0] ex_mem_address, ex_result, ex_ma_result; 228 | logic [1:0] ex_word_offset, ex_ma_word_offset; 229 | logic [29-DATA_ADDR_WIDTH:0] ex_address_high_bits; // beyond our address width so should be 0 230 | 231 | always_comb begin 232 | ex_result = execute(de_ex_instr, de_ex_rs1_value, de_ex_rs2_value); 233 | 234 | // --- Memory Access --------------------------------------------------- 235 | 236 | main_read_enable = !de_ex_invalid && !interrupt && !ex_mem_address_error && de_ex_instr.memory_read && !stall_for_memory_pending; 237 | main_write_enable = !de_ex_invalid && !interrupt && !ex_mem_address_error && de_ex_instr.memory_write && !stall_for_memory_pending; 238 | 239 | // do address calculation 240 | ex_mem_address = de_ex_rs1_value + de_ex_instr.immediate; 241 | // our memory is word addressed, so cut off the bottom two bits (this becomes the word offset), 242 | // and the higher bits beyond our address range which should be 0. 243 | {ex_address_high_bits, main_address, ex_word_offset} = ex_mem_address; 244 | 245 | // set byte_enable mask according to whether we are loading/storing a word, half word or byte. 246 | main_byte_enable = compute_byte_enable(de_ex_instr.memory_width, ex_word_offset); 247 | 248 | // shift the store value into the correct position in the 32-bit word 249 | main_write_data = de_ex_rs2_value << ex_word_offset*8; 250 | end 251 | 252 | always_ff @(posedge clock) 253 | if (reset) begin 254 | main_read_pending <= 0; 255 | end else begin 256 | if (!stall_ex) begin 257 | ex_ma_instr <= de_ex_instr; 258 | ex_ma_result <= ex_result; 259 | ex_ma_word_offset <= ex_word_offset; 260 | main_read_pending <= main_read_enable; 261 | end 262 | end 263 | 264 | // === Branching or Reset ================================================== 265 | 266 | logic ex_branch_taken; 267 | logic [31:0] ex_branch_target, ex_next_pc; 268 | 269 | always_comb begin 270 | ex_branch_taken = !de_ex_invalid && is_branch_taken(de_ex_instr.op, de_ex_rs1_value, de_ex_rs2_value); 271 | ex_branch_target = target_pc(de_ex_instr, de_ex_rs1_value); 272 | ex_next_pc = ex_branch_taken ? ex_branch_target : pc + 4; //note that pc + 4 is actually a prediction for 3 instructions' time 273 | end 274 | 275 | always_ff @(posedge clock) 276 | if (reset) begin 277 | pc <= INITIAL_PC; 278 | if_invalid <= 1; 279 | if_de_invalid <= 1; 280 | de_ex_invalid <= 1; 281 | ex_ma_invalid <= 1; 282 | ma_wb_invalid <= 1; 283 | end else begin 284 | // logic for stage invalidation upon taking a branch or stalling 285 | // don't change the registers if the corresponding stage is stalled 286 | 287 | if (!stall_if) begin 288 | // if a trap is taken, go to the handler instead 289 | pc <= (if_exception || ex_exception) ? mtvec : ex_next_pc; 290 | 291 | // invalidate on any exception, interrupt or branch. 292 | if_invalid <= interrupt || ex_exception || if_exception || ex_branch_taken; 293 | 294 | // invalidate on an EX exception, interrupt or branch. 295 | // an IF exception can only happen after a branch so this stage would already be invalid. 296 | if_de_invalid <= if_invalid || interrupt || ex_exception || ex_branch_taken; 297 | end 298 | 299 | // invalidate in an EX exception, interrupt, branch or load dependency stall. 300 | // an IF exception can only happen after a branch so this stage would already be invalid. 301 | if (!stall_de) de_ex_invalid <= if_de_invalid || interrupt || ex_exception || ex_branch_taken; 302 | else if (!stall_ex) de_ex_invalid <= 1; // we only stall de but not ex on load dep, so insert a bubble 303 | 304 | // invalidate on an interrupt or any EX exception that could be caused by an instruction that writes back. 305 | // i.e. an exception on a load or an invalid instruction. 306 | if (!stall_ex) ex_ma_invalid <= de_ex_invalid || interrupt || ex_mem_address_error && de_ex_instr.memory_read || de_ex_instr.op == INVALID; 307 | // we only stall ex and not ma when memory pending, so replay (no bubble here) 308 | 309 | // if ma received invalid data, insert a bubble into wb 310 | if (!stall_ma) ma_wb_invalid <= ex_ma_invalid || stall_for_memory_pending; 311 | end 312 | 313 | // === Memory Align ======================================================== 314 | 315 | instr_t ma_wb_instr; 316 | logic[31:0] ma_result, ma_load_value, ma_wb_value; 317 | 318 | always_comb begin 319 | // align the loaded value: if we stalled on last cycle then take buffered data instead 320 | ma_load_value = load_shift_mask_extend(ex_ma_instr.memory_width, 321 | ex_ma_instr.memory_read_unsigned, 322 | main_read_data_valid ? main_read_data : main_read_data_buffer, 323 | ex_ma_word_offset); 324 | // if this isn't a load instruction, pass through the ALU result instead 325 | ma_result = ex_ma_instr.memory_read ? ma_load_value : ex_ma_result; 326 | end 327 | 328 | always_ff @(posedge clock) 329 | if (reset) begin 330 | main_read_data_buffer_valid <= 0; 331 | end else begin 332 | if (!stall_ma) begin 333 | ma_wb_instr <= ex_ma_instr; 334 | ma_wb_value <= ma_result; 335 | main_read_data_buffer_valid <= 0; 336 | end else begin 337 | main_read_data_buffer_valid <= main_read_data_buffer_valid || main_read_data_valid; 338 | end 339 | //buffer the last data returned in case of stall 340 | if (main_read_data_valid) begin 341 | main_read_data_buffer <= main_read_data; 342 | end 343 | end 344 | 345 | // === Write Back ========================================================== 346 | 347 | always_ff @(posedge clock) begin 348 | if (!stall_wb && !ma_wb_invalid) begin 349 | if (ma_wb_instr.enable_wb) begin 350 | registers[ma_wb_instr.rd] <= ma_wb_value; 351 | end 352 | instret <= instret + 1; 353 | end 354 | end 355 | 356 | // === Forwarding ========================================================== 357 | 358 | logic could_forward_from_ex, could_forward_from_ma, could_forward_from_wb; 359 | register_t de_rs1, de_rs2; 360 | 361 | always_comb begin 362 | // check if stages are eligible to have their values forwarded 363 | // forward from EX result: instruction must not be a load since result won't be ready until end of MA stage 364 | could_forward_from_ex = !de_ex_invalid && de_ex_instr.enable_wb && !de_ex_instr.memory_read; 365 | could_forward_from_ma = !ex_ma_invalid && ex_ma_instr.enable_wb; 366 | could_forward_from_wb = !ma_wb_invalid && ma_wb_instr.enable_wb; 367 | 368 | // now we also check whether source and destination registers match up 369 | // prioritise forwarding from earlier stages (more recent instructions), 370 | // since these may overwrite values written by later stages (less recent instructions). 371 | if (could_forward_from_ex && de_ex_instr.rd == de_instr.rs1) de_rs1_forward = ex_result; 372 | else if (could_forward_from_ma && ex_ma_instr.rd == de_instr.rs1) de_rs1_forward = ma_result; 373 | else if (could_forward_from_wb && ma_wb_instr.rd == de_instr.rs1) de_rs1_forward = ma_wb_value; 374 | else de_rs1_forward = de_rs1_fetched; 375 | 376 | if (could_forward_from_ex && de_ex_instr.rd == de_instr.rs2) de_rs2_forward = ex_result; 377 | else if (could_forward_from_ma && ex_ma_instr.rd == de_instr.rs2) de_rs2_forward = ma_result; 378 | else if (could_forward_from_wb && ma_wb_instr.rd == de_instr.rs2) de_rs2_forward = ma_wb_value; 379 | else de_rs2_forward = de_rs2_fetched; 380 | end 381 | 382 | 383 | `ifdef MACHINE_MODE 384 | 385 | // === Interrupts and Exceptions =========================================== 386 | 387 | logic [31:0] mcause; // trap cause 388 | logic [31:0] mepc; // return address after handling trap 389 | logic [31:0] mbadaddr; // address of instruction which caused an access/misaligned fault 390 | logic [31:0] mscratch; // machine mode scratch register 391 | logic [63:0] timecmp = '0; // time compare register for triggering timer interrupt 392 | 393 | logic [31:0] trap_pc; // the address of the instruction that caused the trap or suffered the interrupt 394 | logic [31:0] potential_mepc; 395 | 396 | always_comb begin 397 | // wire external interrupt signal to the mip.meip register bit 398 | mip.meip = inr_irq; 399 | // raise a timer interrupt when time (cycle count) is less than timecmp 400 | mip.mtip = cycles >= timecmp; 401 | // interrupt is only raised if appropriate interrupt enable bits are set 402 | interrupt = mstatus.mie && (mip.meip && mie.meie || mip.msip && mie.msie || mip.mtip && mie.mtie); 403 | // instruction fetch fault or misaligned exception 404 | if_exception = pc[31:INSTR_ADDR_WIDTH+2] != '0 || !is_aligned(pc[1:0], W); 405 | // load/store fault or misaligned exception 406 | ex_mem_address_error = ex_address_high_bits != '0 || !is_aligned(ex_word_offset, de_ex_instr.memory_width); 407 | // any exception or trap raised by the currently executing instruction 408 | ex_exception = !de_ex_invalid && (ex_mem_address_error && (de_ex_instr.memory_read || de_ex_instr.memory_write) 409 | || de_ex_instr.op == INVALID || de_ex_instr.op == ECALL || de_ex_instr.op == EBREAK); 410 | 411 | if (if_exception) 412 | trap_pc = pc; 413 | else if (de_ex_invalid) 414 | // if we get an interrupt while the execute stage is invalid, return to the next valid instruction instead. 415 | trap_pc = potential_mepc; 416 | else 417 | trap_pc = de_ex_instr.pc; 418 | end 419 | 420 | always_ff @(posedge clock) begin 421 | // In case an interrupt happens while EX is invalid, we must remember what PC to return to after the handler. 422 | // EX could be invalidated by (a) an interrupt/exception, (b) a branch, or (c) a load dependency. 423 | // We needn't worry about (a) because interrupts will first be disabled in this case. 424 | // So whenever EX is valid, we just remember the branch target if a branch is happening, for case (b), 425 | // or otherwise the PC of the intruction about to be decoded, which would be next up in case (c). 426 | if (!de_ex_invalid) begin 427 | potential_mepc <= ex_branch_taken ? ex_branch_target : if_de_pc; 428 | end 429 | 430 | if (reset) begin 431 | // reset the CSR state for interrupts/exceptions 432 | mtvec <= DEFAULT_TRAP_VECTOR; 433 | mstatus <= '0; 434 | mie <= '0; 435 | end 436 | 437 | if ((!stall_if && if_exception) || (!stall_ex && ex_exception) || interrupt) begin 438 | // Entering a trap handler. Push 0 onto the mstatus interrupts-enabled stack 439 | mstatus.mpie <= mstatus.mie; 440 | mstatus.mie <= '0; 441 | // record the address of the instruction that caused the trap or the instruction that got interrupted 442 | mbadaddr <= trap_pc; 443 | mepc <= trap_pc; 444 | // set the trap cause 445 | mcause <= get_trap_cause(); 446 | end 447 | 448 | if (!stall_ex && !de_ex_invalid && de_ex_instr.op == MRET) begin 449 | // Returning from trap handler. Pop the mstatus interrupts-enabled stack. 450 | mstatus.mie <= mstatus.mpie; 451 | mstatus.mpie <= '1; 452 | end 453 | 454 | // Do CSR write/set/clear operations if we are executing a CSR instruction 455 | if (!stall_ex && !de_ex_invalid && !interrupt) 456 | // CSR operations can't cause a trap because they decode into INVALID instead 457 | execute_csr(de_ex_instr, de_ex_rs1_value); 458 | end 459 | 460 | `else 461 | // if machine mode is disabled, there are never any interrupts or exceptions. 462 | always_comb begin 463 | interrupt = '0; 464 | if_exception = '0; 465 | ex_mem_address_error = '0; 466 | ex_exception = '0; 467 | end 468 | `endif 469 | 470 | 471 | // === Decode functions ==================================================== 472 | 473 | function automatic logic [31:0] fetch(register_t register); 474 | // register zero is wired to constant 0. 475 | return register == zero ? '0 : registers[register]; 476 | endfunction 477 | 478 | 479 | function automatic instr_t decode_instr(logic [31:0] instr, logic [31:0] pc); 480 | // registers, funct7 and funct3 are in the same place in every instruction type 481 | decode_instr.rd = register_t'(instr`rd); 482 | decode_instr.rs1 = register_t'(instr`rs1); 483 | decode_instr.rs2 = register_t'(instr`rs2); 484 | decode_instr.funct12 = funct12_t'(instr`funct12); 485 | 486 | decode_instr.op = decode_opcode(instr); 487 | 488 | // we check whether a register is used for forwarding purposes -- no need to forward the zero register 489 | decode_instr.rs1_used = decode_instr.rs1 != zero 490 | && instr`opcode != OPC_LUI 491 | && instr`opcode != OPC_AUIPC 492 | && instr`opcode != OPC_JAL 493 | && instr`opcode != OPC_MISC_MEM; 494 | 495 | decode_instr.rs2_used = decode_instr.rs2 != zero 496 | && (instr`opcode == OPC_BRANCH 497 | || instr`opcode == OPC_STORE 498 | || instr`opcode == OPC_OP); 499 | 500 | {decode_instr.immediate_used, decode_instr.immediate} = decode_immediate(instr); 501 | 502 | decode_instr.memory_write = instr`opcode == OPC_STORE; 503 | decode_instr.memory_read = instr`opcode == OPC_LOAD; 504 | decode_instr.memory_read_unsigned = instr[14]; // if memory_read is true, this indicates an unsigned read. 505 | decode_instr.memory_width = mem_width_t'(instr[13:12]); 506 | 507 | // write back for all except s-type instructions and not to register 0 508 | decode_instr.enable_wb = decode_instr.rd != '0 509 | && instr`opcode != OPC_BRANCH 510 | && instr`opcode != OPC_STORE; 511 | 512 | decode_instr.pc = pc; 513 | endfunction 514 | 515 | 516 | function automatic operation_t decode_opcode(logic [31:0] instr); 517 | logic [11:0] funct12 = instr`funct12; 518 | logic [2:0] funct3 = instr`funct3; 519 | logic [4:0] rs1 = instr`rs1; 520 | logic legal_csr_op = validate_csr_op(rs1 != zero, csr_t'(funct12)); 521 | 522 | // ensure the two LSBs are 1 523 | if (instr[1:0] != 2'b11) 524 | return INVALID; 525 | 526 | unique case (instr`opcode) 527 | OPC_LUI: return LUI; 528 | OPC_AUIPC: return AUIPC; 529 | OPC_JAL: return JAL; 530 | OPC_JALR: return JALR; 531 | OPC_BRANCH: 532 | unique case (funct3) 533 | F3_BEQ: return BEQ; 534 | F3_BNE: return BNE; 535 | F3_BLT: return BLT; 536 | F3_BLTU: return BLTU; 537 | F3_BGE: return BGE; 538 | F3_BGEU: return BGEU; 539 | endcase 540 | OPC_LOAD: return LOAD; 541 | OPC_STORE: return STORE; 542 | OPC_OP, OPC_OP_IMM: 543 | unique case (funct3) 544 | // there is no SUBI instruction so also check opcode 545 | F3_ADDSUB: return instr[5] && funct12[10] ? SUB : ADD; 546 | F3_SLT: return SLT; 547 | F3_SLTU: return SLTU; 548 | F3_XOR: return XOR; 549 | F3_OR: return OR; 550 | F3_AND: return AND; 551 | // for immediate shifts we check the 6th bit in the shift amount is 0 552 | // for non-immediate shifts this value must be 0 anyway (it is the end of the funct7 code) 553 | F3_SLL: return funct12[5] ? INVALID : SL; 554 | F3_SR: return funct12[5] ? INVALID : (funct12[10] ? SRA : SRL); 555 | default: return INVALID; 556 | endcase 557 | OPC_MISC_MEM: return funct3[0] ? FENCE_I : FENCE; 558 | OPC_SYSTEM: 559 | unique case (funct3[1:0]) 560 | // when rs1 is zero we are not writing to the CSR. This is used when checking for 561 | // an illegal write to a read-only CSR. 562 | F2_CSRRW: return legal_csr_op ? CSRRW : INVALID; 563 | F2_CSRRS: return legal_csr_op ? CSRRS : INVALID; 564 | F2_CSRRC: return legal_csr_op ? CSRRC : INVALID; 565 | F2_PRIV: 566 | unique case (funct12) 567 | F12_ECALL: return ECALL; 568 | F12_EBREAK: return EBREAK; 569 | `ifdef MACHINE_MODE 570 | F12_MRET: return MRET; 571 | F12_WFI: return WFI; 572 | `endif 573 | default: return INVALID; 574 | endcase 575 | endcase 576 | default: return INVALID; 577 | endcase 578 | endfunction 579 | 580 | function automatic logic [32:0] decode_immediate(logic [31:0] instr); 581 | // returns an extra top bit to indicate whether the immediate is used 582 | // all except u-type instructions have sign-extended immediates. 583 | logic [19:0] sign_ext_20 = {20{instr[31]}}; 584 | logic [11:0] sign_ext_12 = {12{instr[31]}}; 585 | unique case (instr`opcode) 586 | OPC_JALR, OPC_LOAD, OPC_OP_IMM: // i-type 587 | return {1'b1, sign_ext_20, instr[31:20]}; 588 | OPC_STORE: // s-type 589 | return {1'b1, sign_ext_20, instr[31:25], instr[11:7]}; 590 | OPC_BRANCH: // sb-type 591 | return {1'b1, sign_ext_20, instr[7], instr[30:25], instr[11:8], 1'b0}; 592 | OPC_JAL: // uj-type 593 | return {1'b1, sign_ext_12, instr[19:12], instr[20], instr[30:21], 1'b0}; 594 | OPC_LUI, OPC_AUIPC: // u-type 595 | return {1'b1, instr[31:12], 12'b0}; 596 | OPC_SYSTEM: // no ordinary immediate but possibly a csr zimm (5-bit immediate) 597 | return {instr[14], 32'bx}; 598 | default: // no immediate 599 | return {1'b0, 32'bx}; 600 | endcase 601 | endfunction 602 | 603 | function automatic logic validate_csr_op(logic write, csr_t csr); 604 | // first check we aren't writing to a read-only CSR 605 | if (write && csr[11:10] == 2'b11) 606 | return '0; 607 | unique case (csr) 608 | `ifdef MACHINE_MODE 609 | // all the CSRs we support in machine mode... 610 | MVENDORID, MARCHID, MIMPID, MHARTID, MEDELEG, MIDELEG, 611 | MISA, MTVEC, MSTATUS, MIP, MIE, MSCRATCH, MEPC, MCAUSE, MBADADDR, DSCRATCH, 612 | MCYCLE, MTIME, MINSTRET, MCYCLEH, MTIMEH, MINSTRETH, MTIMECMP, MTIMECMPH, 613 | `endif 614 | // in user-mode only timer CSRs can be read 615 | CYCLE, TIME, CYCLEH, TIMEH: 616 | return '1; 617 | default: return '0; 618 | endcase 619 | 620 | endfunction 621 | 622 | 623 | // === Execute functions =================================================== 624 | 625 | function automatic logic [31:0] execute(instr_t instr, logic [31:0] rs1_value, logic [31:0] rs2_value); 626 | 627 | logic [31:0] rs2_value_or_imm = instr.immediate_used ? instr.immediate : rs2_value; 628 | 629 | // implement both logical and arithmetic as an arithmetic right shift, with a 33rd bit set to 0 or 1 as required. 630 | // logic signed [32:0] rshift_operand = {(instr.funct7_bit & rs1_value[31]), rs1_value}; 631 | 632 | // shifts use the lower 5 bits of the intermediate or rs2 value 633 | logic [4:0] shift_amount = rs2_value_or_imm[4:0]; 634 | 635 | unique case (instr.op) 636 | ADD: return rs1_value + rs2_value_or_imm; 637 | SUB: return rs1_value - rs2_value; 638 | SLT: return $signed(rs1_value) < $signed(rs2_value_or_imm); 639 | SLTU: return rs1_value < rs2_value_or_imm; 640 | XOR: return rs1_value ^ rs2_value_or_imm; 641 | OR: return rs1_value | rs2_value_or_imm; 642 | AND: return rs1_value & rs2_value_or_imm; 643 | SL: return rs1_value << shift_amount; 644 | SRL: return rs1_value >> shift_amount; 645 | SRA: return $signed(rs1_value) >>> shift_amount; 646 | LUI: return instr.immediate; 647 | AUIPC: return instr.immediate + instr.pc; 648 | // JAL(R) stores the address of the instruction that followed the jump 649 | JAL, JALR: return instr.pc + 4; 650 | CSRRW, CSRRS, CSRRC: return read_csr(csr_t'(instr.funct12)); 651 | default: return 'x; 652 | endcase 653 | endfunction 654 | 655 | 656 | function automatic logic is_branch_taken(operation_t operation, logic [31:0] rs1_value, logic [31:0] rs2_value); 657 | unique case (operation) 658 | BEQ: return rs1_value == rs2_value; 659 | BNE: return rs1_value != rs2_value; 660 | BGEU: return rs1_value >= rs2_value; 661 | BLTU: return rs1_value < rs2_value; 662 | BGE: return $signed(rs1_value) >= $signed(rs2_value); 663 | BLT: return $signed(rs1_value) < $signed(rs2_value); 664 | // we implement fence.i (sync instruction and data memory) by doing a branch to reload the next instruction 665 | JAL, JALR, FENCE_I, MRET: return '1; 666 | default: return '0; 667 | endcase 668 | endfunction 669 | 670 | 671 | function automatic logic [31:0] target_pc(instr_t instr, logic [31:0] rs1_value); 672 | unique case (instr.op) 673 | JAL, BEQ, BNE, BLT, BGE, BLTU, BGEU: return instr.pc + instr.immediate; 674 | JALR: return (rs1_value + instr.immediate) & 32'h_ff_ff_ff_fe; // set LSB to 0 675 | FENCE_I: return instr.pc + 4; 676 | `ifdef MACHINE_MODE 677 | MRET: return mepc; // return from interrupt handler 678 | `endif 679 | default: return 'x; 680 | endcase 681 | endfunction 682 | 683 | 684 | // === Memory Access functions ============================================= 685 | 686 | function automatic logic [3:0] compute_byte_enable(mem_width_t width, logic [1:0] word_offset); 687 | unique case (width) 688 | B: return 4'b0001 << word_offset; 689 | H: return 4'b0011 << word_offset; 690 | W: return 4'b1111 << word_offset; 691 | default: return 'x; 692 | endcase 693 | endfunction 694 | 695 | function automatic logic [31:0] load_shift_mask_extend(mem_width_t width, logic is_unsigned, logic [31:0] value, logic [1:0] word_offset); 696 | logic [31:0] masked_value = load_mask(width, value, word_offset); 697 | unique case (width) 698 | B: return is_unsigned 699 | ? {24'b0, masked_value[7:0]} 700 | : {{24{masked_value[7]}}, masked_value[7:0]}; 701 | H: return is_unsigned 702 | ? {16'b0, masked_value[15:0]} 703 | : {{16{masked_value[15]}}, masked_value[15:0]}; 704 | W: return value; 705 | default: return 'x; 706 | endcase 707 | endfunction 708 | 709 | function automatic logic [31:0] load_mask(mem_width_t width, logic [31:0] value, logic [1:0] word_offset); 710 | unique case (width) 711 | B: return (value >> word_offset*8) & 32'h_00_00_00_ff; 712 | H: return (value >> word_offset*8) & 32'h_00_00_ff_ff; 713 | default: return 'x; 714 | endcase 715 | endfunction 716 | 717 | 718 | 719 | // === CSR functions ======================================================= 720 | 721 | function automatic logic [31:0] read_csr(csr_t csr_addr); 722 | case (csr_addr) 723 | `ifdef MACHINE_MODE 724 | MVENDORID, MARCHID, MIMPID, MHARTID, MEDELEG, MIDELEG: return '0; 725 | MISA: return 32'b01000000_00000000_00000001_00000000; 726 | MTVEC: return {mtvec[31:2], 2'b0}; // must be aligned on a 4-byte boundary 727 | MSTATUS: return {19'b0, 2'b11, 3'b0, mstatus.mpie, 3'b0, mstatus.mie, 3'b0}; 728 | MIP: return {20'b0, mip.meip, 3'b0, mip.mtip, 3'b0, mip.msip, 3'b0}; 729 | MIE: return {20'b0, mie.meie, 3'b0, mie.mtie, 3'b0, mie.msie, 3'b0}; 730 | MSCRATCH: return mscratch; 731 | MEPC: return {mepc[31:2], 2'b0}; // must be aligned on a 4-byte boundary 732 | MCAUSE: return {mcause[31], 27'b0, mcause[3:0]}; 733 | MBADADDR: return mbadaddr; 734 | DSCRATCH: return dscratch; 735 | MINSTRET: return instret[31:0]; 736 | MINSTRETH: return instret[63:32]; 737 | MTIMECMP: return timecmp[31:0]; 738 | MTIMECMPH: return timecmp[63:32]; 739 | // since we have a fixed frequency, we can say time = cycle count. 740 | MCYCLE, MTIME: return cycles[31:0]; 741 | MCYCLEH, MTIMEH: return cycles[63:32]; 742 | `endif 743 | CYCLE, TIME: return cycles[31:0]; 744 | CYCLEH, TIMEH: return cycles[63:32]; 745 | default: return 'x; 746 | endcase 747 | endfunction 748 | 749 | `ifdef MACHINE_MODE 750 | `define write_csr(operation, value, csr) \ 751 | case (operation) \ 752 | CSRRW: csr <= value; \ 753 | CSRRS: csr <= csr | value; \ 754 | CSRRC: csr <= csr & ~value; \ 755 | endcase 756 | 757 | task automatic execute_csr(instr_t instr, logic [31:0] rs1_value); 758 | // for immediate versions of the CSR instructions, the rs1 field contains a 5-bit immediate. 759 | logic[31:0] value = instr.immediate_used ? instr.rs1 : rs1_value; 760 | logic[11:0] csr_addr = instr.funct12; 761 | case (csr_addr) 762 | MTVEC: `write_csr(instr.op, value, mtvec) 763 | MSTATUS: `write_csr(instr.op, value, mstatus) 764 | MIE: `write_csr(instr.op, value, mie) 765 | MSCRATCH: `write_csr(instr.op, value, mscratch) 766 | MEPC: `write_csr(instr.op, value, mepc) 767 | MCAUSE: `write_csr(instr.op, value, mcause) 768 | MBADADDR: `write_csr(instr.op, value, mbadaddr) 769 | MTIMECMP: `write_csr(instr.op, value, timecmp[31:0]) 770 | MTIMECMPH: `write_csr(instr.op, value, timecmp[63:32]) 771 | DSCRATCH: `write_csr(instr.op, value, dscratch) 772 | endcase 773 | endtask 774 | 775 | 776 | // == Exception functions ======================================================= 777 | 778 | function automatic mcause_t get_trap_cause(); 779 | // we return a struct containing a bit indicating whether to trap, then the cause. 780 | if (mstatus.mie) begin 781 | if (mip.meip && mie.meie) return MEI; 782 | if (mip.msip && mie.msie) return MSI; 783 | if (mip.mtip && mie.mtie) return MTI; 784 | end 785 | 786 | if (pc[31:INSTR_ADDR_WIDTH+2] != '0) 787 | return INSTR_FAULT; 788 | if (!is_aligned(pc[1:0], W)) 789 | return INSTR_MISALIGN; 790 | 791 | unique case (de_ex_instr.op) 792 | INVALID: return ILLEGAL_INSTR; 793 | LOAD: 794 | if (ex_address_high_bits != '0) 795 | return LOAD_FAULT; 796 | else if (!is_aligned(ex_word_offset, de_ex_instr.memory_width)) 797 | return LOAD_MISALIGN; 798 | STORE: 799 | if (ex_address_high_bits != '0) 800 | return STORE_FAULT; 801 | else if (!is_aligned(ex_word_offset, de_ex_instr.memory_width)) 802 | return STORE_MISALIGN; 803 | 804 | ECALL: return ECALL_M; 805 | EBREAK: return BREAK; 806 | default: ; 807 | endcase 808 | 809 | return mcause_t'('x); 810 | endfunction 811 | 812 | 813 | function automatic logic is_aligned(logic [1:0] word_offset, mem_width_t width); 814 | unique case (width) 815 | W: return word_offset == '0; 816 | H: return word_offset[0] == '0; 817 | default: return '1; 818 | endcase 819 | endfunction 820 | `endif 821 | 822 | // === Simluation and Debugging ============================================ 823 | 824 | // debug output from the MA stage 825 | always_comb begin 826 | debug_register28 = registers[28]; 827 | debug_scratch = dscratch; 828 | debug_pc = ex_ma_instr.pc; 829 | end 830 | 831 | `ifdef SIMULATION 832 | `include "clarvi_debug.sv" 833 | `endif 834 | 835 | endmodule 836 | -------------------------------------------------------------------------------- /clarvi_avalon.sv: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright (c) 2016, Robert Eady 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | *******************************************************************************/ 25 | 26 | 27 | // This is an Avalon MM wrapper for clarvi. 28 | 29 | `timescale 1ns/10ps 30 | 31 | module clarvi_avalon #( 32 | parameter DATA_ADDR_WIDTH = 14, 33 | parameter INSTR_ADDR_WIDTH = 14, 34 | parameter INITIAL_PC = 0, 35 | parameter DEFAULT_TRAP_VECTOR = 0 36 | )( 37 | input logic clock, 38 | input logic reset, 39 | 40 | // data memory port (read/write) 41 | output logic [DATA_ADDR_WIDTH-1:0] avm_main_address, 42 | output logic [3:0] avm_main_byteenable, 43 | output logic avm_main_read, 44 | input logic [31:0] avm_main_readdata, 45 | output logic avm_main_write, 46 | output logic [31:0] avm_main_writedata, 47 | input logic avm_main_waitrequest, 48 | input logic avm_main_readdatavalid, 49 | 50 | // instruction memory port (read-only) 51 | output logic [INSTR_ADDR_WIDTH-1:0] avm_instr_address, 52 | output logic avm_instr_read, 53 | input logic [31:0] avm_instr_readdata, 54 | input logic avm_instr_waitrequest, 55 | input logic avm_instr_readdatavalid, 56 | 57 | // external interrupt signal, active high 58 | input logic inr_irq, 59 | 60 | // debug ports 61 | output logic [31:0] debug_register28, 62 | output logic [31:0] debug_scratch, 63 | output logic [31:0] debug_pc 64 | ); 65 | 66 | // We only have readdatavalid signal to allow the use of pipelining with a fixed 1-cycle latency memory. 67 | // Longer or variable latency slaves are not supported! 68 | 69 | clarvi #( 70 | .DATA_ADDR_WIDTH(DATA_ADDR_WIDTH), 71 | .INSTR_ADDR_WIDTH(INSTR_ADDR_WIDTH), 72 | .INITIAL_PC(INITIAL_PC), 73 | .DEFAULT_TRAP_VECTOR(DEFAULT_TRAP_VECTOR) 74 | ) clarvi ( 75 | .main_address (avm_main_address), 76 | .main_byte_enable (avm_main_byteenable), 77 | .main_read_enable (avm_main_read), 78 | .main_read_data (avm_main_readdata), 79 | .main_read_data_valid (avm_main_readdatavalid), 80 | .main_write_enable (avm_main_write), 81 | .main_write_data (avm_main_writedata), 82 | .main_wait (avm_main_waitrequest), 83 | .instr_address (avm_instr_address), 84 | .instr_read_enable (avm_instr_read), 85 | .instr_read_data (avm_instr_readdata), 86 | .instr_wait (avm_instr_waitrequest), 87 | .clock (clock), 88 | .reset (reset), 89 | .inr_irq (inr_irq), 90 | .debug_register28 (debug_register28), 91 | .debug_scratch (debug_scratch), 92 | .debug_pc (debug_pc) 93 | ); 94 | 95 | endmodule 96 | -------------------------------------------------------------------------------- /clarvi_debug.sv: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright (c) 2016, Robert Eady 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | *******************************************************************************/ 25 | 26 | 27 | always_ff @(posedge clock) begin 28 | // it is most convenient to catch instructions in the MA stage. 29 | if (!ex_ma_invalid && !stall_wb) begin 30 | case (ex_ma_instr.op) 31 | CSRRW, CSRRS, CSRRC: 32 | // catch writes to dscratch and output them 33 | if (ex_ma_instr.funct12 == DSCRATCH) 34 | $display("Debug output: %s = 0x%h", ex_ma_instr.rs1, dscratch); 35 | endcase 36 | end 37 | 38 | // However, if we are going to stop the simulator, it is better to catch instructions 39 | // in the WB stage so that the preceeding instruction will have written back and retired. 40 | if (!ma_wb_invalid && !stall_wb) begin 41 | case (ma_wb_instr.op) 42 | ECALL, INVALID: begin 43 | $display("time: %0d, %p instruction at %h, stopping simulator", $time, ma_wb_instr, ma_wb_instr.pc); 44 | $stop(); 45 | end 46 | endcase 47 | end 48 | end 49 | 50 | `ifdef TRACE 51 | 52 | logic [31:0] db_rs1_value, db_rs2_value, db_result, db_mem_address, db_branch_target; 53 | logic db_invalid, db_branch_taken; 54 | instr_t db_instr; 55 | 56 | always_comb begin 57 | db_instr = ex_ma_instr; 58 | db_invalid = ex_ma_invalid || stall_ma; 59 | db_result = ma_result; 60 | end 61 | 62 | always_ff @(posedge clock) begin 63 | if (!stall_ma) begin 64 | db_rs1_value <= de_ex_rs1_value; 65 | db_rs2_value <= de_ex_rs2_value; 66 | db_mem_address <= ex_mem_address; 67 | db_branch_target <= ex_branch_target; 68 | db_branch_taken <= ex_branch_taken; 69 | end 70 | print_instruction(); 71 | end 72 | 73 | task automatic print_instruction(); 74 | string register_result = ""; 75 | string register_values = ""; 76 | csr_t csr = csr_t'(db_instr.funct12); 77 | 78 | // first output the PC 79 | $write("0x%h: ", db_instr.pc); 80 | 81 | if (db_invalid) begin 82 | // the stage is invalid (e.g. because we took a branch) 83 | $display("---"); 84 | return; 85 | end 86 | 87 | // write the destination register assignment to a string 88 | if (db_instr.enable_wb) 89 | register_result = $sformatf("%s := 0x%h", db_instr.rd, db_result); 90 | 91 | // write the source register values to a string 92 | if (db_instr.rs1_used && db_instr.rs2_used) 93 | register_values = $sformatf("%s = 0x%h, %s = 0x%h", db_instr.rs1, db_rs1_value, db_instr.rs2, db_rs2_value); 94 | else if (db_instr.rs1_used) 95 | register_values = $sformatf("%s = 0x%h", db_instr.rs1, db_rs1_value); 96 | else if (db_instr.rs2_used) 97 | register_values = $sformatf("%s = 0x%h", db_instr.rs2, db_rs2_value); 98 | 99 | // for each kind of instruction, output an appropriate trace, perhaps using the source/designation register strings from above. 100 | case (db_instr.op) 101 | INVALID: $write("%s", db_instr.op); 102 | JAL: $write("%s\t%s, %0d\t\t%s, target = 0x%h", db_instr.op, db_instr.rd, $signed(db_instr.immediate), register_result, db_branch_target); 103 | JALR: $write("%s\t%s, %s, %0d\t\t%s, %s, target = 0x%h", db_instr.op, db_instr.rd, db_instr.rs1, $signed(db_instr.immediate), register_result, register_values, db_branch_target); 104 | ADD, SUB, SLT, SLTU, XOR, OR, AND, SL, SRL, SRA: begin 105 | if (db_instr.immediate_used) 106 | $write("%s%s\t%s, %s, %0d\t\t%s, %s", db_instr.op, "I", db_instr.rd, db_instr.rs1, $signed(db_instr.immediate), register_result, register_values); 107 | else 108 | $write("%s\t%s, %s, %s\t\t%s, %s", db_instr.op, db_instr.rd, db_instr.rs1, db_instr.rs2, register_result, register_values); 109 | end 110 | BEQ, BNE, BLT, BGE, BLTU, BGEU: 111 | $write("%s\t%s, %s, 0x%h\t%s, branch %s", db_instr.op, db_instr.rs1, db_instr.rs2, db_branch_target, register_values, db_branch_taken ? "taken" : "not taken"); 112 | LOAD: $write("L%s%s\t%s, %0d(%s)\t\t%s = mem[0x%h], %s", db_instr.memory_width, db_instr.memory_read_unsigned ? "U" : "", db_instr.rd, $signed(db_instr.immediate), db_instr.rs1, register_result, db_mem_address, register_values); 113 | STORE: $write("S%s\t%s, %0d(%s)\t\tmem[%h] := 0x%h, %s", db_instr.memory_width, db_instr.rs2, $signed(db_instr.immediate), db_instr.rs1, db_mem_address, db_rs2_value, register_values); 114 | ECALL, EBREAK, MRET, WFI, FENCE, FENCE_I: 115 | $write("%s", db_instr.op); 116 | CSRRW, CSRRS, CSRRC: 117 | $write("%s\t%s, %s, %s", db_instr.op, db_instr.rd, csr, db_instr.immediate_used ? $sformatf("%0d", db_instr.rs1) : db_instr.rs1.name); 118 | default: $write("%s\t%s, 0x%h\t\t%s", db_instr.op, db_instr.rd, db_instr.immediate, register_result); 119 | endcase 120 | 121 | // new line 122 | $display(); 123 | endtask 124 | `endif // TRACE 125 | -------------------------------------------------------------------------------- /clarvi_hw.tcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016, Robert Eady 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, 10 | # this list of conditions and the following disclaimer in the documentation 11 | # and/or other materials provided with the distribution. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | 25 | # TCL File Generated by Component Editor 16.0 26 | # Thu Aug 25 18:22:03 BST 2016 27 | # DO NOT MODIFY 28 | 29 | 30 | # 31 | # clarvi "clarvi" v1.0 32 | # 2016.08.25.18:22:03 33 | # 34 | # 35 | 36 | # 37 | # request TCL package from ACDS 16.0 38 | # 39 | package require -exact qsys 16.0 40 | 41 | 42 | # 43 | # module clarvi 44 | # 45 | set_module_property DESCRIPTION "" 46 | set_module_property NAME clarvi 47 | set_module_property VERSION 1.0 48 | set_module_property INTERNAL false 49 | set_module_property OPAQUE_ADDRESS_MAP true 50 | set_module_property AUTHOR "" 51 | set_module_property DISPLAY_NAME clarvi 52 | set_module_property INSTANTIATE_IN_SYSTEM_MODULE true 53 | set_module_property EDITABLE true 54 | set_module_property REPORT_TO_TALKBACK false 55 | set_module_property ALLOW_GREYBOX_GENERATION false 56 | set_module_property REPORT_HIERARCHY false 57 | 58 | 59 | # 60 | # file sets 61 | # 62 | add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" "" 63 | set_fileset_property QUARTUS_SYNTH TOP_LEVEL clarvi_avalon 64 | set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false 65 | set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false 66 | add_fileset_file clarvi_avalon.sv SYSTEM_VERILOG PATH ../clarvi_avalon.sv TOP_LEVEL_FILE 67 | add_fileset_file clarvi.sv SYSTEM_VERILOG PATH ../clarvi.sv 68 | add_fileset_file riscv.svh SYSTEM_VERILOG_INCLUDE PATH ../riscv.svh 69 | 70 | 71 | # 72 | # parameters 73 | # 74 | add_parameter DATA_ADDR_WIDTH INTEGER 14 75 | set_parameter_property DATA_ADDR_WIDTH DEFAULT_VALUE 14 76 | set_parameter_property DATA_ADDR_WIDTH DISPLAY_NAME DATA_ADDR_WIDTH 77 | set_parameter_property DATA_ADDR_WIDTH TYPE INTEGER 78 | set_parameter_property DATA_ADDR_WIDTH UNITS None 79 | set_parameter_property DATA_ADDR_WIDTH ALLOWED_RANGES -2147483648:2147483647 80 | set_parameter_property DATA_ADDR_WIDTH HDL_PARAMETER true 81 | add_parameter INSTR_ADDR_WIDTH INTEGER 14 82 | set_parameter_property INSTR_ADDR_WIDTH DEFAULT_VALUE 14 83 | set_parameter_property INSTR_ADDR_WIDTH DISPLAY_NAME INSTR_ADDR_WIDTH 84 | set_parameter_property INSTR_ADDR_WIDTH TYPE INTEGER 85 | set_parameter_property INSTR_ADDR_WIDTH UNITS None 86 | set_parameter_property INSTR_ADDR_WIDTH ALLOWED_RANGES -2147483648:2147483647 87 | set_parameter_property INSTR_ADDR_WIDTH HDL_PARAMETER true 88 | add_parameter INITIAL_PC INTEGER 0 89 | set_parameter_property INITIAL_PC DEFAULT_VALUE 0 90 | set_parameter_property INITIAL_PC DISPLAY_NAME INITIAL_PC 91 | set_parameter_property INITIAL_PC TYPE INTEGER 92 | set_parameter_property INITIAL_PC UNITS None 93 | set_parameter_property INITIAL_PC ALLOWED_RANGES -2147483648:2147483647 94 | set_parameter_property INITIAL_PC HDL_PARAMETER true 95 | add_parameter DEFAULT_TRAP_VECTOR INTEGER 0 96 | set_parameter_property DEFAULT_TRAP_VECTOR DEFAULT_VALUE 0 97 | set_parameter_property DEFAULT_TRAP_VECTOR DISPLAY_NAME DEFAULT_TRAP_VECTOR 98 | set_parameter_property DEFAULT_TRAP_VECTOR TYPE INTEGER 99 | set_parameter_property DEFAULT_TRAP_VECTOR UNITS None 100 | set_parameter_property DEFAULT_TRAP_VECTOR ALLOWED_RANGES -2147483648:2147483647 101 | set_parameter_property DEFAULT_TRAP_VECTOR HDL_PARAMETER true 102 | 103 | 104 | # 105 | # display items 106 | # 107 | 108 | 109 | # 110 | # connection point reset 111 | # 112 | add_interface reset reset end 113 | set_interface_property reset associatedClock clock 114 | set_interface_property reset synchronousEdges DEASSERT 115 | set_interface_property reset ENABLED true 116 | set_interface_property reset EXPORT_OF "" 117 | set_interface_property reset PORT_NAME_MAP "" 118 | set_interface_property reset CMSIS_SVD_VARIABLES "" 119 | set_interface_property reset SVD_ADDRESS_GROUP "" 120 | 121 | add_interface_port reset reset reset Input 1 122 | 123 | 124 | # 125 | # connection point interrupt_receiver_0 126 | # 127 | add_interface interrupt_receiver_0 interrupt start 128 | set_interface_property interrupt_receiver_0 associatedAddressablePoint "" 129 | set_interface_property interrupt_receiver_0 irqScheme INDIVIDUAL_REQUESTS 130 | set_interface_property interrupt_receiver_0 ENABLED true 131 | set_interface_property interrupt_receiver_0 EXPORT_OF "" 132 | set_interface_property interrupt_receiver_0 PORT_NAME_MAP "" 133 | set_interface_property interrupt_receiver_0 CMSIS_SVD_VARIABLES "" 134 | set_interface_property interrupt_receiver_0 SVD_ADDRESS_GROUP "" 135 | 136 | add_interface_port interrupt_receiver_0 inr_irq irq Input 1 137 | 138 | 139 | # 140 | # connection point main 141 | # 142 | add_interface main avalon start 143 | set_interface_property main addressUnits WORDS 144 | set_interface_property main associatedClock clock 145 | set_interface_property main associatedReset reset 146 | set_interface_property main bitsPerSymbol 8 147 | set_interface_property main burstOnBurstBoundariesOnly false 148 | set_interface_property main burstcountUnits WORDS 149 | set_interface_property main doStreamReads false 150 | set_interface_property main doStreamWrites false 151 | set_interface_property main holdTime 0 152 | set_interface_property main linewrapBursts false 153 | set_interface_property main maximumPendingReadTransactions 0 154 | set_interface_property main maximumPendingWriteTransactions 0 155 | set_interface_property main readLatency 0 156 | set_interface_property main readWaitTime 0 157 | set_interface_property main setupTime 0 158 | set_interface_property main timingUnits Cycles 159 | set_interface_property main writeWaitTime 0 160 | set_interface_property main ENABLED true 161 | set_interface_property main EXPORT_OF "" 162 | set_interface_property main PORT_NAME_MAP "" 163 | set_interface_property main CMSIS_SVD_VARIABLES "" 164 | set_interface_property main SVD_ADDRESS_GROUP "" 165 | 166 | add_interface_port main avm_main_address address Output DATA_ADDR_WIDTH 167 | add_interface_port main avm_main_byteenable byteenable Output 4 168 | add_interface_port main avm_main_read read Output 1 169 | add_interface_port main avm_main_readdata readdata Input 32 170 | add_interface_port main avm_main_write write Output 1 171 | add_interface_port main avm_main_writedata writedata Output 32 172 | add_interface_port main avm_main_waitrequest waitrequest Input 1 173 | add_interface_port main avm_main_readdatavalid readdatavalid Input 1 174 | 175 | 176 | # 177 | # connection point instr 178 | # 179 | add_interface instr avalon start 180 | set_interface_property instr addressUnits WORDS 181 | set_interface_property instr associatedClock clock 182 | set_interface_property instr associatedReset reset 183 | set_interface_property instr bitsPerSymbol 8 184 | set_interface_property instr burstOnBurstBoundariesOnly false 185 | set_interface_property instr burstcountUnits WORDS 186 | set_interface_property instr doStreamReads false 187 | set_interface_property instr doStreamWrites false 188 | set_interface_property instr holdTime 0 189 | set_interface_property instr linewrapBursts false 190 | set_interface_property instr maximumPendingReadTransactions 0 191 | set_interface_property instr maximumPendingWriteTransactions 0 192 | set_interface_property instr readLatency 0 193 | set_interface_property instr readWaitTime 0 194 | set_interface_property instr setupTime 0 195 | set_interface_property instr timingUnits Cycles 196 | set_interface_property instr writeWaitTime 0 197 | set_interface_property instr ENABLED true 198 | set_interface_property instr EXPORT_OF "" 199 | set_interface_property instr PORT_NAME_MAP "" 200 | set_interface_property instr CMSIS_SVD_VARIABLES "" 201 | set_interface_property instr SVD_ADDRESS_GROUP "" 202 | 203 | add_interface_port instr avm_instr_address address Output INSTR_ADDR_WIDTH 204 | add_interface_port instr avm_instr_read read Output 1 205 | add_interface_port instr avm_instr_readdata readdata Input 32 206 | add_interface_port instr avm_instr_waitrequest waitrequest Input 1 207 | add_interface_port instr avm_instr_readdatavalid readdatavalid Input 1 208 | 209 | 210 | # 211 | # connection point clock 212 | # 213 | add_interface clock clock end 214 | set_interface_property clock clockRate 0 215 | set_interface_property clock ENABLED true 216 | set_interface_property clock EXPORT_OF "" 217 | set_interface_property clock PORT_NAME_MAP "" 218 | set_interface_property clock CMSIS_SVD_VARIABLES "" 219 | set_interface_property clock SVD_ADDRESS_GROUP "" 220 | 221 | add_interface_port clock clock clk Input 1 222 | 223 | 224 | # 225 | # connection point debug 226 | # 227 | add_interface debug conduit end 228 | set_interface_property debug associatedClock "" 229 | set_interface_property debug associatedReset "" 230 | set_interface_property debug ENABLED true 231 | set_interface_property debug EXPORT_OF "" 232 | set_interface_property debug PORT_NAME_MAP "" 233 | set_interface_property debug CMSIS_SVD_VARIABLES "" 234 | set_interface_property debug SVD_ADDRESS_GROUP "" 235 | 236 | add_interface_port debug debug_register28 register28 Output 32 237 | add_interface_port debug debug_scratch scratch Output 32 238 | add_interface_port debug debug_pc pc Output 32 239 | -------------------------------------------------------------------------------- /info for developers.md: -------------------------------------------------------------------------------- 1 | # Documentation for developers 2 | 3 | Some more detailed information about the structure of the Clarvi code. To be expanded. 4 | 5 | ## Use of SystemVerilog 6 | 7 | A general remark: the code employs SystemVerilog rather than just Verilog features where possible. In particular, `logic` and user-defined types are prefered to `reg`/`wire` and `always_comb` is prefered to `assign` statements. 8 | 9 | However, this is at times constrained by poor support from Altera synthesis tools for certain constructs. For instance this means that some declarations are earlier than I would like, union types are not used although they would be convenient, and `logic` is used instead of custom types in many places. 10 | 11 | ## General Structure 12 | 13 | The Clarvi code is in two halves. The first half is roughly divided up into sections corresponding to pipeline stages, with declarations and process blocks (always_comb and always_ff) that correspond to the signals produced by that stage. 14 | 15 | Combinational functions and occasionally tasks are also used heavily. These are located in the second half of the code, below the per-stage declarations and process blocks. Beware that some functions/tasks access state declared in the first half of the code in addition to their arguments, merely for convenience. 16 | 17 | The choice to use functions instead of separate modules was made to reduce the amount of wiring-up boilerplate code required, admitedly at the cost of some degree of isolation between components. 18 | 19 | ## Debugging 20 | 21 | There are two debugging aspects to the code: 22 | 23 | 1. The `clarvi_debug.sv` code is included in the main `clarvi.sv` file when run in ModelSim. It contains code for stopping the simulator in certain conditions, such as an invalid instruction or an `ecall`, and for outputting an instruction trace. 24 | 25 | The debugging code generally looks at the contents of the MA stage, since at this point the all information about the instruction's execution is known. However, for stopping the simulator, it is more sensible to look at the contents of the WB stage, so that the preceeding instruction is given the chance to write back first. 26 | 27 | 2. The `sim.sv` testbench includes some modules for debugging or testing various aspects of the core from an external perspective. 28 | 29 | The `memory_debug` module makes it easy to catch reads/writes, for instance to output debugging info when particular addresses are accessed. 30 | 31 | There are also `mock_waitrequest` and `mock_interrupt` modules to test out the behaviour of the core under memory contention and when interrupts occur. 32 | -------------------------------------------------------------------------------- /riscv.svh: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright (c) 2016, Robert Eady 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | *******************************************************************************/ 25 | 26 | 27 | // instruction parts, that are always in the same place 28 | `define opext [1 : 0] 29 | `define opcode [6 : 2] 30 | `define rd [11: 7] 31 | `define funct3 [14:12] 32 | `define rs1 [19:15] 33 | `define rs2 [24:20] 34 | `define funct7 [31:25] 35 | `define funct12 [31:20] 36 | 37 | 38 | // RISC-V opcodes 39 | typedef enum logic [4:0] { 40 | OPC_LUI = 5'b01101, 41 | OPC_AUIPC = 5'b00101, 42 | OPC_JAL = 5'b11011, 43 | OPC_JALR = 5'b11001, 44 | OPC_BRANCH = 5'b11000, 45 | OPC_LOAD = 5'b00000, 46 | OPC_STORE = 5'b01000, 47 | OPC_OP_IMM = 5'b00100, 48 | OPC_OP = 5'b01100, 49 | OPC_MISC_MEM = 5'b00011, 50 | OPC_SYSTEM = 5'b11100 51 | } opcode_t; 52 | 53 | 54 | // registers 55 | typedef enum logic [4:0] { 56 | zero, 57 | ra, 58 | sp, 59 | gp, 60 | tp, 61 | t0, t1, t2, 62 | fp, s1, 63 | a0, a1, a2, a3, a4, a5, a6, a7, 64 | s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, 65 | t3, t4, t5, t6 66 | } register_t; 67 | 68 | // internal, decoded opcodes 69 | typedef enum logic [4:0] { 70 | LUI, 71 | AUIPC, 72 | JAL, 73 | JALR, 74 | BEQ, 75 | BNE, 76 | BLT, 77 | BGE, 78 | BLTU, 79 | BGEU, 80 | LOAD, 81 | STORE, 82 | ADD, 83 | SUB, 84 | SLT, 85 | SLTU, 86 | XOR, 87 | OR, 88 | AND, 89 | SL, 90 | SRL, 91 | SRA, 92 | FENCE, 93 | FENCE_I, 94 | ECALL, 95 | EBREAK, 96 | MRET, 97 | WFI, 98 | CSRRW, 99 | CSRRS, 100 | CSRRC, 101 | INVALID 102 | } operation_t; 103 | 104 | // memory operation widths 105 | typedef enum logic [1:0] { 106 | B = 2'b00, 107 | H = 2'b01, 108 | W = 2'b10 109 | } mem_width_t; 110 | 111 | // machine mode funct12 codes 112 | typedef enum logic [11:0] { 113 | F12_ECALL = 12'b000000000000, 114 | F12_EBREAK = 12'b000000000001, 115 | F12_MRET = 12'b001100000010, 116 | F12_WFI = 12'b000100000101 117 | } funct12_t; 118 | 119 | // holds all the information about a decoded instruction 120 | typedef struct packed { 121 | operation_t op; 122 | register_t rd; 123 | register_t rs1; 124 | register_t rs2; 125 | logic rs1_used; 126 | logic rs2_used; 127 | logic immediate_used; 128 | logic [31:0] immediate; 129 | funct12_t funct12; 130 | logic memory_write; 131 | logic memory_read; 132 | logic memory_read_unsigned; 133 | mem_width_t memory_width; 134 | logic enable_wb; 135 | logic [31:0] pc; 136 | } instr_t; 137 | 138 | 139 | // all the funct3 codes 140 | 141 | typedef enum logic [2:0] { 142 | F3_ADDSUB = 3'b000, 143 | F3_SLT = 3'b010, 144 | F3_SLTU = 3'b011, 145 | F3_XOR = 3'b100, 146 | F3_OR = 3'b110, 147 | F3_AND = 3'b111, 148 | F3_SLL = 3'b001, 149 | F3_SR = 3'b101 150 | } funct3_op_t; 151 | 152 | typedef enum logic [2:0] { 153 | F3_BEQ = 3'b000, 154 | F3_BNE = 3'b001, 155 | F3_BLT = 3'b100, 156 | F3_BGE = 3'b101, 157 | F3_BLTU = 3'b110, 158 | F3_BGEU = 3'b111 159 | } funct3_branch_t; 160 | 161 | typedef enum logic [2:0] { 162 | F3_LB = 3'b000, 163 | F3_LH = 3'b001, 164 | F3_LW = 3'b010, 165 | F3_LBU = 3'b100, 166 | F3_LHU = 3'b101 167 | } funct3_load_t; 168 | 169 | typedef enum logic [2:0] { 170 | F3_SB = 3'b000, 171 | F3_SH = 3'b001, 172 | F3_SW = 3'b010 173 | } funct3_store_t; 174 | 175 | typedef enum logic [2:0] { 176 | F3_FENCE = 3'b000, 177 | F3_FENCEI = 3'b001 178 | } funct3_misc_mem_t; 179 | 180 | typedef enum logic [2:0] { 181 | F3_CSRRW = 3'b001, 182 | F3_CSRRS = 3'b010, 183 | F3_CSRRC = 3'b011, 184 | F3_CSRRWI = 3'b101, 185 | F3_CSRRSI = 3'b110, 186 | F3_CSRRCI = 3'b111, 187 | F3_PRIV = 3'b000 188 | } funct3_system_t; 189 | 190 | // non-immediate part of the system funct3 codes 191 | typedef enum logic [1:0] { 192 | F2_PRIV = 2'b00, 193 | F2_CSRRW = 2'b01, 194 | F2_CSRRS = 2'b10, 195 | F2_CSRRC = 2'b11 196 | } funct2_system_t; 197 | 198 | 199 | // CSR addresses 200 | typedef enum logic [11:0] { 201 | CYCLE = 12'hC00, 202 | TIME = 12'hC01, 203 | INSTRET = 12'hC02, 204 | CYCLEH = 12'hC80, 205 | TIMEH = 12'hC81, 206 | INSTRETH = 12'hC82, 207 | 208 | MISA = 12'hF10, 209 | MVENDORID = 12'hF11, 210 | MARCHID = 12'hF12, 211 | MIMPID = 12'hF13, 212 | MHARTID = 12'hF14, 213 | 214 | MSTATUS = 12'h300, 215 | MEDELEG = 12'h302, 216 | MIDELEG = 12'h303, 217 | MIE = 12'h304, 218 | MTVEC = 12'h305, 219 | 220 | MSCRATCH = 12'h340, 221 | MEPC = 12'h341, 222 | MCAUSE = 12'h342, 223 | MBADADDR = 12'h343, 224 | MIP = 12'h344, 225 | 226 | MCYCLE = 12'hF00, 227 | MTIME = 12'hF01, 228 | MINSTRET = 12'hF02, 229 | MCYCLEH = 12'hF80, 230 | MTIMEH = 12'hF81, 231 | MINSTRETH = 12'hF82, 232 | 233 | // non-standard but we don't want to memory-map mtimecmp 234 | MTIMECMP = 12'h7C1, 235 | MTIMECMPH = 12'h7C2, 236 | 237 | // provisional debug CSRs 238 | DCSR = 12'h7B0, 239 | DPC = 12'h7B1, 240 | DSCRATCH = 12'h7B2 241 | } csr_t; 242 | 243 | 244 | // mstatus register 245 | typedef struct packed { 246 | logic sd; 247 | logic [1:0] unused1; 248 | logic [4:0] vm; 249 | logic [3:0] unused2; 250 | logic mxr; 251 | logic pum; 252 | logic mprv; 253 | logic [1:0] xs; 254 | logic [1:0] fs; 255 | logic [1:0] mpp; 256 | logic [1:0] hpp; 257 | logic spp; 258 | logic mpie; 259 | logic hpie; 260 | logic spie; 261 | logic upie; 262 | logic mie; 263 | logic hie; 264 | logic sie; 265 | logic uie; 266 | } mstatus_t; 267 | 268 | 269 | // mcause register 270 | typedef enum logic [31:0] { 271 | // interrupt codes have the top bit set to 1. 272 | USI = {1'b1, 31'd0}, 273 | SSI = {1'b1, 31'd1}, 274 | HSI = {1'b1, 31'd2}, 275 | MSI = {1'b1, 31'd3}, 276 | UTI = {1'b1, 31'd4}, 277 | STI = {1'b1, 31'd5}, 278 | HTI = {1'b1, 31'd6}, 279 | MTI = {1'b1, 31'd7}, 280 | UEI = {1'b1, 31'd8}, 281 | SEI = {1'b1, 31'd9}, 282 | HEI = {1'b1, 31'd10}, 283 | MEI = {1'b1, 31'd11}, 284 | 285 | INSTR_MISALIGN = 32'd0, 286 | INSTR_FAULT = 32'd1, 287 | ILLEGAL_INSTR = 32'd2, 288 | BREAK = 32'd3, 289 | LOAD_MISALIGN = 32'd4, 290 | LOAD_FAULT = 32'd5, 291 | STORE_MISALIGN = 32'd6, 292 | STORE_FAULT = 32'd7, 293 | ECALL_U = 32'd8, 294 | ECALL_S = 32'd9, 295 | ECALL_H = 32'd10, 296 | ECALL_M = 32'd11 297 | } mcause_t; 298 | 299 | 300 | // machine interrupts pending register 301 | typedef struct packed { 302 | logic [19:0] unused; 303 | logic meip; 304 | logic heip; 305 | logic seip; 306 | logic ueip; 307 | logic mtip; 308 | logic htip; 309 | logic stip; 310 | logic utip; 311 | logic msip; 312 | logic hsip; 313 | logic ssip; 314 | logic usip; 315 | } mip_t; 316 | 317 | // machine interrupts enabled register 318 | typedef struct packed { 319 | logic [19:0] unused; 320 | logic meie; 321 | logic heie; 322 | logic seie; 323 | logic ueie; 324 | logic mtie; 325 | logic htie; 326 | logic stie; 327 | logic utie; 328 | logic msie; 329 | logic hsie; 330 | logic ssie; 331 | logic usie; 332 | } mie_t; 333 | -------------------------------------------------------------------------------- /sim.sv: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright (c) 2016, Robert Eady 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | *******************************************************************************/ 25 | 26 | 27 | `timescale 1ns/10ps 28 | 29 | module clarvi_sim(); 30 | logic clock = 1; 31 | logic reset = 0; 32 | 33 | localparam ADDR_WIDTH = 16; 34 | 35 | logic [ADDR_WIDTH-1:0] main_address; 36 | logic [3:0] main_byteenable; 37 | logic main_read; 38 | logic [31:0] main_readdata; 39 | logic main_write; 40 | logic [31:0] main_writedata; 41 | logic main_waitrequest = 0; 42 | logic main_readdatavalid; 43 | logic [ADDR_WIDTH-1:0] instr_address; 44 | logic instr_read; 45 | logic [31:0] instr_readdata; 46 | logic instr_waitrequest = 0; 47 | logic instr_readdatavalid = 1; 48 | 49 | logic interrupt = 0; 50 | 51 | 52 | dual_port_bram #( 53 | .ADDRESS_WIDTH(ADDR_WIDTH) 54 | ) mem ( 55 | .clock, 56 | .reset, 57 | .avs_a_address (main_address), 58 | .avs_a_byteenable (main_byteenable), 59 | .avs_a_read (main_read), 60 | .avs_a_readdata (main_readdata), 61 | .avs_a_write (main_write), 62 | .avs_a_writedata (main_writedata), 63 | .avs_b_address (instr_address), 64 | .avs_b_byteenable (4'b1111), 65 | .avs_b_read (instr_read), 66 | .avs_b_readdata (instr_readdata), 67 | .avs_b_write (1'b0), 68 | .avs_b_writedata (32'dx) 69 | ); 70 | 71 | // components for mocking interrupt or waitrequest signals: 72 | // mock_waitrequest wr(main_waitrequest, instr_waitrequest); 73 | // mock_interrupt mi(interrupt); 74 | 75 | memory_debug #( 76 | .ADDR_WIDTH(ADDR_WIDTH) 77 | ) main_mem_debug ( 78 | .clock, 79 | .address(main_address), 80 | .read_enable(main_read), 81 | .read_data(main_readdata), 82 | .write_enable(main_write), 83 | .write_data(main_writedata) 84 | ); 85 | 86 | clarvi_avalon #( 87 | .INSTR_ADDR_WIDTH(ADDR_WIDTH), 88 | .DATA_ADDR_WIDTH(ADDR_WIDTH) 89 | ) clarvi ( 90 | .clock, 91 | .reset, 92 | .avm_main_address (main_address), 93 | .avm_main_byteenable (main_byteenable), 94 | .avm_main_read (main_read), 95 | .avm_main_readdata (main_readdata), 96 | .avm_main_write (main_write), 97 | .avm_main_writedata (main_writedata), 98 | .avm_main_waitrequest (main_waitrequest), 99 | .avm_main_readdatavalid (main_readdatavalid), 100 | .avm_instr_address (instr_address), 101 | .avm_instr_read (instr_read), 102 | .avm_instr_readdata (instr_readdata), 103 | .avm_instr_waitrequest (instr_waitrequest), 104 | .avm_instr_readdatavalid (instr_readdatavalid), 105 | .inr_irq(interrupt), 106 | .debug_register28(), 107 | .debug_scratch(), 108 | .debug_pc() 109 | ); 110 | 111 | initial begin 112 | forever #5 clock = ~clock; 113 | end 114 | endmodule 115 | 116 | 117 | module memory_debug #( 118 | parameter ADDR_WIDTH = 12 119 | )( 120 | input logic clock, 121 | input logic [ADDR_WIDTH-1:0] address, 122 | input logic read_enable, 123 | input logic [31:0] read_data, 124 | input logic write_enable, 125 | input logic [31:0] write_data 126 | ); 127 | 128 | always_ff @(posedge clock) begin 129 | // detect writes to certain addresses 130 | if (write_enable) begin 131 | casez (address[17:0] << 2) // turn our word address into a byte address 132 | 18'h10000: $display("HEX write, address %h, data %h", address, write_data); 133 | 18'h2000?: $display("PIO write, address %h, data %h", address, write_data); 134 | endcase 135 | end 136 | end 137 | endmodule 138 | 139 | 140 | 141 | module mock_waitrequest( 142 | output logic waitrequest1, 143 | output logic waitrequest2 144 | ); 145 | initial begin 146 | #2 waitrequest1 = 0; 147 | forever begin 148 | #40 waitrequest1 = 1; 149 | #20 waitrequest1 = 0; 150 | end 151 | end 152 | 153 | initial begin 154 | #2 waitrequest2 = 0; 155 | forever begin 156 | #50 waitrequest2 = 1; 157 | #30 waitrequest2 = 0; 158 | end 159 | end 160 | endmodule 161 | 162 | 163 | module mock_interrupt( 164 | output logic interrupt 165 | ); 166 | initial begin 167 | interrupt = 0; 168 | #50 interrupt = 1; 169 | #10000 interrupt = 0; 170 | #500 interrupt = 1; 171 | #50 interrupt = 0; 172 | end 173 | endmodule 174 | -------------------------------------------------------------------------------- /sim.tcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016, Robert Eady 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, 10 | # this list of conditions and the following disclaimer in the documentation 11 | # and/or other materials provided with the distribution. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | 25 | vlib work 26 | 27 | # used to enable trace by passing TRACE as an argument 28 | if {$argc == 2} { 29 | vlog clarvi.sv +define+$2 30 | } else { 31 | vlog clarvi.sv 32 | } 33 | 34 | vlog clarvi_avalon.sv 35 | vlog bram.sv 36 | vlog sim.sv 37 | 38 | if {$argc > 0} { 39 | vsim work.clarvi_sim -GINIT_FILE=$1 -t ns -voptargs=+acc=npr 40 | } else { 41 | vsim work.clarvi_sim -t ns -voptargs=+acc=npr 42 | } 43 | 44 | add wave -position insertpoint \ 45 | {/clarvi_sim/clock} 46 | -------------------------------------------------------------------------------- /software/Makefile: -------------------------------------------------------------------------------- 1 | # the name of the program we're going to build 2 | PROJECT = program 3 | # build directory 4 | BUILD = build 5 | 6 | # name of the Quartus program 7 | FPGA_PROJECT_PATH = ../quartus 8 | FPGA_PROJECT = clarvi 9 | 10 | # source files 11 | C_FILES := $(wildcard src/*.c) 12 | AS_FILES := $(wildcard src/*.s) 13 | ASP_FILES := $(wildcard src/*.S) 14 | 15 | # object files 16 | C_OBJ_FILES := $(patsubst src/%.c,build/%.o,$(C_FILES)) 17 | AS_OBJ_FILES := $(patsubst src/%.s,build/%.o,$(AS_FILES)) 18 | ASP_OBJ_FILES := $(patsubst src/%.S,build/%.o,$(ASP_FILES)) 19 | 20 | 21 | # settings for the compilers 22 | RISCV_PREFIX = riscv32-unknown-elf- 23 | CC = $(RISCV_PREFIX)gcc 24 | LD = $(RISCV_PREFIX)ld 25 | OBJCOPY = $(RISCV_PREFIX)objcopy 26 | OBJDUMP = $(RISCV_PREFIX)objdump 27 | 28 | TARGET_ARCH = -m32 -march=RV32I 29 | CCFLAGS = -O0 $(TARGET_ARCH) 30 | 31 | # Lists of rules: the name of a file, followed by the files it depends on. 32 | # When typing 'make' not followed by a rule name, the first rule is followed. This rule depends on 33 | # everything, causing all the parts to be built 34 | 35 | all: dirs $(BUILD)/mem.hex $(BUILD)/$(PROJECT).dump 36 | 37 | # how to build a .o file from a .c file 38 | $(BUILD)/%.o: src/%.c 39 | $(CC) -c -o $@ $< $(CCFLAGS) 40 | 41 | # how to build a .o file from a .s file 42 | $(BUILD)/%.o: src/%.s 43 | $(CC) -c -o $@ $< $(CCFLAGS) 44 | 45 | # how to build a .o file from a .S file 46 | $(BUILD)/%.o: src/%.S 47 | $(CC) -c -o $@ $< $(CCFLAGS) 48 | 49 | # link with gcc 50 | $(BUILD)/$(PROJECT).elf: ${AS_OBJ_FILES} ${C_OBJ_FILES} ${ASP_OBJ_FILES} 51 | $(CC) -o $@ $^ -T link.ld -lgcc -nostdlib 52 | 53 | # build an elf executable 54 | $(BUILD)/$(PROJECT).dump: $(BUILD)/$(PROJECT).elf 55 | $(OBJDUMP) -S -s $< > $@ 56 | 57 | # extract the binary data from data and text sections to get a binary image of memory 58 | $(BUILD)/mem.bin: $(BUILD)/$(PROJECT).elf 59 | $(OBJCOPY) -O binary --only-section=.data* --only-section=.text* $< $@ 60 | 61 | # convert to an ASCII hex file for simulation 62 | $(BUILD)/mem.txt: $(BUILD)/mem.bin 63 | hexdump -v -e '"%08x\n"' $< > $@ 64 | 65 | # convert to an Intel HEX file for downloading to the FPGA 66 | $(BUILD)/mem.hex: $(BUILD)/mem.txt 67 | python txt2hex.py $< $@ 4 68 | 69 | 70 | # make software project folder 71 | dirs: 72 | mkdir -p $(BUILD) 73 | 74 | # update the memory files inside the FPGA bitfile 75 | update-mem: all 76 | cd ${FPGA_PROJECT_PATH} && quartus_cdb ${FPGA_PROJECT} -c ${FPGA_PROJECT} --update_mif 77 | cd ${FPGA_PROJECT_PATH} && quartus_asm --read_settings_files=on --write_settings_files=off ${FPGA_PROJECT} -c ${FPGA_PROJECT} 78 | 79 | # download the bitfile to your board 80 | download: 81 | cd ${FPGA_PROJECT_PATH} && quartus_pgm -m jtag -o P\;output_files/${FPGA_PROJECT}.sof@2 82 | 83 | # build the whole FPGA from the command line 84 | # not that it's harder to spot warnings in this output compared with the GUI 85 | build_fpga: 86 | cd ${FPGA_PROJECT_PATH} && quartus_sh --flow compile ${FPGA_PROJECT} 87 | 88 | # 'clean' rule: delete all the files so we can start afresh 89 | clean: 90 | rm -rf $(BUILD) 91 | -------------------------------------------------------------------------------- /software/link.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * The stack starts at the top of memory, defined by __sp, and grows down. 3 | * Unfortunately this means we must hardcode the size of memory. 4 | * Here we choose 64K. Change this value to change the working memory size. 5 | */ 6 | __sp = 0x10000; 7 | 8 | SECTIONS 9 | { 10 | .text.init : { 11 | *(.text.init) 12 | } 13 | 14 | .text : { 15 | *(.text) 16 | } 17 | 18 | .data : { 19 | *(.bss) 20 | *(.sdata) 21 | *(.rodata) 22 | *(.data*) 23 | *(.got*) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /software/readme.md: -------------------------------------------------------------------------------- 1 | Place your C (`.c`) and assembly (`.s` or `.S`) source files in the src directory. 2 | Ensure that you do not have multiple source files with the same name (e.g. `main.c` and `main.s`). 3 | 4 | Run `make` to build the software. This produces a build directory, containing: 5 | 6 | - object files (`.o`) produced from your source code 7 | - a `mem.txt` file which is the memory image for use in the simulator 8 | - a `mem.hex` file which is the memory image to program the FPGA's RAM with 9 | - a `program.dump` file which is the full disassembled program output. 10 | - and some intermediate `.bin` and `.elf` files which you can ignore. 11 | 12 | You can also run: 13 | 14 | - `make clean` to remove the build directory 15 | - `make update-mem` to regenerate the FPGA bitfile with the software 16 | - `make download` to download this bitfile to your board. 17 | -------------------------------------------------------------------------------- /software/src/init.s: -------------------------------------------------------------------------------- 1 | # RISC-V baremetal init.s 2 | # This code is executed first. 3 | 4 | .section .text.init 5 | entry: 6 | 7 | la sp, __sp-32 # set up the stack pointer, using a constant defined in the linker script. 8 | 9 | la t0, end # on hardware, ECALL doesn't stop the CPU, so define 10 | # a handler to catch the ECALL and spin 11 | csrrw zero,0x305,t0 # set the address of the handler (CSR 0x305 is the trap handler base register) 12 | 13 | call main # call the main function 14 | ecall # halt the simluation when it returns 15 | 16 | end: 17 | j end # loop when finished if there is no environment to return to. 18 | -------------------------------------------------------------------------------- /software/src/main.c: -------------------------------------------------------------------------------- 1 | int main(void) { 2 | 3 | } 4 | -------------------------------------------------------------------------------- /software/txt2hex.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Convert the Yarvi .txt format to Intel .hex 4 | 5 | import sys 6 | 7 | argc = len(sys.argv) 8 | if argc != 3 and argc != 4: 9 | sys.exit("Syntax: %s [
]" % sys.argv[0]) 10 | 11 | addr_resolution = int(sys.argv[3]) if argc == 4 else 1 12 | 13 | def txt2hex(txtfile, hexfile): 14 | address = 0 15 | EOF = ':00000001FF' 16 | recordtype = '00' 17 | for line in txtfile: 18 | line_stripped = line.rstrip('\r\n') 19 | numbytes = len(line_stripped)/2 20 | data = line_stripped.upper() 21 | # the inner part of the line to be checksummed 22 | hexline = format(numbytes, '02X') + format(address, '04X') + recordtype + data 23 | # do the checksum and add colon at the front 24 | hexline = ':' + hexline + checksum(hexline) 25 | hexfile.write(hexline+'\n') 26 | # advance the address 27 | address += numbytes / addr_resolution 28 | hexfile.write(EOF+'\n') 29 | 30 | def checksum(line): 31 | sum = 0 32 | # for each pair of letters (1 byte) 33 | for i in range(0, len(line), 2): 34 | byte = line[i:i+2] 35 | # accumulate the numeric value of the hex byte 36 | sum += int(byte, 16) 37 | # take the two's complement of the LSB of the sum and convert back to hex 38 | return format(((sum ^ 0xff) + 1) % 256, '02X') 39 | 40 | 41 | # allow "-" as the first argument meaning read from stdin 42 | with (sys.stdin if sys.argv[1] == '-' else open(sys.argv[1], 'r')) as txtfile: 43 | with open(sys.argv[2], 'w') as hexfile: 44 | txt2hex(txtfile, hexfile) 45 | -------------------------------------------------------------------------------- /test-compile.tcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016, Robert Eady 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, 10 | # this list of conditions and the following disclaimer in the documentation 11 | # and/or other materials provided with the distribution. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | 25 | vlib work 26 | 27 | vlog clarvi.sv 28 | vlog clarvi_avalon.sv 29 | vlog bram.sv 30 | vlog sim.sv 31 | -------------------------------------------------------------------------------- /test.tcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016, Robert Eady 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, 10 | # this list of conditions and the following disclaimer in the documentation 11 | # and/or other materials provided with the distribution. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | 25 | source test-compile.tcl 26 | 27 | if {$argc == 1} { 28 | vsim work.clarvi_sim -GINIT_FILE=$1 -t ns -voptargs=+acc=npr 29 | } else { 30 | vsim work.clarvi_sim -t ns -voptargs=+acc=npr 31 | } 32 | 33 | add wave -position insertpoint -radix unsigned \ 34 | {/clarvi_sim/clock} \ 35 | {/clarvi_sim/clarvi/clarvi/registers[28]} 36 | -------------------------------------------------------------------------------- /tests-all.sh: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016, Robert Eady 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, 10 | # this list of conditions and the following disclaimer in the documentation 11 | # and/or other materials provided with the distribution. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | 25 | if [ "$1" ]; then 26 | # the first argument is the test environment e.g. b or p 27 | vsim -c -do tests-all.tcl -Gtest_env=$1 | fgrep $'@\n** Error\n** Warn' 28 | else 29 | vsim -c -do tests-all.tcl | fgrep $'@\n** Error\n** Warn' 30 | fi 31 | -------------------------------------------------------------------------------- /tests-all.tcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016, Robert Eady 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, 10 | # this list of conditions and the following disclaimer in the documentation 11 | # and/or other materials provided with the distribution. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | 25 | source test-compile.tcl 26 | 27 | set colour_green "\033\[0;32m" 28 | set colour_red "\033\[0;31m" 29 | set colour_cyan "\033\[0;36m" 30 | set colour_reset "\033\[0m" 31 | 32 | # allow the test environment to be provided as an argument to vsim 33 | set test_env [lsearch -inline $argv "-Gtest_env=*" ] 34 | if { $test_env ne "" } { 35 | set e [ string range $test_env [ expr [ string first "=" $test_env ]+1 ] end ] 36 | set search_string "*-$e-*.mem.txt" 37 | } else { 38 | set search_string "*.mem.txt" 39 | } 40 | 41 | 42 | onbreak {resume} 43 | 44 | foreach testMem [ lsort [ glob -dir tests/build $search_string ] ] { 45 | 46 | set testBase [ lindex [ split $testMem "." ] 0 ] 47 | 48 | echo "$colour_cyan @ Test: ${testBase} $colour_reset" 49 | 50 | vsim work.clarvi_sim -GINIT_FILE=$testMem -quiet -t ns -voptargs=+acc=npr 51 | run 1ms 52 | 53 | if { [ runStatus ] eq "break"} { 54 | set reg28 [ examine -decimal {registers[28]} ] 55 | set cycles [ examine -decimal cycles ] 56 | set test [ expr $reg28 >> 1 ] 57 | if { $reg28 eq "1" } { 58 | echo "$colour_green @ PASS in $cycles cycles $colour_reset" 59 | } else { 60 | echo "$colour_red @ FAIL on test $test $colour_reset" 61 | } 62 | } elseif { [ runStatus ] eq "ready" } { 63 | echo "$colour_red @ FAIL tests did not terminate $colour_reset" 64 | } 65 | } 66 | 67 | quit 68 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016, Robert Eady 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, 10 | # this list of conditions and the following disclaimer in the documentation 11 | # and/or other materials provided with the distribution. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | #======================================================================= 25 | # Makefile for riscv-tests/isa 26 | # 27 | # Modified for clarvi by Jamie Wood, Rob Eady 28 | #----------------------------------------------------------------------- 29 | 30 | # Set this to the correct directory for your risc-v toolchain installation 31 | src_dir := riscv-tools/riscv-tests/isa 32 | 33 | #include $(src_dir)/rv64ui/Makefrag 34 | #include $(src_dir)/rv64um/Makefrag 35 | #include $(src_dir)/rv64ua/Makefrag 36 | #include $(src_dir)/rv64uf/Makefrag 37 | #include $(src_dir)/rv64ud/Makefrag 38 | #include $(src_dir)/rv64si/Makefrag 39 | #include $(src_dir)/rv64mi/Makefrag 40 | include $(src_dir)/rv32ui/Makefrag 41 | #include $(src_dir)/rv32um/Makefrag 42 | #include $(src_dir)/rv32ua/Makefrag 43 | #include $(src_dir)/rv32si/Makefrag 44 | include $(src_dir)/rv32mi/Makefrag 45 | 46 | default: all 47 | 48 | #-------------------------------------------------------------------- 49 | # Build rules 50 | #-------------------------------------------------------------------- 51 | 52 | XLEN = 32 53 | 54 | RISCV_PREFIX ?= riscv$(XLEN)-unknown-elf- 55 | RISCV_GCC ?= $(RISCV_PREFIX)gcc 56 | ENTROPY ?= -DENTROPY=$(shell echo $$$$) 57 | RISCV_GCC_OPTS ?= $(ENTROPY) -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles 58 | RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump --disassemble-all --disassemble-zeroes --section=.text --section=.text.startup --section=.text.init --section=.data 59 | RISCV_OBJCOPY = $(RISCV_PREFIX)objcopy 60 | RISCV_SIM ?= spike 61 | 62 | vpath %.S $(src_dir) 63 | 64 | #------------------------------------------------------------ 65 | # Build assembly tests 66 | 67 | %.mem.txt: %.mem 68 | hexdump -v -e '"%08x\n"' $< > $@ 69 | 70 | %.mem.hex: %.mem.txt 71 | python txt2hex.py $< $@ 4 72 | 73 | #img: 74 | # mkdir -p img 75 | 76 | %.mem: % 77 | $(RISCV_OBJCOPY) -O binary --only-section=.data* --only-section=.text* $< $@ 78 | 79 | 80 | %.dump: % 81 | $(RISCV_OBJDUMP) $< > $@ 82 | 83 | %.out: % 84 | $(RISCV_SIM) $< 2> $@ 85 | 86 | %.out32: % 87 | $(RISCV_SIM) --isa=RV32 $< 2> $@ 88 | 89 | define compile_template 90 | 91 | $$($(1)_p_tests): $(1)-p-%: $(1)/%.S 92 | $$(RISCV_GCC) $(2) $$(RISCV_GCC_OPTS) -I$(src_dir)/../env/p -I$(src_dir)/macros/scalar -Tlink.ld $$< -o $$@ 93 | $(1)_tests += $$($(1)_p_tests) 94 | 95 | # $$($(1)_v_tests): $(1)-v-%: $(1)/%.S 96 | # $$(RISCV_GCC) $(2) $$(RISCV_GCC_OPTS) -std=gnu99 -O2 -I$(src_dir)/../env/v -I$(src_dir)/macros/scalar -T$(src_dir)/../env/v/link.ld $(src_dir)/../env/v/entry.S $(src_dir)/../env/v/*.c $$< -lc -o $$@ 97 | # $(1)_tests += $$($(1)_v_tests) 98 | 99 | # baremetal tests that don't use privileged instructions in initialisation 100 | $$($(1)_b_tests): $(1)-b-%: $(1)/%.S 101 | $$(RISCV_GCC) $(2) $$(RISCV_GCC_OPTS) -Ienv/b -I$(src_dir)/macros/scalar -Tlink.ld $$< -o $$@ 102 | $(1)_tests += $$($(1)_b_tests) 103 | 104 | $(1)_tests_dump = $$(addsuffix .dump, $$($(1)_tests)) 105 | 106 | $(1): $$($(1)_tests_dump) 107 | 108 | .PHONY: $(1) 109 | 110 | tests += $$($(1)_tests) 111 | 112 | endef 113 | 114 | $(eval $(call compile_template,rv32ui,-m32)) 115 | # $(eval $(call compile_template,rv32um,-m32)) 116 | # $(eval $(call compile_template,rv32ua,-m32)) 117 | # $(eval $(call compile_template,rv32si,-m32)) 118 | $(eval $(call compile_template,rv32mi,-m32)) 119 | ifeq ($(XLEN),64) 120 | $(eval $(call compile_template,rv64ui)) 121 | $(eval $(call compile_template,rv64um)) 122 | $(eval $(call compile_template,rv64ua)) 123 | $(eval $(call compile_template,rv64uf)) 124 | $(eval $(call compile_template,rv64ud)) 125 | $(eval $(call compile_template,rv64si)) 126 | $(eval $(call compile_template,rv64mi)) 127 | endif 128 | 129 | tests_dump = $(addsuffix .dump, $(tests)) 130 | tests_hex = $(addsuffix .hex, $(tests)) 131 | tests_out = $(addsuffix .out, $(spike_tests)) 132 | tests32_out = $(addsuffix .out32, $(spike32_tests)) 133 | 134 | tests_mem_txt = $(addsuffix .mem.txt, $(tests)) 135 | tests_mem_hex = $(addsuffix .mem.hex, $(tests)) 136 | tests_mem_ver = $(addsuffix .mem.ver, $(tests)) # generated by the testbench 137 | 138 | run: $(tests_out) $(tests32_out) 139 | echo; perl -ne 'print " [$$1] $$ARGV \t$$2\n" if /\*{3}(.{8})\*{3}(.*)/' \ 140 | $(tests_out) $(tests32_out); echo; 141 | 142 | junk += $(tests) $(tests_dump) $(tests_hex) $(tests_out) $(tests32_out) img $(tests_mem_hex) $(tests_mem_txt) $(tests_mem_ver) 143 | 144 | #------------------------------------------------------------ 145 | # Default 146 | 147 | all: $(tests_dump) $(tests_mem_hex) $(tests_mem_txt) 148 | 149 | #------------------------------------------------------------ 150 | # Clean up 151 | 152 | clean: 153 | rm -rf $(junk) 154 | -------------------------------------------------------------------------------- /tests/env/b/riscv_test.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright (c) 2012-2015, The Regents of the University of California (Regents). 3 | All Rights Reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 3. Neither the name of the Regents nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 17 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING 18 | OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS 19 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED 24 | HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE 25 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 26 | *******************************************************************************/ 27 | 28 | #ifndef _ENV_PHYSICAL_SINGLE_CORE_H 29 | #define _ENV_PHYSICAL_SINGLE_CORE_H 30 | 31 | #include "../encoding.h" 32 | 33 | //----------------------------------------------------------------------- 34 | // Begin Macro 35 | //----------------------------------------------------------------------- 36 | 37 | #define RVTEST_RV64U \ 38 | .macro init; \ 39 | .endm 40 | 41 | #define RVTEST_RV64UF \ 42 | .macro init; \ 43 | RVTEST_FP_ENABLE; \ 44 | .endm 45 | 46 | #define RVTEST_RV32U \ 47 | .macro init; \ 48 | .endm 49 | 50 | #define RVTEST_RV32UF \ 51 | .macro init; \ 52 | RVTEST_FP_ENABLE; \ 53 | .endm 54 | 55 | #define RVTEST_RV64M \ 56 | .macro init; \ 57 | RVTEST_ENABLE_MACHINE; \ 58 | .endm 59 | 60 | #define RVTEST_RV64S \ 61 | .macro init; \ 62 | RVTEST_ENABLE_SUPERVISOR; \ 63 | .endm 64 | 65 | #define RVTEST_RV64SV \ 66 | .macro init; \ 67 | RVTEST_ENABLE_SUPERVISOR; \ 68 | .endm 69 | 70 | #define RVTEST_RV32M \ 71 | .macro init; \ 72 | RVTEST_ENABLE_MACHINE; \ 73 | .endm 74 | 75 | #define RVTEST_RV32S \ 76 | .macro init; \ 77 | RVTEST_ENABLE_SUPERVISOR; \ 78 | .endm 79 | 80 | #ifdef __riscv64 81 | # define CHECK_XLEN csrr a0, misa; bltz a0, 1f; RVTEST_PASS; 1: 82 | #else 83 | # define CHECK_XLEN csrr a0, misa; bgez a0, 1f; RVTEST_PASS; 1: 84 | #endif 85 | 86 | #define RVTEST_ENABLE_SUPERVISOR \ 87 | li a0, MSTATUS_MPP & (MSTATUS_MPP >> 1); \ 88 | csrs mstatus, a0; \ 89 | li a0, SIP_SSIP | SIP_STIP; \ 90 | csrs mideleg, a0; \ 91 | 92 | #define RVTEST_ENABLE_MACHINE \ 93 | li a0, MSTATUS_MPP; \ 94 | csrs mstatus, a0; \ 95 | 96 | #define RVTEST_FP_ENABLE \ 97 | li a0, MSTATUS_FS & (MSTATUS_FS >> 1); \ 98 | csrs mstatus, a0; \ 99 | csrwi fcsr, 0 100 | 101 | #define RISCV_MULTICORE_DISABLE \ 102 | csrr a0, mhartid; \ 103 | 1: bnez a0, 1b 104 | 105 | #define EXTRA_TVEC_USER 106 | #define EXTRA_TVEC_MACHINE 107 | #define EXTRA_INIT 108 | #define EXTRA_INIT_TIMER 109 | 110 | #define INTERRUPT_HANDLER j other_exception /* No interrupts should occur */ 111 | 112 | #define RVTEST_CODE_BEGIN \ 113 | .section .text.init; \ 114 | .align 6; \ 115 | .weak stvec_handler; \ 116 | .weak mtvec_handler; \ 117 | .globl _start; \ 118 | _start: \ 119 | /* machine mode stuff deleted */ \ 120 | 1: 121 | 122 | //----------------------------------------------------------------------- 123 | // End Macro 124 | //----------------------------------------------------------------------- 125 | 126 | #define RVTEST_CODE_END \ 127 | loop: j loop; 128 | 129 | //----------------------------------------------------------------------- 130 | // Pass/Fail Macro 131 | //----------------------------------------------------------------------- 132 | 133 | #define RVTEST_PASS \ 134 | fence; \ 135 | li TESTNUM, 1; \ 136 | ecall; 137 | 138 | #define TESTNUM x28 139 | #define RVTEST_FAIL \ 140 | fence; \ 141 | 1: beqz TESTNUM, 1b; \ 142 | sll TESTNUM, TESTNUM, 1; \ 143 | or TESTNUM, TESTNUM, 1; \ 144 | ecall; 145 | 146 | //----------------------------------------------------------------------- 147 | // Data Section Macro 148 | //----------------------------------------------------------------------- 149 | 150 | #define EXTRA_DATA 151 | 152 | #define RVTEST_DATA_BEGIN \ 153 | EXTRA_DATA \ 154 | .pushsection .tohost,"aw",@progbits; \ 155 | .align 6; .global tohost; tohost: .dword 0; \ 156 | .align 6; .global fromhost; fromhost: .dword 0; \ 157 | .popsection; \ 158 | .align 4; .global begin_signature; begin_signature: 159 | 160 | #define RVTEST_DATA_END .align 4; .global end_signature; end_signature: 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /tests/env/encoding.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright (c) 2012-2015, The Regents of the University of California (Regents). 3 | All Rights Reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 3. Neither the name of the Regents nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 17 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING 18 | OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS 19 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 20 | 21 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 | PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED 24 | HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE 25 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 26 | *******************************************************************************/ 27 | 28 | 29 | #ifndef RISCV_CSR_ENCODING_H 30 | #define RISCV_CSR_ENCODING_H 31 | 32 | #define MSTATUS_UIE 0x00000001 33 | #define MSTATUS_SIE 0x00000002 34 | #define MSTATUS_HIE 0x00000004 35 | #define MSTATUS_MIE 0x00000008 36 | #define MSTATUS_UPIE 0x00000010 37 | #define MSTATUS_SPIE 0x00000020 38 | #define MSTATUS_HPIE 0x00000040 39 | #define MSTATUS_MPIE 0x00000080 40 | #define MSTATUS_SPP 0x00000100 41 | #define MSTATUS_HPP 0x00000600 42 | #define MSTATUS_MPP 0x00001800 43 | #define MSTATUS_FS 0x00006000 44 | #define MSTATUS_XS 0x00018000 45 | #define MSTATUS_MPRV 0x00020000 46 | #define MSTATUS_PUM 0x00040000 47 | #define MSTATUS_MXR 0x00080000 48 | #define MSTATUS_VM 0x1F000000 49 | #define MSTATUS32_SD 0x80000000 50 | #define MSTATUS64_SD 0x8000000000000000 51 | 52 | #define SSTATUS_UIE 0x00000001 53 | #define SSTATUS_SIE 0x00000002 54 | #define SSTATUS_UPIE 0x00000010 55 | #define SSTATUS_SPIE 0x00000020 56 | #define SSTATUS_SPP 0x00000100 57 | #define SSTATUS_FS 0x00006000 58 | #define SSTATUS_XS 0x00018000 59 | #define SSTATUS_PUM 0x00040000 60 | #define SSTATUS32_SD 0x80000000 61 | #define SSTATUS64_SD 0x8000000000000000 62 | 63 | #define DCSR_XDEBUGVER (3U<<30) 64 | #define DCSR_NDRESET (1<<29) 65 | #define DCSR_FULLRESET (1<<28) 66 | #define DCSR_HWBPCOUNT (0xfff<<16) 67 | #define DCSR_EBREAKM (1<<15) 68 | #define DCSR_EBREAKH (1<<14) 69 | #define DCSR_EBREAKS (1<<13) 70 | #define DCSR_EBREAKU (1<<12) 71 | #define DCSR_STOPCYCLE (1<<10) 72 | #define DCSR_STOPTIME (1<<9) 73 | #define DCSR_CAUSE (7<<6) 74 | #define DCSR_DEBUGINT (1<<5) 75 | #define DCSR_HALT (1<<3) 76 | #define DCSR_STEP (1<<2) 77 | #define DCSR_PRV (3<<0) 78 | 79 | #define DCSR_CAUSE_NONE 0 80 | #define DCSR_CAUSE_SWBP 1 81 | #define DCSR_CAUSE_HWBP 2 82 | #define DCSR_CAUSE_DEBUGINT 3 83 | #define DCSR_CAUSE_STEP 4 84 | #define DCSR_CAUSE_HALT 5 85 | 86 | #define MIP_SSIP (1 << IRQ_S_SOFT) 87 | #define MIP_HSIP (1 << IRQ_H_SOFT) 88 | #define MIP_MSIP (1 << IRQ_M_SOFT) 89 | #define MIP_STIP (1 << IRQ_S_TIMER) 90 | #define MIP_HTIP (1 << IRQ_H_TIMER) 91 | #define MIP_MTIP (1 << IRQ_M_TIMER) 92 | #define MIP_SEIP (1 << IRQ_S_EXT) 93 | #define MIP_HEIP (1 << IRQ_H_EXT) 94 | #define MIP_MEIP (1 << IRQ_M_EXT) 95 | 96 | #define SIP_SSIP MIP_SSIP 97 | #define SIP_STIP MIP_STIP 98 | 99 | #define PRV_U 0 100 | #define PRV_S 1 101 | #define PRV_H 2 102 | #define PRV_M 3 103 | 104 | #define VM_MBARE 0 105 | #define VM_MBB 1 106 | #define VM_MBBID 2 107 | #define VM_SV32 8 108 | #define VM_SV39 9 109 | #define VM_SV48 10 110 | 111 | #define IRQ_S_SOFT 1 112 | #define IRQ_H_SOFT 2 113 | #define IRQ_M_SOFT 3 114 | #define IRQ_S_TIMER 5 115 | #define IRQ_H_TIMER 6 116 | #define IRQ_M_TIMER 7 117 | #define IRQ_S_EXT 9 118 | #define IRQ_H_EXT 10 119 | #define IRQ_M_EXT 11 120 | #define IRQ_COP 12 121 | #define IRQ_HOST 13 122 | 123 | #define DEFAULT_RSTVEC 0x00001000 124 | #define DEFAULT_NMIVEC 0x00001004 125 | #define DEFAULT_MTVEC 0x00001010 126 | #define CONFIG_STRING_ADDR 0x0000100C 127 | #define EXT_IO_BASE 0x40000000 128 | #define DRAM_BASE 0x80000000 129 | 130 | // breakpoint control fields 131 | #define BPCONTROL_X 0x00000001 132 | #define BPCONTROL_W 0x00000002 133 | #define BPCONTROL_R 0x00000004 134 | #define BPCONTROL_U 0x00000008 135 | #define BPCONTROL_S 0x00000010 136 | #define BPCONTROL_H 0x00000020 137 | #define BPCONTROL_M 0x00000040 138 | #define BPCONTROL_BPMATCH 0x00000780 139 | #ifdef __riscv64 140 | # define BPCONTROL_BPAMASKMAX 0x0F80000000000000 141 | # define BPCONTROL_TDRTYPE 0xF000000000000000 142 | #else 143 | # define BPCONTROL_BPAMASKMAX 0x0F800000 144 | # define BPCONTROL_TDRTYPE 0xF0000000 145 | #endif 146 | 147 | // page table entry (PTE) fields 148 | #define PTE_V 0x001 // Valid 149 | #define PTE_R 0x002 // Read 150 | #define PTE_W 0x004 // Write 151 | #define PTE_X 0x008 // Execute 152 | #define PTE_U 0x010 // User 153 | #define PTE_G 0x020 // Global 154 | #define PTE_A 0x040 // Accessed 155 | #define PTE_D 0x080 // Dirty 156 | #define PTE_SOFT 0x300 // Reserved for Software 157 | 158 | #define PTE_PPN_SHIFT 10 159 | 160 | #define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V) 161 | 162 | #ifdef __riscv 163 | 164 | #ifdef __riscv64 165 | # define MSTATUS_SD MSTATUS64_SD 166 | # define SSTATUS_SD SSTATUS64_SD 167 | # define RISCV_PGLEVEL_BITS 9 168 | #else 169 | # define MSTATUS_SD MSTATUS32_SD 170 | # define SSTATUS_SD SSTATUS32_SD 171 | # define RISCV_PGLEVEL_BITS 10 172 | #endif 173 | #define RISCV_PGSHIFT 12 174 | #define RISCV_PGSIZE (1 << RISCV_PGSHIFT) 175 | 176 | #ifndef __ASSEMBLER__ 177 | 178 | #ifdef __GNUC__ 179 | 180 | #define read_csr(reg) ({ unsigned long __tmp; \ 181 | asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ 182 | __tmp; }) 183 | 184 | #define write_csr(reg, val) ({ \ 185 | if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ 186 | asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ 187 | else \ 188 | asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) 189 | 190 | #define swap_csr(reg, val) ({ unsigned long __tmp; \ 191 | if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ 192 | asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "i"(val)); \ 193 | else \ 194 | asm volatile ("csrrw %0, " #reg ", %1" : "=r"(__tmp) : "r"(val)); \ 195 | __tmp; }) 196 | 197 | #define set_csr(reg, bit) ({ unsigned long __tmp; \ 198 | if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ 199 | asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ 200 | else \ 201 | asm volatile ("csrrs %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ 202 | __tmp; }) 203 | 204 | #define clear_csr(reg, bit) ({ unsigned long __tmp; \ 205 | if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ 206 | asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "i"(bit)); \ 207 | else \ 208 | asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "r"(bit)); \ 209 | __tmp; }) 210 | 211 | #define rdtime() read_csr(time) 212 | #define rdcycle() read_csr(cycle) 213 | #define rdinstret() read_csr(instret) 214 | 215 | #endif 216 | 217 | #endif 218 | 219 | #endif 220 | 221 | #endif 222 | /* Automatically generated by parse-opcodes */ 223 | #ifndef RISCV_ENCODING_H 224 | #define RISCV_ENCODING_H 225 | #define MATCH_BEQ 0x63 226 | #define MASK_BEQ 0x707f 227 | #define MATCH_BNE 0x1063 228 | #define MASK_BNE 0x707f 229 | #define MATCH_BLT 0x4063 230 | #define MASK_BLT 0x707f 231 | #define MATCH_BGE 0x5063 232 | #define MASK_BGE 0x707f 233 | #define MATCH_BLTU 0x6063 234 | #define MASK_BLTU 0x707f 235 | #define MATCH_BGEU 0x7063 236 | #define MASK_BGEU 0x707f 237 | #define MATCH_JALR 0x67 238 | #define MASK_JALR 0x707f 239 | #define MATCH_JAL 0x6f 240 | #define MASK_JAL 0x7f 241 | #define MATCH_LUI 0x37 242 | #define MASK_LUI 0x7f 243 | #define MATCH_AUIPC 0x17 244 | #define MASK_AUIPC 0x7f 245 | #define MATCH_ADDI 0x13 246 | #define MASK_ADDI 0x707f 247 | #define MATCH_SLLI 0x1013 248 | #define MASK_SLLI 0xfc00707f 249 | #define MATCH_SLTI 0x2013 250 | #define MASK_SLTI 0x707f 251 | #define MATCH_SLTIU 0x3013 252 | #define MASK_SLTIU 0x707f 253 | #define MATCH_XORI 0x4013 254 | #define MASK_XORI 0x707f 255 | #define MATCH_SRLI 0x5013 256 | #define MASK_SRLI 0xfc00707f 257 | #define MATCH_SRAI 0x40005013 258 | #define MASK_SRAI 0xfc00707f 259 | #define MATCH_ORI 0x6013 260 | #define MASK_ORI 0x707f 261 | #define MATCH_ANDI 0x7013 262 | #define MASK_ANDI 0x707f 263 | #define MATCH_ADD 0x33 264 | #define MASK_ADD 0xfe00707f 265 | #define MATCH_SUB 0x40000033 266 | #define MASK_SUB 0xfe00707f 267 | #define MATCH_SLL 0x1033 268 | #define MASK_SLL 0xfe00707f 269 | #define MATCH_SLT 0x2033 270 | #define MASK_SLT 0xfe00707f 271 | #define MATCH_SLTU 0x3033 272 | #define MASK_SLTU 0xfe00707f 273 | #define MATCH_XOR 0x4033 274 | #define MASK_XOR 0xfe00707f 275 | #define MATCH_SRL 0x5033 276 | #define MASK_SRL 0xfe00707f 277 | #define MATCH_SRA 0x40005033 278 | #define MASK_SRA 0xfe00707f 279 | #define MATCH_OR 0x6033 280 | #define MASK_OR 0xfe00707f 281 | #define MATCH_AND 0x7033 282 | #define MASK_AND 0xfe00707f 283 | #define MATCH_ADDIW 0x1b 284 | #define MASK_ADDIW 0x707f 285 | #define MATCH_SLLIW 0x101b 286 | #define MASK_SLLIW 0xfe00707f 287 | #define MATCH_SRLIW 0x501b 288 | #define MASK_SRLIW 0xfe00707f 289 | #define MATCH_SRAIW 0x4000501b 290 | #define MASK_SRAIW 0xfe00707f 291 | #define MATCH_ADDW 0x3b 292 | #define MASK_ADDW 0xfe00707f 293 | #define MATCH_SUBW 0x4000003b 294 | #define MASK_SUBW 0xfe00707f 295 | #define MATCH_SLLW 0x103b 296 | #define MASK_SLLW 0xfe00707f 297 | #define MATCH_SRLW 0x503b 298 | #define MASK_SRLW 0xfe00707f 299 | #define MATCH_SRAW 0x4000503b 300 | #define MASK_SRAW 0xfe00707f 301 | #define MATCH_LB 0x3 302 | #define MASK_LB 0x707f 303 | #define MATCH_LH 0x1003 304 | #define MASK_LH 0x707f 305 | #define MATCH_LW 0x2003 306 | #define MASK_LW 0x707f 307 | #define MATCH_LD 0x3003 308 | #define MASK_LD 0x707f 309 | #define MATCH_LBU 0x4003 310 | #define MASK_LBU 0x707f 311 | #define MATCH_LHU 0x5003 312 | #define MASK_LHU 0x707f 313 | #define MATCH_LWU 0x6003 314 | #define MASK_LWU 0x707f 315 | #define MATCH_SB 0x23 316 | #define MASK_SB 0x707f 317 | #define MATCH_SH 0x1023 318 | #define MASK_SH 0x707f 319 | #define MATCH_SW 0x2023 320 | #define MASK_SW 0x707f 321 | #define MATCH_SD 0x3023 322 | #define MASK_SD 0x707f 323 | #define MATCH_FENCE 0xf 324 | #define MASK_FENCE 0x707f 325 | #define MATCH_FENCE_I 0x100f 326 | #define MASK_FENCE_I 0x707f 327 | #define MATCH_MUL 0x2000033 328 | #define MASK_MUL 0xfe00707f 329 | #define MATCH_MULH 0x2001033 330 | #define MASK_MULH 0xfe00707f 331 | #define MATCH_MULHSU 0x2002033 332 | #define MASK_MULHSU 0xfe00707f 333 | #define MATCH_MULHU 0x2003033 334 | #define MASK_MULHU 0xfe00707f 335 | #define MATCH_DIV 0x2004033 336 | #define MASK_DIV 0xfe00707f 337 | #define MATCH_DIVU 0x2005033 338 | #define MASK_DIVU 0xfe00707f 339 | #define MATCH_REM 0x2006033 340 | #define MASK_REM 0xfe00707f 341 | #define MATCH_REMU 0x2007033 342 | #define MASK_REMU 0xfe00707f 343 | #define MATCH_MULW 0x200003b 344 | #define MASK_MULW 0xfe00707f 345 | #define MATCH_DIVW 0x200403b 346 | #define MASK_DIVW 0xfe00707f 347 | #define MATCH_DIVUW 0x200503b 348 | #define MASK_DIVUW 0xfe00707f 349 | #define MATCH_REMW 0x200603b 350 | #define MASK_REMW 0xfe00707f 351 | #define MATCH_REMUW 0x200703b 352 | #define MASK_REMUW 0xfe00707f 353 | #define MATCH_AMOADD_W 0x202f 354 | #define MASK_AMOADD_W 0xf800707f 355 | #define MATCH_AMOXOR_W 0x2000202f 356 | #define MASK_AMOXOR_W 0xf800707f 357 | #define MATCH_AMOOR_W 0x4000202f 358 | #define MASK_AMOOR_W 0xf800707f 359 | #define MATCH_AMOAND_W 0x6000202f 360 | #define MASK_AMOAND_W 0xf800707f 361 | #define MATCH_AMOMIN_W 0x8000202f 362 | #define MASK_AMOMIN_W 0xf800707f 363 | #define MATCH_AMOMAX_W 0xa000202f 364 | #define MASK_AMOMAX_W 0xf800707f 365 | #define MATCH_AMOMINU_W 0xc000202f 366 | #define MASK_AMOMINU_W 0xf800707f 367 | #define MATCH_AMOMAXU_W 0xe000202f 368 | #define MASK_AMOMAXU_W 0xf800707f 369 | #define MATCH_AMOSWAP_W 0x800202f 370 | #define MASK_AMOSWAP_W 0xf800707f 371 | #define MATCH_LR_W 0x1000202f 372 | #define MASK_LR_W 0xf9f0707f 373 | #define MATCH_SC_W 0x1800202f 374 | #define MASK_SC_W 0xf800707f 375 | #define MATCH_AMOADD_D 0x302f 376 | #define MASK_AMOADD_D 0xf800707f 377 | #define MATCH_AMOXOR_D 0x2000302f 378 | #define MASK_AMOXOR_D 0xf800707f 379 | #define MATCH_AMOOR_D 0x4000302f 380 | #define MASK_AMOOR_D 0xf800707f 381 | #define MATCH_AMOAND_D 0x6000302f 382 | #define MASK_AMOAND_D 0xf800707f 383 | #define MATCH_AMOMIN_D 0x8000302f 384 | #define MASK_AMOMIN_D 0xf800707f 385 | #define MATCH_AMOMAX_D 0xa000302f 386 | #define MASK_AMOMAX_D 0xf800707f 387 | #define MATCH_AMOMINU_D 0xc000302f 388 | #define MASK_AMOMINU_D 0xf800707f 389 | #define MATCH_AMOMAXU_D 0xe000302f 390 | #define MASK_AMOMAXU_D 0xf800707f 391 | #define MATCH_AMOSWAP_D 0x800302f 392 | #define MASK_AMOSWAP_D 0xf800707f 393 | #define MATCH_LR_D 0x1000302f 394 | #define MASK_LR_D 0xf9f0707f 395 | #define MATCH_SC_D 0x1800302f 396 | #define MASK_SC_D 0xf800707f 397 | #define MATCH_ECALL 0x73 398 | #define MASK_ECALL 0xffffffff 399 | #define MATCH_EBREAK 0x100073 400 | #define MASK_EBREAK 0xffffffff 401 | #define MATCH_URET 0x200073 402 | #define MASK_URET 0xffffffff 403 | #define MATCH_SRET 0x10200073 404 | #define MASK_SRET 0xffffffff 405 | #define MATCH_HRET 0x20200073 406 | #define MASK_HRET 0xffffffff 407 | #define MATCH_MRET 0x30200073 408 | #define MASK_MRET 0xffffffff 409 | #define MATCH_DRET 0x7b200073 410 | #define MASK_DRET 0xffffffff 411 | #define MATCH_SFENCE_VM 0x10400073 412 | #define MASK_SFENCE_VM 0xfff07fff 413 | #define MATCH_WFI 0x10500073 414 | #define MASK_WFI 0xffffffff 415 | #define MATCH_CSRRW 0x1073 416 | #define MASK_CSRRW 0x707f 417 | #define MATCH_CSRRS 0x2073 418 | #define MASK_CSRRS 0x707f 419 | #define MATCH_CSRRC 0x3073 420 | #define MASK_CSRRC 0x707f 421 | #define MATCH_CSRRWI 0x5073 422 | #define MASK_CSRRWI 0x707f 423 | #define MATCH_CSRRSI 0x6073 424 | #define MASK_CSRRSI 0x707f 425 | #define MATCH_CSRRCI 0x7073 426 | #define MASK_CSRRCI 0x707f 427 | #define MATCH_FADD_S 0x53 428 | #define MASK_FADD_S 0xfe00007f 429 | #define MATCH_FSUB_S 0x8000053 430 | #define MASK_FSUB_S 0xfe00007f 431 | #define MATCH_FMUL_S 0x10000053 432 | #define MASK_FMUL_S 0xfe00007f 433 | #define MATCH_FDIV_S 0x18000053 434 | #define MASK_FDIV_S 0xfe00007f 435 | #define MATCH_FSGNJ_S 0x20000053 436 | #define MASK_FSGNJ_S 0xfe00707f 437 | #define MATCH_FSGNJN_S 0x20001053 438 | #define MASK_FSGNJN_S 0xfe00707f 439 | #define MATCH_FSGNJX_S 0x20002053 440 | #define MASK_FSGNJX_S 0xfe00707f 441 | #define MATCH_FMIN_S 0x28000053 442 | #define MASK_FMIN_S 0xfe00707f 443 | #define MATCH_FMAX_S 0x28001053 444 | #define MASK_FMAX_S 0xfe00707f 445 | #define MATCH_FSQRT_S 0x58000053 446 | #define MASK_FSQRT_S 0xfff0007f 447 | #define MATCH_FADD_D 0x2000053 448 | #define MASK_FADD_D 0xfe00007f 449 | #define MATCH_FSUB_D 0xa000053 450 | #define MASK_FSUB_D 0xfe00007f 451 | #define MATCH_FMUL_D 0x12000053 452 | #define MASK_FMUL_D 0xfe00007f 453 | #define MATCH_FDIV_D 0x1a000053 454 | #define MASK_FDIV_D 0xfe00007f 455 | #define MATCH_FSGNJ_D 0x22000053 456 | #define MASK_FSGNJ_D 0xfe00707f 457 | #define MATCH_FSGNJN_D 0x22001053 458 | #define MASK_FSGNJN_D 0xfe00707f 459 | #define MATCH_FSGNJX_D 0x22002053 460 | #define MASK_FSGNJX_D 0xfe00707f 461 | #define MATCH_FMIN_D 0x2a000053 462 | #define MASK_FMIN_D 0xfe00707f 463 | #define MATCH_FMAX_D 0x2a001053 464 | #define MASK_FMAX_D 0xfe00707f 465 | #define MATCH_FCVT_S_D 0x40100053 466 | #define MASK_FCVT_S_D 0xfff0007f 467 | #define MATCH_FCVT_D_S 0x42000053 468 | #define MASK_FCVT_D_S 0xfff0007f 469 | #define MATCH_FSQRT_D 0x5a000053 470 | #define MASK_FSQRT_D 0xfff0007f 471 | #define MATCH_FLE_S 0xa0000053 472 | #define MASK_FLE_S 0xfe00707f 473 | #define MATCH_FLT_S 0xa0001053 474 | #define MASK_FLT_S 0xfe00707f 475 | #define MATCH_FEQ_S 0xa0002053 476 | #define MASK_FEQ_S 0xfe00707f 477 | #define MATCH_FLE_D 0xa2000053 478 | #define MASK_FLE_D 0xfe00707f 479 | #define MATCH_FLT_D 0xa2001053 480 | #define MASK_FLT_D 0xfe00707f 481 | #define MATCH_FEQ_D 0xa2002053 482 | #define MASK_FEQ_D 0xfe00707f 483 | #define MATCH_FCVT_W_S 0xc0000053 484 | #define MASK_FCVT_W_S 0xfff0007f 485 | #define MATCH_FCVT_WU_S 0xc0100053 486 | #define MASK_FCVT_WU_S 0xfff0007f 487 | #define MATCH_FCVT_L_S 0xc0200053 488 | #define MASK_FCVT_L_S 0xfff0007f 489 | #define MATCH_FCVT_LU_S 0xc0300053 490 | #define MASK_FCVT_LU_S 0xfff0007f 491 | #define MATCH_FMV_X_S 0xe0000053 492 | #define MASK_FMV_X_S 0xfff0707f 493 | #define MATCH_FCLASS_S 0xe0001053 494 | #define MASK_FCLASS_S 0xfff0707f 495 | #define MATCH_FCVT_W_D 0xc2000053 496 | #define MASK_FCVT_W_D 0xfff0007f 497 | #define MATCH_FCVT_WU_D 0xc2100053 498 | #define MASK_FCVT_WU_D 0xfff0007f 499 | #define MATCH_FCVT_L_D 0xc2200053 500 | #define MASK_FCVT_L_D 0xfff0007f 501 | #define MATCH_FCVT_LU_D 0xc2300053 502 | #define MASK_FCVT_LU_D 0xfff0007f 503 | #define MATCH_FMV_X_D 0xe2000053 504 | #define MASK_FMV_X_D 0xfff0707f 505 | #define MATCH_FCLASS_D 0xe2001053 506 | #define MASK_FCLASS_D 0xfff0707f 507 | #define MATCH_FCVT_S_W 0xd0000053 508 | #define MASK_FCVT_S_W 0xfff0007f 509 | #define MATCH_FCVT_S_WU 0xd0100053 510 | #define MASK_FCVT_S_WU 0xfff0007f 511 | #define MATCH_FCVT_S_L 0xd0200053 512 | #define MASK_FCVT_S_L 0xfff0007f 513 | #define MATCH_FCVT_S_LU 0xd0300053 514 | #define MASK_FCVT_S_LU 0xfff0007f 515 | #define MATCH_FMV_S_X 0xf0000053 516 | #define MASK_FMV_S_X 0xfff0707f 517 | #define MATCH_FCVT_D_W 0xd2000053 518 | #define MASK_FCVT_D_W 0xfff0007f 519 | #define MATCH_FCVT_D_WU 0xd2100053 520 | #define MASK_FCVT_D_WU 0xfff0007f 521 | #define MATCH_FCVT_D_L 0xd2200053 522 | #define MASK_FCVT_D_L 0xfff0007f 523 | #define MATCH_FCVT_D_LU 0xd2300053 524 | #define MASK_FCVT_D_LU 0xfff0007f 525 | #define MATCH_FMV_D_X 0xf2000053 526 | #define MASK_FMV_D_X 0xfff0707f 527 | #define MATCH_FLW 0x2007 528 | #define MASK_FLW 0x707f 529 | #define MATCH_FLD 0x3007 530 | #define MASK_FLD 0x707f 531 | #define MATCH_FSW 0x2027 532 | #define MASK_FSW 0x707f 533 | #define MATCH_FSD 0x3027 534 | #define MASK_FSD 0x707f 535 | #define MATCH_FMADD_S 0x43 536 | #define MASK_FMADD_S 0x600007f 537 | #define MATCH_FMSUB_S 0x47 538 | #define MASK_FMSUB_S 0x600007f 539 | #define MATCH_FNMSUB_S 0x4b 540 | #define MASK_FNMSUB_S 0x600007f 541 | #define MATCH_FNMADD_S 0x4f 542 | #define MASK_FNMADD_S 0x600007f 543 | #define MATCH_FMADD_D 0x2000043 544 | #define MASK_FMADD_D 0x600007f 545 | #define MATCH_FMSUB_D 0x2000047 546 | #define MASK_FMSUB_D 0x600007f 547 | #define MATCH_FNMSUB_D 0x200004b 548 | #define MASK_FNMSUB_D 0x600007f 549 | #define MATCH_FNMADD_D 0x200004f 550 | #define MASK_FNMADD_D 0x600007f 551 | #define MATCH_C_NOP 0x1 552 | #define MASK_C_NOP 0xffff 553 | #define MATCH_C_ADDI16SP 0x6101 554 | #define MASK_C_ADDI16SP 0xef83 555 | #define MATCH_C_JR 0x8002 556 | #define MASK_C_JR 0xf07f 557 | #define MATCH_C_JALR 0x9002 558 | #define MASK_C_JALR 0xf07f 559 | #define MATCH_C_EBREAK 0x9002 560 | #define MASK_C_EBREAK 0xffff 561 | #define MATCH_C_LD 0x6000 562 | #define MASK_C_LD 0xe003 563 | #define MATCH_C_SD 0xe000 564 | #define MASK_C_SD 0xe003 565 | #define MATCH_C_ADDIW 0x2001 566 | #define MASK_C_ADDIW 0xe003 567 | #define MATCH_C_LDSP 0x6002 568 | #define MASK_C_LDSP 0xe003 569 | #define MATCH_C_SDSP 0xe002 570 | #define MASK_C_SDSP 0xe003 571 | #define MATCH_C_ADDI4SPN 0x0 572 | #define MASK_C_ADDI4SPN 0xe003 573 | #define MATCH_C_FLD 0x2000 574 | #define MASK_C_FLD 0xe003 575 | #define MATCH_C_LW 0x4000 576 | #define MASK_C_LW 0xe003 577 | #define MATCH_C_FLW 0x6000 578 | #define MASK_C_FLW 0xe003 579 | #define MATCH_C_FSD 0xa000 580 | #define MASK_C_FSD 0xe003 581 | #define MATCH_C_SW 0xc000 582 | #define MASK_C_SW 0xe003 583 | #define MATCH_C_FSW 0xe000 584 | #define MASK_C_FSW 0xe003 585 | #define MATCH_C_ADDI 0x1 586 | #define MASK_C_ADDI 0xe003 587 | #define MATCH_C_JAL 0x2001 588 | #define MASK_C_JAL 0xe003 589 | #define MATCH_C_LI 0x4001 590 | #define MASK_C_LI 0xe003 591 | #define MATCH_C_LUI 0x6001 592 | #define MASK_C_LUI 0xe003 593 | #define MATCH_C_SRLI 0x8001 594 | #define MASK_C_SRLI 0xec03 595 | #define MATCH_C_SRAI 0x8401 596 | #define MASK_C_SRAI 0xec03 597 | #define MATCH_C_ANDI 0x8801 598 | #define MASK_C_ANDI 0xec03 599 | #define MATCH_C_SUB 0x8c01 600 | #define MASK_C_SUB 0xfc63 601 | #define MATCH_C_XOR 0x8c21 602 | #define MASK_C_XOR 0xfc63 603 | #define MATCH_C_OR 0x8c41 604 | #define MASK_C_OR 0xfc63 605 | #define MATCH_C_AND 0x8c61 606 | #define MASK_C_AND 0xfc63 607 | #define MATCH_C_SUBW 0x9c01 608 | #define MASK_C_SUBW 0xfc63 609 | #define MATCH_C_ADDW 0x9c21 610 | #define MASK_C_ADDW 0xfc63 611 | #define MATCH_C_J 0xa001 612 | #define MASK_C_J 0xe003 613 | #define MATCH_C_BEQZ 0xc001 614 | #define MASK_C_BEQZ 0xe003 615 | #define MATCH_C_BNEZ 0xe001 616 | #define MASK_C_BNEZ 0xe003 617 | #define MATCH_C_SLLI 0x2 618 | #define MASK_C_SLLI 0xe003 619 | #define MATCH_C_FLDSP 0x2002 620 | #define MASK_C_FLDSP 0xe003 621 | #define MATCH_C_LWSP 0x4002 622 | #define MASK_C_LWSP 0xe003 623 | #define MATCH_C_FLWSP 0x6002 624 | #define MASK_C_FLWSP 0xe003 625 | #define MATCH_C_MV 0x8002 626 | #define MASK_C_MV 0xf003 627 | #define MATCH_C_ADD 0x9002 628 | #define MASK_C_ADD 0xf003 629 | #define MATCH_C_FSDSP 0xa002 630 | #define MASK_C_FSDSP 0xe003 631 | #define MATCH_C_SWSP 0xc002 632 | #define MASK_C_SWSP 0xe003 633 | #define MATCH_C_FSWSP 0xe002 634 | #define MASK_C_FSWSP 0xe003 635 | #define MATCH_CUSTOM0 0xb 636 | #define MASK_CUSTOM0 0x707f 637 | #define MATCH_CUSTOM0_RS1 0x200b 638 | #define MASK_CUSTOM0_RS1 0x707f 639 | #define MATCH_CUSTOM0_RS1_RS2 0x300b 640 | #define MASK_CUSTOM0_RS1_RS2 0x707f 641 | #define MATCH_CUSTOM0_RD 0x400b 642 | #define MASK_CUSTOM0_RD 0x707f 643 | #define MATCH_CUSTOM0_RD_RS1 0x600b 644 | #define MASK_CUSTOM0_RD_RS1 0x707f 645 | #define MATCH_CUSTOM0_RD_RS1_RS2 0x700b 646 | #define MASK_CUSTOM0_RD_RS1_RS2 0x707f 647 | #define MATCH_CUSTOM1 0x2b 648 | #define MASK_CUSTOM1 0x707f 649 | #define MATCH_CUSTOM1_RS1 0x202b 650 | #define MASK_CUSTOM1_RS1 0x707f 651 | #define MATCH_CUSTOM1_RS1_RS2 0x302b 652 | #define MASK_CUSTOM1_RS1_RS2 0x707f 653 | #define MATCH_CUSTOM1_RD 0x402b 654 | #define MASK_CUSTOM1_RD 0x707f 655 | #define MATCH_CUSTOM1_RD_RS1 0x602b 656 | #define MASK_CUSTOM1_RD_RS1 0x707f 657 | #define MATCH_CUSTOM1_RD_RS1_RS2 0x702b 658 | #define MASK_CUSTOM1_RD_RS1_RS2 0x707f 659 | #define MATCH_CUSTOM2 0x5b 660 | #define MASK_CUSTOM2 0x707f 661 | #define MATCH_CUSTOM2_RS1 0x205b 662 | #define MASK_CUSTOM2_RS1 0x707f 663 | #define MATCH_CUSTOM2_RS1_RS2 0x305b 664 | #define MASK_CUSTOM2_RS1_RS2 0x707f 665 | #define MATCH_CUSTOM2_RD 0x405b 666 | #define MASK_CUSTOM2_RD 0x707f 667 | #define MATCH_CUSTOM2_RD_RS1 0x605b 668 | #define MASK_CUSTOM2_RD_RS1 0x707f 669 | #define MATCH_CUSTOM2_RD_RS1_RS2 0x705b 670 | #define MASK_CUSTOM2_RD_RS1_RS2 0x707f 671 | #define MATCH_CUSTOM3 0x7b 672 | #define MASK_CUSTOM3 0x707f 673 | #define MATCH_CUSTOM3_RS1 0x207b 674 | #define MASK_CUSTOM3_RS1 0x707f 675 | #define MATCH_CUSTOM3_RS1_RS2 0x307b 676 | #define MASK_CUSTOM3_RS1_RS2 0x707f 677 | #define MATCH_CUSTOM3_RD 0x407b 678 | #define MASK_CUSTOM3_RD 0x707f 679 | #define MATCH_CUSTOM3_RD_RS1 0x607b 680 | #define MASK_CUSTOM3_RD_RS1 0x707f 681 | #define MATCH_CUSTOM3_RD_RS1_RS2 0x707b 682 | #define MASK_CUSTOM3_RD_RS1_RS2 0x707f 683 | #define CSR_FFLAGS 0x1 684 | #define CSR_FRM 0x2 685 | #define CSR_FCSR 0x3 686 | #define CSR_CYCLE 0xc00 687 | #define CSR_TIME 0xc01 688 | #define CSR_INSTRET 0xc02 689 | #define CSR_SSTATUS 0x100 690 | #define CSR_SIE 0x104 691 | #define CSR_STVEC 0x105 692 | #define CSR_SSCRATCH 0x140 693 | #define CSR_SEPC 0x141 694 | #define CSR_SCAUSE 0x142 695 | #define CSR_SBADADDR 0x143 696 | #define CSR_SIP 0x144 697 | #define CSR_SPTBR 0x180 698 | #define CSR_SCYCLE 0xd00 699 | #define CSR_STIME 0xd01 700 | #define CSR_SINSTRET 0xd02 701 | #define CSR_MSTATUS 0x300 702 | #define CSR_MEDELEG 0x302 703 | #define CSR_MIDELEG 0x303 704 | #define CSR_MIE 0x304 705 | #define CSR_MTVEC 0x305 706 | #define CSR_MSCRATCH 0x340 707 | #define CSR_MEPC 0x341 708 | #define CSR_MCAUSE 0x342 709 | #define CSR_MBADADDR 0x343 710 | #define CSR_MIP 0x344 711 | #define CSR_MUCOUNTEREN 0x310 712 | #define CSR_MSCOUNTEREN 0x311 713 | #define CSR_MUCYCLE_DELTA 0x700 714 | #define CSR_MUTIME_DELTA 0x701 715 | #define CSR_MUINSTRET_DELTA 0x702 716 | #define CSR_MSCYCLE_DELTA 0x704 717 | #define CSR_MSTIME_DELTA 0x705 718 | #define CSR_MSINSTRET_DELTA 0x706 719 | #define CSR_TDRSELECT 0x7a0 720 | #define CSR_TDRDATA1 0x7a1 721 | #define CSR_TDRDATA2 0x7a2 722 | #define CSR_TDRDATA3 0x7a3 723 | #define CSR_DCSR 0x7b0 724 | #define CSR_DPC 0x7b1 725 | #define CSR_DSCRATCH 0x7b2 726 | #define CSR_MCYCLE 0xf00 727 | #define CSR_MTIME 0xf01 728 | #define CSR_MINSTRET 0xf02 729 | #define CSR_MISA 0xf10 730 | #define CSR_MVENDORID 0xf11 731 | #define CSR_MARCHID 0xf12 732 | #define CSR_MIMPID 0xf13 733 | #define CSR_MHARTID 0xf14 734 | #define CSR_MRESET 0x7c2 735 | #define CSR_CYCLEH 0xc80 736 | #define CSR_TIMEH 0xc81 737 | #define CSR_INSTRETH 0xc82 738 | #define CSR_MUCYCLE_DELTAH 0x780 739 | #define CSR_MUTIME_DELTAH 0x781 740 | #define CSR_MUINSTRET_DELTAH 0x782 741 | #define CSR_MSCYCLE_DELTAH 0x784 742 | #define CSR_MSTIME_DELTAH 0x785 743 | #define CSR_MSINSTRET_DELTAH 0x786 744 | #define CSR_MCYCLEH 0xf80 745 | #define CSR_MTIMEH 0xf81 746 | #define CSR_MINSTRETH 0xf82 747 | #define CAUSE_MISALIGNED_FETCH 0x0 748 | #define CAUSE_FAULT_FETCH 0x1 749 | #define CAUSE_ILLEGAL_INSTRUCTION 0x2 750 | #define CAUSE_BREAKPOINT 0x3 751 | #define CAUSE_MISALIGNED_LOAD 0x4 752 | #define CAUSE_FAULT_LOAD 0x5 753 | #define CAUSE_MISALIGNED_STORE 0x6 754 | #define CAUSE_FAULT_STORE 0x7 755 | #define CAUSE_USER_ECALL 0x8 756 | #define CAUSE_SUPERVISOR_ECALL 0x9 757 | #define CAUSE_HYPERVISOR_ECALL 0xa 758 | #define CAUSE_MACHINE_ECALL 0xb 759 | #endif 760 | #ifdef DECLARE_INSN 761 | DECLARE_INSN(beq, MATCH_BEQ, MASK_BEQ) 762 | DECLARE_INSN(bne, MATCH_BNE, MASK_BNE) 763 | DECLARE_INSN(blt, MATCH_BLT, MASK_BLT) 764 | DECLARE_INSN(bge, MATCH_BGE, MASK_BGE) 765 | DECLARE_INSN(bltu, MATCH_BLTU, MASK_BLTU) 766 | DECLARE_INSN(bgeu, MATCH_BGEU, MASK_BGEU) 767 | DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR) 768 | DECLARE_INSN(jal, MATCH_JAL, MASK_JAL) 769 | DECLARE_INSN(lui, MATCH_LUI, MASK_LUI) 770 | DECLARE_INSN(auipc, MATCH_AUIPC, MASK_AUIPC) 771 | DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI) 772 | DECLARE_INSN(slli, MATCH_SLLI, MASK_SLLI) 773 | DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI) 774 | DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU) 775 | DECLARE_INSN(xori, MATCH_XORI, MASK_XORI) 776 | DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI) 777 | DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI) 778 | DECLARE_INSN(ori, MATCH_ORI, MASK_ORI) 779 | DECLARE_INSN(andi, MATCH_ANDI, MASK_ANDI) 780 | DECLARE_INSN(add, MATCH_ADD, MASK_ADD) 781 | DECLARE_INSN(sub, MATCH_SUB, MASK_SUB) 782 | DECLARE_INSN(sll, MATCH_SLL, MASK_SLL) 783 | DECLARE_INSN(slt, MATCH_SLT, MASK_SLT) 784 | DECLARE_INSN(sltu, MATCH_SLTU, MASK_SLTU) 785 | DECLARE_INSN(xor, MATCH_XOR, MASK_XOR) 786 | DECLARE_INSN(srl, MATCH_SRL, MASK_SRL) 787 | DECLARE_INSN(sra, MATCH_SRA, MASK_SRA) 788 | DECLARE_INSN(or, MATCH_OR, MASK_OR) 789 | DECLARE_INSN(and, MATCH_AND, MASK_AND) 790 | DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW) 791 | DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW) 792 | DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW) 793 | DECLARE_INSN(sraiw, MATCH_SRAIW, MASK_SRAIW) 794 | DECLARE_INSN(addw, MATCH_ADDW, MASK_ADDW) 795 | DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW) 796 | DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW) 797 | DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW) 798 | DECLARE_INSN(sraw, MATCH_SRAW, MASK_SRAW) 799 | DECLARE_INSN(lb, MATCH_LB, MASK_LB) 800 | DECLARE_INSN(lh, MATCH_LH, MASK_LH) 801 | DECLARE_INSN(lw, MATCH_LW, MASK_LW) 802 | DECLARE_INSN(ld, MATCH_LD, MASK_LD) 803 | DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU) 804 | DECLARE_INSN(lhu, MATCH_LHU, MASK_LHU) 805 | DECLARE_INSN(lwu, MATCH_LWU, MASK_LWU) 806 | DECLARE_INSN(sb, MATCH_SB, MASK_SB) 807 | DECLARE_INSN(sh, MATCH_SH, MASK_SH) 808 | DECLARE_INSN(sw, MATCH_SW, MASK_SW) 809 | DECLARE_INSN(sd, MATCH_SD, MASK_SD) 810 | DECLARE_INSN(fence, MATCH_FENCE, MASK_FENCE) 811 | DECLARE_INSN(fence_i, MATCH_FENCE_I, MASK_FENCE_I) 812 | DECLARE_INSN(mul, MATCH_MUL, MASK_MUL) 813 | DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH) 814 | DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU) 815 | DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU) 816 | DECLARE_INSN(div, MATCH_DIV, MASK_DIV) 817 | DECLARE_INSN(divu, MATCH_DIVU, MASK_DIVU) 818 | DECLARE_INSN(rem, MATCH_REM, MASK_REM) 819 | DECLARE_INSN(remu, MATCH_REMU, MASK_REMU) 820 | DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW) 821 | DECLARE_INSN(divw, MATCH_DIVW, MASK_DIVW) 822 | DECLARE_INSN(divuw, MATCH_DIVUW, MASK_DIVUW) 823 | DECLARE_INSN(remw, MATCH_REMW, MASK_REMW) 824 | DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW) 825 | DECLARE_INSN(amoadd_w, MATCH_AMOADD_W, MASK_AMOADD_W) 826 | DECLARE_INSN(amoxor_w, MATCH_AMOXOR_W, MASK_AMOXOR_W) 827 | DECLARE_INSN(amoor_w, MATCH_AMOOR_W, MASK_AMOOR_W) 828 | DECLARE_INSN(amoand_w, MATCH_AMOAND_W, MASK_AMOAND_W) 829 | DECLARE_INSN(amomin_w, MATCH_AMOMIN_W, MASK_AMOMIN_W) 830 | DECLARE_INSN(amomax_w, MATCH_AMOMAX_W, MASK_AMOMAX_W) 831 | DECLARE_INSN(amominu_w, MATCH_AMOMINU_W, MASK_AMOMINU_W) 832 | DECLARE_INSN(amomaxu_w, MATCH_AMOMAXU_W, MASK_AMOMAXU_W) 833 | DECLARE_INSN(amoswap_w, MATCH_AMOSWAP_W, MASK_AMOSWAP_W) 834 | DECLARE_INSN(lr_w, MATCH_LR_W, MASK_LR_W) 835 | DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W) 836 | DECLARE_INSN(amoadd_d, MATCH_AMOADD_D, MASK_AMOADD_D) 837 | DECLARE_INSN(amoxor_d, MATCH_AMOXOR_D, MASK_AMOXOR_D) 838 | DECLARE_INSN(amoor_d, MATCH_AMOOR_D, MASK_AMOOR_D) 839 | DECLARE_INSN(amoand_d, MATCH_AMOAND_D, MASK_AMOAND_D) 840 | DECLARE_INSN(amomin_d, MATCH_AMOMIN_D, MASK_AMOMIN_D) 841 | DECLARE_INSN(amomax_d, MATCH_AMOMAX_D, MASK_AMOMAX_D) 842 | DECLARE_INSN(amominu_d, MATCH_AMOMINU_D, MASK_AMOMINU_D) 843 | DECLARE_INSN(amomaxu_d, MATCH_AMOMAXU_D, MASK_AMOMAXU_D) 844 | DECLARE_INSN(amoswap_d, MATCH_AMOSWAP_D, MASK_AMOSWAP_D) 845 | DECLARE_INSN(lr_d, MATCH_LR_D, MASK_LR_D) 846 | DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D) 847 | DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL) 848 | DECLARE_INSN(ebreak, MATCH_EBREAK, MASK_EBREAK) 849 | DECLARE_INSN(uret, MATCH_URET, MASK_URET) 850 | DECLARE_INSN(sret, MATCH_SRET, MASK_SRET) 851 | DECLARE_INSN(hret, MATCH_HRET, MASK_HRET) 852 | DECLARE_INSN(mret, MATCH_MRET, MASK_MRET) 853 | DECLARE_INSN(dret, MATCH_DRET, MASK_DRET) 854 | DECLARE_INSN(sfence_vm, MATCH_SFENCE_VM, MASK_SFENCE_VM) 855 | DECLARE_INSN(wfi, MATCH_WFI, MASK_WFI) 856 | DECLARE_INSN(csrrw, MATCH_CSRRW, MASK_CSRRW) 857 | DECLARE_INSN(csrrs, MATCH_CSRRS, MASK_CSRRS) 858 | DECLARE_INSN(csrrc, MATCH_CSRRC, MASK_CSRRC) 859 | DECLARE_INSN(csrrwi, MATCH_CSRRWI, MASK_CSRRWI) 860 | DECLARE_INSN(csrrsi, MATCH_CSRRSI, MASK_CSRRSI) 861 | DECLARE_INSN(csrrci, MATCH_CSRRCI, MASK_CSRRCI) 862 | DECLARE_INSN(fadd_s, MATCH_FADD_S, MASK_FADD_S) 863 | DECLARE_INSN(fsub_s, MATCH_FSUB_S, MASK_FSUB_S) 864 | DECLARE_INSN(fmul_s, MATCH_FMUL_S, MASK_FMUL_S) 865 | DECLARE_INSN(fdiv_s, MATCH_FDIV_S, MASK_FDIV_S) 866 | DECLARE_INSN(fsgnj_s, MATCH_FSGNJ_S, MASK_FSGNJ_S) 867 | DECLARE_INSN(fsgnjn_s, MATCH_FSGNJN_S, MASK_FSGNJN_S) 868 | DECLARE_INSN(fsgnjx_s, MATCH_FSGNJX_S, MASK_FSGNJX_S) 869 | DECLARE_INSN(fmin_s, MATCH_FMIN_S, MASK_FMIN_S) 870 | DECLARE_INSN(fmax_s, MATCH_FMAX_S, MASK_FMAX_S) 871 | DECLARE_INSN(fsqrt_s, MATCH_FSQRT_S, MASK_FSQRT_S) 872 | DECLARE_INSN(fadd_d, MATCH_FADD_D, MASK_FADD_D) 873 | DECLARE_INSN(fsub_d, MATCH_FSUB_D, MASK_FSUB_D) 874 | DECLARE_INSN(fmul_d, MATCH_FMUL_D, MASK_FMUL_D) 875 | DECLARE_INSN(fdiv_d, MATCH_FDIV_D, MASK_FDIV_D) 876 | DECLARE_INSN(fsgnj_d, MATCH_FSGNJ_D, MASK_FSGNJ_D) 877 | DECLARE_INSN(fsgnjn_d, MATCH_FSGNJN_D, MASK_FSGNJN_D) 878 | DECLARE_INSN(fsgnjx_d, MATCH_FSGNJX_D, MASK_FSGNJX_D) 879 | DECLARE_INSN(fmin_d, MATCH_FMIN_D, MASK_FMIN_D) 880 | DECLARE_INSN(fmax_d, MATCH_FMAX_D, MASK_FMAX_D) 881 | DECLARE_INSN(fcvt_s_d, MATCH_FCVT_S_D, MASK_FCVT_S_D) 882 | DECLARE_INSN(fcvt_d_s, MATCH_FCVT_D_S, MASK_FCVT_D_S) 883 | DECLARE_INSN(fsqrt_d, MATCH_FSQRT_D, MASK_FSQRT_D) 884 | DECLARE_INSN(fle_s, MATCH_FLE_S, MASK_FLE_S) 885 | DECLARE_INSN(flt_s, MATCH_FLT_S, MASK_FLT_S) 886 | DECLARE_INSN(feq_s, MATCH_FEQ_S, MASK_FEQ_S) 887 | DECLARE_INSN(fle_d, MATCH_FLE_D, MASK_FLE_D) 888 | DECLARE_INSN(flt_d, MATCH_FLT_D, MASK_FLT_D) 889 | DECLARE_INSN(feq_d, MATCH_FEQ_D, MASK_FEQ_D) 890 | DECLARE_INSN(fcvt_w_s, MATCH_FCVT_W_S, MASK_FCVT_W_S) 891 | DECLARE_INSN(fcvt_wu_s, MATCH_FCVT_WU_S, MASK_FCVT_WU_S) 892 | DECLARE_INSN(fcvt_l_s, MATCH_FCVT_L_S, MASK_FCVT_L_S) 893 | DECLARE_INSN(fcvt_lu_s, MATCH_FCVT_LU_S, MASK_FCVT_LU_S) 894 | DECLARE_INSN(fmv_x_s, MATCH_FMV_X_S, MASK_FMV_X_S) 895 | DECLARE_INSN(fclass_s, MATCH_FCLASS_S, MASK_FCLASS_S) 896 | DECLARE_INSN(fcvt_w_d, MATCH_FCVT_W_D, MASK_FCVT_W_D) 897 | DECLARE_INSN(fcvt_wu_d, MATCH_FCVT_WU_D, MASK_FCVT_WU_D) 898 | DECLARE_INSN(fcvt_l_d, MATCH_FCVT_L_D, MASK_FCVT_L_D) 899 | DECLARE_INSN(fcvt_lu_d, MATCH_FCVT_LU_D, MASK_FCVT_LU_D) 900 | DECLARE_INSN(fmv_x_d, MATCH_FMV_X_D, MASK_FMV_X_D) 901 | DECLARE_INSN(fclass_d, MATCH_FCLASS_D, MASK_FCLASS_D) 902 | DECLARE_INSN(fcvt_s_w, MATCH_FCVT_S_W, MASK_FCVT_S_W) 903 | DECLARE_INSN(fcvt_s_wu, MATCH_FCVT_S_WU, MASK_FCVT_S_WU) 904 | DECLARE_INSN(fcvt_s_l, MATCH_FCVT_S_L, MASK_FCVT_S_L) 905 | DECLARE_INSN(fcvt_s_lu, MATCH_FCVT_S_LU, MASK_FCVT_S_LU) 906 | DECLARE_INSN(fmv_s_x, MATCH_FMV_S_X, MASK_FMV_S_X) 907 | DECLARE_INSN(fcvt_d_w, MATCH_FCVT_D_W, MASK_FCVT_D_W) 908 | DECLARE_INSN(fcvt_d_wu, MATCH_FCVT_D_WU, MASK_FCVT_D_WU) 909 | DECLARE_INSN(fcvt_d_l, MATCH_FCVT_D_L, MASK_FCVT_D_L) 910 | DECLARE_INSN(fcvt_d_lu, MATCH_FCVT_D_LU, MASK_FCVT_D_LU) 911 | DECLARE_INSN(fmv_d_x, MATCH_FMV_D_X, MASK_FMV_D_X) 912 | DECLARE_INSN(flw, MATCH_FLW, MASK_FLW) 913 | DECLARE_INSN(fld, MATCH_FLD, MASK_FLD) 914 | DECLARE_INSN(fsw, MATCH_FSW, MASK_FSW) 915 | DECLARE_INSN(fsd, MATCH_FSD, MASK_FSD) 916 | DECLARE_INSN(fmadd_s, MATCH_FMADD_S, MASK_FMADD_S) 917 | DECLARE_INSN(fmsub_s, MATCH_FMSUB_S, MASK_FMSUB_S) 918 | DECLARE_INSN(fnmsub_s, MATCH_FNMSUB_S, MASK_FNMSUB_S) 919 | DECLARE_INSN(fnmadd_s, MATCH_FNMADD_S, MASK_FNMADD_S) 920 | DECLARE_INSN(fmadd_d, MATCH_FMADD_D, MASK_FMADD_D) 921 | DECLARE_INSN(fmsub_d, MATCH_FMSUB_D, MASK_FMSUB_D) 922 | DECLARE_INSN(fnmsub_d, MATCH_FNMSUB_D, MASK_FNMSUB_D) 923 | DECLARE_INSN(fnmadd_d, MATCH_FNMADD_D, MASK_FNMADD_D) 924 | DECLARE_INSN(c_nop, MATCH_C_NOP, MASK_C_NOP) 925 | DECLARE_INSN(c_addi16sp, MATCH_C_ADDI16SP, MASK_C_ADDI16SP) 926 | DECLARE_INSN(c_jr, MATCH_C_JR, MASK_C_JR) 927 | DECLARE_INSN(c_jalr, MATCH_C_JALR, MASK_C_JALR) 928 | DECLARE_INSN(c_ebreak, MATCH_C_EBREAK, MASK_C_EBREAK) 929 | DECLARE_INSN(c_ld, MATCH_C_LD, MASK_C_LD) 930 | DECLARE_INSN(c_sd, MATCH_C_SD, MASK_C_SD) 931 | DECLARE_INSN(c_addiw, MATCH_C_ADDIW, MASK_C_ADDIW) 932 | DECLARE_INSN(c_ldsp, MATCH_C_LDSP, MASK_C_LDSP) 933 | DECLARE_INSN(c_sdsp, MATCH_C_SDSP, MASK_C_SDSP) 934 | DECLARE_INSN(c_addi4spn, MATCH_C_ADDI4SPN, MASK_C_ADDI4SPN) 935 | DECLARE_INSN(c_fld, MATCH_C_FLD, MASK_C_FLD) 936 | DECLARE_INSN(c_lw, MATCH_C_LW, MASK_C_LW) 937 | DECLARE_INSN(c_flw, MATCH_C_FLW, MASK_C_FLW) 938 | DECLARE_INSN(c_fsd, MATCH_C_FSD, MASK_C_FSD) 939 | DECLARE_INSN(c_sw, MATCH_C_SW, MASK_C_SW) 940 | DECLARE_INSN(c_fsw, MATCH_C_FSW, MASK_C_FSW) 941 | DECLARE_INSN(c_addi, MATCH_C_ADDI, MASK_C_ADDI) 942 | DECLARE_INSN(c_jal, MATCH_C_JAL, MASK_C_JAL) 943 | DECLARE_INSN(c_li, MATCH_C_LI, MASK_C_LI) 944 | DECLARE_INSN(c_lui, MATCH_C_LUI, MASK_C_LUI) 945 | DECLARE_INSN(c_srli, MATCH_C_SRLI, MASK_C_SRLI) 946 | DECLARE_INSN(c_srai, MATCH_C_SRAI, MASK_C_SRAI) 947 | DECLARE_INSN(c_andi, MATCH_C_ANDI, MASK_C_ANDI) 948 | DECLARE_INSN(c_sub, MATCH_C_SUB, MASK_C_SUB) 949 | DECLARE_INSN(c_xor, MATCH_C_XOR, MASK_C_XOR) 950 | DECLARE_INSN(c_or, MATCH_C_OR, MASK_C_OR) 951 | DECLARE_INSN(c_and, MATCH_C_AND, MASK_C_AND) 952 | DECLARE_INSN(c_subw, MATCH_C_SUBW, MASK_C_SUBW) 953 | DECLARE_INSN(c_addw, MATCH_C_ADDW, MASK_C_ADDW) 954 | DECLARE_INSN(c_j, MATCH_C_J, MASK_C_J) 955 | DECLARE_INSN(c_beqz, MATCH_C_BEQZ, MASK_C_BEQZ) 956 | DECLARE_INSN(c_bnez, MATCH_C_BNEZ, MASK_C_BNEZ) 957 | DECLARE_INSN(c_slli, MATCH_C_SLLI, MASK_C_SLLI) 958 | DECLARE_INSN(c_fldsp, MATCH_C_FLDSP, MASK_C_FLDSP) 959 | DECLARE_INSN(c_lwsp, MATCH_C_LWSP, MASK_C_LWSP) 960 | DECLARE_INSN(c_flwsp, MATCH_C_FLWSP, MASK_C_FLWSP) 961 | DECLARE_INSN(c_mv, MATCH_C_MV, MASK_C_MV) 962 | DECLARE_INSN(c_add, MATCH_C_ADD, MASK_C_ADD) 963 | DECLARE_INSN(c_fsdsp, MATCH_C_FSDSP, MASK_C_FSDSP) 964 | DECLARE_INSN(c_swsp, MATCH_C_SWSP, MASK_C_SWSP) 965 | DECLARE_INSN(c_fswsp, MATCH_C_FSWSP, MASK_C_FSWSP) 966 | DECLARE_INSN(custom0, MATCH_CUSTOM0, MASK_CUSTOM0) 967 | DECLARE_INSN(custom0_rs1, MATCH_CUSTOM0_RS1, MASK_CUSTOM0_RS1) 968 | DECLARE_INSN(custom0_rs1_rs2, MATCH_CUSTOM0_RS1_RS2, MASK_CUSTOM0_RS1_RS2) 969 | DECLARE_INSN(custom0_rd, MATCH_CUSTOM0_RD, MASK_CUSTOM0_RD) 970 | DECLARE_INSN(custom0_rd_rs1, MATCH_CUSTOM0_RD_RS1, MASK_CUSTOM0_RD_RS1) 971 | DECLARE_INSN(custom0_rd_rs1_rs2, MATCH_CUSTOM0_RD_RS1_RS2, MASK_CUSTOM0_RD_RS1_RS2) 972 | DECLARE_INSN(custom1, MATCH_CUSTOM1, MASK_CUSTOM1) 973 | DECLARE_INSN(custom1_rs1, MATCH_CUSTOM1_RS1, MASK_CUSTOM1_RS1) 974 | DECLARE_INSN(custom1_rs1_rs2, MATCH_CUSTOM1_RS1_RS2, MASK_CUSTOM1_RS1_RS2) 975 | DECLARE_INSN(custom1_rd, MATCH_CUSTOM1_RD, MASK_CUSTOM1_RD) 976 | DECLARE_INSN(custom1_rd_rs1, MATCH_CUSTOM1_RD_RS1, MASK_CUSTOM1_RD_RS1) 977 | DECLARE_INSN(custom1_rd_rs1_rs2, MATCH_CUSTOM1_RD_RS1_RS2, MASK_CUSTOM1_RD_RS1_RS2) 978 | DECLARE_INSN(custom2, MATCH_CUSTOM2, MASK_CUSTOM2) 979 | DECLARE_INSN(custom2_rs1, MATCH_CUSTOM2_RS1, MASK_CUSTOM2_RS1) 980 | DECLARE_INSN(custom2_rs1_rs2, MATCH_CUSTOM2_RS1_RS2, MASK_CUSTOM2_RS1_RS2) 981 | DECLARE_INSN(custom2_rd, MATCH_CUSTOM2_RD, MASK_CUSTOM2_RD) 982 | DECLARE_INSN(custom2_rd_rs1, MATCH_CUSTOM2_RD_RS1, MASK_CUSTOM2_RD_RS1) 983 | DECLARE_INSN(custom2_rd_rs1_rs2, MATCH_CUSTOM2_RD_RS1_RS2, MASK_CUSTOM2_RD_RS1_RS2) 984 | DECLARE_INSN(custom3, MATCH_CUSTOM3, MASK_CUSTOM3) 985 | DECLARE_INSN(custom3_rs1, MATCH_CUSTOM3_RS1, MASK_CUSTOM3_RS1) 986 | DECLARE_INSN(custom3_rs1_rs2, MATCH_CUSTOM3_RS1_RS2, MASK_CUSTOM3_RS1_RS2) 987 | DECLARE_INSN(custom3_rd, MATCH_CUSTOM3_RD, MASK_CUSTOM3_RD) 988 | DECLARE_INSN(custom3_rd_rs1, MATCH_CUSTOM3_RD_RS1, MASK_CUSTOM3_RD_RS1) 989 | DECLARE_INSN(custom3_rd_rs1_rs2, MATCH_CUSTOM3_RD_RS1_RS2, MASK_CUSTOM3_RD_RS1_RS2) 990 | #endif 991 | #ifdef DECLARE_CSR 992 | DECLARE_CSR(fflags, CSR_FFLAGS) 993 | DECLARE_CSR(frm, CSR_FRM) 994 | DECLARE_CSR(fcsr, CSR_FCSR) 995 | DECLARE_CSR(cycle, CSR_CYCLE) 996 | DECLARE_CSR(time, CSR_TIME) 997 | DECLARE_CSR(instret, CSR_INSTRET) 998 | DECLARE_CSR(sstatus, CSR_SSTATUS) 999 | DECLARE_CSR(sie, CSR_SIE) 1000 | DECLARE_CSR(stvec, CSR_STVEC) 1001 | DECLARE_CSR(sscratch, CSR_SSCRATCH) 1002 | DECLARE_CSR(sepc, CSR_SEPC) 1003 | DECLARE_CSR(scause, CSR_SCAUSE) 1004 | DECLARE_CSR(sbadaddr, CSR_SBADADDR) 1005 | DECLARE_CSR(sip, CSR_SIP) 1006 | DECLARE_CSR(sptbr, CSR_SPTBR) 1007 | DECLARE_CSR(scycle, CSR_SCYCLE) 1008 | DECLARE_CSR(stime, CSR_STIME) 1009 | DECLARE_CSR(sinstret, CSR_SINSTRET) 1010 | DECLARE_CSR(mstatus, CSR_MSTATUS) 1011 | DECLARE_CSR(medeleg, CSR_MEDELEG) 1012 | DECLARE_CSR(mideleg, CSR_MIDELEG) 1013 | DECLARE_CSR(mie, CSR_MIE) 1014 | DECLARE_CSR(mtvec, CSR_MTVEC) 1015 | DECLARE_CSR(mscratch, CSR_MSCRATCH) 1016 | DECLARE_CSR(mepc, CSR_MEPC) 1017 | DECLARE_CSR(mcause, CSR_MCAUSE) 1018 | DECLARE_CSR(mbadaddr, CSR_MBADADDR) 1019 | DECLARE_CSR(mip, CSR_MIP) 1020 | DECLARE_CSR(mucounteren, CSR_MUCOUNTEREN) 1021 | DECLARE_CSR(mscounteren, CSR_MSCOUNTEREN) 1022 | DECLARE_CSR(mucycle_delta, CSR_MUCYCLE_DELTA) 1023 | DECLARE_CSR(mutime_delta, CSR_MUTIME_DELTA) 1024 | DECLARE_CSR(muinstret_delta, CSR_MUINSTRET_DELTA) 1025 | DECLARE_CSR(mscycle_delta, CSR_MSCYCLE_DELTA) 1026 | DECLARE_CSR(mstime_delta, CSR_MSTIME_DELTA) 1027 | DECLARE_CSR(msinstret_delta, CSR_MSINSTRET_DELTA) 1028 | DECLARE_CSR(tdrselect, CSR_TDRSELECT) 1029 | DECLARE_CSR(tdrdata1, CSR_TDRDATA1) 1030 | DECLARE_CSR(tdrdata2, CSR_TDRDATA2) 1031 | DECLARE_CSR(tdrdata3, CSR_TDRDATA3) 1032 | DECLARE_CSR(dcsr, CSR_DCSR) 1033 | DECLARE_CSR(dpc, CSR_DPC) 1034 | DECLARE_CSR(dscratch, CSR_DSCRATCH) 1035 | DECLARE_CSR(mcycle, CSR_MCYCLE) 1036 | DECLARE_CSR(mtime, CSR_MTIME) 1037 | DECLARE_CSR(minstret, CSR_MINSTRET) 1038 | DECLARE_CSR(misa, CSR_MISA) 1039 | DECLARE_CSR(mvendorid, CSR_MVENDORID) 1040 | DECLARE_CSR(marchid, CSR_MARCHID) 1041 | DECLARE_CSR(mimpid, CSR_MIMPID) 1042 | DECLARE_CSR(mhartid, CSR_MHARTID) 1043 | DECLARE_CSR(mreset, CSR_MRESET) 1044 | DECLARE_CSR(cycleh, CSR_CYCLEH) 1045 | DECLARE_CSR(timeh, CSR_TIMEH) 1046 | DECLARE_CSR(instreth, CSR_INSTRETH) 1047 | DECLARE_CSR(mucycle_deltah, CSR_MUCYCLE_DELTAH) 1048 | DECLARE_CSR(mutime_deltah, CSR_MUTIME_DELTAH) 1049 | DECLARE_CSR(muinstret_deltah, CSR_MUINSTRET_DELTAH) 1050 | DECLARE_CSR(mscycle_deltah, CSR_MSCYCLE_DELTAH) 1051 | DECLARE_CSR(mstime_deltah, CSR_MSTIME_DELTAH) 1052 | DECLARE_CSR(msinstret_deltah, CSR_MSINSTRET_DELTAH) 1053 | DECLARE_CSR(mcycleh, CSR_MCYCLEH) 1054 | DECLARE_CSR(mtimeh, CSR_MTIMEH) 1055 | DECLARE_CSR(minstreth, CSR_MINSTRETH) 1056 | #endif 1057 | #ifdef DECLARE_CAUSE 1058 | DECLARE_CAUSE("misaligned fetch", CAUSE_MISALIGNED_FETCH) 1059 | DECLARE_CAUSE("fault fetch", CAUSE_FAULT_FETCH) 1060 | DECLARE_CAUSE("illegal instruction", CAUSE_ILLEGAL_INSTRUCTION) 1061 | DECLARE_CAUSE("breakpoint", CAUSE_BREAKPOINT) 1062 | DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD) 1063 | DECLARE_CAUSE("fault load", CAUSE_FAULT_LOAD) 1064 | DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE) 1065 | DECLARE_CAUSE("fault store", CAUSE_FAULT_STORE) 1066 | DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL) 1067 | DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL) 1068 | DECLARE_CAUSE("hypervisor_ecall", CAUSE_HYPERVISOR_ECALL) 1069 | DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL) 1070 | #endif 1071 | -------------------------------------------------------------------------------- /tests/link.ld: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | Copyright (c) 2016, Robert Eady 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 18 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | *******************************************************************************/ 25 | 26 | /* 27 | * The stack starts at the top of memory, defined by __sp, and grows down. 28 | * Unfortunately this means we must hardcode the size of memory. 29 | * Here we choose 64K. Change this value to change the working memory size. 30 | */ 31 | __sp = 0x10000; 32 | 33 | SECTIONS 34 | { 35 | .text.init : { 36 | *(.text.init) 37 | } 38 | 39 | .text : { 40 | *(.text) 41 | } 42 | 43 | .data : { 44 | *(.bss) 45 | *(.sdata) 46 | *(.rodata) 47 | *(.data*) 48 | *(.got*) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/txt2hex.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016, Robert Eady 2 | # All rights reserved. 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are met: 6 | # 7 | # 1. Redistributions of source code must retain the above copyright notice, this 8 | # list of conditions and the following disclaimer. 9 | # 2. Redistributions in binary form must reproduce the above copyright notice, 10 | # this list of conditions and the following disclaimer in the documentation 11 | # and/or other materials provided with the distribution. 12 | # 13 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | 25 | # Convert the Yarvi .txt format to Intel .hex 26 | 27 | import sys 28 | 29 | argc = len(sys.argv) 30 | if argc != 3 and argc != 4: 31 | sys.exit("Syntax: %s [
]" % sys.argv[0]) 32 | 33 | addr_resolution = int(sys.argv[3]) if argc == 4 else 1 34 | 35 | def txt2hex(txtfile, hexfile): 36 | address = 0 37 | EOF = ':00000001FF' 38 | recordtype = '00' 39 | for line in txtfile: 40 | line_stripped = line.rstrip('\r\n') 41 | numbytes = len(line_stripped)/2 42 | data = line_stripped.upper() 43 | # the inner part of the line to be checksummed 44 | hexline = format(numbytes, '02X') + format(address, '04X') + recordtype + data 45 | # do the checksum and add colon at the front 46 | hexline = ':' + hexline + checksum(hexline) 47 | hexfile.write(hexline+'\n') 48 | # advance the address 49 | address += numbytes / addr_resolution 50 | hexfile.write(EOF+'\n') 51 | 52 | def checksum(line): 53 | sum = 0 54 | # for each pair of letters (1 byte) 55 | for i in range(0, len(line), 2): 56 | byte = line[i:i+2] 57 | # accumulate the numeric value of the hex byte 58 | sum += int(byte, 16) 59 | # take the two's complement of the LSB of the sum and convert back to hex 60 | return format(((sum ^ 0xff) + 1) % 256, '02X') 61 | 62 | 63 | # allow "-" as the first argument meaning read from stdin 64 | with (sys.stdin if sys.argv[1] == '-' else open(sys.argv[1], 'r')) as txtfile: 65 | with open(sys.argv[2], 'w') as hexfile: 66 | txt2hex(txtfile, hexfile) 67 | --------------------------------------------------------------------------------