├── Makefile ├── README.md ├── README.rst ├── README_OOO.rst ├── bin ├── baremetal_link.ld ├── compile.sh ├── riscv_test_bin └── rv_load_memory.sh ├── dc-gui.tcl ├── debug.rc ├── design_doc ├── [CP1] Design Document.pdf ├── [CP1] Progress Report.pdf ├── [CP1] Roadmap.pdf ├── [CP2] Datapath.png ├── [CP2] Design Document.pdf ├── [CP2] Progress Report.pdf ├── [CP2] Roadmap.pdf ├── _CP4__Final_Report.pdf └── pseudo.sv ├── doc └── figures │ └── diagram.png ├── extract_address.py ├── hdl ├── arbiter_control.sv ├── arbiter_datapath.sv ├── cache │ ├── array.sv │ ├── cache.sv │ ├── cache_control.sv │ ├── cache_datapath.sv │ ├── data_array.sv │ └── line_adapter.sv ├── cache_sys.sv ├── cacheline_adaptor.sv ├── cpu │ ├── alu.sv │ ├── bht.sv │ ├── btb.sv │ ├── btb_array.sv │ ├── cmp.sv │ ├── control_rom.sv │ ├── cpu.sv │ ├── ex_mem_reg.sv │ ├── forward_control_unit.sv │ ├── ghr.sv │ ├── id_ex_reg.sv │ ├── if_id_reg.sv │ ├── immediate_gen.sv │ ├── ir.sv │ ├── mask_gen.sv │ ├── mem_wb_reg.sv │ ├── pc_inc.sv │ ├── pc_reg.sv │ ├── perf_counter.sv │ ├── pht.sv │ ├── regfile.sv │ ├── register.sv │ └── stall_control_unit.sv ├── l2_cache │ ├── ewb.sv │ ├── l2_array.sv │ ├── l2_cache.sv │ ├── l2_cache_control.sv │ ├── l2_cache_datapath.sv │ └── l2_data_array.sv ├── mp4.sv ├── pipeline_d_cache │ ├── p_d_cache.sv │ ├── p_d_cache_control.sv │ ├── p_d_cache_metadata_check.sv │ └── p_d_cache_reg.sv └── pipeline_i_cache │ ├── p_i_cache.sv │ ├── p_i_cache_control.sv │ ├── p_i_cache_metadata_check.sv │ ├── p_i_cache_reg.sv │ └── p_line_adapter.sv ├── hvl ├── magic_dual_port.sv ├── param_memory.sv ├── rvfi_itf.sv ├── rvfimon.v ├── shadow_memory.sv ├── source_tb.sv ├── tb_itf.sv └── top.sv ├── pkg ├── cache_mux_types.sv ├── rv32i_mux_types.sv └── rv32i_types.sv ├── run_dv.sh ├── run_test_asm.sh ├── run_verdi.sh ├── synthesis.tcl ├── testcode ├── comp1.s ├── comp2_c.s ├── comp2_i.s ├── comp2_m.s ├── comp2_mc.s ├── comp3.s ├── mp4-cp1.s ├── mp4-cp2.s ├── mp4-cp3.s ├── src │ ├── comp1.c │ ├── comp2.c │ ├── comp3.c │ ├── comp3_data.h │ └── target.h └── test_forwarding.s └── warn.config /Makefile: -------------------------------------------------------------------------------- 1 | SHELL = /bin/bash -o pipefail 2 | 3 | #Collect All Source Files 4 | PKG_SRCS := $(shell find $(PWD)/pkg -name '*.sv') 5 | HDL_SRCS := $(shell find $(PWD)/hdl -name '*.sv') 6 | HVL_SRCS := $(shell find $(PWD)/hvl -name '*.sv' -o -name '*.v') 7 | SRCS := $(PKG_SRCS) $(HDL_SRCS) $(HVL_SRCS) 8 | 9 | SYNTH_TCL := $(CURDIR)/synthesis.tcl 10 | 11 | VCS_FLAGS= -full64 -lca -sverilog +lint=all,noNS -timescale=1ns/10ps -debug_acc+all -kdb -fsdb -msg_config=../warn.config -l compile.log +incdir+../pkg +incdir+../hvl -top mp4_tb 12 | 13 | sim/simv: $(SRCS) 14 | mkdir -p sim 15 | cd sim && vcs $(SRCS) $(VCS_FLAGS) 16 | 17 | run: sim/simv $(ASM) 18 | bin/rv_load_memory.sh $(ASM) 2>&1 | tee sim/asm.log 19 | cd sim && ./simv -l simulation.log 20 | cd sim && fsdb2saif dump.fsdb 21 | 22 | synth: $(SRCS) $(SYNTH_TCL) 23 | mkdir -p synth/reports 24 | cd synth && dc_shell -f $(SYNTH_TCL) 2>&1 | tee synthesis.log 25 | @if grep -q -i -e error -e LINK-5 synth/synthesis.log; then \ 26 | echo -e "\033[0;31m Fix errors below \033[0m"; \ 27 | grep -i -e error -e LINK-5 synth/synthesis.log; exit 1; \ 28 | else \ 29 | echo -e "\033[0;32m Synthesis Successful \033[0m Check timing and power report under synth/reports/"; \ 30 | fi 31 | 32 | clean: 33 | rm -rf sim synth 34 | 35 | .PHONY: clean 36 | .PHONY: run 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RISCVPipelinedProcessor 2 | Pipelined Processor which implements RV32i Instruction Set. Also contains pipelined L1 4-way set-associative Instruction Cache, direct-mapped L1 Data Cache, and a 4-way set-associative L2 Victim Cache with a fully-associative 8-entry Victim Buffer. Also has a tournament branch predictor (global and local predictors) and a set-associative BTB. 3 | 4 | SystemVerilog HDL code in hdl folder. 5 | -------------------------------------------------------------------------------- /bin/baremetal_link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | ENTRY(_start) 3 | 4 | SECTIONS 5 | { 6 | . = 0x80000000; 7 | .text.init : { *(.text.init) } 8 | . = ALIGN(0x1000); 9 | .tohost : { *(.tohost) } 10 | . = ALIGN(0x1000); 11 | .text : { *(.text) } 12 | . = ALIGN(0x1000); 13 | .data : { *(.data) } 14 | .bss : { *(.bss) } 15 | _end = .; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /bin/compile.sh: -------------------------------------------------------------------------------- 1 | # Author: ECE 411 Staff, Umur Darbaz 2 | # This script is provided to you as a compilation wrapper. The flags are needed to properly 3 | # compile the RISCV assembly for Spike (RISCV-ISA-SIMULATOR) Baremetal mode. 4 | 5 | RISCV_GCC=riscv32-unknown-elf-gcc 6 | LINK_FILE=./baremetal_link.ld 7 | FLAGS="-march=rv32i -mabi=ilp32 -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -T$LINK_FILE -Wl,--no-relax" 8 | BINARY_NAME=riscv_test_bin 9 | 10 | if [ -z "$1" ]; then 11 | echo "ERROR: An assembly source file must be provided." 12 | exit 1 13 | fi 14 | 15 | if [ ! -f "$1" ]; then 16 | echo "ERROR: The specified source file $1 does not exit." 17 | exit 2 18 | fi 19 | 20 | $RISCV_GCC $FLAGS -o $BINARY_NAME $1 21 | -------------------------------------------------------------------------------- /bin/riscv_test_bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avikram2/RISCVPipelinedProcessor/19f2d165ebc325b386088c20e5f9d248d734633e/bin/riscv_test_bin -------------------------------------------------------------------------------- /bin/rv_load_memory.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Settings 4 | ECE411DIR=$HOME/mp4 5 | DEFAULT_TARGET=$ECE411DIR/mp4/sim/memory.lst 6 | ASSEMBLER=/class/ece411/software/riscv-tools/bin/riscv32-unknown-elf-gcc 7 | OBJCOPY=/class/ece411/software/riscv-tools/bin/riscv32-unknown-elf-objcopy 8 | OBJDUMP=/class/ece411/software/riscv-tools/bin/riscv32-unknown-elf-objdump 9 | 10 | # CHANGE FOR CP2 11 | ADDRESSABILITY=32 12 | # possible_error: change addressability. 13 | 14 | # Command line parameters 15 | ASM_FILE=$1 16 | TARGET_FILE=${2:-$DEFAULT_TARGET} 17 | ADDRESSABILITY=${3:-$ADDRESSABILITY} 18 | 19 | # Print usage 20 | if [[ "$#" -lt 1 ]]; then 21 | echo "Compile a RISC-V assembly file and write a memory file for simulation." 22 | echo "Usage: $0 [memory-file]" 23 | exit 0 24 | fi 25 | 26 | # Remove temporary directory on exit 27 | cleanup() 28 | { 29 | rm -rf -- "$WORK_DIR" 30 | # echo "$WORK_DIR" 31 | } 32 | trap cleanup exit 33 | 34 | # Create temporary directory 35 | WORK_DIR="$(mktemp -d)" 36 | 37 | # Copy files to temporary directory 38 | cp "$ASM_FILE" "$WORK_DIR" 39 | 40 | # Fail if assembler cannot be found 41 | if [ ! -x "$ASSEMBLER" ]; then 42 | echo "Cannot execute assembler at $ASSEMBLER." >&2 43 | echo "Make sure it exists and is executable." >&2 44 | exit 1 45 | fi 46 | 47 | OBJ_FILE="${WORK_DIR}/$(basename $ASM_FILE .asm).obj" 48 | 49 | # Assemble code 50 | "$ASSEMBLER" -ffreestanding -nostdlib -march=rv32i "${WORK_DIR}/$(basename $ASM_FILE)" -Wl,--no-relax -o "$OBJ_FILE" 51 | 52 | # Fail if object file doesn't exist or has no memory content 53 | if [[ ! -e "$OBJ_FILE" || "$(cat "$OBJ_FILE" | wc -c)" -le "1" ]]; then 54 | echo "Error assembling $ASM_FILE, not generating binary file" >&2 55 | exit 2 56 | fi 57 | 58 | # Fail if objcopy cannot be found 59 | if [ ! -x "$OBJCOPY" ]; then 60 | echo "Cannot execute objcopy at $OBJCOPY" >&2 61 | echo "Make sure it exists and is executable." >&2 62 | exit 1 63 | fi 64 | 65 | BIN_FILE="${WORK_DIR}/$(basename $ASM_FILE .asm).bin" 66 | 67 | "$OBJDUMP" -D "$OBJ_FILE" -Mnumeric 68 | "$OBJCOPY" -O binary "$OBJ_FILE" "$BIN_FILE" 69 | hexdump $BIN_FILE 70 | 71 | # Fail if binary file doesn't exist or has no memory content 72 | if [[ ! -e "$BIN_FILE" || "$(cat "$BIN_FILE" | wc -c)" -le "1" ]]; then 73 | echo "Error binarizing $OBJ_FILE, not generating memory file" >&2 74 | exit 3 75 | fi 76 | 77 | # Fail if the target directory doesn't exist 78 | if [[ ! -d "$(dirname "$TARGET_FILE")" ]]; then 79 | echo "Directory $(dirname "$TARGET_FILE") does not exist." >&2 80 | echo "Did you specify the correct target path? Aborting." >&2 81 | exit 4 82 | fi 83 | 84 | # Ask if user wants to overwrite target 85 | if [ -e "$TARGET_FILE" ]; then 86 | echo "Target file $TARGET_FILE exists." 87 | read -p "Overwrite? [y/N] " CONF 88 | shopt -s nocasematch 89 | if [[ "${CONF}" != "y" && "${CONF}" != "yes" ]]; then 90 | echo "Aborting." >&2 91 | exit 0 92 | fi 93 | shopt -u nocasematch 94 | fi 95 | 96 | 97 | 98 | # Write memory to file 99 | function log2 { 100 | local x=0 101 | for (( y=$1-1 ; $y > 0; y >>= 1 )) ; do 102 | let x=$x+1 103 | done 104 | echo $x 105 | } 106 | 107 | z=$( log2 $ADDRESSABILITY ) 108 | hex="0x00000060" 109 | result=$(( hex >> $z )) 110 | mem_start=$(printf "@%08x\n" $result) 111 | 112 | { 113 | echo $mem_start 114 | hexdump -ve $ADDRESSABILITY'/1 "%02X " "\n"' "$BIN_FILE" \ 115 | | awk '{for (i = NF; i > 0; i--) printf "%s", $i; print ""}' 116 | } > "$TARGET_FILE" 117 | 118 | echo "Assembled $ASM_FILE and wrote memory contents to $TARGET_FILE" 119 | -------------------------------------------------------------------------------- /dc-gui.tcl: -------------------------------------------------------------------------------- 1 | set target_library [getenv STD_CELL_LIB] 2 | set synthetic_library [list dw_foundation.sldb] 3 | set link_library [list "*" $target_library $synthetic_library] 4 | set symbol_library [list generic.sdb] 5 | read_file -format ddc synth.ddc -------------------------------------------------------------------------------- /debug.rc: -------------------------------------------------------------------------------- 1 | Magic 271485 2 | Revision Verdi_R-2020.12-SP1-1 3 | 4 | ; Window Layout 5 | viewPort 0 25 1690 710 469 65 6 | 7 | ; File list: 8 | ; openDirFile [-d delimiter] [-s time_offset] [-rf auto_bus_rule_file] path_name file_name 9 | openDirFile -d / "" "/home/lclee3/mp4/mp4/sim/dump.fsdb" 10 | 11 | ; file time scale: 12 | ; fileTimeScale ### s|ms|us|ns|ps 13 | 14 | ; signal spacing: 15 | signalSpacing 5 16 | 17 | ; windowTimeUnit is used for zoom, cursor & marker 18 | ; waveform viewport range 19 | zoom 686275880.691566 713306532.595181 20 | cursor 711955000.000000 21 | marker 0.000000 22 | 23 | ; user define markers 24 | ; userMarker time_pos marker_name color linestyle 25 | ; visible top row signal index 26 | top 0 27 | ; marker line index 28 | markerPos 21 29 | 30 | ; event list 31 | ; addEvent event_name event_expression 32 | ; curEvent event_name 33 | 34 | 35 | 36 | COMPLEX_EVENT_BEGIN 37 | 38 | 39 | COMPLEX_EVENT_END 40 | 41 | 42 | 43 | ; toolbar current search type 44 | ; curSTATUS search_type 45 | curSTATUS ByChange 46 | 47 | 48 | addGroup "G1" 49 | activeDirFile "" "/home/lclee3/mp4/mp4/sim/dump.fsdb" 50 | addSignal -h 15 -UNSIGNED -HEX /mp4_tb/dut/cpu/debug_ID_PC[31:0] 51 | addSignal -h 15 -holdScope debug_ID_IR[31:0] 52 | addSignal -h 15 -holdScope debug_EX_PC[31:0] 53 | addSignal -h 15 -holdScope debug_EX_IR[31:0] 54 | addSignal -h 15 -holdScope debug_MEM_PC[31:0] 55 | addSignal -h 15 -holdScope debug_MEM_IR[31:0] 56 | addSignal -h 15 -holdScope debug_WB_PC[31:0] 57 | addSignal -h 15 -holdScope debug_WB_IR[31:0] 58 | addSignal -h 15 -holdScope debug_WB_target_address[31:0] 59 | addSignal -h 15 -UNSIGNED -UDEC -holdScope num_control_flow_instr[31:0] 60 | addSignal -h 15 -UNSIGNED -UDEC -holdScope num_br_instr[31:0] 61 | addSignal -h 15 -UNSIGNED -UDEC -holdScope num_ctrl_instr_wo_stall[31:0] 62 | addSignal -h 15 -UNSIGNED -UDEC -holdScope num_correct_branch_predict[31:0] 63 | addSignal -h 15 -UNSIGNED -UDEC /mp4_tb/dut/cache_sys/num_l2_request[31:0] 64 | addSignal -h 15 -UNSIGNED -UDEC /mp4_tb/dut/cache_sys/l2_cache/control/num_l2_miss[31:0] 65 | addSignal -h 15 /mp4_tb/dut/cpu/num_control_flow_instr_overflow 66 | addSignal -h 15 -holdScope num_br_instr_overflow 67 | addSignal -h 15 -holdScope num_ctrl_instr_wo_stall_overflow 68 | addSignal -h 15 -holdScope num_correct_branch_predict_overflow 69 | addSignal -h 15 /mp4_tb/dut/cache_sys/num_l2_request_overflow 70 | addSignal -h 15 /mp4_tb/dut/cache_sys/l2_cache/control/num_l2_miss_overflow 71 | addSignal -h 15 /mp4_tb/dut/cpu/debug_halt 72 | addGroup "G2" 73 | 74 | ; getSignalForm Scope Hierarchy Status 75 | ; active file of getSignalForm 76 | 77 | -------------------------------------------------------------------------------- /design_doc/[CP1] Design Document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avikram2/RISCVPipelinedProcessor/19f2d165ebc325b386088c20e5f9d248d734633e/design_doc/[CP1] Design Document.pdf -------------------------------------------------------------------------------- /design_doc/[CP1] Progress Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avikram2/RISCVPipelinedProcessor/19f2d165ebc325b386088c20e5f9d248d734633e/design_doc/[CP1] Progress Report.pdf -------------------------------------------------------------------------------- /design_doc/[CP1] Roadmap.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avikram2/RISCVPipelinedProcessor/19f2d165ebc325b386088c20e5f9d248d734633e/design_doc/[CP1] Roadmap.pdf -------------------------------------------------------------------------------- /design_doc/[CP2] Datapath.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avikram2/RISCVPipelinedProcessor/19f2d165ebc325b386088c20e5f9d248d734633e/design_doc/[CP2] Datapath.png -------------------------------------------------------------------------------- /design_doc/[CP2] Design Document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avikram2/RISCVPipelinedProcessor/19f2d165ebc325b386088c20e5f9d248d734633e/design_doc/[CP2] Design Document.pdf -------------------------------------------------------------------------------- /design_doc/[CP2] Progress Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avikram2/RISCVPipelinedProcessor/19f2d165ebc325b386088c20e5f9d248d734633e/design_doc/[CP2] Progress Report.pdf -------------------------------------------------------------------------------- /design_doc/[CP2] Roadmap.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avikram2/RISCVPipelinedProcessor/19f2d165ebc325b386088c20e5f9d248d734633e/design_doc/[CP2] Roadmap.pdf -------------------------------------------------------------------------------- /design_doc/_CP4__Final_Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avikram2/RISCVPipelinedProcessor/19f2d165ebc325b386088c20e5f9d248d734633e/design_doc/_CP4__Final_Report.pdf -------------------------------------------------------------------------------- /design_doc/pseudo.sv: -------------------------------------------------------------------------------- 1 | // Decide if we need to WB or not. This is in checking state 2 | if(hit == 1'b1) 3 | begin 4 | next_state = DEFAULT; 5 | end 6 | else if(v_array_0_dataout == 1'b0 || v_array_1_dataout == 1'b0 || v_array_2_dataout == 1'b0 || v_array_3_dataout == 1'b0) 7 | begin 8 | next_state = NO_WB_1; 9 | end 10 | else 11 | begin 12 | if(LRU_array_dataout[2] == 1'b0) 13 | begin 14 | if(LRU_array_dataout[0] == 1'b0) 15 | begin 16 | if(d_array_3_dataout == 1'b0) 17 | next_state = NO_WB_1; 18 | else 19 | next_state = WRITE_BACK; 20 | end 21 | else 22 | begin 23 | if(d_array_2_dataout == 1'b0) 24 | next_state = NO_WB_1; 25 | else 26 | next_state = WRITE_BACK; 27 | end 28 | end 29 | else 30 | begin 31 | if(LRU_array_dataout[1] == 1'b0) 32 | begin 33 | if(d_array_1_dataout == 1'b0) 34 | next_state = NO_WB_1; 35 | else 36 | next_state = WRITE_BACK; 37 | end 38 | else 39 | begin 40 | if(d_array_0_dataout == 1'b0) 41 | next_state = NO_WB_1; 42 | else 43 | next_state = WRITE_BACK; 44 | end 45 | end 46 | end 47 | 48 | // At WRITE_BACK state, just look at LRU to decide which way to write back 49 | // since we already know (no free cacheline) + (LRU is dirty) 50 | // load valid_way_3 to 0, load dirty_way_3 to 0 51 | if(LRU_array_dataout[2] == 1'b0) 52 | begin 53 | if(LRU_array_dataout[0] == 1'b0) 54 | begin 55 | // writing way 3 data back 56 | end 57 | else 58 | begin 59 | // writing way 2 data back 60 | end 61 | end 62 | else 63 | begin 64 | if(LRU_array_dataout[1] == 1'b0) 65 | begin 66 | // writing way 1 data back 67 | end 68 | else 69 | begin 70 | // writing way 0 data back 71 | end 72 | end 73 | 74 | 75 | // At NO_WB_2, decide which way to allocate. 76 | 77 | if(v_array_0_dataout == 1'b0) 78 | begin 79 | // Alloc way 0 80 | end 81 | else if(v_array_1_dataout == 1'b0) 82 | begin 83 | // Alloc way 1 84 | end 85 | else if(v_array_2_dataout == 1'b0) 86 | begin 87 | // Alloc way 2 88 | end 89 | else if(v_array_3_dataout == 1'b0) 90 | begin 91 | // Alloc way 3 92 | end 93 | else 94 | begin 95 | if(LRU_array_dataout[2] == 1'b0) 96 | begin 97 | if(LRU_array_dataout[0] == 1'b0) 98 | begin 99 | // Alloc way 3 100 | end 101 | else 102 | begin 103 | // Alloc way 2 104 | end 105 | end 106 | else 107 | begin 108 | if(LRU_array_dataout[1] == 1'b0) 109 | begin 110 | // Alloc way 1 111 | end 112 | else 113 | begin 114 | // Alloc way 0 115 | end 116 | end 117 | end 118 | 119 | 120 | // Update LRU array when there is a hit. 121 | if(way_0_hit) 122 | begin 123 | LRU_array_datain[2:0] = {1'b0, 1'b0, LRU_array_dataout[0]}; 124 | end 125 | else if(way_1_hit) 126 | begin 127 | LRU_array_datain[2:0] = {1'b0, 1'b1, LRU_array_dataout[0]}; 128 | end 129 | else if(way_2_hit) 130 | begin 131 | LRU_array_datain[2:0] = {1'b1, LRU_array_dataout[1], 1'b0}; 132 | end 133 | else if(way_3_hit) 134 | begin 135 | LRU_array_datain[2:0] = {1'b1, LRU_array_dataout[1], 1'b1}; 136 | end 137 | 138 | -------------------------------------------------------------------------------- /doc/figures/diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avikram2/RISCVPipelinedProcessor/19f2d165ebc325b386088c20e5f9d248d734633e/doc/figures/diagram.png -------------------------------------------------------------------------------- /extract_address.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | import sys 3 | 4 | TAG_BITS = 24 5 | INDEX_BITS = 3 6 | 7 | ZERO = "000000000000000000000000000" 8 | 9 | VERBOSE = True 10 | 11 | def parse_data(filename): 12 | with open(filename) as fp: 13 | lines = fp.readlines() 14 | filtered_lines = [line[line.rfind("=")+1:].strip() for line in lines if line.strip().startswith("a_pmem_address")] 15 | filtered_lines = [addr for addr in filtered_lines if 'x' not in addr] 16 | #careful, python indexing doesn't include the end index (unlike sys verilog) and is the other way! 17 | 18 | address_counter = Counter(filtered_lines) 19 | 20 | #address_set = set(filtered_lines) 21 | 22 | distinct_addresses = [key for key in address_counter.keys() if key != ZERO] 23 | 24 | print("Number of distinct non-zero and non-x addresses, which resolve to the same cache line, is {}".format(len(distinct_addresses) 25 | )) 26 | if (VERBOSE): 27 | with open(filename + '_addr_set.txt', 'w') as fp: 28 | fp.writelines(map(lambda x: x + '\n', distinct_addresses)) 29 | 30 | if __name__ == "__main__": 31 | parse_data(sys.argv[1]) 32 | -------------------------------------------------------------------------------- /hdl/arbiter_control.sv: -------------------------------------------------------------------------------- 1 | 2 | module arbiter_control 3 | import rv32i_types::*; 4 | ( 5 | input clk, 6 | input rst, 7 | 8 | /* I-Cache Side Signals */ 9 | output logic i_pmem_resp, 10 | input logic i_pmem_read, 11 | 12 | /* D-Cache Side Signals */ 13 | output logic d_pmem_resp, 14 | input logic d_pmem_read, 15 | input logic d_pmem_write, 16 | 17 | /* Memory Side Signals */ 18 | input logic a_pmem_resp, 19 | output logic a_pmem_read, 20 | output logic a_pmem_write, 21 | 22 | /* Control to Datapath */ 23 | output arbiteraddressmux::arbiteraddressmux_sel_t arbiter_address_MUX_sel 24 | ); 25 | 26 | enum int unsigned { 27 | IDLE, 28 | SERVE_D_CACHE, 29 | SERVE_I_CACHE 30 | } state, next_state; 31 | 32 | 33 | function void set_defaults(); 34 | 35 | 36 | i_pmem_resp = 1'b0; 37 | d_pmem_resp = 1'b0; 38 | a_pmem_write = 1'b0; 39 | a_pmem_read = 1'b0; 40 | arbiter_address_MUX_sel = arbiteraddressmux::d_cache; 41 | 42 | endfunction 43 | 44 | 45 | always_comb 46 | begin : state_actions 47 | 48 | set_defaults(); 49 | 50 | case(state) 51 | IDLE: 52 | begin 53 | 54 | end 55 | SERVE_D_CACHE: 56 | begin 57 | arbiter_address_MUX_sel = arbiteraddressmux::d_cache; 58 | 59 | if (d_pmem_read) 60 | a_pmem_read = 1'b1; 61 | else if (d_pmem_write) 62 | a_pmem_write = 1'b1; 63 | 64 | d_pmem_resp = a_pmem_resp; 65 | 66 | end 67 | SERVE_I_CACHE: 68 | begin 69 | arbiter_address_MUX_sel = arbiteraddressmux::i_cache; 70 | 71 | a_pmem_read = 1'b1; 72 | 73 | i_pmem_resp = a_pmem_resp; 74 | end 75 | 76 | endcase 77 | end 78 | 79 | always_comb 80 | begin : next_state_logic 81 | 82 | next_state = state; 83 | 84 | case(state) 85 | IDLE: 86 | begin 87 | if(d_pmem_read || d_pmem_write) 88 | next_state = SERVE_D_CACHE; 89 | else if(i_pmem_read) 90 | next_state = SERVE_I_CACHE; 91 | end 92 | SERVE_D_CACHE: 93 | begin 94 | if(a_pmem_resp) 95 | next_state = IDLE; 96 | end 97 | SERVE_I_CACHE: 98 | begin 99 | if(a_pmem_resp) 100 | next_state = IDLE; 101 | end 102 | endcase 103 | end 104 | 105 | always_ff @(posedge clk) 106 | begin: next_state_assignment 107 | /* Assignment of next state on clock edge */ 108 | if (rst) 109 | state <= IDLE; 110 | else 111 | state <= next_state; 112 | end 113 | 114 | endmodule : arbiter_control -------------------------------------------------------------------------------- /hdl/arbiter_datapath.sv: -------------------------------------------------------------------------------- 1 | 2 | module arbiter_datapath 3 | import rv32i_types::*; 4 | ( 5 | 6 | /* I-Cache Side Signals */ 7 | input logic [31:0] i_pmem_address, 8 | output logic [255:0] i_pmem_rdata, 9 | 10 | /* D-Cache Side Signals */ 11 | input logic [31:0] d_pmem_address, 12 | input logic [255:0] d_pmem_wdata, 13 | output logic [255:0] d_pmem_rdata, 14 | 15 | 16 | /* Physical Memory Side Signals */ 17 | output logic [31:0] a_pmem_address, 18 | output logic [255:0] a_pmem_wdata, 19 | input logic [255:0] a_pmem_rdata, 20 | 21 | /* Control to Datapath */ 22 | input arbiteraddressmux::arbiteraddressmux_sel_t arbiter_address_MUX_sel 23 | 24 | ); 25 | 26 | assign a_pmem_wdata = d_pmem_wdata; 27 | assign i_pmem_rdata = a_pmem_rdata; 28 | assign d_pmem_rdata = a_pmem_rdata; 29 | 30 | 31 | always_comb begin : ARBITERADDRESSMUX 32 | 33 | a_pmem_address = '0; 34 | 35 | unique case (arbiter_address_MUX_sel) 36 | arbiteraddressmux::d_cache : a_pmem_address = d_pmem_address; 37 | arbiteraddressmux::i_cache : a_pmem_address = i_pmem_address; 38 | default: ; 39 | endcase 40 | end 41 | 42 | 43 | endmodule : arbiter_datapath -------------------------------------------------------------------------------- /hdl/cache/array.sv: -------------------------------------------------------------------------------- 1 | 2 | module array #(parameter width = 1) 3 | ( 4 | input clk, 5 | input rst, 6 | input logic load, 7 | input logic [2:0] rindex, 8 | input logic [2:0] windex, 9 | input logic [width-1:0] datain, 10 | output logic [width-1:0] dataout 11 | ); 12 | 13 | logic [width-1:0] data [8]; 14 | 15 | always_comb begin 16 | dataout = (load & (rindex == windex)) ? datain : data[rindex]; 17 | end 18 | 19 | always_ff @(posedge clk) 20 | begin 21 | if(rst) 22 | begin 23 | for (int i = 0; i < 8; ++i) 24 | data[i] <= '0; 25 | end 26 | else if(load) 27 | data[windex] <= datain; 28 | end 29 | 30 | endmodule : array 31 | -------------------------------------------------------------------------------- /hdl/cache/cache.sv: -------------------------------------------------------------------------------- 1 | module cache ( 2 | input clk, 3 | input rst, 4 | 5 | /* Physical memory signals */ 6 | input logic pmem_resp, 7 | input logic [255:0] pmem_rdata, 8 | output logic [31:0] pmem_address, 9 | output logic [255:0] pmem_wdata, 10 | output logic pmem_read, 11 | output logic pmem_write, 12 | 13 | /* CPU memory signals */ 14 | input logic mem_read, 15 | input logic mem_write, 16 | input logic [3:0] mem_byte_enable_cpu, 17 | input logic [31:0] mem_address, 18 | input logic [31:0] mem_wdata_cpu, 19 | output logic mem_resp, 20 | output logic [31:0] mem_rdata_cpu 21 | ); 22 | 23 | logic tag_load; 24 | logic valid_load; 25 | logic dirty_load; 26 | logic dirty_in; 27 | logic dirty_out; 28 | 29 | logic hit; 30 | logic [1:0] writing; 31 | 32 | logic [255:0] mem_wdata; 33 | logic [255:0] mem_rdata; 34 | logic [31:0] mem_byte_enable; 35 | 36 | cache_control control(.*); 37 | cache_datapath datapath(.*); 38 | 39 | line_adapter bus ( 40 | .mem_wdata_line(mem_wdata), 41 | .mem_rdata_line(mem_rdata), 42 | .mem_wdata(mem_wdata_cpu), 43 | .mem_rdata(mem_rdata_cpu), 44 | .mem_byte_enable(mem_byte_enable_cpu), 45 | .mem_byte_enable_line(mem_byte_enable), 46 | .address(mem_address) 47 | ); 48 | 49 | endmodule : cache 50 | -------------------------------------------------------------------------------- /hdl/cache/cache_control.sv: -------------------------------------------------------------------------------- 1 | module cache_control ( 2 | input clk, 3 | input rst, 4 | 5 | /* CPU memory data signals */ 6 | input logic mem_read, 7 | input logic mem_write, 8 | output logic mem_resp, 9 | 10 | /* Physical memory data signals */ 11 | input logic pmem_resp, 12 | output logic pmem_read, 13 | output logic pmem_write, 14 | 15 | /* Control signals */ 16 | output logic tag_load, 17 | output logic valid_load, 18 | output logic dirty_load, 19 | output logic dirty_in, 20 | input logic dirty_out, 21 | 22 | input logic hit, 23 | output logic [1:0] writing 24 | ); 25 | 26 | /* State Enumeration */ 27 | enum int unsigned 28 | { 29 | check_hit, 30 | read_mem 31 | } state, next_state; 32 | 33 | /* State Control Signals */ 34 | always_comb begin : state_actions 35 | 36 | /* Defaults */ 37 | tag_load = 1'b0; 38 | valid_load = 1'b0; 39 | dirty_load = 1'b0; 40 | dirty_in = 1'b0; 41 | writing = 2'b11; 42 | 43 | mem_resp = 1'b0; 44 | pmem_write = 1'b0; 45 | pmem_read = 1'b0; 46 | 47 | case(state) 48 | check_hit: begin 49 | if (mem_read || mem_write) begin 50 | if (hit) begin 51 | mem_resp = 1'b1; 52 | if (mem_write) begin 53 | dirty_load = 1'b1; 54 | dirty_in = 1'b1; 55 | writing = 2'b01; 56 | end 57 | end else begin 58 | if (dirty_out) 59 | pmem_write = 1'b1; 60 | end 61 | end 62 | end 63 | 64 | read_mem: begin 65 | pmem_read = 1'b1; 66 | writing = 2'b00; 67 | if (pmem_resp) begin 68 | tag_load = 1'b1; 69 | valid_load = 1'b1; 70 | end 71 | dirty_load = 1'b1; 72 | dirty_in = 1'b0; 73 | end 74 | 75 | endcase 76 | end 77 | 78 | /* Next State Logic */ 79 | always_comb begin : next_state_logic 80 | 81 | /* Default state transition */ 82 | next_state = state; 83 | 84 | case(state) 85 | check_hit: begin 86 | if ((mem_read || mem_write) && !hit) begin 87 | if (dirty_out) begin 88 | if (pmem_resp) 89 | next_state = read_mem; 90 | end else begin 91 | next_state = read_mem; 92 | end 93 | end 94 | end 95 | 96 | read_mem: begin 97 | if (pmem_resp) 98 | next_state = check_hit; 99 | end 100 | 101 | endcase 102 | end 103 | 104 | /* Next State Assignment */ 105 | always_ff @(posedge clk) begin: next_state_assignment 106 | if(rst) 107 | state <= check_hit; 108 | else 109 | state <= next_state; 110 | end 111 | 112 | endmodule : cache_control 113 | -------------------------------------------------------------------------------- /hdl/cache/cache_datapath.sv: -------------------------------------------------------------------------------- 1 | module cache_datapath ( 2 | input clk, 3 | input rst, 4 | 5 | /* CPU memory data signals */ 6 | input logic [31:0] mem_byte_enable, 7 | input logic [31:0] mem_address, 8 | input logic [255:0] mem_wdata, 9 | output logic [255:0] mem_rdata, 10 | 11 | /* Physical memory data signals */ 12 | input logic [255:0] pmem_rdata, 13 | output logic [255:0] pmem_wdata, 14 | output logic [31:0] pmem_address, 15 | 16 | /* Control signals */ 17 | input logic tag_load, 18 | input logic valid_load, 19 | input logic dirty_load, 20 | input logic dirty_in, 21 | output logic dirty_out, 22 | 23 | output logic hit, 24 | input logic [1:0] writing 25 | ); 26 | 27 | logic [255:0] line_in, line_out; 28 | logic [23:0] address_tag, tag_out; 29 | logic [2:0] index; 30 | logic [31:0] mask; 31 | logic valid_out; 32 | 33 | always_comb begin 34 | address_tag = mem_address[31:8]; 35 | index = mem_address[7:5]; 36 | hit = valid_out && (tag_out == address_tag); 37 | pmem_address = (dirty_out) ? {tag_out, mem_address[7:0]} : mem_address; 38 | mem_rdata = line_out; 39 | pmem_wdata = line_out; 40 | 41 | case(writing) 42 | 2'b00: begin // load from memory 43 | mask = 32'hFFFFFFFF; 44 | line_in = pmem_rdata; 45 | end 46 | 2'b01: begin // write from cpu 47 | mask = mem_byte_enable; 48 | line_in = mem_wdata; 49 | end 50 | default: begin // don't change data 51 | mask = 32'b0; 52 | line_in = mem_wdata; 53 | end 54 | endcase 55 | end 56 | 57 | data_array DM_cache (clk, rst, mask, index, index, line_in, line_out); 58 | array #(24) tag (clk, rst, tag_load, index, index, address_tag, tag_out); 59 | array #(1) valid (clk, rst, valid_load, index, index, 1'b1, valid_out); 60 | array #(1) dirty (clk, rst, dirty_load, index, index, dirty_in, dirty_out); 61 | 62 | endmodule : cache_datapath 63 | -------------------------------------------------------------------------------- /hdl/cache/data_array.sv: -------------------------------------------------------------------------------- 1 | module data_array ( 2 | input clk, 3 | input rst, 4 | input logic [31:0] write_en, 5 | input logic [2:0] rindex, 6 | input logic [2:0] windex, 7 | input logic [255:0] datain, 8 | output logic [255:0] dataout 9 | ); 10 | 11 | logic [255:0] data [8]; 12 | 13 | always_comb begin 14 | for (int i = 0; i < 32; i++) begin 15 | dataout[8*i +: 8] = (write_en[i] & (rindex == windex)) ? datain[8*i +: 8] : data[rindex][8*i +: 8]; 16 | end 17 | end 18 | 19 | always_ff @(posedge clk) begin 20 | if(rst) 21 | begin 22 | for (int i = 0; i < 8; ++i) 23 | data[i] <= '0; 24 | end 25 | else 26 | begin 27 | for (int i = 0; i < 32; i++) begin 28 | data[windex][8*i +: 8] <= write_en[i] ? datain[8*i +: 8] : data[windex][8*i +: 8]; 29 | end 30 | end 31 | end 32 | 33 | endmodule : data_array 34 | -------------------------------------------------------------------------------- /hdl/cache/line_adapter.sv: -------------------------------------------------------------------------------- 1 | module line_adapter ( 2 | output logic [255:0] mem_wdata_line, 3 | input logic [255:0] mem_rdata_line, 4 | input logic [31:0] mem_wdata, 5 | output logic [31:0] mem_rdata, 6 | input logic [3:0] mem_byte_enable, 7 | output logic [31:0] mem_byte_enable_line, 8 | input logic [31:0] address 9 | ); 10 | 11 | assign mem_wdata_line = {8{mem_wdata}}; 12 | assign mem_rdata = mem_rdata_line[(32*address[4:2]) +: 32]; 13 | assign mem_byte_enable_line = {28'h0, mem_byte_enable} << (address[4:2]*4); 14 | 15 | endmodule : line_adapter 16 | -------------------------------------------------------------------------------- /hdl/cache_sys.sv: -------------------------------------------------------------------------------- 1 | module cache_sys 2 | import rv32i_types::*; 3 | ( 4 | input clk, 5 | input rst, 6 | 7 | /* Physical Memory Signals */ 8 | output logic pmem_read, 9 | output logic pmem_write, 10 | output rv32i_word pmem_address, 11 | output [63:0] pmem_wdata, 12 | input [63:0] pmem_rdata, 13 | input logic pmem_resp, 14 | 15 | 16 | /* CPU Memory Signals: I-Cache */ 17 | input logic instr_read, 18 | input rv32i_word instr_mem_address, 19 | output rv32i_word instr_mem_rdata, 20 | output logic instr_mem_resp, 21 | input logic if_id_reg_load, 22 | 23 | 24 | /* CPU Memory Signals: D-Cache */ 25 | input logic data_read, 26 | input logic data_write, 27 | input rv32i_word data_mem_address, 28 | input logic [3:0] data_mbe, 29 | input rv32i_word data_mem_wdata, 30 | output rv32i_word data_mem_rdata, 31 | output logic data_mem_resp 32 | ); 33 | 34 | logic [31:0] a_pmem_address; 35 | logic [31:0] cla_pmem_address; 36 | 37 | logic i_pmem_resp; 38 | logic [255:0] i_pmem_rdata; 39 | logic [31:0] i_pmem_address; 40 | logic i_pmem_read; 41 | 42 | logic d_pmem_resp; 43 | logic [255:0] d_pmem_rdata; 44 | logic [31:0] d_pmem_address; 45 | logic [255:0] d_pmem_wdata; 46 | logic d_pmem_read; 47 | logic d_pmem_write; 48 | 49 | arbiteraddressmux::arbiteraddressmux_sel_t arbiter_address_MUX_sel; 50 | 51 | logic a_pmem_resp; 52 | logic [255:0] a_pmem_rdata; 53 | logic [255:0] a_pmem_wdata; 54 | logic a_pmem_read; 55 | logic a_pmem_write; 56 | 57 | logic cla_pmem_resp; 58 | logic [255:0] cla_pmem_rdata; 59 | logic [255:0] cla_pmem_wdata; 60 | logic cla_pmem_read; 61 | logic cla_pmem_write; 62 | 63 | /* Does not pass synthesis, use for simulation only. */ 64 | 65 | // always @ (posedge cla_pmem_read or posedge cla_pmem_write) 66 | // begin 67 | // $display("a_pmem_address = %27b", cla_pmem_address[31:5]); 68 | // end 69 | 70 | /* L2 Perf Counter Signals*/ 71 | logic [perf_counter_width-1:0] num_l2_request; 72 | logic num_l2_request_overflow; 73 | // logic [perf_counter_width-1:0] num_l2_miss; 74 | // logic num_l2_miss_overflow; 75 | 76 | p_i_cache i_cache ( 77 | 78 | .clk(clk), 79 | .rst(rst), 80 | 81 | /* Physical memory signals */ 82 | .pmem_resp(i_pmem_resp), 83 | .pmem_rdata(i_pmem_rdata), 84 | .pmem_address(i_pmem_address), 85 | .pmem_wdata(), // output by cache, no hardwire 86 | .pmem_read(i_pmem_read), 87 | .pmem_write(), // output by cache, no hardwire 88 | 89 | /* CPU memory signals */ 90 | .mem_read(instr_read), 91 | .mem_write(1'b0), 92 | .mem_byte_enable_cpu(4'b0), 93 | .mem_address(instr_mem_address), 94 | .mem_wdata_cpu(32'b0), 95 | .mem_resp(instr_mem_resp), 96 | .mem_rdata_cpu(instr_mem_rdata), 97 | .if_id_reg_load(if_id_reg_load) 98 | 99 | ); 100 | 101 | /* Count the total number of L2 cache requests. */ 102 | perf_counter #(.width(perf_counter_width)) l2total 103 | ( 104 | .clk(a_pmem_read || a_pmem_write), 105 | .rst(rst), 106 | .count(1'b1), 107 | .overflow(num_l2_request_overflow), 108 | .out(num_l2_request) 109 | ); 110 | 111 | // /* Count the total number of L2 cache misses. */ 112 | // perf_counter #(.width(perf_counter_width)) l2miss 113 | // ( 114 | // .clk(cla_pmem_read || cla_pmem_write), 115 | // .rst(rst), 116 | // .count(1'b1), 117 | // .overflow(num_l2_miss_overflow), 118 | // .out(num_l2_miss) 119 | // ); 120 | 121 | cache d_cache ( 122 | 123 | .clk(clk), 124 | .rst(rst), 125 | 126 | /* Physical memory signals */ 127 | .pmem_resp(d_pmem_resp), 128 | .pmem_rdata(d_pmem_rdata), 129 | .pmem_address(d_pmem_address), 130 | .pmem_wdata(d_pmem_wdata), 131 | .pmem_read(d_pmem_read), 132 | .pmem_write(d_pmem_write), 133 | 134 | /* CPU memory signals */ 135 | .mem_read(data_read), 136 | .mem_write(data_write), 137 | .mem_byte_enable_cpu(data_mbe), 138 | .mem_address(data_mem_address), 139 | .mem_wdata_cpu(data_mem_wdata), 140 | .mem_resp(data_mem_resp), 141 | .mem_rdata_cpu(data_mem_rdata) 142 | 143 | ); 144 | 145 | arbiter_datapath arbiter_datapath ( 146 | 147 | 148 | /* I-Cache Side Signals */ 149 | .i_pmem_address(i_pmem_address), 150 | .i_pmem_rdata(i_pmem_rdata), 151 | 152 | /* D-Cache Side Signals */ 153 | .d_pmem_address(d_pmem_address), 154 | .d_pmem_wdata(d_pmem_wdata), 155 | .d_pmem_rdata(d_pmem_rdata), 156 | 157 | 158 | /* Physical Memory Side Signals */ 159 | .a_pmem_address(a_pmem_address), 160 | .a_pmem_wdata(a_pmem_wdata), 161 | .a_pmem_rdata(a_pmem_rdata), 162 | 163 | /* Control to Datapath */ 164 | .arbiter_address_MUX_sel(arbiter_address_MUX_sel) 165 | ); 166 | 167 | arbiter_control arbiter_control ( 168 | .clk(clk), 169 | .rst(rst), 170 | 171 | /* I-Cache Side Signals */ 172 | .i_pmem_resp(i_pmem_resp), 173 | .i_pmem_read(i_pmem_read), 174 | 175 | /* D-Cache Side Signals */ 176 | .d_pmem_resp(d_pmem_resp), 177 | .d_pmem_read(d_pmem_read), 178 | .d_pmem_write(d_pmem_write), 179 | 180 | /* Memory Side Signals */ 181 | .a_pmem_resp(a_pmem_resp), 182 | .a_pmem_read(a_pmem_read), 183 | .a_pmem_write(a_pmem_write), 184 | 185 | /* Control to Datapath */ 186 | .arbiter_address_MUX_sel(arbiter_address_MUX_sel) 187 | ); 188 | 189 | l2_cache l2_cache ( 190 | .clk(clk), 191 | .rst(rst), 192 | 193 | /* Arbiter Side Signals */ 194 | .mem_address(a_pmem_address), 195 | .mem_rdata256(a_pmem_rdata), 196 | .mem_wdata256(a_pmem_wdata), 197 | .mem_read(a_pmem_read), 198 | .mem_write(a_pmem_write), 199 | .mem_resp(a_pmem_resp), 200 | 201 | /* Cacheline Adaptor Side Signals */ 202 | .pmem_address(cla_pmem_address), 203 | .pmem_rdata(cla_pmem_rdata), 204 | .pmem_wdata(cla_pmem_wdata), 205 | .pmem_read(cla_pmem_read), 206 | .pmem_write(cla_pmem_write), 207 | .pmem_resp(cla_pmem_resp) 208 | ); 209 | 210 | cacheline_adaptor cacheline_adaptor ( 211 | 212 | .clk(clk), 213 | .reset_n(~rst), 214 | 215 | // Port to LLC (Lowest Level Cache) 216 | .line_i(cla_pmem_wdata), 217 | .line_o(cla_pmem_rdata), 218 | .address_i(cla_pmem_address), 219 | .read_i(cla_pmem_read), 220 | .write_i(cla_pmem_write), 221 | .resp_o(cla_pmem_resp), 222 | 223 | // Port to memory 224 | .burst_i(pmem_rdata), 225 | .burst_o(pmem_wdata), 226 | .address_o(pmem_address), 227 | .read_o(pmem_read), 228 | .write_o(pmem_write), 229 | .resp_i(pmem_resp) 230 | ); 231 | 232 | endmodule : cache_sys 233 | -------------------------------------------------------------------------------- /hdl/cacheline_adaptor.sv: -------------------------------------------------------------------------------- 1 | module cacheline_adaptor 2 | ( 3 | input clk, 4 | input reset_n, 5 | 6 | // Port to LLC (Lowest Level Cache) 7 | input logic [255:0] line_i, 8 | output logic [255:0] line_o, // a cache line is 32 BYTES 9 | input logic [31:0] address_i, 10 | input read_i, 11 | input write_i, 12 | output logic resp_o, 13 | 14 | // Port to memory 15 | input logic [63:0] burst_i, 16 | output logic [63:0] burst_o, // each DRAM burst is 8 BYTES 17 | output logic [31:0] address_o, // always assigned to address_i 18 | output logic read_o, 19 | output logic write_o, 20 | input resp_i 21 | ); 22 | 23 | logic [255:0] buffer; 24 | logic [2:0] read_pos; 25 | 26 | 27 | assign address_o = address_i; 28 | 29 | // FSM Ref: https://www.intel.com/content/www/us/en/docs/programmable/683082/22-1/systemverilog-state-machine-coding-example.html 30 | 31 | enum int unsigned { INIT = 0, READ_WAIT_DRAM = 1, READ_BURST_0 = 2, 32 | READ_BURST_1 = 3, READ_BURST_2 = 4, READ_DONE = 6, 33 | WRITE_WAIT = 7, WRITE_BURST_0 = 8, WRITE_BURST_1 = 9, 34 | WRITE_BURST_2 = 10, WRITE_BURST_3 = 11, WRITE_DONE = 12} state, next_state; 35 | 36 | always_comb begin 37 | 38 | next_state = state; 39 | case(state) 40 | INIT: 41 | begin 42 | if(read_i == 1'b1 && write_i == 1'b0) 43 | next_state = READ_WAIT_DRAM; 44 | if(read_i == 1'b0 && write_i == 1'b1) 45 | next_state = WRITE_WAIT; 46 | end 47 | READ_WAIT_DRAM: 48 | begin 49 | if(resp_i == 1'b1) 50 | next_state = READ_BURST_0; 51 | end 52 | READ_BURST_0: next_state = READ_BURST_1; 53 | READ_BURST_1: next_state = READ_BURST_2; 54 | READ_BURST_2: next_state = READ_DONE; 55 | READ_DONE: next_state = INIT; 56 | WRITE_WAIT: 57 | begin 58 | if(resp_i == 1'b1) 59 | next_state = WRITE_BURST_0; 60 | end 61 | WRITE_BURST_0: next_state = WRITE_BURST_1; 62 | WRITE_BURST_1: next_state = WRITE_BURST_2; 63 | WRITE_BURST_2: next_state = WRITE_DONE; 64 | WRITE_DONE: next_state = INIT; 65 | endcase 66 | end 67 | 68 | always_comb begin 69 | 70 | case(state) 71 | INIT: 72 | begin 73 | line_o = '0; 74 | resp_o = 1'b0; 75 | burst_o = '0; 76 | read_o = 1'b0; 77 | write_o = 1'b0; 78 | read_pos = 3'b111; 79 | end 80 | READ_WAIT_DRAM: 81 | begin 82 | line_o = '0; 83 | resp_o = 1'b0; 84 | burst_o = '0; 85 | read_o = 1'b1; 86 | write_o = 1'b0; 87 | read_pos = 3'b111; 88 | end 89 | READ_BURST_0: 90 | begin 91 | line_o = '0; 92 | resp_o = 1'b0; 93 | burst_o = '0; 94 | read_o = 1'b1; 95 | write_o = 1'b0; 96 | read_pos = 3'b000; 97 | end 98 | READ_BURST_1: 99 | begin 100 | line_o = '0; 101 | resp_o = 1'b0; 102 | burst_o = '0; 103 | read_o = 1'b1; 104 | write_o = 1'b0; 105 | read_pos = 3'b001; 106 | end 107 | READ_BURST_2: 108 | begin 109 | line_o = '0; 110 | resp_o = 1'b0; 111 | burst_o = '0; 112 | read_o = 1'b1; 113 | write_o = 1'b0; 114 | read_pos = 3'b010; 115 | end 116 | READ_DONE: 117 | begin 118 | line_o = buffer; 119 | resp_o = 1'b1; 120 | burst_o = '0; 121 | read_o = 1'b0; 122 | write_o = 1'b0; 123 | read_pos = 3'b111; 124 | end 125 | WRITE_WAIT: 126 | begin 127 | line_o = '0; 128 | resp_o = 1'b0; 129 | burst_o = buffer[63:0]; 130 | read_o = 1'b0; 131 | write_o = 1'b1; 132 | read_pos = 3'b111; 133 | end 134 | WRITE_BURST_0: 135 | begin 136 | line_o = '0; 137 | resp_o = 1'b0; 138 | burst_o = buffer[127:64]; 139 | read_o = 1'b0; 140 | write_o = 1'b1; 141 | read_pos = 3'b111; 142 | end 143 | WRITE_BURST_1: 144 | begin 145 | line_o = '0; 146 | resp_o = 1'b0; 147 | burst_o = buffer[191:128]; 148 | read_o = 1'b0; 149 | write_o = 1'b1; 150 | read_pos = 3'b111; 151 | end 152 | WRITE_BURST_2: 153 | begin 154 | line_o = '0; 155 | resp_o = 1'b0; 156 | burst_o = buffer[255:192]; 157 | read_o = 1'b0; 158 | write_o = 1'b1; 159 | read_pos = 3'b111; 160 | end 161 | WRITE_DONE: 162 | begin 163 | line_o = '0; 164 | resp_o = 1'b1; 165 | burst_o = '0; 166 | read_o = 1'b0; 167 | write_o = 1'b0; 168 | read_pos = 3'b111; 169 | end 170 | endcase 171 | end 172 | 173 | 174 | 175 | 176 | always_ff @(posedge clk) begin 177 | if (~reset_n) 178 | begin 179 | // reset 180 | buffer <= '0; 181 | state <= INIT; 182 | end 183 | else 184 | begin 185 | state <= next_state; 186 | if(state == READ_WAIT_DRAM && resp_i == 1'b1) 187 | buffer[63:0] <= burst_i; 188 | else if(read_pos == 3'b000) 189 | buffer[127:64] <= burst_i; 190 | else if(read_pos == 3'b001) 191 | buffer[191:128] <= burst_i; 192 | else if(read_pos == 3'b010) 193 | buffer[255:192] <= burst_i; 194 | else if(state == WRITE_WAIT) 195 | buffer <= line_i; 196 | end 197 | end 198 | 199 | 200 | endmodule : cacheline_adaptor -------------------------------------------------------------------------------- /hdl/cpu/alu.sv: -------------------------------------------------------------------------------- 1 | 2 | module alu 3 | import rv32i_types::*; 4 | ( 5 | input alu_ops aluop, 6 | input [31:0] a, b, 7 | output logic [31:0] f 8 | ); 9 | 10 | always_comb 11 | begin 12 | unique case (aluop) 13 | alu_add: f = a + b; 14 | alu_sll: f = a << b[4:0]; 15 | alu_sra: f = $signed(a) >>> b[4:0]; 16 | alu_sub: f = a - b; 17 | alu_xor: f = a ^ b; 18 | alu_srl: f = a >> b[4:0]; 19 | alu_or: f = a | b; 20 | alu_and: f = a & b; 21 | endcase 22 | end 23 | 24 | endmodule : alu 25 | -------------------------------------------------------------------------------- /hdl/cpu/bht.sv: -------------------------------------------------------------------------------- 1 | module bht 2 | import rv32i_types::*; 3 | #( 4 | parameter s_index = 4, 5 | parameter depth = 4 6 | ) 7 | ( 8 | input logic clk, 9 | input logic rst, 10 | input logic load, 11 | input logic [s_index-1:0] rindex, 12 | input logic [s_index-1:0] windex, 13 | input logic in, 14 | output logic [depth-1:0] out 15 | ); 16 | 17 | 18 | localparam num_sets = 2**s_index; 19 | 20 | logic [depth-1:0] data [num_sets-1:0]; 21 | logic [depth-1:0] _in; 22 | 23 | always_comb 24 | begin 25 | _in = data[windex]; 26 | if (load) 27 | begin 28 | _in = data[windex] << 1; 29 | _in[0] = in; 30 | end 31 | end 32 | 33 | always_ff @(posedge clk) 34 | begin 35 | if (rst) 36 | begin 37 | for (int i = 0; i < num_sets; ++i) 38 | data[i] <= '1; 39 | end 40 | else 41 | begin 42 | data[windex] <= _in; 43 | end 44 | end 45 | 46 | always_comb 47 | begin 48 | if((rindex == windex) && load) 49 | // transparent 50 | out = _in; 51 | else 52 | out = data[rindex]; 53 | 54 | end 55 | 56 | endmodule : bht 57 | -------------------------------------------------------------------------------- /hdl/cpu/btb_array.sv: -------------------------------------------------------------------------------- 1 | module btb_array 2 | import rv32i_types::*; 3 | #( 4 | parameter s_index = 3, 5 | parameter width = 32 6 | ) 7 | ( 8 | input logic clk, 9 | input logic rst, 10 | input logic load, 11 | input logic [s_index-1:0] rindex, 12 | input logic [s_index-1:0] windex, 13 | input [width-1:0] in, 14 | output logic [width-1:0] out 15 | ); 16 | 17 | localparam num_sets = 2**s_index; 18 | 19 | logic [width-1:0] data [num_sets]; 20 | 21 | always_ff @(posedge clk) 22 | begin 23 | if (rst) 24 | begin 25 | for (int i = 0; i < num_sets; ++i) 26 | data[i] <= '0; 27 | end 28 | else if (load) 29 | data[windex] <= in; 30 | end 31 | 32 | always_comb 33 | begin 34 | // if((rindex == windex) && load) 35 | // // transparent 36 | // out = in; 37 | // else 38 | out = data[rindex]; 39 | end 40 | 41 | endmodule : btb_array 42 | -------------------------------------------------------------------------------- /hdl/cpu/cmp.sv: -------------------------------------------------------------------------------- 1 | module cmp 2 | import rv32i_types::*; 3 | ( 4 | input branch_funct3_t cmpop, 5 | input logic [31:0] a, b, 6 | output logic f 7 | ); 8 | 9 | 10 | always_comb 11 | begin 12 | f = '0; 13 | unique case(cmpop) 14 | beq: f = (a == b); 15 | bne: f = (a != b); 16 | blt: f = $signed(a) < $signed(b); 17 | bge: f = $signed(a) >= $signed(b); 18 | bltu: f = (a < b); 19 | bgeu: f = (a >= b); 20 | default:; //$display("CMP DEFAULT"); 21 | endcase 22 | 23 | end 24 | endmodule : cmp 25 | 26 | -------------------------------------------------------------------------------- /hdl/cpu/control_rom.sv: -------------------------------------------------------------------------------- 1 | 2 | module control_rom 3 | import rv32i_types::*; 4 | ( 5 | input rv32i_opcode opcode, 6 | input [2:0] funct3, 7 | input [6:0] funct7, 8 | input rv32i_reg rs1_id, rs2_id, rd_id, 9 | output rv32i_control_word ctrl 10 | ); 11 | 12 | branch_funct3_t branch_funct3; 13 | store_funct3_t store_funct3; 14 | load_funct3_t load_funct3; 15 | arith_funct3_t arith_funct3; 16 | 17 | assign arith_funct3 = arith_funct3_t'(funct3); 18 | assign branch_funct3 = branch_funct3_t'(funct3); 19 | assign load_funct3 = load_funct3_t'(funct3); 20 | assign store_funct3 = store_funct3_t'(funct3); 21 | 22 | function void set_defaults(); 23 | ctrl.opcode = opcode; 24 | ctrl.funct3 = funct3; 25 | ctrl.funct7 = funct7; 26 | ctrl.rs1_id = rs1_id; 27 | ctrl.rs2_id = rs2_id; 28 | ctrl.rd_id = rd_id; 29 | ctrl.aluop = alu_ops'(funct3); 30 | ctrl.cmpop = branch_funct3_t'(funct3); 31 | ctrl.cmp_MUX_sel = cmpmux::rs2_out; 32 | ctrl.alu_1_MUX_sel = alumux::rs1_out; 33 | ctrl.alu_2_MUX_sel = alumux::imm; 34 | ctrl.regfile_MUX_sel = regfilemux::alu_out; 35 | ctrl.target_address_MUX_sel = targetaddressmux::pc; 36 | ctrl.load_regfile = 1'b0; 37 | ctrl.load_pc = 1'b1; 38 | ctrl.mem_read = 1'b0; 39 | ctrl.mem_write = 1'b0; 40 | endfunction 41 | 42 | function void setALU(alumux::alumux1_sel_t sel1, alumux::alumux2_sel_t sel2, logic setop, alu_ops op); 43 | ctrl.alu_1_MUX_sel = sel1; 44 | ctrl.alu_2_MUX_sel = sel2; 45 | 46 | if (setop) 47 | ctrl.aluop = op; 48 | endfunction 49 | 50 | function automatic void setCMP(cmpmux::cmpmux_sel_t sel, branch_funct3_t op); 51 | ctrl.cmpop = op; 52 | ctrl.cmp_MUX_sel = sel; 53 | endfunction 54 | 55 | function void loadPC(logic load_pc); 56 | ctrl.load_pc = load_pc; 57 | endfunction 58 | 59 | function void loadRegfile(regfilemux::regfilemux_sel_t sel); 60 | ctrl.load_regfile = 1'b1; 61 | ctrl.regfile_MUX_sel = sel; 62 | endfunction 63 | 64 | function void mem_read(); 65 | ctrl.mem_read = 1'b1; 66 | endfunction 67 | 68 | function void mem_write(); 69 | ctrl.mem_write = 1'b1; 70 | endfunction 71 | 72 | always_comb begin 73 | /* Default assignments */ 74 | set_defaults(); 75 | 76 | /* Assign control signals based on opcode */ 77 | case(opcode) 78 | op_lui : begin 79 | loadRegfile(regfilemux::imm); 80 | end 81 | op_auipc : begin 82 | setALU(alumux::pc_out, alumux::imm, 1, alu_add); 83 | loadRegfile(regfilemux::alu_out); 84 | end 85 | op_jal : begin 86 | setALU(alumux::pc_out, alumux::imm, 1, alu_add); 87 | loadRegfile(regfilemux::pc_plus4); 88 | end 89 | op_jalr : begin 90 | setALU(alumux::rs1_out, alumux::imm, 1, alu_add); 91 | loadRegfile(regfilemux::pc_plus4); 92 | ctrl.target_address_MUX_sel = targetaddressmux::rs1_out; 93 | end 94 | op_br : begin 95 | setCMP(cmpmux::rs2_out, branch_funct3); 96 | setALU(alumux::pc_out, alumux::imm, 1, alu_add); 97 | 98 | end 99 | 100 | op_load : begin 101 | setALU(alumux::rs1_out, alumux::imm, 1, alu_add); 102 | loadRegfile(regfilemux::load); 103 | mem_read(); 104 | end 105 | 106 | op_store : begin 107 | setALU(alumux::rs1_out, alumux::imm, 1, alu_add); 108 | mem_write(); 109 | end 110 | 111 | op_imm : begin 112 | unique case (arith_funct3) 113 | slt: 114 | begin 115 | setCMP(cmpmux::imm, blt); 116 | loadRegfile(regfilemux::br_en); 117 | end 118 | sltu : 119 | begin 120 | setCMP(cmpmux::imm, bltu); 121 | loadRegfile(regfilemux::br_en); 122 | end 123 | sr : 124 | begin 125 | setALU(alumux::rs1_out, alumux::imm, 1, (funct7[5]) ? alu_sra: alu_ops'(arith_funct3)); 126 | loadRegfile(regfilemux::alu_out); 127 | end 128 | add, sll, axor, aor, aand : 129 | begin 130 | setALU(alumux::rs1_out, alumux::imm, 1, alu_ops'(arith_funct3)); 131 | loadRegfile(regfilemux::alu_out); 132 | end 133 | 134 | endcase 135 | end 136 | 137 | op_reg : begin 138 | unique case (arith_funct3) 139 | slt: 140 | begin 141 | setCMP(cmpmux::rs2_out, blt); 142 | loadRegfile(regfilemux::br_en); 143 | end 144 | sltu : 145 | begin 146 | setCMP(cmpmux::rs2_out, bltu); 147 | loadRegfile(regfilemux::br_en); 148 | end 149 | sr : 150 | begin 151 | setALU(alumux::rs1_out, alumux::rs2_out, 1, (funct7[5]) ? alu_sra : alu_ops'(arith_funct3)); 152 | loadRegfile(regfilemux::alu_out); 153 | end 154 | add : 155 | begin 156 | setALU(alumux::rs1_out, alumux::rs2_out, 1, (funct7[5]) ? alu_sub : alu_ops'(arith_funct3)); 157 | loadRegfile(regfilemux::alu_out); 158 | end 159 | 160 | sll, axor, aor, aand : 161 | begin 162 | setALU(alumux::rs1_out, alumux::rs2_out, 1, alu_ops'(arith_funct3)); 163 | loadRegfile(regfilemux::alu_out); 164 | end 165 | 166 | endcase 167 | end 168 | 169 | endcase 170 | 171 | if(rd_id == 5'b0) 172 | ctrl.load_regfile = 1'b0; 173 | end 174 | endmodule : control_rom -------------------------------------------------------------------------------- /hdl/cpu/ex_mem_reg.sv: -------------------------------------------------------------------------------- 1 | module ex_mem_reg 2 | import rv32i_types::*; 3 | ( 4 | input logic clk, 5 | input logic rst, 6 | input logic flush, 7 | input logic load, 8 | input ex_mem_pipeline_reg in, 9 | output ex_mem_pipeline_reg out 10 | ); 11 | 12 | ex_mem_pipeline_reg data; 13 | 14 | always_ff @ (posedge clk) begin 15 | if (rst) begin 16 | data <= '0; 17 | end 18 | 19 | else if (load) begin 20 | if(flush) 21 | data <= '0; 22 | else 23 | data <= in; 24 | end 25 | end 26 | 27 | always_comb begin 28 | 29 | out = data; 30 | 31 | end 32 | 33 | endmodule: ex_mem_reg -------------------------------------------------------------------------------- /hdl/cpu/forward_control_unit.sv: -------------------------------------------------------------------------------- 1 | module forward_control_unit 2 | import rv32i_types::*; 3 | ( 4 | /* Inputs Required for Forwarding Detection */ 5 | input rv32i_control_word id_ex_in_ctrl, 6 | input rv32i_control_word id_ex_out_ctrl, 7 | input rv32i_control_word ex_mem_out_ctrl, 8 | input rv32i_control_word mem_wb_out_ctrl, 9 | 10 | /* Forwarding MUX Selection Signals */ 11 | output idforwardamux::idforwardamux_sel_t id_forward_A_MUX_sel, 12 | output idforwardbmux::idforwardbmux_sel_t id_forward_B_MUX_sel, 13 | output exforwardamux::exforwardamux_sel_t ex_forward_A_MUX_sel, 14 | output exforwardbmux::exforwardbmux_sel_t ex_forward_B_MUX_sel, 15 | output wbmemforwardmux::wbmemforwardmux_sel_t wb_mem_forward_MUX_sel 16 | ); 17 | 18 | 19 | 20 | function void set_defaults_mem(); 21 | 22 | wb_mem_forward_MUX_sel = wbmemforwardmux::no_forward; 23 | 24 | endfunction 25 | 26 | function void set_defaults_ex(); 27 | 28 | ex_forward_A_MUX_sel = exforwardamux::no_forward; 29 | ex_forward_B_MUX_sel = exforwardbmux::no_forward; 30 | 31 | endfunction 32 | 33 | function void set_defaults_id(); 34 | 35 | id_forward_A_MUX_sel = idforwardamux::no_forward; 36 | id_forward_B_MUX_sel = idforwardbmux::no_forward; 37 | 38 | endfunction 39 | 40 | 41 | 42 | always_comb begin: MEM_EX_AND_WB_EX 43 | 44 | 45 | set_defaults_ex(); 46 | /* MEM-EX Forward Path */ 47 | if(ex_mem_out_ctrl.load_regfile && (ex_mem_out_ctrl.rd_id == id_ex_out_ctrl.rs1_id) && ex_mem_out_ctrl.rd_id != 0) 48 | begin 49 | if(ex_mem_out_ctrl.opcode != op_load) 50 | begin 51 | if(ex_mem_out_ctrl.opcode == op_lui) 52 | ex_forward_A_MUX_sel = exforwardamux::mem_imm; 53 | else if (ex_mem_out_ctrl.regfile_MUX_sel == regfilemux::br_en) 54 | ex_forward_A_MUX_sel = exforwardamux::mem_br_en; 55 | else 56 | ex_forward_A_MUX_sel = exforwardamux::mem_alu_out; 57 | end 58 | end 59 | 60 | if(ex_mem_out_ctrl.load_regfile && (ex_mem_out_ctrl.rd_id == id_ex_out_ctrl.rs2_id) && ex_mem_out_ctrl.rd_id != 0) 61 | begin 62 | if(ex_mem_out_ctrl.opcode != op_load) 63 | begin 64 | if (ex_mem_out_ctrl.opcode == op_lui) 65 | ex_forward_B_MUX_sel = exforwardbmux::mem_imm; 66 | else if (ex_mem_out_ctrl.regfile_MUX_sel == regfilemux::br_en) 67 | ex_forward_B_MUX_sel = exforwardbmux::mem_br_en; 68 | else 69 | ex_forward_B_MUX_sel = exforwardbmux::mem_alu_out; 70 | end 71 | end 72 | 73 | /* WB-EX Forward Path */ 74 | if (mem_wb_out_ctrl.load_regfile && (mem_wb_out_ctrl.rd_id == id_ex_out_ctrl.rs1_id) && mem_wb_out_ctrl.rd_id != 0) 75 | begin 76 | if (ex_forward_A_MUX_sel == exforwardamux::no_forward) begin //Double Data Hazards 77 | ex_forward_A_MUX_sel = exforwardamux::wb_regfile_MUX_out; 78 | end 79 | end 80 | if (mem_wb_out_ctrl.load_regfile && (mem_wb_out_ctrl.rd_id == id_ex_out_ctrl.rs2_id) && mem_wb_out_ctrl.rd_id != 0) 81 | begin 82 | if (ex_forward_B_MUX_sel == exforwardbmux::no_forward) begin //Double Data Hazards, unset 83 | ex_forward_B_MUX_sel = exforwardbmux::wb_regfile_MUX_out; 84 | end 85 | end 86 | 87 | end 88 | 89 | always_comb begin : EX_ID_AND_MEM_ID 90 | 91 | set_defaults_id(); 92 | 93 | if(id_ex_in_ctrl.opcode == op_br || id_ex_in_ctrl.opcode == op_jalr || 94 | (id_ex_in_ctrl.opcode == op_reg && arith_funct3_t'(id_ex_in_ctrl.funct3) == sltu) || 95 | (id_ex_in_ctrl.opcode == op_reg && arith_funct3_t'(id_ex_in_ctrl.funct3) == slt) || 96 | (id_ex_in_ctrl.opcode == op_imm && arith_funct3_t'(id_ex_in_ctrl.funct3) == sltu) || 97 | (id_ex_in_ctrl.opcode == op_imm && arith_funct3_t'(id_ex_in_ctrl.funct3) == slt)) 98 | begin 99 | /* EX-ID Forwarding Path */ 100 | 101 | if (id_ex_out_ctrl.load_regfile && (id_ex_out_ctrl.rd_id == id_ex_in_ctrl.rs1_id) && id_ex_out_ctrl.rd_id != 0) 102 | begin 103 | 104 | if (id_ex_out_ctrl.opcode == op_lui) 105 | id_forward_A_MUX_sel = idforwardamux::ex_imm; 106 | 107 | else if (id_ex_out_ctrl.regfile_MUX_sel == regfilemux::br_en) //anything which loads br_en into reg file 108 | id_forward_A_MUX_sel = idforwardamux::ex_br_en; 109 | end 110 | 111 | if (id_ex_out_ctrl.load_regfile && (id_ex_out_ctrl.rd_id == id_ex_in_ctrl.rs2_id) && id_ex_out_ctrl.rd_id != 0) 112 | begin 113 | 114 | if (id_ex_out_ctrl.opcode == op_lui) 115 | id_forward_B_MUX_sel = idforwardbmux::ex_imm; 116 | 117 | else if (id_ex_out_ctrl.regfile_MUX_sel == regfilemux::br_en) //anything which loads br_en into reg file 118 | id_forward_B_MUX_sel = idforwardbmux::ex_br_en; 119 | end 120 | 121 | /* MEM-ID Forwarding Path */ 122 | 123 | if (ex_mem_out_ctrl.load_regfile && (ex_mem_out_ctrl.rd_id == id_ex_in_ctrl.rs1_id) && ex_mem_out_ctrl.rd_id != 0) 124 | begin 125 | if (id_forward_A_MUX_sel == idforwardamux::no_forward) 126 | begin 127 | if (ex_mem_out_ctrl.opcode == op_jal || ex_mem_out_ctrl.opcode == op_jalr) 128 | id_forward_A_MUX_sel = idforwardamux::mem_pc_plus4; 129 | else if (ex_mem_out_ctrl.opcode == op_lui) 130 | id_forward_A_MUX_sel = idforwardamux::mem_imm; 131 | else if (ex_mem_out_ctrl.opcode != op_load) 132 | id_forward_A_MUX_sel = idforwardamux::mem_alu_out; 133 | end 134 | 135 | end 136 | 137 | if (ex_mem_out_ctrl.load_regfile && (ex_mem_out_ctrl.rd_id == id_ex_in_ctrl.rs2_id) && ex_mem_out_ctrl.rd_id != 0) 138 | begin 139 | if (id_forward_B_MUX_sel == idforwardbmux::no_forward) 140 | begin 141 | if (ex_mem_out_ctrl.opcode == op_jal || ex_mem_out_ctrl.opcode == op_jalr) 142 | id_forward_B_MUX_sel = idforwardbmux::mem_pc_plus4; 143 | else if (ex_mem_out_ctrl.opcode == op_lui) 144 | id_forward_B_MUX_sel = idforwardbmux::mem_imm; 145 | else if (ex_mem_out_ctrl.opcode != op_load) 146 | id_forward_B_MUX_sel = idforwardbmux::mem_alu_out; 147 | end 148 | 149 | end 150 | 151 | end 152 | 153 | end 154 | 155 | 156 | always_comb begin : WB_MEM 157 | 158 | set_defaults_mem(); 159 | 160 | if (mem_wb_out_ctrl.opcode == op_load) 161 | begin 162 | if (ex_mem_out_ctrl.opcode == op_store) // needed! 163 | begin 164 | if (mem_wb_out_ctrl.load_regfile && (mem_wb_out_ctrl.rd_id == ex_mem_out_ctrl.rs2_id) && mem_wb_out_ctrl.rd_id != 0) 165 | wb_mem_forward_MUX_sel = wbmemforwardmux::regfile_MUX_out; 166 | end 167 | 168 | end 169 | 170 | end 171 | 172 | 173 | endmodule : forward_control_unit -------------------------------------------------------------------------------- /hdl/cpu/ghr.sv: -------------------------------------------------------------------------------- 1 | module ghr 2 | import rv32i_types::*; 3 | #( 4 | parameter depth = 4 5 | ) 6 | ( 7 | input logic clk, 8 | input logic rst, 9 | input logic load, 10 | input logic in, 11 | output logic [depth-1:0] out 12 | ); 13 | 14 | /* LSB is the most recent history. */ 15 | /* 1 is taken. 0 is not taken. */ 16 | /* Initialize to all taken. */ 17 | 18 | logic [depth-1:0] data; 19 | logic [depth-1:0] _in; 20 | 21 | always_comb 22 | begin 23 | _in = data; 24 | if (load) 25 | begin 26 | _in = data << 1; // will place 0 in LSB 27 | _in[0] = in; // update LSB with correct value 28 | end 29 | end 30 | 31 | always_ff @(posedge clk) 32 | begin 33 | if (rst) 34 | begin 35 | data <= '1; 36 | end 37 | else 38 | begin 39 | data <= _in; 40 | end 41 | end 42 | 43 | always_comb 44 | begin 45 | if(load) 46 | // transparent 47 | out = _in; 48 | else 49 | out = data; 50 | 51 | end 52 | 53 | endmodule : ghr 54 | -------------------------------------------------------------------------------- /hdl/cpu/id_ex_reg.sv: -------------------------------------------------------------------------------- 1 | module id_ex_reg 2 | import rv32i_types::*; 3 | ( 4 | input logic clk, 5 | input logic rst, 6 | input logic flush, 7 | input logic load, 8 | input id_ex_pipeline_reg in, 9 | output id_ex_pipeline_reg out 10 | ); 11 | 12 | id_ex_pipeline_reg data; 13 | 14 | always_ff @ (posedge clk) begin 15 | if (rst) begin 16 | data <= '0; 17 | end 18 | 19 | else if (load) begin 20 | if(flush) 21 | data <= '0; 22 | else 23 | data <= in; 24 | end 25 | end 26 | 27 | always_comb begin 28 | 29 | out = data; 30 | 31 | end 32 | 33 | endmodule: id_ex_reg -------------------------------------------------------------------------------- /hdl/cpu/if_id_reg.sv: -------------------------------------------------------------------------------- 1 | module if_id_reg 2 | import rv32i_types::*; 3 | ( 4 | input logic clk, 5 | input logic rst, 6 | input logic flush, 7 | input logic load, 8 | input if_id_pipeline_reg in, 9 | output if_id_pipeline_reg out 10 | ); 11 | 12 | if_id_pipeline_reg data; 13 | 14 | 15 | always_ff @ (posedge clk) begin 16 | if (rst) begin 17 | data <= '0; 18 | end 19 | 20 | else if (load) begin 21 | if(flush) 22 | begin 23 | data.pc <= '0; 24 | data.ir <= 32'h00000013; 25 | end 26 | else 27 | data <= in; 28 | end 29 | end 30 | 31 | always_comb begin 32 | 33 | out = data; 34 | 35 | end 36 | 37 | endmodule: if_id_reg -------------------------------------------------------------------------------- /hdl/cpu/immediate_gen.sv: -------------------------------------------------------------------------------- 1 | `define BAD_MUX_SEL $display("%0d: %s: %0t: Illegal MUX Select", `__LINE__, `__FILE__, $time) 2 | 3 | module immediate_gen 4 | import rv32i_types::*; 5 | ( 6 | input logic [31:0] ir, 7 | 8 | output rv32i_word imm 9 | 10 | ); 11 | 12 | rv32i_word i_imm; 13 | rv32i_word s_imm; 14 | rv32i_word b_imm; 15 | rv32i_word u_imm; 16 | rv32i_word j_imm; 17 | rv32i_opcode opcode; 18 | 19 | assign i_imm = {{21{ir[31]}}, ir[30:20]}; 20 | assign s_imm = {{21{ir[31]}}, ir[30:25], ir[11:7]}; 21 | assign b_imm = {{20{ir[31]}}, ir[7], ir[30:25], ir[11:8], 1'b0}; 22 | assign u_imm = {ir[31:12], 12'h000}; 23 | assign j_imm = {{12{ir[31]}}, ir[19:12], ir[20], ir[30:21], 1'b0}; 24 | 25 | assign opcode = rv32i_opcode'(ir[6:0]); 26 | 27 | always_comb begin 28 | 29 | imm = '0; // set to 0 for debugging 30 | 31 | unique case(opcode) 32 | 33 | op_lui, op_auipc: 34 | begin 35 | imm = u_imm; 36 | end 37 | 38 | op_jal: 39 | begin 40 | imm = j_imm; 41 | end 42 | 43 | op_jalr: 44 | begin 45 | imm = i_imm; 46 | end 47 | 48 | op_br: 49 | begin 50 | imm = b_imm; 51 | end 52 | 53 | op_load: 54 | begin 55 | imm = i_imm; 56 | end 57 | 58 | op_store: 59 | begin 60 | imm = s_imm; 61 | end 62 | 63 | op_imm: 64 | begin 65 | imm = i_imm; 66 | end 67 | 68 | default: 69 | begin 70 | 71 | // $display("%0b", opcode); 72 | end 73 | endcase 74 | 75 | end 76 | 77 | 78 | endmodule : immediate_gen -------------------------------------------------------------------------------- /hdl/cpu/ir.sv: -------------------------------------------------------------------------------- 1 | 2 | module ir 3 | import rv32i_types::*; 4 | ( 5 | input clk, 6 | input rst, 7 | input load, 8 | input [31:0] in, 9 | output [2:0] funct3, 10 | output [6:0] funct7, 11 | output rv32i_opcode opcode, 12 | output [31:0] i_imm, 13 | output [31:0] s_imm, 14 | output [31:0] b_imm, 15 | output [31:0] u_imm, 16 | output [31:0] j_imm, 17 | output [4:0] rs1, 18 | output [4:0] rs2, 19 | output [4:0] rd 20 | ); 21 | 22 | logic [31:0] data; 23 | 24 | assign funct3 = data[14:12]; 25 | assign funct7 = data[31:25]; 26 | assign opcode = rv32i_opcode'(data[6:0]); 27 | assign i_imm = {{21{data[31]}}, data[30:20]}; 28 | assign s_imm = {{21{data[31]}}, data[30:25], data[11:7]}; 29 | assign b_imm = {{20{data[31]}}, data[7], data[30:25], data[11:8], 1'b0}; 30 | assign u_imm = {data[31:12], 12'h000}; 31 | assign j_imm = {{12{data[31]}}, data[19:12], data[20], data[30:21], 1'b0}; 32 | assign rs1 = data[19:15]; 33 | assign rs2 = data[24:20]; 34 | assign rd = data[11:7]; 35 | 36 | //why "=" instead of "<=" 37 | always_ff @(posedge clk) 38 | begin 39 | if (rst) 40 | begin 41 | data <= '0; 42 | end 43 | else if (load == 1) 44 | begin 45 | data <= in; 46 | end 47 | else 48 | begin 49 | data <= data; 50 | end 51 | end 52 | 53 | endmodule : ir 54 | -------------------------------------------------------------------------------- /hdl/cpu/mask_gen.sv: -------------------------------------------------------------------------------- 1 | `define BAD_MUX_SEL $display("%0d: %s: %0t: Illegal MUX Select", `__LINE__, `__FILE__, $time) 2 | 3 | module mask_gen 4 | import rv32i_types::*; 5 | ( 6 | input rv32i_word alu_out, 7 | input logic [2:0] funct3, 8 | 9 | output rv32i_mem_wmask write_read_mask 10 | 11 | ); 12 | 13 | always_comb begin 14 | 15 | write_read_mask = '0; 16 | 17 | unique case (funct3) 18 | 19 | 3'b000, 3'b100: // SB, LB, LBU 20 | begin 21 | unique case(alu_out[1:0]) 22 | 2'b00: write_read_mask = 4'b0001; 23 | 2'b01: write_read_mask = 4'b0010; 24 | 2'b10: write_read_mask = 4'b0100; 25 | 2'b11: write_read_mask = 4'b1000; 26 | default: ; 27 | endcase 28 | end 29 | 3'b001, 3'b101: // SH, LHU, LH 30 | begin 31 | unique case(alu_out[1:0]) 32 | 2'b00: write_read_mask = 4'b0011; 33 | 2'b10: write_read_mask = 4'b1100; 34 | default: ; 35 | endcase 36 | end 37 | 3'b010: // SW, LW 38 | begin 39 | write_read_mask = 4'b1111; 40 | end 41 | default: ; 42 | endcase 43 | 44 | end 45 | 46 | endmodule: mask_gen -------------------------------------------------------------------------------- /hdl/cpu/mem_wb_reg.sv: -------------------------------------------------------------------------------- 1 | module mem_wb_reg 2 | import rv32i_types::*; 3 | ( 4 | input logic clk, 5 | input logic rst, 6 | input logic flush, 7 | input logic load, 8 | input mem_wb_pipeline_reg in, 9 | output mem_wb_pipeline_reg out 10 | ); 11 | 12 | mem_wb_pipeline_reg data; 13 | 14 | always_ff @ (posedge clk) begin 15 | if (rst) begin 16 | data <= '0; 17 | end 18 | 19 | else if (load) begin 20 | if(flush) 21 | data <= '0; 22 | else 23 | data <= in; 24 | end 25 | end 26 | 27 | always_comb begin 28 | 29 | out = data; 30 | 31 | end 32 | 33 | endmodule: mem_wb_reg -------------------------------------------------------------------------------- /hdl/cpu/pc_inc.sv: -------------------------------------------------------------------------------- 1 | module pc_inc 2 | import rv32i_types::*; 3 | ( 4 | input rv32i_word in, 5 | output rv32i_word out 6 | ); 7 | 8 | assign out = in + 32'd4; 9 | 10 | endmodule : pc_inc 11 | -------------------------------------------------------------------------------- /hdl/cpu/pc_reg.sv: -------------------------------------------------------------------------------- 1 | module pc_register #(parameter width = 32) 2 | ( 3 | input clk, 4 | input rst, 5 | input load, 6 | input [width-1:0] in, 7 | output logic [width-1:0] out 8 | ); 9 | 10 | /* 11 | * PC needs to start at 0x60 12 | */ 13 | logic [width-1:0] data; 14 | 15 | always_ff @(posedge clk) 16 | begin 17 | if (rst) 18 | begin 19 | data <= 32'h00000060; 20 | end 21 | else if (load) 22 | begin 23 | data <= in; 24 | end 25 | else 26 | begin 27 | data <= data; 28 | end 29 | end 30 | 31 | always_comb 32 | begin 33 | out = data; 34 | end 35 | 36 | endmodule : pc_register 37 | -------------------------------------------------------------------------------- /hdl/cpu/perf_counter.sv: -------------------------------------------------------------------------------- 1 | module perf_counter #(parameter width = 32) 2 | ( 3 | input logic clk, 4 | input logic rst, 5 | input logic count, 6 | output logic overflow, 7 | output logic [width-1:0] out 8 | ); 9 | 10 | logic [width-1:0] data; 11 | logic _overflow; 12 | 13 | always_ff @(posedge clk or posedge rst) 14 | begin 15 | if (rst) 16 | begin 17 | data <= '0; 18 | _overflow <= 1'b0; 19 | end 20 | else 21 | begin 22 | if(count) 23 | begin 24 | data <= data + 1'b1; 25 | end 26 | 27 | if(data == '1) 28 | begin 29 | _overflow <= 1'b1; 30 | end 31 | end 32 | 33 | end 34 | 35 | always_comb 36 | begin 37 | overflow = _overflow; 38 | out = data; 39 | end 40 | 41 | endmodule : perf_counter 42 | -------------------------------------------------------------------------------- /hdl/cpu/pht.sv: -------------------------------------------------------------------------------- 1 | module pht 2 | import rv32i_types::*; 3 | #( 4 | parameter s_index = 4 5 | ) 6 | ( 7 | input logic clk, 8 | input logic rst, 9 | input logic increment, 10 | input logic decrement, 11 | input logic [s_index-1:0] rindex, 12 | input logic [s_index-1:0] windex, 13 | output logic out 14 | ); 15 | 16 | /* Increment when the branch is taken. Decrement otherwise. */ 17 | /* If the counter is 10 or 11, the branch predictor determines taken. */ 18 | /* Initialized to Weakly Taken. */ 19 | 20 | localparam num_sets = 2**s_index; 21 | 22 | logic [2:0] data [num_sets-1:0]; 23 | logic [2:0] in; 24 | 25 | always_comb 26 | begin 27 | in = data[windex]; 28 | if(increment) 29 | begin 30 | if(data[windex] != 3'b111) 31 | in = data[windex] + 3'b001; 32 | end 33 | else if(decrement) 34 | begin 35 | if(data[windex] != 3'b000) 36 | in = data[windex] - 3'b001; 37 | end 38 | end 39 | 40 | always_ff @(posedge clk) 41 | begin 42 | if (rst) 43 | begin 44 | for (int i = 0; i < num_sets; ++i) 45 | data[i] <= 3'b100; 46 | end 47 | else 48 | begin 49 | data[windex] <= in; 50 | end 51 | end 52 | 53 | always_comb 54 | begin 55 | if((rindex == windex) && (decrement || increment)) 56 | // transparent 57 | out = in[2]; 58 | else 59 | out = data[rindex][2]; 60 | 61 | end 62 | 63 | endmodule : pht 64 | -------------------------------------------------------------------------------- /hdl/cpu/regfile.sv: -------------------------------------------------------------------------------- 1 | 2 | module regfile 3 | ( 4 | input clk, 5 | input rst, 6 | input load, 7 | input [31:0] in, 8 | input [4:0] src_a, src_b, dest, 9 | output logic [31:0] reg_a, reg_b 10 | ); 11 | 12 | //logic [31:0] data [32] /* synthesis ramstyle = "logic" */ = '{default:'0}; 13 | logic [31:0] data [32]; 14 | 15 | always_ff @(posedge clk) 16 | begin 17 | if (rst) 18 | begin 19 | for (int i=0; i<32; i=i+1) begin 20 | data[i] <= '0; 21 | end 22 | end 23 | else if (load && dest) 24 | begin 25 | data[dest] <= in; 26 | end 27 | end 28 | 29 | /* Transparent Register File */ 30 | always_comb 31 | begin 32 | 33 | if(src_a == dest && load) // CP1_possible_error: transparent logic 34 | reg_a = src_a ? in : '0; 35 | else 36 | reg_a = src_a ? data[src_a] : '0; 37 | 38 | if(src_b == dest && load) 39 | reg_b = src_b ? in : '0; 40 | else 41 | reg_b = src_b ? data[src_b] : '0; 42 | 43 | end 44 | 45 | endmodule : regfile 46 | -------------------------------------------------------------------------------- /hdl/cpu/register.sv: -------------------------------------------------------------------------------- 1 | module register #(parameter width = 32) 2 | ( 3 | input clk, 4 | input rst, 5 | input load, 6 | input [width-1:0] in, 7 | output logic [width-1:0] out 8 | ); 9 | 10 | logic [width-1:0] data; 11 | 12 | always_ff @(posedge clk) 13 | begin 14 | if (rst) 15 | begin 16 | data <= '0; 17 | end 18 | else if (load) 19 | begin 20 | data <= in; 21 | end 22 | else 23 | begin 24 | data <= data; 25 | end 26 | end 27 | 28 | always_comb 29 | begin 30 | out = data; 31 | end 32 | 33 | endmodule : register 34 | -------------------------------------------------------------------------------- /hdl/l2_cache/ewb.sv: -------------------------------------------------------------------------------- 1 | module ewb 2 | import rv32i_types::*; 3 | #( 4 | width = 256, 5 | index = 3, 6 | tag = 24, 7 | cap = 8 8 | ) 9 | ( 10 | input logic clk, 11 | input logic rst, 12 | 13 | // valid-ready input protocol 14 | input logic [width-1:0] data_i, 15 | input logic [31:0] addr_i, 16 | input logic valid_i, 17 | output logic full_o, 18 | 19 | input logic tag_check, 20 | input logic [26:0] tag_i, 21 | output logic hit_o, 22 | output logic [width-1:0] read_o, 23 | 24 | // valid-yumi output protocol 25 | output logic empty_o, 26 | output logic [width-1:0] data_o, 27 | output logic [31:0] addr_o, 28 | input logic yumi_i, 29 | 30 | input logic write_ewb_i, 31 | input logic [width-1:0] replace_i 32 | ); 33 | 34 | /******************************** Declarations *******************************/ 35 | // Need memory to hold queued data 36 | logic [width-1:0] queue_data [cap]; 37 | logic [31:0] queue_addr [cap]; 38 | logic queue_valid [cap]; 39 | 40 | // Pointers which point to the read and write ends of the queue 41 | logic [index-1:0] read_ptr, write_ptr, read_ptr_next, write_ptr_next; 42 | logic [index:0] queue_counter; 43 | 44 | assign write_ptr_next = ({29'b0, write_ptr} == cap-1)? '0: write_ptr + 3'b1; 45 | assign read_ptr_next = ({29'b0, read_ptr} == cap-1)? '0: read_ptr + 3'b1; 46 | 47 | // Helper logic 48 | logic enqueue, dequeue; 49 | 50 | assign full_o = ({28'b0, queue_counter} == cap)? 1'b1: 1'b0; 51 | assign empty_o = (queue_counter == '0)? 1'b1: 1'b0; 52 | assign enqueue = (valid_i == 1'b1) && (full_o == 1'b0); 53 | assign dequeue = (yumi_i == 1'b1) && (empty_o == 1'b0); 54 | 55 | /*************************** Non-Blocking Assignments ************************/ 56 | always_ff @(posedge clk) begin 57 | if (rst) begin 58 | read_ptr <= '0; 59 | write_ptr <= '0; 60 | queue_counter <= '0; 61 | for (int i = 0; i < cap; ++i) 62 | begin 63 | queue_data[i] <= '0; 64 | queue_addr[i] <= '0; 65 | queue_valid[i] <= '0; 66 | end 67 | end 68 | else begin 69 | case ({enqueue, dequeue}) 70 | 2'b01: begin : dequeue_case 71 | queue_valid[read_ptr] <= 1'b0; 72 | read_ptr <= read_ptr_next; 73 | queue_counter <= queue_counter - 4'b1; 74 | end 75 | 2'b10: begin : enqueue_case 76 | queue_data[write_ptr] <= data_i; 77 | queue_addr[write_ptr] <= addr_i; 78 | queue_valid[write_ptr] <= 1'b1; 79 | write_ptr <= write_ptr_next; 80 | queue_counter <= queue_counter + 4'b1; 81 | end 82 | default:; 83 | endcase 84 | 85 | //queue_data[(i+read_ptr)%cap] <= replace_i; 86 | if (queue_addr[0][31:5] == tag_i) 87 | begin 88 | if (write_ewb_i == 1'b1) 89 | begin 90 | queue_data[0] <= replace_i; 91 | queue_valid[0] <= 1'b1; 92 | end 93 | end 94 | 95 | else if (queue_addr[1][31:5] == tag_i) begin 96 | if (write_ewb_i == 1'b1) 97 | begin 98 | queue_data[1] <= replace_i; 99 | queue_valid[1] <= 1'b1; 100 | end 101 | 102 | end 103 | 104 | else if (queue_addr[2][31:5] == tag_i) begin 105 | if (write_ewb_i == 1'b1) 106 | begin 107 | queue_data[2] <= replace_i; 108 | queue_valid[2] <= 1'b1; 109 | end 110 | 111 | end 112 | 113 | 114 | else if (queue_addr[3][31:5] == tag_i) begin 115 | if (write_ewb_i == 1'b1) 116 | begin 117 | queue_data[3] <= replace_i; 118 | queue_valid[3] <= 1'b1; 119 | end 120 | 121 | end 122 | 123 | else if (queue_addr[4][31:5] == tag_i) begin 124 | if (write_ewb_i == 1'b1) 125 | begin 126 | queue_data[4] <= replace_i; 127 | queue_valid[4] <= 1'b1; 128 | end 129 | end 130 | 131 | else if (queue_addr[5][31:5] == tag_i) begin 132 | if (write_ewb_i == 1'b1) 133 | begin 134 | queue_data[5] <= replace_i; 135 | queue_valid[5] <= 1'b1; 136 | end 137 | 138 | end 139 | 140 | else if (queue_addr[6][31:5] == tag_i) begin 141 | if (write_ewb_i == 1'b1) 142 | begin 143 | queue_data[6] <= replace_i; 144 | queue_valid[6] <= 1'b1; 145 | end 146 | end 147 | 148 | else if (queue_addr[7][31:5] == tag_i) begin 149 | if (write_ewb_i == 1'b1) 150 | begin 151 | queue_data[7] <= replace_i; 152 | queue_valid[7] <= 1'b1; 153 | end 154 | 155 | end 156 | 157 | 158 | end 159 | 160 | end 161 | 162 | always_comb begin 163 | hit_o = 1'b0; 164 | read_o = '0; 165 | if (queue_addr[0][31:5] == tag_i && queue_valid[0] == 1'b1) 166 | begin 167 | read_o = queue_data[0]; 168 | hit_o = 1'b1; 169 | 170 | end 171 | 172 | else if (queue_addr[1][31:5] == tag_i && queue_valid[1] == 1'b1) begin 173 | read_o = queue_data[1]; 174 | hit_o = 1'b1; 175 | 176 | end 177 | 178 | else if (queue_addr[2][31:5] == tag_i && queue_valid[2] == 1'b1) begin 179 | read_o = queue_data[2]; 180 | hit_o = 1'b1; 181 | 182 | end 183 | 184 | 185 | else if (queue_addr[3][31:5] == tag_i && queue_valid[3] == 1'b1) begin 186 | read_o = queue_data[3]; 187 | hit_o = 1'b1; 188 | 189 | end 190 | 191 | else if (queue_addr[4][31:5] == tag_i && queue_valid[4] == 1'b1) begin 192 | read_o = queue_data[4]; 193 | hit_o = 1'b1; 194 | end 195 | 196 | else if (queue_addr[5][31:5] == tag_i && queue_valid[5] == 1'b1) begin 197 | read_o = queue_data[5]; 198 | hit_o = 1'b1; 199 | 200 | end 201 | 202 | else if (queue_addr[6][31:5] == tag_i && queue_valid[6] == 1'b1) begin 203 | read_o = queue_data[6]; 204 | hit_o = 1'b1; 205 | 206 | end 207 | 208 | else if (queue_addr[7][31:5] == tag_i && queue_valid[7] == 1'b1) begin 209 | read_o = queue_data[7]; 210 | hit_o = 1'b1; 211 | 212 | end 213 | end 214 | 215 | assign data_o = queue_data[read_ptr]; 216 | assign addr_o = queue_addr[read_ptr]; 217 | 218 | endmodule : ewb 219 | -------------------------------------------------------------------------------- /hdl/l2_cache/l2_array.sv: -------------------------------------------------------------------------------- 1 | /* DO NOT MODIFY. WILL BE OVERRIDDEN BY THE AUTOGRADER. 2 | A register array to be used for tag arrays, LRU array, etc. */ 3 | 4 | module l2_array #( 5 | parameter s_index = 3, 6 | parameter width = 1 7 | ) 8 | ( 9 | clk, 10 | rst, 11 | read, 12 | load, 13 | rindex, 14 | windex, 15 | datain, 16 | dataout 17 | ); 18 | 19 | localparam num_sets = 2**s_index; 20 | 21 | input clk; 22 | input rst; 23 | input read; 24 | input load; 25 | input [s_index-1:0] rindex; 26 | input [s_index-1:0] windex; 27 | input [width-1:0] datain; 28 | output logic [width-1:0] dataout; 29 | 30 | logic [width-1:0] data [num_sets-1:0] /* synthesis ramstyle = "logic" */; 31 | logic [width-1:0] _dataout; 32 | assign dataout = _dataout; 33 | 34 | always_ff @(posedge clk) 35 | begin 36 | if (rst) begin 37 | for (int i = 0; i < num_sets; ++i) 38 | data[i] <= '0; 39 | end 40 | else begin 41 | if (read) 42 | _dataout <= (load & (rindex == windex)) ? datain : data[rindex]; 43 | 44 | if(load) 45 | data[windex] <= datain; 46 | end 47 | end 48 | 49 | endmodule : l2_array 50 | -------------------------------------------------------------------------------- /hdl/l2_cache/l2_cache.sv: -------------------------------------------------------------------------------- 1 | /* MODIFY. Your cache design. It contains the cache 2 | controller, cache datapath, and bus adapter. */ 3 | 4 | module l2_cache 5 | import rv32i_types::*; 6 | import cache_mux_types::*; 7 | #( 8 | parameter s_offset = 5, 9 | parameter s_index = 3, 10 | parameter s_tag = 32 - s_offset - s_index, 11 | parameter s_mask = 2**s_offset, 12 | parameter s_line = 8*s_mask, 13 | parameter num_sets = 2**s_index, 14 | parameter num_ways = 4 15 | ) 16 | ( 17 | input clk, 18 | input rst, 19 | 20 | /* CPU memory signals */ 21 | input logic [31:0] mem_address, 22 | output logic [255:0] mem_rdata256, 23 | input logic [255:0] mem_wdata256, 24 | input logic mem_read, 25 | input logic mem_write, 26 | output logic mem_resp, 27 | 28 | /* Physical memory signals */ 29 | output logic [31:0] pmem_address, 30 | input logic [255:0] pmem_rdata, 31 | output logic [255:0] pmem_wdata, 32 | output logic pmem_read, 33 | output logic pmem_write, 34 | input logic pmem_resp 35 | ); 36 | 37 | logic [31:0] mem_byte_enable256; 38 | assign mem_byte_enable256 = '1; 39 | 40 | /* Datapath to Control */ 41 | logic hit; 42 | logic way_0_hit; 43 | logic way_1_hit; 44 | logic way_2_hit; 45 | logic way_3_hit; 46 | 47 | logic v_array_0_dataout; 48 | logic v_array_1_dataout; 49 | logic v_array_2_dataout; 50 | logic v_array_3_dataout; 51 | 52 | logic d_array_0_dataout; 53 | logic d_array_1_dataout; 54 | logic d_array_2_dataout; 55 | logic d_array_3_dataout; 56 | 57 | logic [2:0] LRU_array_dataout; 58 | 59 | /* Control to Datapath */ 60 | logic v_array_0_load; 61 | logic v_array_0_datain; 62 | logic v_array_1_load; 63 | logic v_array_1_datain; 64 | logic v_array_2_load; 65 | logic v_array_2_datain; 66 | logic v_array_3_load; 67 | logic v_array_3_datain; 68 | 69 | logic d_array_0_load; 70 | logic d_array_0_datain; 71 | logic d_array_1_load; 72 | logic d_array_1_datain; 73 | logic d_array_2_load; 74 | logic d_array_2_datain; 75 | logic d_array_3_load; 76 | logic d_array_3_datain; 77 | 78 | logic tag_array_0_load; 79 | logic tag_array_1_load; 80 | logic tag_array_2_load; 81 | logic tag_array_3_load; 82 | 83 | logic [31:0] datapath_pmem_address; 84 | logic [31:0] ewb_pmem_address; 85 | 86 | logic LRU_array_load; 87 | logic [2:0] LRU_array_datain; 88 | 89 | logic memory_buffer_register_load; 90 | 91 | dataarraymux_sel_t write_en_0_MUX_sel; 92 | dataarraymux_sel_t write_en_1_MUX_sel; 93 | dataarraymux_sel_t write_en_2_MUX_sel; 94 | dataarraymux_sel_t write_en_3_MUX_sel; 95 | dataarraymux_sel_t data_array_0_datain_MUX_sel; 96 | dataarraymux_sel_t data_array_1_datain_MUX_sel; 97 | dataarraymux_sel_t data_array_2_datain_MUX_sel; 98 | dataarraymux_sel_t data_array_3_datain_MUX_sel; 99 | 100 | logic [1:0] dataout_MUX_sel; 101 | 102 | pmemaddressmux_sel_t pmem_address_MUX_sel; 103 | 104 | 105 | logic load_ewb; 106 | logic wb_ewb; 107 | logic tag_check; 108 | logic ewb_hit; 109 | 110 | logic ewb_full; 111 | 112 | logic [255:0] ewb_dataout; 113 | logic [255:0] datapath_dataout; 114 | logic ewb_empty; 115 | 116 | ewb ewb ( 117 | .clk, 118 | .rst, 119 | .data_i(datapath_dataout), 120 | .addr_i(datapath_pmem_address), 121 | 122 | .tag_check(tag_check), 123 | .tag_i(mem_address[31:5]), 124 | .hit_o(ewb_hit), 125 | .read_o(ewb_dataout), 126 | .empty_o(ewb_empty), 127 | .valid_i(load_ewb), 128 | .data_o(pmem_wdata), 129 | .addr_o(ewb_pmem_address), 130 | .yumi_i(wb_ewb), 131 | .write_ewb_i(mem_write), 132 | .replace_i(mem_wdata256), 133 | .full_o(ewb_full) 134 | ); 135 | 136 | always_comb begin 137 | mem_rdata256 = datapath_dataout; 138 | if (hit == 1'b1) 139 | mem_rdata256 = datapath_dataout; 140 | else if (ewb_hit == 1'b1) 141 | mem_rdata256 = ewb_dataout; 142 | end 143 | 144 | always_comb begin 145 | pmem_address = datapath_pmem_address; 146 | if (pmem_write == 1'b1) 147 | pmem_address = ewb_pmem_address; 148 | 149 | end 150 | 151 | l2_cache_control control (.*); 152 | 153 | l2_cache_datapath datapath (.mem_rdata256(datapath_dataout), .pmem_wdata(), .pmem_address(datapath_pmem_address), .*); 154 | 155 | 156 | endmodule : l2_cache 157 | -------------------------------------------------------------------------------- /hdl/l2_cache/l2_data_array.sv: -------------------------------------------------------------------------------- 1 | /* DO NOT MODIFY. WILL BE OVERRIDDEN BY THE AUTOGRADER. 2 | A special register array specifically for your 3 | data arrays. This module supports a write mask to 4 | help you update the values in the array. */ 5 | 6 | module l2_data_array #( 7 | parameter s_offset = 5, 8 | parameter s_index = 3 9 | ) 10 | ( 11 | clk, 12 | read, 13 | write_en, 14 | rindex, 15 | windex, 16 | datain, 17 | dataout 18 | ); 19 | 20 | localparam s_mask = 2**s_offset; 21 | localparam s_line = 8*s_mask; 22 | localparam num_sets = 2**s_index; 23 | 24 | input clk; 25 | input read; 26 | input [s_mask-1:0] write_en; 27 | input [s_index-1:0] rindex; 28 | input [s_index-1:0] windex; 29 | input [s_line-1:0] datain; 30 | output logic [s_line-1:0] dataout; 31 | 32 | logic [s_line-1:0] data [num_sets-1:0] /* synthesis ramstyle = "logic" */; 33 | logic [s_line-1:0] _dataout; 34 | assign dataout = _dataout; 35 | 36 | always_ff @(posedge clk) 37 | begin 38 | if (read) 39 | for (int i = 0; i < s_mask; i++) 40 | _dataout[8*i +: 8] <= (write_en[i] & (rindex == windex)) ? 41 | datain[8*i +: 8] : data[rindex][8*i +: 8]; 42 | 43 | for (int i = 0; i < s_mask; i++) 44 | begin 45 | data[windex][8*i +: 8] <= write_en[i] ? datain[8*i +: 8] : 46 | data[windex][8*i +: 8]; 47 | end 48 | end 49 | 50 | endmodule : l2_data_array 51 | -------------------------------------------------------------------------------- /hdl/mp4.sv: -------------------------------------------------------------------------------- 1 | module mp4 2 | import rv32i_types::*; 3 | ( 4 | input clk, 5 | input rst, 6 | 7 | input pmem_resp, 8 | output logic pmem_read, 9 | output logic pmem_write, 10 | output rv32i_word pmem_address, 11 | input [63:0] pmem_rdata, 12 | output [63:0] pmem_wdata 13 | 14 | ); 15 | 16 | logic instr_mem_resp; 17 | rv32i_word instr_mem_rdata; 18 | logic data_mem_resp; 19 | rv32i_word data_mem_rdata; 20 | logic instr_read; 21 | rv32i_word instr_mem_address; 22 | logic data_read; 23 | logic data_write; 24 | logic [3:0] data_mbe; 25 | rv32i_word data_mem_address; 26 | rv32i_word data_mem_wdata; 27 | logic continue_i_cache; 28 | 29 | cpu cpu ( 30 | 31 | .clk(clk), 32 | .rst(rst), 33 | 34 | /* I-Cache Ports */ 35 | .instr_read(instr_read), 36 | .instr_mem_address(instr_mem_address), 37 | .instr_mem_rdata(instr_mem_rdata), 38 | .instr_mem_resp(instr_mem_resp), 39 | .continue_i_cache(continue_i_cache), 40 | 41 | 42 | /* D-Cache Ports */ 43 | .data_read(data_read), 44 | .data_write(data_write), 45 | .data_mem_address(data_mem_address), 46 | .data_mem_rdata(data_mem_rdata), 47 | .data_mbe(data_mbe), 48 | .data_mem_wdata(data_mem_wdata), 49 | .data_mem_resp(data_mem_resp) 50 | 51 | ); 52 | 53 | cache_sys cache_sys ( 54 | 55 | .clk(clk), 56 | .rst(rst), 57 | 58 | /* Physical Memory Signals */ 59 | .pmem_read(pmem_read), 60 | .pmem_write(pmem_write), 61 | .pmem_address(pmem_address), 62 | .pmem_wdata(pmem_wdata), 63 | .pmem_rdata(pmem_rdata), 64 | .pmem_resp(pmem_resp), 65 | 66 | 67 | /* CPU Memory Signals: I-Cache */ 68 | .instr_read(instr_read), 69 | .instr_mem_address(instr_mem_address), 70 | .instr_mem_rdata(instr_mem_rdata), 71 | .instr_mem_resp(instr_mem_resp), 72 | .if_id_reg_load(continue_i_cache), 73 | 74 | 75 | /* CPU Memory Signals: D-Cache */ 76 | .data_read(data_read), 77 | .data_write(data_write), 78 | .data_mem_address(data_mem_address), 79 | .data_mbe(data_mbe), 80 | .data_mem_wdata(data_mem_wdata), 81 | .data_mem_rdata(data_mem_rdata), 82 | .data_mem_resp(data_mem_resp) 83 | 84 | ); 85 | 86 | endmodule : mp4 87 | -------------------------------------------------------------------------------- /hdl/pipeline_d_cache/p_d_cache.sv: -------------------------------------------------------------------------------- 1 | module p_d_cache 2 | import rv32i_types::*; 3 | import cache_mux_types::*; 4 | #( 5 | parameter s_offset = 5, 6 | parameter s_index = 3, 7 | parameter s_tag = 32 - s_offset - s_index, 8 | parameter s_mask = 2**s_offset, 9 | parameter s_line = 8*s_mask, 10 | parameter num_sets = 2**s_index, 11 | parameter num_ways = 4 12 | ) 13 | ( 14 | input clk, 15 | input rst, 16 | /* Physical memory signals */ 17 | input logic pmem_resp, 18 | input logic [255:0] pmem_rdata, 19 | output logic [31:0] pmem_address, 20 | output logic [255:0] pmem_wdata, 21 | output logic pmem_read, 22 | output logic pmem_write, 23 | 24 | /* CPU memory signals */ 25 | input logic mem_read, 26 | input logic mem_write, 27 | input logic [3:0] mem_byte_enable_cpu, 28 | input logic [31:0] mem_address, 29 | input logic [31:0] mem_wdata_cpu, 30 | input logic if_id_reg_load, 31 | output logic mem_resp, 32 | output logic [31:0] mem_rdata_cpu 33 | ); 34 | 35 | 36 | logic [255:0] mem_wdata; 37 | logic [255:0] mem_rdata; 38 | logic [31:0] mem_byte_enable; 39 | 40 | logic v_array_0_dataout; 41 | logic v_array_1_dataout; 42 | logic v_array_2_dataout; 43 | logic v_array_3_dataout; 44 | 45 | logic v_array_0_load; 46 | logic v_array_0_datain; 47 | logic v_array_1_load; 48 | logic v_array_1_datain; 49 | logic v_array_2_load; 50 | logic v_array_2_datain; 51 | logic v_array_3_load; 52 | logic v_array_3_datain; 53 | 54 | logic d_array_0_load; 55 | logic d_array_0_datain; 56 | logic d_array_1_load; 57 | logic d_array_1_datain; 58 | logic d_array_2_load; 59 | logic d_array_2_datain; 60 | logic d_array_3_load; 61 | logic d_array_3_datain; 62 | 63 | logic tag_array_0_load; 64 | logic tag_array_1_load; 65 | logic tag_array_2_load; 66 | logic tag_array_3_load; 67 | 68 | logic LRU_array_load; 69 | 70 | logic [2:0] LRU_array_datain; 71 | 72 | logic load_d_cache_reg; 73 | 74 | logic read_array_flag; 75 | 76 | d_cache_pipeline_reg cache_pipeline_in; 77 | d_cache_pipeline_reg cache_pipeline_out; 78 | 79 | 80 | dataarraymux_sel_t write_en_0_MUX_sel; 81 | dataarraymux_sel_t write_en_1_MUX_sel; 82 | dataarraymux_sel_t write_en_2_MUX_sel; 83 | dataarraymux_sel_t write_en_3_MUX_sel; 84 | dataarraymux_sel_t data_array_0_datain_MUX_sel; 85 | dataarraymux_sel_t data_array_1_datain_MUX_sel; 86 | dataarraymux_sel_t data_array_2_datain_MUX_sel; 87 | dataarraymux_sel_t data_array_3_datain_MUX_sel; 88 | 89 | paddressmux_sel_t address_mux_sel; 90 | 91 | rv32i_word address_MUX_out; 92 | 93 | logic [1:0] dataout_MUX_sel; 94 | 95 | pmemaddressmux_sel_t pmem_address_MUX_sel; 96 | 97 | p_d_cache_control control( 98 | .clk, 99 | .rst, 100 | 101 | /* CPU memory signals */ 102 | .mem_read, 103 | .mem_write, 104 | .mem_resp, 105 | 106 | /* Physical memory signals */ 107 | .pmem_resp, 108 | .pmem_read, 109 | .pmem_write, 110 | 111 | /* Datapath to Control */ 112 | .v_array_0_dataout, 113 | .v_array_1_dataout, 114 | .v_array_2_dataout, 115 | .v_array_3_dataout, 116 | 117 | .cache_pipeline_out, 118 | .cache_pipeline_in, 119 | 120 | /* Control to Datapath */ 121 | .v_array_0_load, 122 | .v_array_0_datain, 123 | .v_array_1_load, 124 | .v_array_1_datain, 125 | .v_array_2_load, 126 | .v_array_2_datain, 127 | .v_array_3_load, 128 | .v_array_3_datain, 129 | .d_array_0_load, 130 | .d_array_0_datain, 131 | .d_array_1_load, 132 | .d_array_1_datain, 133 | .d_array_2_load, 134 | .d_array_2_datain, 135 | .d_array_3_load, 136 | .d_array_3_datain, 137 | .tag_array_0_load, 138 | .tag_array_1_load, 139 | .tag_array_2_load, 140 | .tag_array_3_load, 141 | 142 | .LRU_array_load, 143 | .LRU_array_datain, 144 | 145 | .write_en_0_MUX_sel, 146 | .write_en_1_MUX_sel, 147 | .write_en_2_MUX_sel, 148 | .write_en_3_MUX_sel, 149 | .data_array_0_datain_MUX_sel, 150 | .data_array_1_datain_MUX_sel, 151 | .data_array_2_datain_MUX_sel, 152 | .data_array_3_datain_MUX_sel, 153 | .load_d_cache_reg, 154 | .if_id_reg_load, 155 | .read_array_flag, 156 | .address_mux_sel, 157 | .dataout_MUX_sel, 158 | .pmem_address_MUX_sel 159 | ); 160 | 161 | 162 | //STAGE 1: COMPARE TAG AND SEE IF HIT OR MISS 163 | 164 | assign cache_pipeline_in.cpu_address = mem_address; 165 | assign cache_pipeline_in.mem_write = mem_write; 166 | assign cache_pipeline_in.mem_read = mem_read; 167 | assign cache_pipeline_in.mem_wdata = mem_wdata; 168 | assign cache_pipeline_in.mem_byte_enable256 = mem_byte_enable; 169 | 170 | p_d_cache_metadata_check check 171 | ( 172 | .clk, 173 | .rst, 174 | /* CPU memory signals */ 175 | .mem_address(address_MUX_out), 176 | .mem_byte_enable256(cache_pipeline_in.mem_byte_enable256), 177 | .mem_wdata256(cache_pipeline_in.mem_wdata), // write happens for the previous instruction, which is at the second stage 178 | 179 | /* Physical memory data signals */ 180 | .pmem_rdata, 181 | .pmem_address, 182 | .pmem_wdata, 183 | 184 | .hit(cache_pipeline_in.hit), 185 | .way_0_hit(cache_pipeline_in.way_0_hit), 186 | .way_1_hit(cache_pipeline_in.way_1_hit), 187 | .way_2_hit(cache_pipeline_in.way_2_hit), 188 | .way_3_hit(cache_pipeline_in.way_3_hit), 189 | 190 | .v_array_0_dataout, 191 | .v_array_1_dataout, 192 | .v_array_2_dataout, 193 | .v_array_3_dataout, 194 | 195 | .dirty_out(cache_pipeline_in.dirty), 196 | 197 | // LRU array width is now 3. 198 | .LRU_array_dataout(cache_pipeline_in.LRU_array_dataout), 199 | 200 | /* Control to Datapath */ 201 | .v_array_0_load, 202 | .v_array_0_datain, 203 | .v_array_1_load, 204 | .v_array_1_datain, 205 | .v_array_2_load, 206 | .v_array_2_datain, 207 | .v_array_3_load, 208 | .v_array_3_datain, 209 | 210 | .d_array_0_load, 211 | .d_array_0_datain, 212 | .d_array_1_load, 213 | .d_array_1_datain, 214 | .d_array_2_load, 215 | .d_array_2_datain, 216 | .d_array_3_load, 217 | .d_array_3_datain, 218 | 219 | .tag_array_0_load, 220 | .tag_array_1_load, 221 | .tag_array_2_load, 222 | .tag_array_3_load, 223 | 224 | .LRU_array_load, 225 | .LRU_array_datain, 226 | 227 | .write_en_0_MUX_sel, 228 | .write_en_1_MUX_sel, 229 | .write_en_2_MUX_sel, 230 | .write_en_3_MUX_sel, 231 | 232 | .data_array_0_datain_MUX_sel, 233 | .data_array_1_datain_MUX_sel, 234 | .data_array_2_datain_MUX_sel, 235 | .data_array_3_datain_MUX_sel, 236 | .prev_address(cache_pipeline_out.cpu_address), 237 | .read_array_flag, 238 | .dataout_MUX_sel, 239 | .pmem_address_MUX_sel, 240 | .dataout(cache_pipeline_in.dataout) 241 | ); 242 | 243 | 244 | always_comb begin : ADDRESSMUX 245 | address_MUX_out = mem_address; 246 | unique case (address_mux_sel) 247 | curr_cpu_address: address_MUX_out = mem_address; 248 | prev_cpu_address: address_MUX_out = cache_pipeline_out.cpu_address; 249 | endcase 250 | end 251 | 252 | 253 | p_d_cache_reg pipeline_reg 254 | ( 255 | .clk, 256 | .rst, 257 | .load(load_d_cache_reg), 258 | .in(cache_pipeline_in), 259 | .out(cache_pipeline_out) 260 | ); 261 | 262 | //STAGE 2: DELIVER DATA 263 | assign mem_rdata = cache_pipeline_in.dataout; 264 | 265 | 266 | p_line_adapter bus ( 267 | .mem_wdata_line(mem_wdata), 268 | .mem_rdata_line(mem_rdata), 269 | .mem_wdata(mem_wdata_cpu), 270 | .mem_rdata(mem_rdata_cpu), 271 | .mem_byte_enable(mem_byte_enable_cpu), 272 | .mem_byte_enable_line(mem_byte_enable), 273 | .address(cache_pipeline_out.cpu_address) 274 | ); 275 | 276 | 277 | 278 | 279 | endmodule : p_d_cache 280 | -------------------------------------------------------------------------------- /hdl/pipeline_d_cache/p_d_cache_reg.sv: -------------------------------------------------------------------------------- 1 | module p_d_cache_reg 2 | import rv32i_types::*; 3 | ( 4 | input logic clk, 5 | input logic rst, 6 | input logic load, 7 | input d_cache_pipeline_reg in, 8 | output d_cache_pipeline_reg out 9 | ); 10 | 11 | d_cache_pipeline_reg data; 12 | 13 | always_ff @ (posedge clk) begin 14 | if (rst) begin 15 | data <= '0; 16 | end 17 | 18 | else if (load) begin 19 | data <= in; 20 | end 21 | end 22 | 23 | always_comb begin 24 | 25 | out = data; 26 | 27 | end 28 | 29 | endmodule: p_d_cache_reg -------------------------------------------------------------------------------- /hdl/pipeline_i_cache/p_i_cache.sv: -------------------------------------------------------------------------------- 1 | module p_i_cache 2 | import rv32i_types::*; 3 | import cache_mux_types::*; 4 | #( 5 | parameter s_offset = 5, 6 | parameter s_index = 3, 7 | parameter s_tag = 32 - s_offset - s_index, 8 | parameter s_mask = 2**s_offset, 9 | parameter s_line = 8*s_mask, 10 | parameter num_sets = 2**s_index, 11 | parameter num_ways = 4 12 | ) 13 | ( 14 | input clk, 15 | input rst, 16 | /* Physical memory signals */ 17 | input logic pmem_resp, 18 | input logic [255:0] pmem_rdata, 19 | output logic [31:0] pmem_address, 20 | output logic [255:0] pmem_wdata, 21 | output logic pmem_read, 22 | output logic pmem_write, 23 | 24 | /* CPU memory signals */ 25 | input logic mem_read, 26 | input logic mem_write, 27 | input logic [3:0] mem_byte_enable_cpu, 28 | input logic [31:0] mem_address, 29 | input logic [31:0] mem_wdata_cpu, 30 | input logic if_id_reg_load, 31 | output logic mem_resp, 32 | output logic [31:0] mem_rdata_cpu 33 | ); 34 | 35 | assign pmem_write = 1'b0; 36 | assign pmem_wdata = '0; 37 | 38 | logic [255:0] mem_wdata; 39 | logic [255:0] mem_rdata; 40 | logic [31:0] mem_byte_enable; 41 | 42 | logic v_array_0_dataout; 43 | logic v_array_1_dataout; 44 | logic v_array_2_dataout; 45 | logic v_array_3_dataout; 46 | 47 | logic v_array_0_load; 48 | logic v_array_0_datain; 49 | logic v_array_1_load; 50 | logic v_array_1_datain; 51 | logic v_array_2_load; 52 | logic v_array_2_datain; 53 | logic v_array_3_load; 54 | logic v_array_3_datain; 55 | 56 | logic tag_array_0_load; 57 | logic tag_array_1_load; 58 | logic tag_array_2_load; 59 | logic tag_array_3_load; 60 | 61 | logic LRU_array_load; 62 | 63 | logic [2:0] LRU_array_datain; 64 | 65 | logic load_i_cache_reg; 66 | 67 | logic read_array_flag; 68 | 69 | i_cache_pipeline_reg cache_pipeline_in; 70 | i_cache_pipeline_reg cache_pipeline_out; 71 | i_cache_pipeline_data cache_pipeline_data; 72 | 73 | 74 | dataarraymux_sel_t write_en_0_MUX_sel; 75 | dataarraymux_sel_t write_en_1_MUX_sel; 76 | dataarraymux_sel_t write_en_2_MUX_sel; 77 | dataarraymux_sel_t write_en_3_MUX_sel; 78 | dataarraymux_sel_t data_array_0_datain_MUX_sel; 79 | dataarraymux_sel_t data_array_1_datain_MUX_sel; 80 | dataarraymux_sel_t data_array_2_datain_MUX_sel; 81 | dataarraymux_sel_t data_array_3_datain_MUX_sel; 82 | 83 | paddressmux_sel_t address_mux_sel; 84 | 85 | rv32i_word address_MUX_out; 86 | 87 | p_i_cache_control control( 88 | .clk, 89 | .rst, 90 | 91 | /* CPU memory signals */ 92 | .mem_read, 93 | .mem_resp, 94 | 95 | /* Physical memory signals */ 96 | .pmem_resp, 97 | .pmem_read, 98 | 99 | /* Datapath to Control */ 100 | .v_array_0_dataout, 101 | .v_array_1_dataout, 102 | .v_array_2_dataout, 103 | .v_array_3_dataout, 104 | 105 | .cache_pipeline_data, 106 | 107 | /* Control to Datapath */ 108 | .v_array_0_load, 109 | .v_array_0_datain, 110 | .v_array_1_load, 111 | .v_array_1_datain, 112 | .v_array_2_load, 113 | .v_array_2_datain, 114 | .v_array_3_load, 115 | .v_array_3_datain, 116 | .tag_array_0_load, 117 | .tag_array_1_load, 118 | .tag_array_2_load, 119 | .tag_array_3_load, 120 | 121 | .LRU_array_load, 122 | .LRU_array_datain, 123 | 124 | .write_en_0_MUX_sel, 125 | .write_en_1_MUX_sel, 126 | .write_en_2_MUX_sel, 127 | .write_en_3_MUX_sel, 128 | .data_array_0_datain_MUX_sel, 129 | .data_array_1_datain_MUX_sel, 130 | .data_array_2_datain_MUX_sel, 131 | .data_array_3_datain_MUX_sel, 132 | .load_i_cache_reg, 133 | .if_id_reg_load, 134 | .read_array_flag, 135 | .address_mux_sel 136 | ); 137 | 138 | 139 | //STAGE 1: COMPARE TAG AND SEE IF HIT OR MISS 140 | 141 | assign cache_pipeline_in.cpu_address = mem_address; 142 | 143 | p_i_cache_metadata_check check 144 | ( 145 | .clk, 146 | .rst, 147 | /* CPU memory signals */ 148 | .mem_address(address_MUX_out), 149 | 150 | /* Physical memory data signals */ 151 | .pmem_rdata, 152 | .pmem_address, 153 | 154 | .hit(cache_pipeline_data.hit), 155 | .way_0_hit(cache_pipeline_data.way_0_hit), 156 | .way_1_hit(cache_pipeline_data.way_1_hit), 157 | .way_2_hit(cache_pipeline_data.way_2_hit), 158 | .way_3_hit(cache_pipeline_data.way_3_hit), 159 | 160 | .v_array_0_dataout, 161 | .v_array_1_dataout, 162 | .v_array_2_dataout, 163 | .v_array_3_dataout, 164 | 165 | // LRU array width is now 3. 166 | .LRU_array_dataout(cache_pipeline_data.LRU_array_dataout), 167 | 168 | /* Control to Datapath */ 169 | .v_array_0_load, 170 | .v_array_0_datain, 171 | .v_array_1_load, 172 | .v_array_1_datain, 173 | .v_array_2_load, 174 | .v_array_2_datain, 175 | .v_array_3_load, 176 | .v_array_3_datain, 177 | 178 | .tag_array_0_load, 179 | .tag_array_1_load, 180 | .tag_array_2_load, 181 | .tag_array_3_load, 182 | 183 | .LRU_array_load, 184 | .LRU_array_datain, 185 | 186 | .write_en_0_MUX_sel, 187 | .write_en_1_MUX_sel, 188 | .write_en_2_MUX_sel, 189 | .write_en_3_MUX_sel, 190 | 191 | .data_array_0_datain_MUX_sel, 192 | .data_array_1_datain_MUX_sel, 193 | .data_array_2_datain_MUX_sel, 194 | .data_array_3_datain_MUX_sel, 195 | .prev_address(cache_pipeline_out.cpu_address), 196 | .read_array_flag, 197 | 198 | .dataout(cache_pipeline_data.dataout) 199 | ); 200 | 201 | 202 | always_comb begin : ADDRESSMUX 203 | address_MUX_out = mem_address; 204 | unique case (address_mux_sel) 205 | curr_cpu_address: address_MUX_out = mem_address; 206 | prev_cpu_address: address_MUX_out = cache_pipeline_out.cpu_address; 207 | endcase 208 | end 209 | 210 | 211 | p_i_cache_reg pipeline_reg 212 | ( 213 | .clk, 214 | .rst, 215 | .load(load_i_cache_reg), 216 | .in(cache_pipeline_in), 217 | .out(cache_pipeline_out) 218 | ); 219 | 220 | //STAGE 2: DELIVER DATA 221 | assign mem_rdata = cache_pipeline_data.dataout; 222 | 223 | 224 | p_line_adapter bus ( 225 | .mem_wdata_line(mem_wdata), 226 | .mem_rdata_line(mem_rdata), 227 | .mem_wdata(mem_wdata_cpu), 228 | .mem_rdata(mem_rdata_cpu), 229 | .mem_byte_enable(mem_byte_enable_cpu), 230 | .mem_byte_enable_line(mem_byte_enable), 231 | .address(cache_pipeline_out.cpu_address) 232 | ); 233 | 234 | 235 | 236 | 237 | endmodule : p_i_cache 238 | -------------------------------------------------------------------------------- /hdl/pipeline_i_cache/p_i_cache_control.sv: -------------------------------------------------------------------------------- 1 | module p_i_cache_control 2 | import rv32i_types::*; // MP3CP1_error: is this the right place to put "import" statement? 3 | import cache_mux_types::*; 4 | ( 5 | input clk, 6 | input rst, 7 | 8 | /* CPU memory signals */ 9 | input logic mem_read, 10 | output logic mem_resp, 11 | 12 | /* Physical memory signals */ 13 | input logic pmem_resp, 14 | output logic pmem_read, 15 | 16 | /* Datapath to Control */ 17 | input logic v_array_0_dataout, 18 | input logic v_array_1_dataout, 19 | input logic v_array_2_dataout, 20 | input logic v_array_3_dataout, 21 | 22 | input i_cache_pipeline_data cache_pipeline_data, 23 | input logic if_id_reg_load, 24 | 25 | /* Control to Datapath */ 26 | output logic v_array_0_load, 27 | output logic v_array_0_datain, 28 | output logic v_array_1_load, 29 | output logic v_array_1_datain, 30 | output logic v_array_2_load, 31 | output logic v_array_2_datain, 32 | output logic v_array_3_load, 33 | output logic v_array_3_datain, 34 | 35 | output logic tag_array_0_load, 36 | output logic tag_array_1_load, 37 | output logic tag_array_2_load, 38 | output logic tag_array_3_load, 39 | 40 | output logic LRU_array_load, 41 | output logic [2:0] LRU_array_datain, 42 | 43 | output dataarraymux_sel_t write_en_0_MUX_sel, 44 | output dataarraymux_sel_t write_en_1_MUX_sel, 45 | output dataarraymux_sel_t write_en_2_MUX_sel, 46 | output dataarraymux_sel_t write_en_3_MUX_sel, 47 | output dataarraymux_sel_t data_array_0_datain_MUX_sel, 48 | output dataarraymux_sel_t data_array_1_datain_MUX_sel, 49 | output dataarraymux_sel_t data_array_2_datain_MUX_sel, 50 | output dataarraymux_sel_t data_array_3_datain_MUX_sel, 51 | 52 | output logic load_i_cache_reg, 53 | output logic read_array_flag, 54 | 55 | output paddressmux_sel_t address_mux_sel 56 | ); 57 | 58 | logic num_l1_miss_count; 59 | logic num_l1_miss_overflow; 60 | logic [perf_counter_width-1:0] num_l1_miss; 61 | 62 | logic num_l1_hit_count; 63 | logic num_l1_hit_overflow; 64 | logic [perf_counter_width-1:0] num_l1_hit; 65 | 66 | perf_counter #(.width(perf_counter_width)) l1miss ( 67 | .clk(clk), 68 | .rst(rst), 69 | .count(num_l1_miss_count), 70 | .overflow(num_l1_miss_overflow), 71 | .out(num_l1_miss) 72 | ); 73 | 74 | perf_counter #(.width(perf_counter_width)) l1hit ( 75 | .clk(clk), 76 | .rst(rst), 77 | .count(num_l1_hit_count), 78 | .overflow(num_l1_hit_overflow), 79 | .out(num_l1_hit) 80 | ); 81 | 82 | 83 | 84 | function void set_defaults(); 85 | /* CPU memory signals */ 86 | mem_resp = 1'b0; 87 | 88 | /* Physical memory signals */ 89 | pmem_read = 1'b0; 90 | 91 | /* Control to Datapath */ 92 | v_array_0_load = 1'b0; 93 | v_array_0_datain = 1'b0; 94 | v_array_1_load = 1'b0; 95 | v_array_1_datain = 1'b0; 96 | v_array_2_load = 1'b0; 97 | v_array_2_datain = 1'b0; 98 | v_array_3_load = 1'b0; 99 | v_array_3_datain = 1'b0; 100 | 101 | tag_array_0_load = 1'b0; 102 | tag_array_1_load = 1'b0; 103 | tag_array_2_load = 1'b0; 104 | tag_array_3_load = 1'b0; 105 | 106 | LRU_array_load = 1'b0; 107 | LRU_array_datain = 3'b000; 108 | 109 | write_en_0_MUX_sel = no_write; 110 | write_en_1_MUX_sel = no_write; 111 | write_en_2_MUX_sel = no_write; 112 | write_en_3_MUX_sel = no_write; 113 | data_array_0_datain_MUX_sel = no_write; 114 | data_array_1_datain_MUX_sel = no_write; 115 | data_array_2_datain_MUX_sel = no_write; 116 | data_array_3_datain_MUX_sel = no_write; 117 | 118 | address_mux_sel = curr_cpu_address; 119 | 120 | load_i_cache_reg = 1'b1; 121 | 122 | read_array_flag = 1'b1; 123 | 124 | num_l1_miss_count = 1'b0; 125 | num_l1_hit_count = 1'b0; 126 | 127 | 128 | endfunction 129 | 130 | /* State Enumeration */ 131 | enum int unsigned 132 | { 133 | START, 134 | MISS, 135 | HIT 136 | } state, next_state; 137 | 138 | /* State Control Signals */ 139 | always_comb begin : state_actions 140 | 141 | /* Defaults */ 142 | set_defaults(); 143 | 144 | case(state) 145 | START: begin 146 | end 147 | 148 | MISS: begin 149 | load_i_cache_reg = 1'b0; 150 | address_mux_sel = prev_cpu_address; 151 | if (mem_read == 1'b1) 152 | begin 153 | if (cache_pipeline_data.hit == 1'b0) 154 | begin 155 | pmem_read = 1'b1; 156 | if (pmem_resp == 1'b1) 157 | begin 158 | num_l1_miss_count = 1'b1; 159 | if(v_array_0_dataout == 1'b0) 160 | begin 161 | tag_array_0_load = 1'b1; 162 | v_array_0_load = 1'b1; 163 | v_array_0_datain = 1'b1; 164 | write_en_0_MUX_sel = mem_write_cache; 165 | data_array_0_datain_MUX_sel = mem_write_cache; 166 | end 167 | else if(v_array_1_dataout == 1'b0) 168 | begin 169 | tag_array_1_load = 1'b1; 170 | v_array_1_load = 1'b1; 171 | v_array_1_datain = 1'b1; 172 | write_en_1_MUX_sel = mem_write_cache; 173 | data_array_1_datain_MUX_sel = mem_write_cache; 174 | end 175 | else if(v_array_2_dataout == 1'b0) 176 | begin 177 | tag_array_2_load = 1'b1; 178 | v_array_2_load = 1'b1; 179 | v_array_2_datain = 1'b1; 180 | write_en_2_MUX_sel = mem_write_cache; 181 | data_array_2_datain_MUX_sel = mem_write_cache; 182 | end 183 | else if(v_array_3_dataout == 1'b0) 184 | begin 185 | tag_array_3_load = 1'b1; 186 | v_array_3_load = 1'b1; 187 | v_array_3_datain = 1'b1; 188 | write_en_3_MUX_sel = mem_write_cache; 189 | data_array_3_datain_MUX_sel = mem_write_cache; 190 | end 191 | else 192 | begin 193 | if(cache_pipeline_data.LRU_array_dataout[2] == 1'b0) 194 | begin 195 | if(cache_pipeline_data.LRU_array_dataout[0] == 1'b0) 196 | begin 197 | // Alloc way 3 198 | tag_array_3_load = 1'b1; 199 | v_array_3_load = 1'b1; 200 | v_array_3_datain = 1'b1; 201 | write_en_3_MUX_sel = mem_write_cache; 202 | data_array_3_datain_MUX_sel = mem_write_cache; 203 | end 204 | else 205 | begin 206 | // Alloc way 2 207 | tag_array_2_load = 1'b1; 208 | v_array_2_load = 1'b1; 209 | v_array_2_datain = 1'b1; 210 | write_en_2_MUX_sel = mem_write_cache; 211 | data_array_2_datain_MUX_sel = mem_write_cache; 212 | end 213 | end 214 | else 215 | begin 216 | if(cache_pipeline_data.LRU_array_dataout[1] == 1'b0) 217 | begin 218 | // Alloc way 1 219 | tag_array_1_load = 1'b1; 220 | v_array_1_load = 1'b1; 221 | v_array_1_datain = 1'b1; 222 | write_en_1_MUX_sel = mem_write_cache; 223 | data_array_1_datain_MUX_sel = mem_write_cache; 224 | end 225 | else 226 | begin 227 | // Alloc way 0 228 | tag_array_0_load = 1'b1; 229 | v_array_0_load = 1'b1; 230 | v_array_0_datain = 1'b1; 231 | write_en_0_MUX_sel = mem_write_cache; 232 | data_array_0_datain_MUX_sel = mem_write_cache; 233 | end 234 | end 235 | end 236 | end 237 | end 238 | end 239 | end 240 | 241 | HIT: begin 242 | if (cache_pipeline_data.hit == 1'b1 && if_id_reg_load == 1'b1) 243 | begin 244 | address_mux_sel = curr_cpu_address; //MOVED ON TO HANDLING NEXT REQUEST 245 | num_l1_hit_count = 1'b1; 246 | mem_resp = 1'b1; 247 | LRU_array_load = 1'b1; 248 | if(cache_pipeline_data.way_0_hit) 249 | LRU_array_datain = {1'b0, 1'b0, cache_pipeline_data.LRU_array_dataout[0]}; 250 | else if (cache_pipeline_data.way_1_hit) 251 | LRU_array_datain = {1'b0, 1'b1, cache_pipeline_data.LRU_array_dataout[0]}; 252 | else if (cache_pipeline_data.way_2_hit) 253 | LRU_array_datain = {1'b1, cache_pipeline_data.LRU_array_dataout[1], 1'b0}; 254 | else if (cache_pipeline_data.way_3_hit) 255 | LRU_array_datain = {1'b1, cache_pipeline_data.LRU_array_dataout[1], 1'b1}; 256 | end 257 | else begin 258 | load_i_cache_reg = 1'b0; 259 | read_array_flag = 1'b0; 260 | end 261 | end 262 | 263 | endcase 264 | end 265 | 266 | /* Next State Logic */ 267 | always_comb begin : next_state_logic 268 | /* Default state transition */ 269 | next_state = state; 270 | 271 | case(state) 272 | START: begin 273 | if (mem_read && cache_pipeline_data.hit == 1'b0) begin 274 | next_state = MISS; 275 | end 276 | end 277 | 278 | MISS: begin 279 | if (pmem_resp == 1'b1) 280 | next_state = HIT; 281 | end 282 | 283 | HIT: begin 284 | 285 | if (cache_pipeline_data.hit == 1'b0) 286 | next_state = MISS; 287 | end 288 | 289 | endcase 290 | end 291 | 292 | /* Next State Assignment */ 293 | always_ff @(posedge clk) begin: next_state_assignment 294 | if (rst) 295 | state <= START; 296 | else 297 | state <= next_state; 298 | end 299 | 300 | endmodule : p_i_cache_control 301 | -------------------------------------------------------------------------------- /hdl/pipeline_i_cache/p_i_cache_metadata_check.sv: -------------------------------------------------------------------------------- 1 | `define BAD_MUX_SEL $display("%0d: %s: %0t: Illegal MUX Select", `__LINE__, `__FILE__, $time) 2 | module p_i_cache_metadata_check 3 | import rv32i_types::*; // MP3CP1_error: is this the right place to put "import" statement? 4 | import cache_mux_types::*; 5 | #( 6 | parameter s_offset = 5, 7 | parameter s_index = 3, 8 | parameter s_tag = 32 - s_offset - s_index, 9 | parameter s_mask = 2**s_offset, 10 | parameter s_line = 8*s_mask, 11 | parameter num_sets = 2**s_index, 12 | parameter num_ways = 4 13 | ) 14 | ( 15 | input clk, 16 | input rst, 17 | /* CPU memory signals */ 18 | input logic [31:0] mem_address, 19 | input logic [31:0] prev_address, 20 | 21 | /* Physical memory data signals */ 22 | input logic [255:0] pmem_rdata, 23 | output logic [31:0] pmem_address, 24 | 25 | /* Control signals */ 26 | /* Datapath to Control */ 27 | output logic hit, 28 | output logic way_0_hit, 29 | output logic way_1_hit, 30 | output logic way_2_hit, 31 | output logic way_3_hit, 32 | 33 | output logic v_array_0_dataout, 34 | output logic v_array_1_dataout, 35 | output logic v_array_2_dataout, 36 | output logic v_array_3_dataout, 37 | 38 | // LRU array width is now 3. 39 | output logic [2:0] LRU_array_dataout, 40 | 41 | output logic [255:0] dataout, 42 | 43 | /* Control to Datapath */ 44 | input logic v_array_0_load, 45 | input logic v_array_0_datain, 46 | input logic v_array_1_load, 47 | input logic v_array_1_datain, 48 | input logic v_array_2_load, 49 | input logic v_array_2_datain, 50 | input logic v_array_3_load, 51 | input logic v_array_3_datain, 52 | 53 | input logic tag_array_0_load, 54 | input logic tag_array_1_load, 55 | input logic tag_array_2_load, 56 | input logic tag_array_3_load, 57 | 58 | input logic LRU_array_load, 59 | // LRU array width is now 3. 60 | input logic [2:0] LRU_array_datain, 61 | 62 | input dataarraymux_sel_t write_en_0_MUX_sel, 63 | input dataarraymux_sel_t write_en_1_MUX_sel, 64 | input dataarraymux_sel_t write_en_2_MUX_sel, 65 | input dataarraymux_sel_t write_en_3_MUX_sel, 66 | 67 | input dataarraymux_sel_t data_array_0_datain_MUX_sel, 68 | input dataarraymux_sel_t data_array_1_datain_MUX_sel, 69 | input dataarraymux_sel_t data_array_2_datain_MUX_sel, 70 | input dataarraymux_sel_t data_array_3_datain_MUX_sel, 71 | 72 | input logic read_array_flag 73 | 74 | ); 75 | 76 | logic [255:0] data_array_0_dataout; 77 | logic [255:0] data_array_1_dataout; 78 | logic [255:0] data_array_2_dataout; 79 | logic [255:0] data_array_3_dataout; 80 | logic [255:0] data_array_0_datain_MUX_out; 81 | logic [255:0] data_array_1_datain_MUX_out; 82 | logic [255:0] data_array_2_datain_MUX_out; 83 | logic [255:0] data_array_3_datain_MUX_out; 84 | 85 | logic [31:0] write_en_0_MUX_out; 86 | logic [31:0] write_en_1_MUX_out; 87 | logic [31:0] write_en_2_MUX_out; 88 | logic [31:0] write_en_3_MUX_out; 89 | 90 | logic [s_tag-1:0] tag_array_0_dataout; 91 | logic [s_tag-1:0] tag_array_1_dataout; 92 | logic [s_tag-1:0] tag_array_2_dataout; 93 | logic [s_tag-1:0] tag_array_3_dataout; 94 | 95 | 96 | assign pmem_address = {mem_address[31:5], 5'b0}; 97 | 98 | 99 | //valid array 100 | l2_array #(.s_index(s_index), .width(1)) v_array [num_ways-1:0] ( 101 | .clk({clk, clk, clk, clk}), 102 | .rst({rst, rst, rst, rst}), 103 | .read({read_array_flag, read_array_flag, read_array_flag, read_array_flag}), 104 | .load({v_array_3_load, v_array_2_load, v_array_1_load, v_array_0_load}), 105 | .rindex({mem_address[7:5], mem_address[7:5], mem_address[7:5], mem_address[7:5]}), 106 | .windex({mem_address[7:5], mem_address[7:5], mem_address[7:5], mem_address[7:5]}), 107 | .datain({v_array_3_datain, v_array_2_datain, v_array_1_datain, v_array_0_datain}), 108 | .dataout({v_array_3_dataout, v_array_2_dataout, v_array_1_dataout, v_array_0_dataout}) 109 | ); 110 | 111 | //tag array 112 | l2_array #(.s_index(s_index), .width(s_tag)) tag_array [num_ways-1:0] ( 113 | .clk({clk, clk, clk, clk}), 114 | .rst({rst, rst, rst, rst}), 115 | .read({read_array_flag, read_array_flag, read_array_flag, read_array_flag}), 116 | .load({tag_array_3_load, tag_array_2_load, tag_array_1_load, tag_array_0_load}), 117 | .rindex({mem_address[7:5], mem_address[7:5], mem_address[7:5], mem_address[7:5]}), 118 | .windex({mem_address[7:5], mem_address[7:5], mem_address[7:5], mem_address[7:5]}), 119 | .datain({mem_address[31:8], mem_address[31:8], mem_address[31:8], mem_address[31:8]}), 120 | .dataout({tag_array_3_dataout, tag_array_2_dataout, tag_array_1_dataout, tag_array_0_dataout}) 121 | ); 122 | 123 | //data array 124 | l2_data_array #(.s_offset(s_offset), .s_index(s_index)) data_array [num_ways-1:0] ( 125 | .clk({clk, clk, clk, clk}), 126 | .read({read_array_flag, read_array_flag, read_array_flag, read_array_flag}), 127 | .write_en({write_en_3_MUX_out, write_en_2_MUX_out, write_en_1_MUX_out, write_en_0_MUX_out}), 128 | .rindex({mem_address[7:5], mem_address[7:5], mem_address[7:5], mem_address[7:5]}), 129 | .windex({mem_address[7:5], mem_address[7:5], mem_address[7:5], mem_address[7:5]}), 130 | .datain({data_array_3_datain_MUX_out, data_array_2_datain_MUX_out, data_array_1_datain_MUX_out, data_array_0_datain_MUX_out}), 131 | .dataout({data_array_3_dataout, data_array_2_dataout, data_array_1_dataout, data_array_0_dataout}) 132 | ); 133 | 134 | // LRU array width is now 3. 135 | l2_array #(.s_index(s_index), .width(3)) LRU_array ( 136 | 137 | .clk(clk), 138 | .rst(rst), 139 | .read(read_array_flag), 140 | .load(LRU_array_load), 141 | .rindex(mem_address[7:5]), 142 | .windex(mem_address[7:5]), 143 | .datain(LRU_array_datain), 144 | .dataout(LRU_array_dataout) 145 | 146 | ); 147 | 148 | always_comb begin : WRITE_EN_0_MUX 149 | 150 | unique case (write_en_0_MUX_sel) 151 | 152 | no_write : write_en_0_MUX_out = '0; 153 | mem_write_cache: write_en_0_MUX_out = '1; 154 | 155 | default: 156 | begin 157 | `BAD_MUX_SEL; 158 | write_en_0_MUX_out = '0; 159 | end 160 | endcase 161 | end 162 | 163 | always_comb begin : WRITE_EN_1_MUX 164 | 165 | unique case (write_en_1_MUX_sel) 166 | 167 | no_write : write_en_1_MUX_out = '0; 168 | mem_write_cache: write_en_1_MUX_out = '1; 169 | 170 | default: 171 | begin 172 | `BAD_MUX_SEL; 173 | write_en_1_MUX_out = '0; 174 | end 175 | endcase 176 | end 177 | 178 | always_comb begin : WRITE_EN_2_MUX 179 | 180 | unique case (write_en_2_MUX_sel) 181 | 182 | no_write : write_en_2_MUX_out = '0; 183 | mem_write_cache: write_en_2_MUX_out = '1; 184 | 185 | default: 186 | begin 187 | `BAD_MUX_SEL; 188 | write_en_2_MUX_out = '0; 189 | end 190 | endcase 191 | end 192 | 193 | always_comb begin : WRITE_EN_3_MUX 194 | 195 | unique case (write_en_3_MUX_sel) 196 | 197 | no_write : write_en_3_MUX_out = '0; 198 | mem_write_cache: write_en_3_MUX_out = '1; 199 | 200 | default: 201 | begin 202 | `BAD_MUX_SEL; 203 | write_en_3_MUX_out = '0; 204 | end 205 | endcase 206 | end 207 | 208 | 209 | always_comb begin : data_array_0_datain_MUX 210 | 211 | unique case (data_array_0_datain_MUX_sel) 212 | 213 | no_write : data_array_0_datain_MUX_out = '0; 214 | mem_write_cache: data_array_0_datain_MUX_out = pmem_rdata; 215 | 216 | default: 217 | begin 218 | `BAD_MUX_SEL; 219 | data_array_0_datain_MUX_out = '0; 220 | end 221 | endcase 222 | end 223 | 224 | always_comb begin : data_array_1_datain_MUX 225 | 226 | unique case (data_array_1_datain_MUX_sel) 227 | 228 | no_write : data_array_1_datain_MUX_out = '0; 229 | mem_write_cache: data_array_1_datain_MUX_out = pmem_rdata; 230 | 231 | default: 232 | begin 233 | `BAD_MUX_SEL; 234 | data_array_1_datain_MUX_out = '0; 235 | end 236 | endcase 237 | end 238 | 239 | always_comb begin : data_array_2_datain_MUX 240 | 241 | unique case (data_array_2_datain_MUX_sel) 242 | 243 | no_write : data_array_2_datain_MUX_out = '0; 244 | mem_write_cache: data_array_2_datain_MUX_out = pmem_rdata; 245 | 246 | default: 247 | begin 248 | `BAD_MUX_SEL; 249 | data_array_2_datain_MUX_out = '0; 250 | end 251 | endcase 252 | end 253 | 254 | always_comb begin : data_array_3_datain_MUX 255 | 256 | unique case (data_array_3_datain_MUX_sel) 257 | 258 | no_write : data_array_3_datain_MUX_out = '0; 259 | mem_write_cache: data_array_3_datain_MUX_out = pmem_rdata; 260 | 261 | default: 262 | begin 263 | `BAD_MUX_SEL; 264 | data_array_3_datain_MUX_out = '0; 265 | end 266 | endcase 267 | end 268 | 269 | always_comb begin : HIT_MISS_DETERMINATION 270 | dataout = '0; 271 | hit = 1'b0; 272 | way_0_hit = 1'b0; 273 | way_1_hit = 1'b0; 274 | way_2_hit = 1'b0; 275 | way_3_hit = 1'b0; 276 | 277 | if(tag_array_0_dataout == prev_address[31:8]) 278 | begin 279 | if(v_array_0_dataout == 1'b1) 280 | begin 281 | way_0_hit = 1'b1; 282 | dataout = data_array_0_dataout; 283 | end 284 | end 285 | 286 | if(tag_array_1_dataout == prev_address[31:8]) 287 | begin 288 | if(v_array_1_dataout == 1'b1) 289 | begin 290 | way_1_hit = 1'b1; 291 | dataout = data_array_1_dataout; 292 | end 293 | end 294 | 295 | if(tag_array_2_dataout == prev_address[31:8]) 296 | begin 297 | if(v_array_2_dataout == 1'b1) 298 | begin 299 | way_2_hit = 1'b1; 300 | dataout = data_array_2_dataout; 301 | end 302 | end 303 | 304 | if(tag_array_3_dataout == prev_address[31:8]) 305 | begin 306 | if(v_array_3_dataout == 1'b1) 307 | begin 308 | way_3_hit = 1'b1; 309 | dataout = data_array_3_dataout; 310 | end 311 | end 312 | 313 | if(way_0_hit == 1'b1 || way_1_hit == 1'b1 || 314 | way_2_hit == 1'b1 || way_3_hit == 1'b1) 315 | hit = 1'b1; 316 | 317 | end 318 | 319 | 320 | 321 | 322 | 323 | 324 | endmodule : p_i_cache_metadata_check 325 | -------------------------------------------------------------------------------- /hdl/pipeline_i_cache/p_i_cache_reg.sv: -------------------------------------------------------------------------------- 1 | module p_i_cache_reg 2 | import rv32i_types::*; 3 | ( 4 | input logic clk, 5 | input logic rst, 6 | input logic load, 7 | input i_cache_pipeline_reg in, 8 | output i_cache_pipeline_reg out 9 | ); 10 | 11 | i_cache_pipeline_reg data; 12 | 13 | always_ff @ (posedge clk) begin 14 | if (rst) begin 15 | data <= '0; 16 | end 17 | 18 | else if (load) begin 19 | data <= in; 20 | end 21 | end 22 | 23 | always_comb begin 24 | 25 | out = data; 26 | 27 | end 28 | 29 | endmodule: p_i_cache_reg -------------------------------------------------------------------------------- /hdl/pipeline_i_cache/p_line_adapter.sv: -------------------------------------------------------------------------------- 1 | module p_line_adapter ( 2 | output logic [255:0] mem_wdata_line, 3 | input logic [255:0] mem_rdata_line, 4 | input logic [31:0] mem_wdata, 5 | output logic [31:0] mem_rdata, 6 | input logic [3:0] mem_byte_enable, 7 | output logic [31:0] mem_byte_enable_line, 8 | input logic [31:0] address 9 | ); 10 | 11 | assign mem_wdata_line = {8{mem_wdata}}; 12 | assign mem_rdata = mem_rdata_line[(32*address[4:2]) +: 32]; 13 | assign mem_byte_enable_line = {28'h0, mem_byte_enable} << (address[4:2]*4); 14 | 15 | endmodule : p_line_adapter 16 | -------------------------------------------------------------------------------- /hvl/magic_dual_port.sv: -------------------------------------------------------------------------------- 1 | /* 2 | * Dual-port magic memory 3 | * 4 | */ 5 | 6 | module magic_memory_dp 7 | ( 8 | tb_itf.magic_mem itf 9 | ); 10 | 11 | timeunit 1ns; 12 | timeprecision 1ns; 13 | 14 | logic [7:0] mem [logic [31:0]]; 15 | 16 | initial 17 | begin 18 | string s; 19 | itf.path_mb.peek(s); 20 | $readmemh(s, mem); 21 | end 22 | 23 | always @(itf.mmcb) 24 | begin : response 25 | if (itf.mmcb.read_a) begin 26 | itf.mmcb.resp_a <= 1'b1; 27 | for (int i = 0; i < 4; i++) begin 28 | itf.mmcb.rdata_a[i*8 +: 8] <= mem[itf.mmcb.address_a+i]; 29 | end 30 | end else begin 31 | itf.mmcb.resp_a <= 1'b0; 32 | end 33 | 34 | if (itf.mmcb.read_b) begin 35 | itf.mmcb.resp_b <= 1'b1; 36 | for (int i = 0; i < 4; i++) begin 37 | itf.mmcb.rdata_b[i*8 +: 8] <= mem[itf.mmcb.address_b+i]; 38 | end 39 | end else if (itf.mmcb.write) begin 40 | itf.mmcb.resp_b <= 1'b1; 41 | for (int i = 0; i < 4; i++) begin 42 | if (itf.mmcb.wmask[i]) 43 | begin 44 | mem[itf.mmcb.address_b+i] = itf.mmcb.wdata[i*8 +: 8]; 45 | end 46 | end 47 | end else begin 48 | itf.mmcb.resp_b <= 1'b0; 49 | end 50 | end : response 51 | 52 | endmodule : magic_memory_dp 53 | -------------------------------------------------------------------------------- /hvl/param_memory.sv: -------------------------------------------------------------------------------- 1 | `ifndef MEMORY_CLASS_SV 2 | `define MEMORY_CLASS_SV 3 | module ParamMemory 4 | #( 5 | parameter int DELAY_MEM, // In Cycles 6 | parameter int DELAY_PAGE_HIT, // In Cycles 7 | parameter int BURST_LEN, // In Bits 8 | parameter int CACHE_LINE_WIDTH, // In Bits 9 | parameter int PAGE_SIZE // In Bytes 10 | ) 11 | ( 12 | tb_itf.mem itf 13 | ); 14 | 15 | localparam int BURST_WIDTH = CACHE_LINE_WIDTH / BURST_LEN; 16 | localparam int ADDRLEN = 32; 17 | localparam int CARELEN = ADDRLEN - $clog2(CACHE_LINE_WIDTH / 8); 18 | localparam logic [ADDRLEN-1:0] mask = {{(CARELEN){1'b1}}, 19 | {(ADDRLEN-CARELEN){1'b0}}}; 20 | 21 | logic [CACHE_LINE_WIDTH-1:0] _mem [logic [ADDRLEN-1:0]]; 22 | int signed pageno; 23 | 24 | initial begin 25 | int iteration = 0; 26 | forever begin 27 | @(itf.mcb iff (itf.mcb.rst || itf.mcb.read || itf.mcb.write)) 28 | case ({itf.mcb.rst, itf.mcb.read, itf.mcb.write}) 29 | 3'b100, 3'b101, 3'b111, 3'b110: begin 30 | reset(); 31 | end 32 | 3'b010: memread(itf.mcb.addr); 33 | 3'b001: memwrite(itf.mcb.addr); 34 | default: $error("simultaneous read/write"); 35 | endcase 36 | end 37 | end 38 | 39 | task reset; 40 | string s; 41 | if (pageno == -1) 42 | return; 43 | _mem.delete(); 44 | itf.path_mb.get(s); 45 | $readmemh(s, _mem); 46 | $display("Reset Memory"); 47 | pageno = -1; 48 | endtask 49 | 50 | task automatic memread(input logic [ADDRLEN-1:0] addr); 51 | int signed _pageno; 52 | int delay; 53 | logic [ADDRLEN-1:0] _addr; 54 | logic [31:0] _read_loc; 55 | _addr = addr & mask; 56 | _read_loc = _addr / (CACHE_LINE_WIDTH / 8); 57 | _pageno = addr / PAGE_SIZE; 58 | delay = _pageno == pageno ? DELAY_PAGE_HIT : DELAY_MEM; 59 | pageno = _pageno; 60 | fork : f 61 | begin : error_check 62 | // This process simply runs some assertions at each 63 | // new cycle, asserting error and ending the read if any assertion 64 | // fails 65 | forever @(itf.mcb) begin 66 | read_steady: assert(itf.mcb.read) else begin 67 | $display( 68 | "Grading Error: PMEM Read Error: Read deasserted early" 69 | ); 70 | itf.mcb.error <= 1'b1; 71 | disable f; 72 | break; 73 | end 74 | no_write: assert(!itf.mcb.write) else begin 75 | $display("Grading Error: PMEM Read Error: Write asserted"); 76 | itf.mcb.error <= 1'b1; 77 | disable f; 78 | break; 79 | end 80 | addr_read_steady: assert(itf.mcb.addr == addr) else begin 81 | $display("Grading Error: PMEM Read Error: Address changed"); 82 | $display("Address %8x != addr %8x", itf.mcb.addr, addr); 83 | itf.mcb.error <= 1'b1; 84 | disable f; 85 | break; 86 | end 87 | end 88 | end 89 | begin : memreader 90 | // This process waits for 'duration' cycles and then does a burst 91 | // write. Resp goes high the cycle before the first write is 92 | // done, so the writer must be careful about this point 93 | repeat (delay) @(itf.mcb); 94 | for (int i = 0; i < BURST_LEN; ++i) begin 95 | itf.mcb.rdata <= _mem[_read_loc][BURST_WIDTH*i +: BURST_WIDTH]; 96 | itf.mcb.resp <= 1'b1; 97 | @(itf.mcb); 98 | end 99 | itf.mcb.resp <= 1'b0; 100 | disable f; 101 | end 102 | join 103 | endtask 104 | 105 | /* 106 | * Do a memory write --- executed on $rose(write) 107 | */ 108 | task automatic memwrite(input logic [31:0] addr); 109 | // Calculate the memory latency and update that 'charged' memory data 110 | int signed _pageno; 111 | int delay; 112 | logic [31:0] _addr; 113 | logic [31:0] _read_loc; 114 | _addr = addr & mask; 115 | _read_loc = _addr / (CACHE_LINE_WIDTH / 8); 116 | _pageno = addr / PAGE_SIZE; 117 | delay = _pageno == pageno ? DELAY_PAGE_HIT : DELAY_MEM; 118 | pageno = _pageno; 119 | 120 | fork : f 121 | begin : error_check 122 | // This process simply runs some assertions at each 123 | // new cycle, asserting error and ending the read if any assertion 124 | // fails 125 | forever @(itf.mcb) begin 126 | write_steady: assert(itf.mcb.write) else begin 127 | $display("PMEM Write Error: Write deasserted early\n"); 128 | itf.mcb.error <= 1'b1; 129 | disable f; 130 | break; 131 | end 132 | no_read: assert(!itf.mcb.read) else begin 133 | $display("PMEM Write Error: Read asserted\n"); 134 | itf.mcb.error <= 1'b1; 135 | disable f; 136 | break; 137 | end 138 | addr_write_steady: assert(itf.mcb.addr == addr) else begin 139 | $display("PMEM Write Error: Address changed\n"); 140 | $display("Address %8x != addr %8x", itf.mcb.addr, addr); 141 | itf.mcb.error <= 1'b1; 142 | disable f; 143 | break; 144 | end 145 | end 146 | end 147 | begin : memwrite 148 | // This process waits for 'duration' cycles and then does a burst 149 | // write. Resp goes high the cycle before the first write is 150 | // done, so the writer must be careful about this point 151 | repeat (delay) @(itf.mcb); 152 | for (int i = 0; i < BURST_LEN; ++i) begin 153 | itf.mcb.resp <= 1'b1; 154 | @(itf.mcb); 155 | _mem[_read_loc][BURST_WIDTH*i +: BURST_WIDTH] = itf.mcb.wdata; 156 | end 157 | itf.mcb.resp <= 1'b0; 158 | disable f; 159 | end 160 | join 161 | endtask 162 | endmodule 163 | 164 | `endif 165 | -------------------------------------------------------------------------------- /hvl/rvfi_itf.sv: -------------------------------------------------------------------------------- 1 | `ifndef RVFI_ITF 2 | `define RVFI_ITF 3 | 4 | interface rvfi_itf(input clk, input rst); 5 | 6 | logic halt; 7 | logic commit; 8 | logic [63:0] order; 9 | logic [31:0] inst; 10 | logic trap; 11 | logic [4:0] rs1_addr; 12 | logic [4:0] rs2_addr; 13 | logic [31:0] rs1_rdata; 14 | logic [31:0] rs2_rdata; 15 | logic load_regfile; 16 | logic [4:0] rd_addr; 17 | logic [31:0] rd_wdata; 18 | logic [31:0] pc_rdata; 19 | logic [31:0] pc_wdata; 20 | logic [31:0] mem_addr; 21 | logic [3:0] mem_rmask; 22 | logic [3:0] mem_wmask; 23 | logic [31:0] mem_rdata; 24 | logic [31:0] mem_wdata; 25 | 26 | logic [15:0] errcode; 27 | 28 | endinterface 29 | 30 | `endif 31 | -------------------------------------------------------------------------------- /hvl/shadow_memory.sv: -------------------------------------------------------------------------------- 1 | `ifndef SHADOW_MEMORY 2 | `define SHADOW_MEMORY 3 | 4 | module shadow_memory(tb_itf.sm sm_itf); 5 | 6 | logic [255:0] _mem [logic [31:5]]; 7 | logic [255:0] _imem [logic [31:5]]; 8 | 9 | function void _new(string filepath); 10 | $readmemh(filepath, _mem); 11 | $readmemh(filepath, _imem); 12 | endfunction 13 | 14 | function automatic logic [31:0] read_inst(logic [31:0] addr); 15 | logic [255:0] line; 16 | logic [31:0] rv; 17 | line = _imem[addr[31:5]]; 18 | rv = line[8*{addr[4:2], 2'b00} +: 32]; 19 | return rv; 20 | endfunction 21 | 22 | function automatic logic [31:0] read(logic [31:0] addr); 23 | logic [255:0] line; 24 | logic [31:0] rv; 25 | line = _mem[addr[31:5]]; 26 | rv = line[8*{addr[4:2], 2'b00} +: 32]; 27 | return rv; 28 | endfunction 29 | 30 | function automatic void write(logic [31:0] addr, logic [31:0] wdata, 31 | logic [3:0] mem_byte_enable); 32 | logic [255:0] line; 33 | line = _mem[addr[31:5]]; 34 | foreach (mem_byte_enable[i]) begin 35 | if (mem_byte_enable[i]) 36 | line[8*({addr[4:2], 2'b00} + i) +: 8] = wdata[8*i +: 8]; 37 | end 38 | _mem[addr[31:5]] = line; 39 | endfunction 40 | 41 | int errcount = 0; 42 | initial begin 43 | logic [31:0] rdata_inst; 44 | logic [31:0] rdata_data; 45 | logic _read_data; 46 | string path; 47 | sm_itf.path_mb.peek(path); 48 | _new(path); 49 | fork 50 | begin : instruction 51 | forever begin 52 | @(sm_itf.smcb iff (sm_itf.smcb.read_a && sm_itf.smcb.resp_a)) 53 | rdata_inst = read_inst(sm_itf.smcb.address_a); 54 | if (rdata_inst != sm_itf.smcb.rdata_a) begin 55 | $display("%0t: ShadowMemory Error: Mismatch rdata:", $time, 56 | " Expected %8h, Detected %8h", rdata_inst, 57 | sm_itf.smcb.rdata_a); 58 | errcount++; 59 | end 60 | end 61 | end 62 | 63 | begin : data 64 | forever begin 65 | @(sm_itf.smcb iff ((sm_itf.smcb.read_b || sm_itf.smcb.write) && sm_itf.smcb.resp_b)) 66 | if (sm_itf.smcb.read_b) begin 67 | rdata_data = read(sm_itf.smcb.address_b); 68 | _read_data = 1'b1; 69 | end 70 | else begin 71 | write(sm_itf.smcb.address_b, sm_itf.smcb.wdata, 72 | sm_itf.smcb.mbe); 73 | _read_data = 1'b0; 74 | end 75 | if (_read_data) begin 76 | if (rdata_data != sm_itf.smcb.rdata_b) begin 77 | $display("%0t: ShadowMemory Error: Mismatch rdata:", $time, 78 | " Expected %8h, Detected %8h", rdata_data, 79 | sm_itf.smcb.rdata_b); 80 | errcount++; 81 | end 82 | end 83 | end 84 | end 85 | join_none 86 | end 87 | 88 | endmodule 89 | 90 | `endif 91 | -------------------------------------------------------------------------------- /hvl/source_tb.sv: -------------------------------------------------------------------------------- 1 | `ifndef SOURCE_TB 2 | `define SOURCE_TB 3 | 4 | `define MAGIC_MEM 0 5 | `define PARAM_MEM 1 6 | `define MEMORY `PARAM_MEM 7 | // possible_error_CP2: probably should change this MACRO to go from Magic to Param Mem 8 | 9 | // Set these to 1 to enable the feature for CP2 10 | // possible_error_CP2: enable/disable SM and RVFI 11 | `define USE_SHADOW_MEMORY 0 12 | `define USE_RVFI_MONITOR 0 13 | 14 | `include "tb_itf.sv" 15 | 16 | module source_tb( 17 | tb_itf.magic_mem magic_mem_itf, 18 | tb_itf.mem mem_itf, 19 | tb_itf.sm sm_itf, 20 | tb_itf.tb tb_itf, 21 | rvfi_itf rvfi 22 | ); 23 | 24 | initial begin 25 | $display("Compilation Successful"); 26 | tb_itf.path_mb.put("memory.lst"); 27 | tb_itf.rst = 1'b1; 28 | repeat (5) @(posedge tb_itf.clk); 29 | tb_itf.rst = 1'b0; 30 | end 31 | 32 | /**************************** Halting Conditions *****************************/ 33 | int timeout = 100000000; 34 | 35 | always @(posedge tb_itf.clk) begin 36 | if (rvfi.halt) 37 | $finish; 38 | if (timeout == 0) begin 39 | $display("TOP: Timed out"); 40 | $finish; 41 | end 42 | timeout <= timeout - 1; 43 | end 44 | 45 | always @(rvfi.errcode iff (rvfi.errcode != 0)) begin 46 | repeat(5) @(posedge itf.clk); 47 | $display("TOP: Errcode: %0d", rvfi.errcode); 48 | $finish; 49 | end 50 | 51 | /************************** End Halting Conditions ***************************/ 52 | `define PARAM_RESPONSE_NS 50 * 10 53 | `define PARAM_RESPONSE_CYCLES $ceil(`PARAM_RESPONSE_NS / `PERIOD_NS) 54 | `define PAGE_RESPONSE_CYCLES $ceil(`PARAM_RESPONSE_CYCLES / 2.0) 55 | 56 | generate 57 | if (`MEMORY == `MAGIC_MEM) begin : memory 58 | magic_memory_dp mem(magic_mem_itf); 59 | end 60 | else if (`MEMORY == `PARAM_MEM) begin : memory 61 | ParamMemory #(`PARAM_RESPONSE_CYCLES, `PAGE_RESPONSE_CYCLES, 4, 256, 512) mem(mem_itf); 62 | end 63 | endgenerate 64 | 65 | generate 66 | if (`USE_SHADOW_MEMORY) begin 67 | shadow_memory sm(sm_itf); 68 | end 69 | 70 | if (`USE_RVFI_MONITOR) begin 71 | /* Instantiate RVFI Monitor */ 72 | riscv_formal_monitor_rv32imc monitor( 73 | .clock(rvfi.clk), 74 | .reset(rvfi.rst), 75 | .rvfi_valid(rvfi.commit), 76 | .rvfi_order(rvfi.order), 77 | .rvfi_insn(rvfi.inst), 78 | .rvfi_trap(rvfi.trap), 79 | .rvfi_halt(rvfi.halt), 80 | .rvfi_intr(1'b0), 81 | .rvfi_mode(2'b00), 82 | .rvfi_rs1_addr(rvfi.rs1_addr), 83 | .rvfi_rs2_addr(rvfi.rs2_addr), 84 | .rvfi_rs1_rdata(rvfi.rs1_addr ? rvfi.rs1_rdata : 0), 85 | .rvfi_rs2_rdata(rvfi.rs2_addr ? rvfi.rs2_rdata : 0), 86 | .rvfi_rd_addr(rvfi.load_regfile ? rvfi.rd_addr : 5'b0), 87 | .rvfi_rd_wdata(rvfi.load_regfile ? rvfi.rd_wdata : 0), 88 | .rvfi_pc_rdata(rvfi.pc_rdata), 89 | .rvfi_pc_wdata(rvfi.pc_wdata), 90 | .rvfi_mem_addr({rvfi.mem_addr[31:2], 2'b0}), 91 | .rvfi_mem_rmask(rvfi.mem_rmask), 92 | .rvfi_mem_wmask(rvfi.mem_wmask), 93 | .rvfi_mem_rdata(rvfi.mem_rdata), 94 | .rvfi_mem_wdata(rvfi.mem_wdata), 95 | .rvfi_mem_extamo(1'b0), 96 | .errcode(rvfi.errcode) 97 | ); 98 | end 99 | endgenerate 100 | 101 | endmodule 102 | 103 | `endif 104 | -------------------------------------------------------------------------------- /hvl/tb_itf.sv: -------------------------------------------------------------------------------- 1 | `ifndef TB_ITF_SV 2 | `define TB_ITF_SV 3 | 4 | // Change frequency for accurate timing 5 | `define FREQUENCY_MHZ 181.818181818 6 | `define FREQUENCY (`FREQUENCY_MHZ * 1000000) 7 | `define PERIOD_NS (1000000000/`FREQUENCY) 8 | `define PERIOD_CLK (`PERIOD_NS / 2) 9 | 10 | `timescale 1ns/1ps 11 | 12 | interface tb_itf(); 13 | 14 | /* Generate Clock */ 15 | bit clk, rst; 16 | always #(`PERIOD_CLK) clk = clk === 1'b0; 17 | 18 | /* Needed to validate correctness */ 19 | logic [31:0] registers[32]; 20 | 21 | /* Error Reporting */ 22 | logic inst_sm_error = 1'b0; 23 | logic data_sm_error = 1'b0; 24 | logic sm_error; 25 | assign sm_error = inst_sm_error | data_sm_error; 26 | logic pmem_error = 1'b0; 27 | 28 | /* I Cache Ports */ 29 | logic inst_read; 30 | logic [31:0] inst_addr; 31 | logic inst_resp; 32 | logic [31:0] inst_rdata; 33 | 34 | /* D Cache Ports */ 35 | logic data_read; 36 | logic data_write; 37 | logic [3:0] data_mbe; 38 | logic [31:0] data_addr; 39 | logic [31:0] data_wdata; 40 | logic data_resp; 41 | logic [31:0] data_rdata; 42 | 43 | /* Burst Memory Ports */ 44 | logic mem_read; 45 | logic mem_write; 46 | logic [31:0] mem_addr; 47 | logic [63:0] mem_wdata; 48 | logic mem_resp; 49 | logic [63:0] mem_rdata; 50 | 51 | /* Mailbox for memory path */ 52 | mailbox #(string) path_mb; 53 | initial path_mb = new(); 54 | 55 | /* Burst Memory */ 56 | clocking mcb @(posedge clk); 57 | input read = mem_read, write = mem_write, addr = mem_addr, 58 | wdata = mem_wdata, rst = rst; 59 | output resp = mem_resp, rdata = mem_rdata, error = pmem_error; 60 | endclocking 61 | 62 | /* Shadow Memory */ 63 | clocking smcb @(posedge clk); 64 | input read_a = inst_read, address_a = inst_addr, rdata_a = inst_rdata, 65 | resp_a = inst_resp, read_b = data_read, write = data_write, 66 | address_b = data_addr, rdata_b = data_rdata, wdata = data_wdata, 67 | resp_b = data_resp, mbe = data_mbe; 68 | output inst_sm_error, data_sm_error; 69 | endclocking 70 | 71 | /* Magic Memory */ 72 | clocking mmcb @(negedge clk); 73 | input read_a = inst_read, address_a = inst_addr, read_b = data_read, 74 | write = data_write, wmask = data_mbe, address_b = data_addr, 75 | wdata = data_wdata; 76 | output resp_a = inst_resp, rdata_a = inst_rdata, resp_b = data_resp, 77 | rdata_b = data_rdata; 78 | endclocking 79 | 80 | modport mem(clocking mcb, ref path_mb); 81 | modport magic_mem(clocking mmcb, ref path_mb); 82 | modport sm(clocking smcb, ref path_mb); 83 | modport tb(input clk, registers, output rst, ref path_mb); 84 | 85 | endinterface 86 | `endif 87 | -------------------------------------------------------------------------------- /hvl/top.sv: -------------------------------------------------------------------------------- 1 | module mp4_tb; 2 | import rv32i_types::*; 3 | `timescale 1ns/10ps 4 | 5 | /********************* Do not touch for proper compilation *******************/ 6 | // Instantiate Interfaces 7 | tb_itf itf(); 8 | rvfi_itf rvfi(itf.clk, itf.rst); 9 | 10 | // Instantiate Testbench 11 | source_tb tb( 12 | .magic_mem_itf(itf), 13 | .mem_itf(itf), 14 | .sm_itf(itf), 15 | .tb_itf(itf), 16 | .rvfi(rvfi) 17 | ); 18 | 19 | // Dump signals 20 | initial begin 21 | $fsdbDumpfile("dump.fsdb"); 22 | $fsdbDumpvars(0, mp4_tb, "+all"); 23 | end 24 | /****************************** End do not touch *****************************/ 25 | 26 | 27 | /************************ Signals necessary for monitor **********************/ 28 | 29 | // Set high when a valid instruction is modifying regfile or PC 30 | assign rvfi.commit = (dut.cpu.mem_wb_out.ctrl.load_regfile || dut.cpu.load_pc || dut.cpu.mem_wb_reg_load) && (dut.cpu.debug_WB_IR != 32'h00000013) && (dut.cpu.mem_wb_out.ctrl != '0); 31 | // Set high when target PC == Current PC for a branch 32 | assign rvfi.halt = dut.cpu.debug_halt; 33 | initial rvfi.order = 0; 34 | always @(posedge itf.clk iff rvfi.commit) rvfi.order <= rvfi.order + 1; // Modify for OoO 35 | 36 | assign rvfi.trap = 1'b0; 37 | assign rvfi.inst = dut.cpu.debug_WB_IR; 38 | assign rvfi.rs1_addr = dut.cpu.mem_wb_out.ctrl.rs1_id; 39 | assign rvfi.rs2_addr = dut.cpu.mem_wb_out.ctrl.rs2_id; 40 | assign rvfi.rs1_rdata = dut.cpu.regfile.data[dut.cpu.mem_wb_out.ctrl.rs1_id]; 41 | assign rvfi.rs2_rdata = dut.cpu.regfile.data[dut.cpu.mem_wb_out.ctrl.rs2_id]; 42 | assign rvfi.rd_addr = dut.cpu.mem_wb_out.ctrl.rd_id; 43 | assign rvfi.load_regfile = dut.cpu.mem_wb_out.ctrl.load_regfile; 44 | assign rvfi.rd_wdata = dut.cpu.regfile_MUX_out; 45 | assign rvfi.pc_rdata = dut.cpu.debug_WB_PC; 46 | 47 | always_comb 48 | begin 49 | rvfi.pc_wdata = dut.cpu.debug_MEM_PC; 50 | 51 | if(dut.cpu.debug_MEM_IR == 32'h00000013 || dut.cpu.ex_mem_out.ctrl == '0) 52 | rvfi.pc_wdata = dut.cpu.debug_EX_PC; 53 | if((dut.cpu.debug_MEM_IR == 32'h00000013 || dut.cpu.ex_mem_out.ctrl == '0) && 54 | (dut.cpu.debug_EX_IR == 32'h00000013 || dut.cpu.id_ex_out.ctrl == '0)) 55 | rvfi.pc_wdata = dut.cpu.debug_ID_PC; 56 | if((dut.cpu.debug_MEM_IR == 32'h00000013 || dut.cpu.ex_mem_out.ctrl == '0) && 57 | (dut.cpu.debug_EX_IR == 32'h00000013 || dut.cpu.id_ex_out.ctrl == '0) && 58 | (dut.cpu.debug_ID_IR == 32'h00000013)) 59 | rvfi.pc_wdata = dut.cpu.if_id_in.pc; 60 | end 61 | 62 | assign rvfi.mem_rmask = ((dut.cpu.mem_wb_out.ctrl.opcode == op_load) || (dut.cpu.mem_wb_out.ctrl.mem_read)) ? dut.cpu.mem_wb_out.write_read_mask : 4'b0; 63 | assign rvfi.mem_wmask = ((dut.cpu.mem_wb_out.ctrl.opcode == op_store) || (dut.cpu.mem_wb_out.ctrl.mem_write)) ? dut.cpu.mem_wb_out.write_read_mask : 4'b0; 64 | assign rvfi.mem_rdata = dut.cpu.mem_wb_out.MDR; 65 | assign rvfi.mem_addr = dut.cpu.mem_wb_out.alu_out_address; 66 | assign rvfi.mem_wdata = dut.cpu.mem_wb_out.mem_data_out; 67 | 68 | // possible_error: For an instruction that reads no rs1/rs2 register, this output can have an arbitrary value. However, if this output is nonzero then rvfi_rs1_rdata must carry the value stored in that register in the pre-state. 69 | /* 70 | Instruction and trap: 71 | rvfi.inst [DONE] 72 | rvfi.trap [This honestly not that useful] 73 | 74 | Regfile: 75 | rvfi.rs1_addr [DONE] 76 | rvfi.rs2_addr [DONE] 77 | rvfi.rs1_rdata [DONE] 78 | rvfi.rs2_rdata [DONE] 79 | rvfi.load_regfile [DONE] 80 | rvfi.rd_addr [DONE] 81 | rvfi.rd_wdata [DONE] 82 | 83 | PC: 84 | rvfi.pc_rdata [DONE] 85 | rvfi.pc_wdata [DONE] 86 | 87 | Memory: 88 | rvfi.mem_addr [DONE] 89 | rvfi.mem_rmask [DONE] 90 | rvfi.mem_wmask [DONE] 91 | rvfi.mem_rdata [DONE] 92 | rvfi.mem_wdata [DONE] 93 | 94 | Please refer to rvfi_itf.sv for more information. 95 | */ 96 | 97 | /**************************** End RVFIMON signals ****************************/ 98 | 99 | /********************* Assign Shadow Memory Signals Here *********************/ 100 | 101 | assign itf.inst_read = dut.instr_read; 102 | assign itf.inst_addr = dut.instr_mem_address; 103 | assign itf.inst_resp = dut.instr_mem_resp; 104 | assign itf.inst_rdata = dut.instr_mem_rdata; 105 | 106 | assign itf.data_read = dut.data_read; 107 | assign itf.data_write = dut.data_write; 108 | assign itf.data_mbe = dut.data_mbe; 109 | assign itf.data_addr = dut.data_mem_address; 110 | assign itf.data_wdata = dut.data_mem_wdata; 111 | assign itf.data_resp = dut.data_mem_resp; 112 | assign itf.data_rdata = dut.data_mem_rdata; 113 | /* 114 | The following signals need to be set: 115 | icache signals: 116 | itf.inst_read 117 | itf.inst_addr 118 | itf.inst_resp 119 | itf.inst_rdata 120 | 121 | dcache signals: 122 | itf.data_read 123 | itf.data_write 124 | itf.data_mbe 125 | itf.data_addr 126 | itf.data_wdata 127 | itf.data_resp 128 | itf.data_rdata 129 | 130 | Please refer to tb_itf.sv for more information. 131 | */ 132 | 133 | /*********************** End Shadow Memory Assignments ***********************/ 134 | 135 | // Set this to the proper value 136 | assign itf.registers = dut.cpu.regfile.data; 137 | 138 | /*********************** Instantiate your design here ************************/ 139 | /* 140 | The following signals need to be connected to your top level for CP2: 141 | Burst Memory Ports: 142 | itf.mem_read 143 | itf.mem_write 144 | itf.mem_wdata 145 | itf.mem_rdata 146 | itf.mem_addr 147 | itf.mem_resp 148 | 149 | Please refer to tb_itf.sv for more information. 150 | */ 151 | 152 | mp4 dut( 153 | .clk(itf.clk), 154 | .rst(itf.rst), 155 | 156 | .pmem_read(itf.mem_read), 157 | .pmem_write(itf.mem_write), 158 | .pmem_wdata(itf.mem_wdata), 159 | .pmem_rdata(itf.mem_rdata), 160 | .pmem_address(itf.mem_addr), 161 | .pmem_resp(itf.mem_resp) 162 | ); 163 | /***************************** End Instantiation *****************************/ 164 | 165 | endmodule 166 | -------------------------------------------------------------------------------- /pkg/cache_mux_types.sv: -------------------------------------------------------------------------------- 1 | package cache_mux_types; 2 | 3 | typedef enum bit [1:0] { 4 | no_write = 2'b00 5 | ,cpu_write_cache = 2'b01 6 | ,mem_write_cache = 2'b10 7 | } dataarraymux_sel_t; 8 | 9 | 10 | typedef enum bit { 11 | cache_read_mem = 1'b0 12 | ,cache_write_mem = 1'b1 13 | } pmemaddressmux_sel_t; 14 | 15 | typedef enum bit { 16 | curr_cpu_address = 1'b0 17 | ,prev_cpu_address = 1'b1 18 | } paddressmux_sel_t; 19 | 20 | endpackage : cache_mux_types -------------------------------------------------------------------------------- /pkg/rv32i_mux_types.sv: -------------------------------------------------------------------------------- 1 | package pcmux; 2 | typedef enum bit [2:0] { 3 | pc_plus4 = 3'b000 4 | ,adder_out = 3'b001 5 | ,adder_mod2 = 3'b010 6 | ,btb_out = 3'b011 7 | ,if_id_out_pc_plus4 = 3'b100 8 | } pcmux_sel_t; 9 | endpackage 10 | 11 | package marmux; 12 | typedef enum bit { 13 | pc_out = 1'b0 14 | ,alu_out = 1'b1 15 | } marmux_sel_t; 16 | endpackage 17 | 18 | package cmpmux; 19 | typedef enum bit { 20 | rs2_out = 1'b0 21 | ,imm = 1'b1 22 | } cmpmux_sel_t; 23 | endpackage 24 | 25 | package alumux; 26 | typedef enum bit { 27 | rs1_out = 1'b0 28 | ,pc_out = 1'b1 29 | } alumux1_sel_t; 30 | 31 | typedef enum bit { 32 | imm = 1'b0 33 | ,rs2_out = 1'b1 34 | } alumux2_sel_t; 35 | endpackage 36 | 37 | package regfilemux; 38 | typedef enum bit [2:0] { 39 | alu_out = 3'b000 40 | ,br_en = 3'b001 41 | ,imm = 3'b010 42 | ,load = 3'b011 43 | ,pc_plus4 = 3'b100 44 | } regfilemux_sel_t; 45 | endpackage 46 | 47 | package targetaddressmux; 48 | typedef enum bit { 49 | pc = 1'b0 50 | ,rs1_out = 1'b1 51 | } targetaddressmux_sel_t; 52 | endpackage 53 | 54 | package idforwardamux; 55 | typedef enum bit [2:0] { 56 | no_forward = 3'b000 // 57 | ,ex_br_en = 3'b001 // 58 | ,ex_imm = 3'b010 // 59 | ,mem_pc_plus4 = 3'b011 // 60 | ,mem_alu_out = 3'b100 // 61 | ,mem_imm = 3'b101 // 62 | } idforwardamux_sel_t; 63 | endpackage 64 | 65 | package idforwardbmux; 66 | typedef enum bit [2:0] { 67 | no_forward = 3'b000 68 | ,ex_br_en = 3'b001 69 | ,ex_imm = 3'b010 70 | ,mem_pc_plus4 = 3'b011 71 | ,mem_alu_out = 3'b100 72 | ,mem_imm = 3'b101 73 | } idforwardbmux_sel_t; 74 | endpackage 75 | 76 | package exforwardamux; 77 | typedef enum bit [2:0] { 78 | no_forward = 3'b000 79 | ,mem_alu_out = 3'b001 80 | ,mem_imm = 3'b010 81 | ,wb_regfile_MUX_out = 3'b011 82 | ,mem_br_en = 3'b100 83 | } exforwardamux_sel_t; 84 | endpackage 85 | 86 | package exforwardbmux; 87 | typedef enum bit [2:0] { 88 | no_forward = 3'b000 89 | ,mem_alu_out = 3'b001 90 | ,mem_imm = 3'b010 91 | ,wb_regfile_MUX_out = 3'b011 92 | ,mem_br_en = 3'b100 93 | } exforwardbmux_sel_t; 94 | endpackage 95 | 96 | package wbmemforwardmux; 97 | typedef enum bit { 98 | no_forward = 1'b0 99 | ,regfile_MUX_out = 1'b1 100 | } wbmemforwardmux_sel_t; 101 | endpackage 102 | 103 | package arbiteraddressmux; 104 | typedef enum bit { 105 | d_cache = 1'b0 106 | ,i_cache = 1'b1 107 | } arbiteraddressmux_sel_t; 108 | endpackage 109 | 110 | package tournamentmux; 111 | typedef enum bit { 112 | local_pred = 1'b0 113 | ,global_pred = 1'b1 114 | } tournamentmux_sel_t; 115 | endpackage 116 | -------------------------------------------------------------------------------- /pkg/rv32i_types.sv: -------------------------------------------------------------------------------- 1 | package rv32i_types; 2 | // Mux types are in their own packages to prevent identiier collisions 3 | // e.g. pcmux::pc_plus4 and regfilemux::pc_plus4 are seperate identifiers 4 | // for seperate enumerated types 5 | import pcmux::*; 6 | import marmux::*; 7 | import cmpmux::*; 8 | import alumux::*; 9 | import regfilemux::*; 10 | import targetaddressmux::*; 11 | import idforwardamux::*; 12 | import idforwardbmux::*; 13 | import exforwardamux::*; 14 | import exforwardbmux::*; 15 | import wbmemforwardmux::*; 16 | import arbiteraddressmux::*; 17 | import tournamentmux::*; 18 | 19 | /* Specify the width of performance counters. */ 20 | localparam perf_counter_width = 32; 21 | 22 | /* Specify the depth of branch history recorded. */ 23 | localparam history_depth = 8; 24 | 25 | /* Specify the number of sets in BTB. */ 26 | localparam btb_s_index = 4; 27 | 28 | /* Specify the number of sets in BHT. */ 29 | localparam bht_s_index = 8; 30 | 31 | /* Specify the number of sets in Tournament PHT. */ 32 | localparam tournament_pht_s_index = 8; 33 | 34 | typedef logic [31:0] rv32i_word; 35 | typedef logic [4:0] rv32i_reg; 36 | typedef logic [3:0] rv32i_mem_wmask; 37 | 38 | typedef enum bit [6:0] { 39 | op_lui = 7'b0110111, //load upper immediate (U type) 40 | op_auipc = 7'b0010111, //add upper immediate PC (U type) 41 | op_jal = 7'b1101111, //jump and link (J type) 42 | op_jalr = 7'b1100111, //jump and link register (I type) 43 | op_br = 7'b1100011, //branch (B type) 44 | op_load = 7'b0000011, //load (I type) 45 | op_store = 7'b0100011, //store (S type) 46 | op_imm = 7'b0010011, //arith ops with register/immediate operands (I type) 47 | op_reg = 7'b0110011, //arith ops with register operands (R type) 48 | op_csr = 7'b1110011 //control and status register (I type) 49 | } rv32i_opcode; 50 | 51 | typedef enum bit [2:0] { 52 | beq = 3'b000, 53 | bne = 3'b001, 54 | blt = 3'b100, 55 | bge = 3'b101, 56 | bltu = 3'b110, 57 | bgeu = 3'b111 58 | } branch_funct3_t; 59 | 60 | typedef enum bit [2:0] { 61 | lb = 3'b000, 62 | lh = 3'b001, 63 | lw = 3'b010, 64 | lbu = 3'b100, 65 | lhu = 3'b101 66 | } load_funct3_t; 67 | 68 | typedef enum bit [2:0] { 69 | sb = 3'b000, 70 | sh = 3'b001, 71 | sw = 3'b010 72 | } store_funct3_t; 73 | 74 | typedef enum bit [2:0] { 75 | add = 3'b000, //check bit30 for sub if op_reg opcode 76 | sll = 3'b001, 77 | slt = 3'b010, 78 | sltu = 3'b011, 79 | axor = 3'b100, 80 | sr = 3'b101, //check bit30 for logical/arithmetic 81 | aor = 3'b110, 82 | aand = 3'b111 83 | } arith_funct3_t; 84 | 85 | typedef enum bit [2:0] { 86 | alu_add = 3'b000, 87 | alu_sll = 3'b001, 88 | alu_sra = 3'b010, 89 | alu_sub = 3'b011, 90 | alu_xor = 3'b100, 91 | alu_srl = 3'b101, 92 | alu_or = 3'b110, 93 | alu_and = 3'b111 94 | } alu_ops; 95 | 96 | 97 | typedef enum bit [1:0] { 98 | br = 2'b00 99 | ,jal = 2'b01 100 | ,jalr = 2'b10 101 | } btb_ops; 102 | 103 | typedef struct packed { 104 | 105 | rv32i_word target_address; 106 | btb_ops br_jal_jalr; 107 | 108 | } btb_entry; 109 | 110 | typedef struct packed { 111 | 112 | rv32i_opcode opcode; 113 | logic [2:0] funct3; 114 | logic [6:0] funct7; 115 | rv32i_reg rs1_id; 116 | rv32i_reg rs2_id; 117 | rv32i_reg rd_id; 118 | 119 | alu_ops aluop; 120 | branch_funct3_t cmpop; 121 | 122 | cmpmux_sel_t cmp_MUX_sel; 123 | alumux1_sel_t alu_1_MUX_sel; 124 | alumux2_sel_t alu_2_MUX_sel; 125 | regfilemux_sel_t regfile_MUX_sel; 126 | targetaddressmux_sel_t target_address_MUX_sel; 127 | 128 | logic load_regfile; 129 | logic load_pc; 130 | logic mem_read; 131 | logic mem_write; 132 | 133 | } rv32i_control_word; 134 | 135 | typedef struct packed { 136 | 137 | rv32i_word pc; 138 | rv32i_word ir; 139 | logic btb_read_hit; 140 | btb_entry btb_out; 141 | logic [history_depth-1:0] local_pht_index; 142 | logic [history_depth-1:0] global_pht_index; 143 | logic local_pr; 144 | logic global_pr; 145 | logic br_pr; 146 | 147 | } if_id_pipeline_reg; 148 | 149 | typedef struct packed { 150 | 151 | rv32i_word pc; 152 | rv32i_word ir; 153 | rv32i_word rs1_out; 154 | rv32i_word rs2_out; 155 | rv32i_word imm; 156 | logic br_en; 157 | rv32i_word target_address; 158 | rv32i_control_word ctrl; 159 | 160 | } id_ex_pipeline_reg; 161 | 162 | typedef struct packed { 163 | 164 | rv32i_word pc; 165 | rv32i_word ir; 166 | rv32i_word alu_out; 167 | rv32i_word alu_out_address; 168 | rv32i_mem_wmask write_read_mask; 169 | rv32i_word mem_data_out; 170 | logic br_en; 171 | rv32i_word imm; 172 | rv32i_word target_address; 173 | rv32i_control_word ctrl; 174 | 175 | } ex_mem_pipeline_reg; 176 | 177 | typedef struct packed { 178 | 179 | rv32i_word pc; 180 | rv32i_word ir; 181 | rv32i_word alu_out; 182 | rv32i_word MDR; 183 | rv32i_mem_wmask write_read_mask; 184 | logic br_en; 185 | rv32i_word imm; 186 | rv32i_word target_address; 187 | rv32i_control_word ctrl; 188 | rv32i_word alu_out_address; 189 | rv32i_word mem_data_out; 190 | 191 | } mem_wb_pipeline_reg; 192 | 193 | typedef struct packed { 194 | rv32i_word cpu_address; 195 | } i_cache_pipeline_reg; 196 | 197 | typedef struct packed { 198 | logic [255:0] dataout; 199 | logic way_0_hit; 200 | logic way_1_hit; 201 | logic way_2_hit; 202 | logic way_3_hit; 203 | logic hit; 204 | logic [2:0] LRU_array_dataout; 205 | } i_cache_pipeline_data; 206 | 207 | typedef struct packed { 208 | 209 | rv32i_word cpu_address; 210 | logic [255:0] dataout; 211 | logic [255:0] mem_wdata; 212 | logic [31:0] mem_byte_enable256; 213 | logic way_0_hit; 214 | logic way_1_hit; 215 | logic way_2_hit; 216 | logic way_3_hit; 217 | logic hit; 218 | logic dirty; 219 | logic mem_write; 220 | logic mem_read; 221 | logic [2:0] LRU_array_dataout; 222 | 223 | } d_cache_pipeline_reg; 224 | 225 | endpackage : rv32i_types 226 | 227 | -------------------------------------------------------------------------------- /run_dv.sh: -------------------------------------------------------------------------------- 1 | cd synth && design_vision -f ../dc-gui.tcl -------------------------------------------------------------------------------- /run_test_asm.sh: -------------------------------------------------------------------------------- 1 | make clean 2 | make sim/simv 3 | make run ASM=testcode/$1 > "$1_address_log.txt" 4 | python3 extract_address.py "$1_address_log.txt" 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /run_verdi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p verdi 4 | DUMP=$PWD/sim/dump.fsdb 5 | cd verdi && $VERDI_HOME/bin/verdi -ssf $DUMP 6 | -------------------------------------------------------------------------------- /synthesis.tcl: -------------------------------------------------------------------------------- 1 | set target_library [getenv STD_CELL_LIB] 2 | set synthetic_library [list dw_foundation.sldb] 3 | set link_library [list "*" $target_library $synthetic_library] 4 | set symbol_library [list generic.sdb] 5 | 6 | set design_clock_pin clk 7 | set design_reset_pin rst 8 | 9 | proc ::findFiles { baseDir pattern } { 10 | set dirs [ glob -nocomplain -type d [ file join $baseDir * ] ] 11 | set files {} 12 | foreach dir $dirs { 13 | lappend files {*}[ findFiles $dir $pattern ] 14 | } 15 | lappend files {*}[ glob -nocomplain -type f [ file join $baseDir $pattern ] ] 16 | return $files 17 | } 18 | 19 | suppress_message LINT-31 20 | suppress_message LINT-52 21 | suppress_message LINT-28 22 | suppress_message LINT-29 23 | suppress_message LINT-32 24 | suppress_message LINT-33 25 | suppress_message LINT-28 26 | suppress_message LINT-1 27 | suppress_message LINT-99 28 | suppress_message LINT-2 29 | 30 | set hdlin_check_no_latch true 31 | 32 | set pkgs [glob ../pkg/*.sv] 33 | foreach module $pkgs { 34 | puts "analyzing $module" 35 | analyze -library WORK -format sverilog "${module}" 36 | } 37 | 38 | set modules [ join [ findFiles ../hdl "*.sv" ] \n ] 39 | 40 | foreach module $modules { 41 | puts "analyzing $module" 42 | analyze -library WORK -format sverilog "${module}" 43 | } 44 | 45 | 46 | elaborate mp4 47 | current_design mp4 48 | check_design 49 | read_saif -input ../sim/dump.fsdb.saif -instance mp4_tb/dut 50 | 51 | 52 | set_max_area 500000 -ignore_tns 53 | set clk_name $design_clock_pin 54 | create_clock -period 5.5 -name my_clk $clk_name 55 | set_dont_touch_network [get_clocks my_clk] 56 | set_fix_hold [get_clocks my_clk] 57 | set_clock_uncertainty 0.1 [get_clocks my_clk] 58 | set_ideal_network [get_ports clk] 59 | 60 | set_input_delay 1 [all_inputs] -clock my_clk 61 | set_output_delay 1 [all_outputs] -clock my_clk 62 | set_load 0.1 [all_outputs] 63 | set_max_fanout 1 [all_inputs] 64 | set_fanout_load 8 [all_outputs] 65 | 66 | link 67 | compile_ultra -no_autoungroup -gate_clock 68 | 69 | current_design mp4 70 | 71 | report_area -hier > reports/area.rpt 72 | report_timing > reports/timing.rpt 73 | check_design > reports/check.rpt 74 | report_power -analysis_effort high -hierarchy > reports/power.rpt 75 | 76 | write_file -format ddc -hierarchy -output synth.ddc 77 | exit -------------------------------------------------------------------------------- /testcode/comp1.s: -------------------------------------------------------------------------------- 1 | 2 | # COPYRIGHT 2020 University of Illinois at Urbana-Champaign 3 | # All rights reserved. 4 | 5 | .file "comp1.c" 6 | .option nopic 7 | .text 8 | .align 2 9 | .globl _start 10 | .hidden _start 11 | .type _start, @function 12 | _start: 13 | li sp,0x84000000 14 | addi sp,sp,-16 15 | sw ra,12(sp) 16 | sw s0,8(sp) 17 | sw s10,4(sp) 18 | li s10,-553656320 19 | addi s10,s10,-257 20 | call test_uncorrelated_branches 21 | mv s0,a0 22 | call test_correlated_branches 23 | or s0,s0,a0 24 | call test_mixed 25 | or s0,s0,a0 26 | li a0,12 27 | call fib 28 | beqz s0,.L43 29 | li s10,12247040 30 | addi s10,s10,-1107 31 | j .L44 32 | .L43: 33 | li s10,1611489280 34 | addi s10,s10,13 35 | .L44: 36 | .L45: 37 | j .L45 38 | .size _start, .-_start 39 | .align 2 40 | .globl uncorrelated_branches_kernel 41 | .hidden uncorrelated_branches_kernel 42 | .type uncorrelated_branches_kernel, @function 43 | uncorrelated_branches_kernel: 44 | mv a5,a0 45 | andi a0,a0,1 46 | andi a4,a5,2 47 | beqz a4,.L2 48 | ori a0,a0,2 49 | .L2: 50 | andi a4,a5,4 51 | beqz a4,.L3 52 | ori a0,a0,4 53 | .L3: 54 | andi a4,a5,8 55 | beqz a4,.L4 56 | ori a0,a0,8 57 | .L4: 58 | andi a4,a5,16 59 | beqz a4,.L5 60 | ori a0,a0,16 61 | .L5: 62 | andi a4,a5,32 63 | beqz a4,.L6 64 | ori a0,a0,32 65 | .L6: 66 | andi a4,a5,64 67 | beqz a4,.L7 68 | ori a0,a0,64 69 | .L7: 70 | slli a5,a5,24 71 | srai a5,a5,24 72 | bgez a5,.L8 73 | ori a0,a0,128 74 | .L8: 75 | ret 76 | .size uncorrelated_branches_kernel, .-uncorrelated_branches_kernel 77 | .align 2 78 | .globl correlated_branches_kernel 79 | .hidden correlated_branches_kernel 80 | .type correlated_branches_kernel, @function 81 | correlated_branches_kernel: 82 | mv a5,a0 83 | andi a2,a0,1 84 | andi a4,a0,3 85 | li a3,3 86 | beq a4,a3,.L10 87 | mv a4,a2 88 | .L10: 89 | andi a3,a5,7 90 | li a2,7 91 | beq a3,a2,.L11 92 | mv a3,a4 93 | .L11: 94 | andi a4,a5,15 95 | li a2,15 96 | beq a4,a2,.L12 97 | mv a4,a3 98 | .L12: 99 | andi a3,a5,31 100 | li a2,31 101 | beq a3,a2,.L13 102 | mv a3,a4 103 | .L13: 104 | andi a4,a5,63 105 | li a2,63 106 | beq a4,a2,.L14 107 | mv a4,a3 108 | .L14: 109 | andi a0,a5,127 110 | li a3,127 111 | beq a0,a3,.L15 112 | mv a0,a4 113 | .L15: 114 | li a4,255 115 | bne a5,a4,.L16 116 | mv a0,a5 117 | .L16: 118 | ret 119 | .size correlated_branches_kernel, .-correlated_branches_kernel 120 | .align 2 121 | .globl test_uncorrelated_branches 122 | .hidden test_uncorrelated_branches 123 | .type test_uncorrelated_branches, @function 124 | test_uncorrelated_branches: 125 | addi sp,sp,-16 126 | sw ra,12(sp) 127 | sw s0,8(sp) 128 | sw s1,4(sp) 129 | li s0,0 130 | li s1,255 131 | .L20: 132 | mv a0,s0 133 | call uncorrelated_branches_kernel 134 | andi a0,a0,0xff 135 | bne a0,s0,.L21 136 | addi s0,s0,1 137 | andi s0,s0,0xff 138 | bne s0,s1,.L20 139 | li a0,0 140 | j .L18 141 | .L21: 142 | li a0,1 143 | .L18: 144 | lw ra,12(sp) 145 | lw s0,8(sp) 146 | lw s1,4(sp) 147 | addi sp,sp,16 148 | jr ra 149 | .size test_uncorrelated_branches, .-test_uncorrelated_branches 150 | .align 2 151 | .globl test_correlated_branches 152 | .hidden test_correlated_branches 153 | .type test_correlated_branches, @function 154 | test_correlated_branches: 155 | addi sp,sp,-16 156 | sw ra,12(sp) 157 | sw s0,8(sp) 158 | sw s1,4(sp) 159 | li s0,0 160 | li s1,255 161 | .L26: 162 | mv a0,s0 163 | call correlated_branches_kernel 164 | not a5,s0 165 | slli a5,a5,24 166 | srai a5,a5,24 167 | addi s0,s0,1 168 | andi s0,s0,0xff 169 | and a5,a5,s0 170 | addi a5,a5,-1 171 | andi a0,a0,0xff 172 | andi a5,a5,0xff 173 | bne a0,a5,.L27 174 | bne s0,s1,.L26 175 | li a0,0 176 | j .L24 177 | .L27: 178 | li a0,1 179 | .L24: 180 | lw ra,12(sp) 181 | lw s0,8(sp) 182 | lw s1,4(sp) 183 | addi sp,sp,16 184 | jr ra 185 | .size test_correlated_branches, .-test_correlated_branches 186 | .align 2 187 | .globl test_mixed 188 | .hidden test_mixed 189 | .type test_mixed, @function 190 | test_mixed: 191 | addi sp,sp,-16 192 | sw ra,12(sp) 193 | sw s0,8(sp) 194 | sw s1,4(sp) 195 | sw s2,0(sp) 196 | li s0,0 197 | li s2,255 198 | .L32: 199 | mv a0,s0 200 | call uncorrelated_branches_kernel 201 | mv s1,a0 202 | mv a0,s0 203 | call correlated_branches_kernel 204 | andi a0,a0,0xff 205 | not a5,s0 206 | slli a5,a5,24 207 | srai a5,a5,24 208 | addi a4,s0,1 209 | andi a4,a4,0xff 210 | and a5,a5,a4 211 | addi a5,a5,-1 212 | andi a5,a5,0xff 213 | andi s1,s1,0xff 214 | bne s1,s0,.L33 215 | bne a0,a5,.L34 216 | mv s0,a4 217 | bne a4,s2,.L32 218 | li a0,0 219 | j .L30 220 | .L33: 221 | li a0,1 222 | j .L30 223 | .L34: 224 | li a0,1 225 | .L30: 226 | lw ra,12(sp) 227 | lw s0,8(sp) 228 | lw s1,4(sp) 229 | lw s2,0(sp) 230 | addi sp,sp,16 231 | jr ra 232 | .size test_mixed, .-test_mixed 233 | .align 2 234 | .globl fib 235 | .hidden fib 236 | .type fib, @function 237 | fib: 238 | addi sp,sp,-16 239 | sw ra,12(sp) 240 | sw s0,8(sp) 241 | sw s1,4(sp) 242 | mv s0,a0 243 | li a5,1 244 | ble a0,a5,.L38 245 | addi a0,a0,-1 246 | call fib 247 | mv s1,a0 248 | addi a0,s0,-2 249 | call fib 250 | add s0,s1,a0 251 | .L38: 252 | mv a0,s0 253 | lw ra,12(sp) 254 | lw s0,8(sp) 255 | lw s1,4(sp) 256 | addi sp,sp,16 257 | jr ra 258 | .size fib, .-fib 259 | .align 2 260 | .globl test_function_call 261 | .hidden test_function_call 262 | .type test_function_call, @function 263 | test_function_call: 264 | addi sp,sp,-16 265 | sw ra,12(sp) 266 | li a0,12 267 | call fib 268 | li a0,0 269 | lw ra,12(sp) 270 | addi sp,sp,16 271 | jr ra 272 | .size test_function_call, .-test_function_call 273 | .ident "GCC: (GNU) 7.2.0" 274 | -------------------------------------------------------------------------------- /testcode/comp2_c.s: -------------------------------------------------------------------------------- 1 | .file "cp2.c" 2 | .option nopic 3 | .globl __udivsi3 4 | .globl __umodsi3 5 | .globl __modsi3 6 | .globl __muldi3 7 | .text 8 | .align 1 9 | .globl _start 10 | .type _start, @function 11 | _start: 12 | addi sp,sp,-720 13 | sw ra,716(sp) 14 | sw s0,712(sp) 15 | sw s1,708(sp) 16 | sw s2,704(sp) 17 | sw s3,700(sp) 18 | sw s4,696(sp) 19 | sw s5,692(sp) 20 | sw s10,688(sp) 21 | addi s0,sp,720 22 | li a5,-553656320 23 | addi s10,a5,-257 24 | li a5,60 25 | sw a5,-624(s0) 26 | li a5,1 27 | sw a5,-36(s0) 28 | j .L2 29 | .L3: 30 | lw a5,-36(s0) 31 | addi a5,a5,-1 32 | li a1,12 33 | mv a0,a5 34 | call __udivsi3 35 | mv a5,a0 36 | mv s1,a5 37 | lw a5,-36(s0) 38 | addi a5,a5,-1 39 | li a1,12 40 | mv a0,a5 41 | call __umodsi3 42 | mv a5,a0 43 | mv a4,a5 44 | mv a5,s1 45 | slli a5,a5,1 46 | add a5,a5,s1 47 | slli a5,a5,2 48 | add a5,a5,a4 49 | slli a5,a5,2 50 | addi a4,s0,-32 51 | add a5,a4,a5 52 | lw a4,-592(a5) 53 | mv a5,a4 54 | slli a5,a5,3 55 | sub a5,a5,a4 56 | addi s5,a5,29 57 | lw a5,-36(s0) 58 | li a1,12 59 | mv a0,a5 60 | call __udivsi3 61 | mv a5,a0 62 | mv s1,a5 63 | lw a5,-36(s0) 64 | li a1,12 65 | mv a0,a5 66 | call __umodsi3 67 | mv a5,a0 68 | mv s4,a5 69 | li a1,41 70 | mv a0,s5 71 | call __modsi3 72 | mv a5,a0 73 | mv a4,a5 74 | mv a5,s1 75 | slli a5,a5,1 76 | add a5,a5,s1 77 | slli a5,a5,2 78 | add a5,a5,s4 79 | slli a5,a5,2 80 | addi a3,s0,-32 81 | add a5,a3,a5 82 | sw a4,-592(a5) 83 | lw a5,-36(s0) 84 | addi a5,a5,1 85 | sw a5,-36(s0) 86 | .L2: 87 | lw a4,-36(s0) 88 | li a5,143 89 | bleu a4,a5,.L3 90 | sw zero,-36(s0) 91 | j .L4 92 | .L5: 93 | addi a3,s0,-624 94 | lw a4,-36(s0) 95 | mv a5,a4 96 | slli a5,a5,1 97 | add a5,a5,a4 98 | slli a5,a5,4 99 | add a5,a3,a5 100 | li a1,12 101 | mv a0,a5 102 | call iter 103 | mv a5,a0 104 | mv a6,a1 105 | mv a3,a5 106 | mv a4,a6 107 | lw a5,-36(s0) 108 | slli a5,a5,3 109 | addi a2,s0,-32 110 | add a5,a2,a5 111 | sw a3,-688(a5) 112 | sw a4,-684(a5) 113 | lw a5,-36(s0) 114 | addi a5,a5,1 115 | sw a5,-36(s0) 116 | .L4: 117 | lw a4,-36(s0) 118 | li a5,11 119 | bleu a4,a5,.L5 120 | li a5,0 121 | li a6,0 122 | sw a5,-48(s0) 123 | sw a6,-44(s0) 124 | sw zero,-36(s0) 125 | j .L6 126 | .L7: 127 | lw a5,-36(s0) 128 | addi a5,a5,1 129 | mv s2,a5 130 | li s3,0 131 | lw a5,-36(s0) 132 | slli a5,a5,3 133 | addi a4,s0,-32 134 | add a5,a4,a5 135 | lw a6,-684(a5) 136 | lw a5,-688(a5) 137 | mv a2,a5 138 | mv a3,a6 139 | mv a0,s2 140 | mv a1,s3 141 | call __muldi3 142 | mv a5,a0 143 | mv a6,a1 144 | mv a1,a5 145 | mv a2,a6 146 | lw a3,-48(s0) 147 | lw a4,-44(s0) 148 | add a5,a3,a1 149 | mv a0,a5 150 | sltu a0,a0,a3 151 | add a6,a4,a2 152 | add a4,a0,a6 153 | mv a6,a4 154 | sw a5,-48(s0) 155 | sw a6,-44(s0) 156 | lw a5,-36(s0) 157 | addi a5,a5,1 158 | sw a5,-36(s0) 159 | .L6: 160 | lw a4,-36(s0) 161 | li a5,11 162 | bleu a4,a5,.L7 163 | lw a4,-48(s0) 164 | li a5,76505088 165 | addi a5,a5,-96 166 | bne a4,a5,.L8 167 | lw a4,-44(s0) 168 | li a5,18 169 | bne a4,a5,.L8 170 | li a5,1611489280 171 | addi a5,a5,13 172 | j .L9 173 | .L8: 174 | li a5,195936256 175 | addi a5,a5,222 176 | .L9: 177 | mv s10,a5 178 | .L10: 179 | j .L10 180 | .size _start, .-_start 181 | .align 1 182 | .globl gcd 183 | .type gcd, @function 184 | gcd: 185 | addi sp,sp,-48 186 | sw ra,44(sp) 187 | sw s0,40(sp) 188 | addi s0,sp,48 189 | sw a0,-36(s0) 190 | sw a1,-40(s0) 191 | lw a5,-36(s0) 192 | bnez a5,.L12 193 | lw a5,-40(s0) 194 | bnez a5,.L12 195 | li a5,1 196 | j .L13 197 | .L12: 198 | lw a4,-36(s0) 199 | lw a5,-40(s0) 200 | bge a4,a5,.L15 201 | lw a5,-36(s0) 202 | sw a5,-20(s0) 203 | lw a5,-40(s0) 204 | sw a5,-36(s0) 205 | lw a5,-20(s0) 206 | sw a5,-40(s0) 207 | j .L15 208 | .L17: 209 | lw a5,-36(s0) 210 | lw a1,-40(s0) 211 | mv a0,a5 212 | call __modsi3 213 | mv a5,a0 214 | sw a5,-20(s0) 215 | lw a5,-40(s0) 216 | sw a5,-36(s0) 217 | lw a5,-20(s0) 218 | sw a5,-40(s0) 219 | .L15: 220 | lw a5,-36(s0) 221 | beqz a5,.L16 222 | lw a5,-40(s0) 223 | bnez a5,.L17 224 | .L16: 225 | lw a5,-36(s0) 226 | beqz a5,.L18 227 | lw a5,-36(s0) 228 | j .L13 229 | .L18: 230 | lw a5,-40(s0) 231 | .L13: 232 | mv a0,a5 233 | lw ra,44(sp) 234 | lw s0,40(sp) 235 | addi sp,sp,48 236 | jr ra 237 | .size gcd, .-gcd 238 | .globl __divsi3 239 | .align 1 240 | .globl lcm 241 | .type lcm, @function 242 | lcm: 243 | addi sp,sp,-48 244 | sw ra,44(sp) 245 | sw s0,40(sp) 246 | sw s2,36(sp) 247 | sw s3,32(sp) 248 | sw s4,28(sp) 249 | sw s5,24(sp) 250 | addi s0,sp,48 251 | sw a0,-36(s0) 252 | sw a1,-40(s0) 253 | lw a5,-36(s0) 254 | mv s2,a5 255 | srai a5,a5,31 256 | mv s3,a5 257 | lw a1,-40(s0) 258 | lw a0,-36(s0) 259 | call gcd 260 | mv a5,a0 261 | mv a1,a5 262 | lw a0,-40(s0) 263 | call __divsi3 264 | mv a5,a0 265 | mv s4,a5 266 | srai a5,a5,31 267 | mv s5,a5 268 | mv a2,s4 269 | mv a3,s5 270 | mv a0,s2 271 | mv a1,s3 272 | call __muldi3 273 | mv a5,a0 274 | mv a6,a1 275 | mv a0,a5 276 | mv a1,a6 277 | lw ra,44(sp) 278 | lw s0,40(sp) 279 | lw s2,36(sp) 280 | lw s3,32(sp) 281 | lw s4,28(sp) 282 | lw s5,24(sp) 283 | addi sp,sp,48 284 | jr ra 285 | .size lcm, .-lcm 286 | .align 1 287 | .globl iter 288 | .type iter, @function 289 | iter: 290 | addi sp,sp,-48 291 | sw ra,44(sp) 292 | sw s0,40(sp) 293 | addi s0,sp,48 294 | sw a0,-36(s0) 295 | sw a1,-40(s0) 296 | lw a5,-40(s0) 297 | bnez a5,.L23 298 | li a5,-1 299 | li a6,-1 300 | j .L24 301 | .L23: 302 | lw a5,-36(s0) 303 | lw a5,0(a5) 304 | sw a5,-32(s0) 305 | srai a5,a5,31 306 | sw a5,-28(s0) 307 | li a5,1 308 | sw a5,-20(s0) 309 | j .L25 310 | .L26: 311 | lw a3,-32(s0) 312 | lw a5,-20(s0) 313 | slli a5,a5,2 314 | lw a4,-36(s0) 315 | add a5,a4,a5 316 | lw a5,0(a5) 317 | mv a1,a5 318 | mv a0,a3 319 | call lcm 320 | sw a0,-32(s0) 321 | sw a1,-28(s0) 322 | lw a5,-20(s0) 323 | addi a5,a5,1 324 | sw a5,-20(s0) 325 | .L25: 326 | lw a4,-20(s0) 327 | lw a5,-40(s0) 328 | blt a4,a5,.L26 329 | lw a5,-32(s0) 330 | lw a6,-28(s0) 331 | .L24: 332 | mv a0,a5 333 | mv a1,a6 334 | lw ra,44(sp) 335 | lw s0,40(sp) 336 | addi sp,sp,48 337 | jr ra 338 | .size iter, .-iter 339 | .align 1 340 | .globl __udivmodsi4 341 | .type __udivmodsi4, @function 342 | __udivmodsi4: 343 | addi sp,sp,-48 344 | sw s0,44(sp) 345 | addi s0,sp,48 346 | sw a0,-36(s0) 347 | sw a1,-40(s0) 348 | sw a2,-44(s0) 349 | li a5,1 350 | sw a5,-20(s0) 351 | sw zero,-24(s0) 352 | j .L28 353 | .L30: 354 | lw a5,-40(s0) 355 | slli a5,a5,1 356 | sw a5,-40(s0) 357 | lw a5,-20(s0) 358 | slli a5,a5,1 359 | sw a5,-20(s0) 360 | .L28: 361 | lw a4,-40(s0) 362 | lw a5,-36(s0) 363 | bgeu a4,a5,.L31 364 | lw a5,-20(s0) 365 | beqz a5,.L31 366 | lw a5,-40(s0) 367 | bgez a5,.L30 368 | j .L31 369 | .L33: 370 | lw a4,-36(s0) 371 | lw a5,-40(s0) 372 | bltu a4,a5,.L32 373 | lw a4,-36(s0) 374 | lw a5,-40(s0) 375 | sub a5,a4,a5 376 | sw a5,-36(s0) 377 | lw a4,-24(s0) 378 | lw a5,-20(s0) 379 | or a5,a4,a5 380 | sw a5,-24(s0) 381 | .L32: 382 | lw a5,-20(s0) 383 | srli a5,a5,1 384 | sw a5,-20(s0) 385 | lw a5,-40(s0) 386 | srli a5,a5,1 387 | sw a5,-40(s0) 388 | .L31: 389 | lw a5,-20(s0) 390 | bnez a5,.L33 391 | lw a5,-44(s0) 392 | beqz a5,.L34 393 | lw a5,-36(s0) 394 | j .L35 395 | .L34: 396 | lw a5,-24(s0) 397 | .L35: 398 | mv a0,a5 399 | lw s0,44(sp) 400 | addi sp,sp,48 401 | jr ra 402 | .size __udivmodsi4, .-__udivmodsi4 403 | .align 1 404 | .globl __divsi3 405 | .type __divsi3, @function 406 | __divsi3: 407 | addi sp,sp,-48 408 | sw ra,44(sp) 409 | sw s0,40(sp) 410 | addi s0,sp,48 411 | sw a0,-36(s0) 412 | sw a1,-40(s0) 413 | sw zero,-20(s0) 414 | lw a5,-36(s0) 415 | bgez a5,.L37 416 | lw a5,-36(s0) 417 | sub a5,zero,a5 418 | sw a5,-36(s0) 419 | lw a5,-20(s0) 420 | seqz a5,a5 421 | andi a5,a5,0xff 422 | sw a5,-20(s0) 423 | .L37: 424 | lw a5,-40(s0) 425 | bgez a5,.L38 426 | lw a5,-40(s0) 427 | sub a5,zero,a5 428 | sw a5,-40(s0) 429 | lw a5,-20(s0) 430 | seqz a5,a5 431 | andi a5,a5,0xff 432 | sw a5,-20(s0) 433 | .L38: 434 | lw a5,-36(s0) 435 | lw a4,-40(s0) 436 | li a2,0 437 | mv a1,a4 438 | mv a0,a5 439 | call __udivmodsi4 440 | mv a5,a0 441 | sw a5,-24(s0) 442 | lw a5,-20(s0) 443 | beqz a5,.L39 444 | lw a5,-24(s0) 445 | sub a5,zero,a5 446 | sw a5,-24(s0) 447 | .L39: 448 | lw a5,-24(s0) 449 | mv a0,a5 450 | lw ra,44(sp) 451 | lw s0,40(sp) 452 | addi sp,sp,48 453 | jr ra 454 | .size __divsi3, .-__divsi3 455 | .align 1 456 | .globl __modsi3 457 | .type __modsi3, @function 458 | __modsi3: 459 | addi sp,sp,-48 460 | sw ra,44(sp) 461 | sw s0,40(sp) 462 | addi s0,sp,48 463 | sw a0,-36(s0) 464 | sw a1,-40(s0) 465 | sw zero,-20(s0) 466 | lw a5,-36(s0) 467 | bgez a5,.L42 468 | lw a5,-36(s0) 469 | sub a5,zero,a5 470 | sw a5,-36(s0) 471 | li a5,1 472 | sw a5,-20(s0) 473 | .L42: 474 | lw a5,-40(s0) 475 | bgez a5,.L43 476 | lw a5,-40(s0) 477 | sub a5,zero,a5 478 | sw a5,-40(s0) 479 | .L43: 480 | lw a5,-36(s0) 481 | lw a4,-40(s0) 482 | li a2,1 483 | mv a1,a4 484 | mv a0,a5 485 | call __udivmodsi4 486 | mv a5,a0 487 | sw a5,-24(s0) 488 | lw a5,-20(s0) 489 | beqz a5,.L44 490 | lw a5,-24(s0) 491 | sub a5,zero,a5 492 | sw a5,-24(s0) 493 | .L44: 494 | lw a5,-24(s0) 495 | mv a0,a5 496 | lw ra,44(sp) 497 | lw s0,40(sp) 498 | addi sp,sp,48 499 | jr ra 500 | .size __modsi3, .-__modsi3 501 | .align 1 502 | .globl __udivsi3 503 | .type __udivsi3, @function 504 | __udivsi3: 505 | addi sp,sp,-32 506 | sw ra,28(sp) 507 | sw s0,24(sp) 508 | addi s0,sp,32 509 | sw a0,-20(s0) 510 | sw a1,-24(s0) 511 | lw a5,-20(s0) 512 | lw a4,-24(s0) 513 | li a2,0 514 | mv a1,a4 515 | mv a0,a5 516 | call __udivmodsi4 517 | mv a5,a0 518 | mv a0,a5 519 | lw ra,28(sp) 520 | lw s0,24(sp) 521 | addi sp,sp,32 522 | jr ra 523 | .size __udivsi3, .-__udivsi3 524 | .align 1 525 | .globl __umodsi3 526 | .type __umodsi3, @function 527 | __umodsi3: 528 | addi sp,sp,-32 529 | sw ra,28(sp) 530 | sw s0,24(sp) 531 | addi s0,sp,32 532 | sw a0,-20(s0) 533 | sw a1,-24(s0) 534 | lw a5,-20(s0) 535 | lw a4,-24(s0) 536 | li a2,1 537 | mv a1,a4 538 | mv a0,a5 539 | call __udivmodsi4 540 | mv a5,a0 541 | mv a0,a5 542 | lw ra,28(sp) 543 | lw s0,24(sp) 544 | addi sp,sp,32 545 | jr ra 546 | .size __umodsi3, .-__umodsi3 547 | .align 1 548 | .globl __muldi3 549 | .type __muldi3, @function 550 | __muldi3: 551 | addi sp,sp,-48 552 | sw s0,44(sp) 553 | addi s0,sp,48 554 | sw a0,-40(s0) 555 | sw a1,-36(s0) 556 | sw a2,-48(s0) 557 | sw a3,-44(s0) 558 | li a5,0 559 | li a6,0 560 | sw a5,-24(s0) 561 | sw a6,-20(s0) 562 | j .L51 563 | .L54: 564 | lw a5,-40(s0) 565 | andi t1,a5,1 566 | lw a5,-36(s0) 567 | andi t2,a5,0 568 | mv a5,t1 569 | or a5,a5,t2 570 | beqz a5,.L52 571 | lw a3,-24(s0) 572 | lw a4,-20(s0) 573 | lw a1,-48(s0) 574 | lw a2,-44(s0) 575 | add a5,a3,a1 576 | mv a0,a5 577 | sltu a0,a0,a3 578 | add a6,a4,a2 579 | add a4,a0,a6 580 | mv a6,a4 581 | sw a5,-24(s0) 582 | sw a6,-20(s0) 583 | .L52: 584 | lw a5,-36(s0) 585 | slli a5,a5,31 586 | lw a4,-40(s0) 587 | srli a4,a4,1 588 | or a5,a4,a5 589 | sw a5,-40(s0) 590 | lw a5,-36(s0) 591 | srli a5,a5,1 592 | sw a5,-36(s0) 593 | lw a5,-48(s0) 594 | srli a5,a5,31 595 | lw a4,-44(s0) 596 | slli a4,a4,1 597 | or a5,a4,a5 598 | sw a5,-44(s0) 599 | lw a5,-48(s0) 600 | slli a5,a5,1 601 | sw a5,-48(s0) 602 | .L51: 603 | lw a5,-40(s0) 604 | lw a4,-36(s0) 605 | or a5,a5,a4 606 | bnez a5,.L54 607 | lw a5,-24(s0) 608 | lw a6,-20(s0) 609 | mv a0,a5 610 | mv a1,a6 611 | lw s0,44(sp) 612 | addi sp,sp,48 613 | jr ra 614 | .size __muldi3, .-__muldi3 615 | .ident "GCC: (GNU) 7.2.0" 616 | -------------------------------------------------------------------------------- /testcode/comp2_i.s: -------------------------------------------------------------------------------- 1 | 2 | # COPYRIGHT 2020 University of Illinois at Urbana-Champaign 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | .file "comp2.c" 18 | .option nopic 19 | .globl __modsi3 20 | .text 21 | .align 2 22 | .globl _start 23 | .hidden _start 24 | .type _start, @function 25 | _start: 26 | li sp,0x84000000 27 | addi sp,sp,-704 28 | sw ra,700(sp) 29 | sw s0,696(sp) 30 | sw s1,692(sp) 31 | sw s2,688(sp) 32 | sw s3,684(sp) 33 | sw s4,680(sp) 34 | sw s5,676(sp) 35 | sw s10,672(sp) 36 | li s10,-553656320 37 | addi s10,s10,-257 38 | li a5,60 39 | sw a5,96(sp) 40 | li s1,1 41 | li s2,144 42 | .L26: 43 | addi s4,s1,-1 44 | li a1,12 45 | mv a0,s1 46 | call __udivsi3 47 | mv s0,a0 48 | li a1,12 49 | mv a0,s1 50 | call __umodsi3 51 | slli a4,s0,1 52 | add a4,a4,s0 53 | slli a5,a4,2 54 | mv a4,a5 55 | add s0,a5,a0 56 | slli s0,s0,2 57 | addi a5,sp,672 58 | add s0,a5,s0 59 | li a1,12 60 | mv a0,s4 61 | call __udivsi3 62 | mv s3,a0 63 | li a1,12 64 | mv a0,s4 65 | call __umodsi3 66 | slli a4,s3,1 67 | add a4,a4,s3 68 | slli a5,a4,2 69 | mv a4,a5 70 | add a5,a5,a0 71 | slli a5,a5,2 72 | addi a4,sp,672 73 | add a5,a4,a5 74 | lw a5,-576(a5) 75 | slli a0,a5,3 76 | sub a0,a0,a5 77 | li a1,41 78 | addi a0,a0,29 79 | call __modsi3 80 | sw a0,-576(s0) 81 | addi s1,s1,1 82 | bne s1,s2,.L26 83 | addi s0,sp,96 84 | mv s3,sp 85 | addi s2,sp,672 86 | mv s1,s3 87 | .L27: 88 | li a1,12 89 | mv a0,s0 90 | call iter 91 | sw a0,0(s1) 92 | sw a1,4(s1) 93 | addi s0,s0,48 94 | addi s1,s1,8 95 | bne s0,s2,.L27 96 | li s0,1 97 | li s2,0 98 | li s1,0 99 | li s4,0 100 | li s5,13 101 | .L36: 102 | lw a2,0(s3) 103 | lw a3,4(s3) 104 | mv a0,s0 105 | mv a1,s2 106 | call __muldi3 107 | add a4,s1,a0 108 | sltu a5,a4,s1 109 | add a3,s4,a1 110 | add a5,a5,a3 111 | mv a3,a5 112 | mv s1,a4 113 | mv s4,a5 114 | addi s3,s3,8 115 | addi a5,s0,1 116 | sltu a4,a5,s0 117 | mv s0,a5 118 | add s2,a4,s2 119 | bne a5,s5,.L36 120 | bnez s2,.L36 121 | li a5,76505088 122 | addi a5,a5,-96 123 | bne s1,a5,.L33 124 | li a5,18 125 | beq a3,a5,.L37 126 | .L33: 127 | li a5,195936256 128 | addi a5,a5,222 129 | j .L29 130 | .L37: 131 | li a5,1611489280 132 | addi a5,a5,13 133 | .L29: 134 | mv s10,a5 135 | .L31: 136 | j .L31 137 | .size _start, .-_start 138 | .align 2 139 | .globl gcd 140 | .hidden gcd 141 | .type gcd, @function 142 | gcd: 143 | or a5,a0,a1 144 | beqz a5,.L8 145 | addi sp,sp,-16 146 | sw ra,12(sp) 147 | sw s0,8(sp) 148 | sw s1,4(sp) 149 | mv s1,a1 150 | bge a0,a1,.L3 151 | mv a5,a0 152 | mv a0,a1 153 | mv s1,a5 154 | .L3: 155 | beqz a0,.L9 156 | bnez s1,.L4 157 | mv s1,a0 158 | j .L5 159 | .L6: 160 | mv a1,s0 161 | mv a0,s1 162 | call __modsi3 163 | mv s1,s0 164 | mv s0,a0 165 | .L7: 166 | bnez s0,.L6 167 | j .L5 168 | .L8: 169 | li a0,1 170 | ret 171 | .L9: 172 | mv a0,s1 173 | j .L1 174 | .L5: 175 | mv a0,s1 176 | j .L1 177 | .L4: 178 | mv a1,s1 179 | call __modsi3 180 | mv s0,a0 181 | j .L7 182 | .L1: 183 | lw ra,12(sp) 184 | lw s0,8(sp) 185 | lw s1,4(sp) 186 | addi sp,sp,16 187 | jr ra 188 | .size gcd, .-gcd 189 | .globl __divsi3 190 | .globl __muldi3 191 | .align 2 192 | .globl lcm 193 | .hidden lcm 194 | .type lcm, @function 195 | lcm: 196 | addi sp,sp,-16 197 | sw ra,12(sp) 198 | sw s0,8(sp) 199 | sw s1,4(sp) 200 | mv s0,a0 201 | mv s1,a1 202 | call gcd 203 | mv a1,a0 204 | mv a0,s1 205 | call __divsi3 206 | mv a2,s0 207 | srai a3,s0,31 208 | srai a1,a0,31 209 | call __muldi3 210 | lw ra,12(sp) 211 | lw s0,8(sp) 212 | lw s1,4(sp) 213 | addi sp,sp,16 214 | jr ra 215 | .size lcm, .-lcm 216 | .align 2 217 | .globl iter 218 | .hidden iter 219 | .type iter, @function 220 | iter: 221 | beqz a1,.L19 222 | addi sp,sp,-16 223 | sw ra,12(sp) 224 | sw s0,8(sp) 225 | sw s1,4(sp) 226 | mv s1,a0 227 | mv a5,a1 228 | lw a0,0(a0) 229 | srai a1,a0,31 230 | li a4,1 231 | ble a5,a4,.L16 232 | addi s0,s1,4 233 | slli a5,a5,2 234 | add s1,s1,a5 235 | .L18: 236 | lw a1,0(s0) 237 | call lcm 238 | addi s0,s0,4 239 | bne s0,s1,.L18 240 | j .L16 241 | .L19: 242 | li a0,-1 243 | li a1,-1 244 | ret 245 | .L16: 246 | lw ra,12(sp) 247 | lw s0,8(sp) 248 | lw s1,4(sp) 249 | addi sp,sp,16 250 | jr ra 251 | .size iter, .-iter 252 | .globl __udivsi3 253 | .globl __umodsi3 254 | .align 2 255 | .globl __udivmodsi4 256 | .hidden __udivmodsi4 257 | .type __udivmodsi4, @function 258 | __udivmodsi4: 259 | bgeu a1,a0,.L48 260 | bltz a1,.L49 261 | li a5,1 262 | .L44: 263 | slli a1,a1,1 264 | slli a5,a5,1 265 | bgtu a0,a1,.L41 266 | mv a4,a5 267 | beqz a5,.L43 268 | j .L42 269 | .L41: 270 | beqz a5,.L50 271 | bgez a1,.L44 272 | .L42: 273 | li a4,0 274 | .L46: 275 | bltu a0,a1,.L45 276 | sub a0,a0,a1 277 | or a4,a4,a5 278 | .L45: 279 | srli a5,a5,1 280 | srli a1,a1,1 281 | bnez a5,.L46 282 | j .L43 283 | .L50: 284 | mv a4,a5 285 | .L43: 286 | bnez a2,.L39 287 | mv a0,a4 288 | ret 289 | .L48: 290 | li a5,1 291 | j .L42 292 | .L49: 293 | li a5,1 294 | j .L42 295 | .L39: 296 | ret 297 | .size __udivmodsi4, .-__udivmodsi4 298 | .align 2 299 | .globl __divsi3 300 | .hidden __divsi3 301 | .type __divsi3, @function 302 | __divsi3: 303 | addi sp,sp,-16 304 | sw ra,12(sp) 305 | bgez a0,.L54 306 | sub a0,zero,a0 307 | bltz a1,.L55 308 | j .L60 309 | .L57: 310 | sub a0,zero,a0 311 | j .L53 312 | .L60: 313 | li a2,0 314 | call __udivmodsi4 315 | j .L57 316 | .L59: 317 | li a2,0 318 | call __udivmodsi4 319 | j .L53 320 | .L54: 321 | bgez a1,.L59 322 | li a2,0 323 | sub a1,zero,a1 324 | call __udivmodsi4 325 | j .L57 326 | .L55: 327 | li a2,0 328 | sub a1,zero,a1 329 | call __udivmodsi4 330 | .L53: 331 | lw ra,12(sp) 332 | addi sp,sp,16 333 | jr ra 334 | .size __divsi3, .-__divsi3 335 | .align 2 336 | .globl __modsi3 337 | .hidden __modsi3 338 | .type __modsi3, @function 339 | __modsi3: 340 | addi sp,sp,-16 341 | sw ra,12(sp) 342 | bgez a0,.L63 343 | srai a5,a1,31 344 | xor a1,a5,a1 345 | li a2,1 346 | sub a1,a1,a5 347 | sub a0,zero,a0 348 | call __udivmodsi4 349 | sub a0,zero,a0 350 | j .L62 351 | .L63: 352 | srai a5,a1,31 353 | xor a1,a5,a1 354 | li a2,1 355 | sub a1,a1,a5 356 | call __udivmodsi4 357 | .L62: 358 | lw ra,12(sp) 359 | addi sp,sp,16 360 | jr ra 361 | .size __modsi3, .-__modsi3 362 | .align 2 363 | .globl __udivsi3 364 | .hidden __udivsi3 365 | .type __udivsi3, @function 366 | __udivsi3: 367 | addi sp,sp,-16 368 | sw ra,12(sp) 369 | li a2,0 370 | call __udivmodsi4 371 | lw ra,12(sp) 372 | addi sp,sp,16 373 | jr ra 374 | .size __udivsi3, .-__udivsi3 375 | .align 2 376 | .globl __umodsi3 377 | .hidden __umodsi3 378 | .type __umodsi3, @function 379 | __umodsi3: 380 | addi sp,sp,-16 381 | sw ra,12(sp) 382 | li a2,1 383 | call __udivmodsi4 384 | lw ra,12(sp) 385 | addi sp,sp,16 386 | jr ra 387 | .size __umodsi3, .-__umodsi3 388 | .align 2 389 | .globl __muldi3 390 | .hidden __muldi3 391 | .type __muldi3, @function 392 | __muldi3: 393 | mv a7,a0 394 | mv t1,a1 395 | mv a5,a0 396 | or a5,a0,a1 397 | beqz a5,.L76 398 | li a0,0 399 | li a1,0 400 | .L75: 401 | andi a5,a7,1 402 | beqz a5,.L73 403 | add a5,a0,a2 404 | sltu a0,a5,a0 405 | add a4,a1,a3 406 | add a1,a0,a4 407 | mv a4,a1 408 | mv a0,a5 409 | .L73: 410 | slli a4,t1,31 411 | srli a5,a7,1 412 | or a5,a4,a5 413 | srli t3,t1,1 414 | mv a7,a5 415 | mv t1,t3 416 | srli a6,a2,31 417 | slli a4,a3,1 418 | mv a3,a6 419 | or a3,a6,a4 420 | slli a2,a2,1 421 | mv a4,a5 422 | or a4,a5,t3 423 | bnez a4,.L75 424 | ret 425 | .L76: 426 | ret 427 | .size __muldi3, .-__muldi3 428 | .ident "GCC: (GNU) 7.2.0" 429 | -------------------------------------------------------------------------------- /testcode/comp2_m.s: -------------------------------------------------------------------------------- 1 | 2 | # COPYRIGHT 2020 University of Illinois at Urbana-Champaign 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | .file "comp2.c" 18 | .option nopic 19 | .text 20 | .align 2 21 | .globl _start 22 | .hidden _start 23 | .type _start, @function 24 | _start: 25 | li sp,0x84000000 26 | addi sp,sp,-704 27 | sw ra,700(sp) 28 | sw s0,696(sp) 29 | sw s1,692(sp) 30 | sw s2,688(sp) 31 | sw s3,684(sp) 32 | sw s10,680(sp) 33 | li s10,-553656320 34 | addi s10,s10,-257 35 | li a5,60 36 | sw a5,96(sp) 37 | li a3,1 38 | li a0,12 39 | li t1,41 40 | li a7,144 41 | .L22: 42 | addi a4,a3,-1 43 | divu a5,a3,a0 44 | remu a1,a3,a0 45 | slli a2,a5,1 46 | add a2,a2,a5 47 | slli a5,a2,2 48 | mv a2,a5 49 | add a5,a5,a1 50 | slli a5,a5,2 51 | addi a2,sp,672 52 | add a5,a2,a5 53 | divu a6,a4,a0 54 | remu a2,a4,a0 55 | slli a1,a6,1 56 | add a1,a1,a6 57 | slli a4,a1,2 58 | mv a1,a4 59 | add a4,a4,a2 60 | slli a4,a4,2 61 | addi a2,sp,672 62 | add a4,a2,a4 63 | lw a2,-576(a4) 64 | slli a4,a2,3 65 | sub a4,a4,a2 66 | addi a4,a4,29 67 | rem a4,a4,t1 68 | sw a4,-576(a5) 69 | addi a3,a3,1 70 | bne a3,a7,.L22 71 | addi s1,sp,96 72 | mv s0,sp 73 | addi s3,sp,672 74 | mv s2,s0 75 | .L23: 76 | li a1,12 77 | mv a0,s1 78 | call iter 79 | sw a0,0(s2) 80 | sw a1,4(s2) 81 | addi s1,s1,48 82 | addi s2,s2,8 83 | bne s1,s3,.L23 84 | li a5,1 85 | li a0,0 86 | li a3,0 87 | li a4,0 88 | li a7,13 89 | .L32: 90 | lw a1,0(s0) 91 | mul a2,a1,a0 92 | lw a6,4(s0) 93 | mul a6,a6,a5 94 | add a2,a2,a6 95 | mul t1,a1,a5 96 | mulhu a1,a1,a5 97 | add a2,a2,a1 98 | mv a1,a2 99 | add a1,a3,t1 100 | sltu a3,a1,a3 101 | add a6,a4,a2 102 | add a4,a3,a6 103 | mv a6,a4 104 | mv a3,a1 105 | addi s0,s0,8 106 | addi a2,a5,1 107 | sltu a1,a2,a5 108 | mv a5,a2 109 | add a0,a1,a0 110 | bne a2,a7,.L32 111 | bnez a0,.L32 112 | li a5,76505088 113 | addi a5,a5,-96 114 | bne a3,a5,.L29 115 | li a5,18 116 | beq a4,a5,.L33 117 | .L29: 118 | li a5,195936256 119 | addi a5,a5,222 120 | j .L25 121 | .L33: 122 | li a5,1611489280 123 | addi a5,a5,13 124 | .L25: 125 | mv s10,a5 126 | .L27: 127 | j .L27 128 | .size _start, .-_start 129 | .align 2 130 | .globl gcd 131 | .hidden gcd 132 | .type gcd, @function 133 | gcd: 134 | or a5,a0,a1 135 | beqz a5,.L8 136 | bge a0,a1,.L3 137 | mv a5,a0 138 | mv a0,a1 139 | mv a1,a5 140 | .L3: 141 | beqz a0,.L9 142 | bnez a1,.L4 143 | mv a1,a0 144 | j .L5 145 | .L6: 146 | rem a4,a1,a5 147 | mv a1,a5 148 | mv a5,a4 149 | .L7: 150 | bnez a5,.L6 151 | j .L5 152 | .L8: 153 | li a0,1 154 | ret 155 | .L9: 156 | mv a0,a1 157 | ret 158 | .L5: 159 | mv a0,a1 160 | ret 161 | .L4: 162 | rem a5,a0,a1 163 | j .L7 164 | .size gcd, .-gcd 165 | .align 2 166 | .globl lcm 167 | .hidden lcm 168 | .type lcm, @function 169 | lcm: 170 | addi sp,sp,-16 171 | sw ra,12(sp) 172 | sw s0,8(sp) 173 | sw s1,4(sp) 174 | mv s1,a0 175 | mv s0,a1 176 | call gcd 177 | div a0,s0,a0 178 | srai a1,a0,31 179 | srai a5,s1,31 180 | mul a1,a1,s1 181 | mul a5,a5,a0 182 | add a1,a1,a5 183 | mulhu a5,a0,s1 184 | add a1,a1,a5 185 | mv a5,a1 186 | mul a0,a0,s1 187 | lw ra,12(sp) 188 | lw s0,8(sp) 189 | lw s1,4(sp) 190 | addi sp,sp,16 191 | jr ra 192 | .size lcm, .-lcm 193 | .align 2 194 | .globl iter 195 | .hidden iter 196 | .type iter, @function 197 | iter: 198 | beqz a1,.L15 199 | addi sp,sp,-16 200 | sw ra,12(sp) 201 | sw s0,8(sp) 202 | sw s1,4(sp) 203 | mv s1,a0 204 | mv a5,a1 205 | lw a0,0(a0) 206 | srai a1,a0,31 207 | li a4,1 208 | ble a5,a4,.L12 209 | addi s0,s1,4 210 | slli a5,a5,2 211 | add s1,s1,a5 212 | .L14: 213 | lw a1,0(s0) 214 | call lcm 215 | addi s0,s0,4 216 | bne s0,s1,.L14 217 | j .L12 218 | .L15: 219 | li a0,-1 220 | li a1,-1 221 | ret 222 | .L12: 223 | lw ra,12(sp) 224 | lw s0,8(sp) 225 | lw s1,4(sp) 226 | addi sp,sp,16 227 | jr ra 228 | .size iter, .-iter 229 | .align 2 230 | .globl __udivmodsi4 231 | .hidden __udivmodsi4 232 | .type __udivmodsi4, @function 233 | __udivmodsi4: 234 | bgeu a1,a0,.L44 235 | bltz a1,.L45 236 | li a5,1 237 | .L40: 238 | slli a1,a1,1 239 | slli a5,a5,1 240 | bgtu a0,a1,.L37 241 | mv a4,a5 242 | beqz a5,.L39 243 | j .L38 244 | .L37: 245 | beqz a5,.L46 246 | bgez a1,.L40 247 | .L38: 248 | li a4,0 249 | .L42: 250 | bltu a0,a1,.L41 251 | sub a0,a0,a1 252 | or a4,a4,a5 253 | .L41: 254 | srli a5,a5,1 255 | srli a1,a1,1 256 | bnez a5,.L42 257 | j .L39 258 | .L46: 259 | mv a4,a5 260 | .L39: 261 | bnez a2,.L35 262 | mv a0,a4 263 | ret 264 | .L44: 265 | li a5,1 266 | j .L38 267 | .L45: 268 | li a5,1 269 | j .L38 270 | .L35: 271 | ret 272 | .size __udivmodsi4, .-__udivmodsi4 273 | .align 2 274 | .globl __divsi3 275 | .hidden __divsi3 276 | .type __divsi3, @function 277 | __divsi3: 278 | addi sp,sp,-16 279 | sw ra,12(sp) 280 | bgez a0,.L50 281 | sub a0,zero,a0 282 | bltz a1,.L51 283 | j .L56 284 | .L53: 285 | sub a0,zero,a0 286 | j .L49 287 | .L56: 288 | li a2,0 289 | call __udivmodsi4 290 | j .L53 291 | .L55: 292 | li a2,0 293 | call __udivmodsi4 294 | j .L49 295 | .L50: 296 | bgez a1,.L55 297 | li a2,0 298 | sub a1,zero,a1 299 | call __udivmodsi4 300 | j .L53 301 | .L51: 302 | li a2,0 303 | sub a1,zero,a1 304 | call __udivmodsi4 305 | .L49: 306 | lw ra,12(sp) 307 | addi sp,sp,16 308 | jr ra 309 | .size __divsi3, .-__divsi3 310 | .align 2 311 | .globl __modsi3 312 | .hidden __modsi3 313 | .type __modsi3, @function 314 | __modsi3: 315 | addi sp,sp,-16 316 | sw ra,12(sp) 317 | bgez a0,.L59 318 | srai a5,a1,31 319 | xor a1,a5,a1 320 | li a2,1 321 | sub a1,a1,a5 322 | sub a0,zero,a0 323 | call __udivmodsi4 324 | sub a0,zero,a0 325 | j .L58 326 | .L59: 327 | srai a5,a1,31 328 | xor a1,a5,a1 329 | li a2,1 330 | sub a1,a1,a5 331 | call __udivmodsi4 332 | .L58: 333 | lw ra,12(sp) 334 | addi sp,sp,16 335 | jr ra 336 | .size __modsi3, .-__modsi3 337 | .align 2 338 | .globl __udivsi3 339 | .hidden __udivsi3 340 | .type __udivsi3, @function 341 | __udivsi3: 342 | addi sp,sp,-16 343 | sw ra,12(sp) 344 | li a2,0 345 | call __udivmodsi4 346 | lw ra,12(sp) 347 | addi sp,sp,16 348 | jr ra 349 | .size __udivsi3, .-__udivsi3 350 | .align 2 351 | .globl __umodsi3 352 | .hidden __umodsi3 353 | .type __umodsi3, @function 354 | __umodsi3: 355 | addi sp,sp,-16 356 | sw ra,12(sp) 357 | li a2,1 358 | call __udivmodsi4 359 | lw ra,12(sp) 360 | addi sp,sp,16 361 | jr ra 362 | .size __umodsi3, .-__umodsi3 363 | .align 2 364 | .globl __muldi3 365 | .hidden __muldi3 366 | .type __muldi3, @function 367 | __muldi3: 368 | mv a7,a0 369 | mv t1,a1 370 | mv a5,a0 371 | or a5,a0,a1 372 | beqz a5,.L72 373 | li a0,0 374 | li a1,0 375 | .L71: 376 | andi a5,a7,1 377 | beqz a5,.L69 378 | add a5,a0,a2 379 | sltu a0,a5,a0 380 | add a4,a1,a3 381 | add a1,a0,a4 382 | mv a4,a1 383 | mv a0,a5 384 | .L69: 385 | slli a4,t1,31 386 | srli a5,a7,1 387 | or a5,a4,a5 388 | srli t3,t1,1 389 | mv a7,a5 390 | mv t1,t3 391 | srli a6,a2,31 392 | slli a4,a3,1 393 | mv a3,a6 394 | or a3,a6,a4 395 | slli a2,a2,1 396 | mv a4,a5 397 | or a4,a5,t3 398 | bnez a4,.L71 399 | ret 400 | .L72: 401 | ret 402 | .size __muldi3, .-__muldi3 403 | .ident "GCC: (GNU) 7.2.0" 404 | -------------------------------------------------------------------------------- /testcode/comp2_mc.s: -------------------------------------------------------------------------------- 1 | .file "cp2.c" 2 | .option nopic 3 | .text 4 | .align 1 5 | .globl _start 6 | .type _start, @function 7 | _start: 8 | addi sp,sp,-720 9 | sw ra,716(sp) 10 | sw s0,712(sp) 11 | sw s2,708(sp) 12 | sw s3,704(sp) 13 | sw s4,700(sp) 14 | sw s5,696(sp) 15 | sw s10,692(sp) 16 | addi s0,sp,720 17 | li a5,-553656320 18 | addi s10,a5,-257 19 | li a5,60 20 | sw a5,-624(s0) 21 | li a5,1 22 | sw a5,-36(s0) 23 | j .L2 24 | .L3: 25 | lw a5,-36(s0) 26 | addi a4,a5,-1 27 | li a5,12 28 | divu a4,a4,a5 29 | lw a5,-36(s0) 30 | addi a3,a5,-1 31 | li a5,12 32 | remu a3,a3,a5 33 | mv a5,a4 34 | slli a5,a5,1 35 | add a5,a5,a4 36 | slli a5,a5,2 37 | add a5,a5,a3 38 | slli a5,a5,2 39 | addi a4,s0,-32 40 | add a5,a4,a5 41 | lw a4,-592(a5) 42 | mv a5,a4 43 | slli a5,a5,3 44 | sub a5,a5,a4 45 | addi a3,a5,29 46 | lw a4,-36(s0) 47 | li a5,12 48 | divu a4,a4,a5 49 | lw a2,-36(s0) 50 | li a5,12 51 | remu a2,a2,a5 52 | li a5,41 53 | rem a3,a3,a5 54 | mv a5,a4 55 | slli a5,a5,1 56 | add a5,a5,a4 57 | slli a5,a5,2 58 | add a5,a5,a2 59 | slli a5,a5,2 60 | addi a4,s0,-32 61 | add a5,a4,a5 62 | sw a3,-592(a5) 63 | lw a5,-36(s0) 64 | addi a5,a5,1 65 | sw a5,-36(s0) 66 | .L2: 67 | lw a4,-36(s0) 68 | li a5,143 69 | bleu a4,a5,.L3 70 | sw zero,-36(s0) 71 | j .L4 72 | .L5: 73 | addi a3,s0,-624 74 | lw a4,-36(s0) 75 | mv a5,a4 76 | slli a5,a5,1 77 | add a5,a5,a4 78 | slli a5,a5,4 79 | add a5,a3,a5 80 | li a1,12 81 | mv a0,a5 82 | call iter 83 | mv a5,a0 84 | mv a6,a1 85 | mv a3,a5 86 | mv a4,a6 87 | lw a5,-36(s0) 88 | slli a5,a5,3 89 | addi a2,s0,-32 90 | add a5,a2,a5 91 | sw a3,-688(a5) 92 | sw a4,-684(a5) 93 | lw a5,-36(s0) 94 | addi a5,a5,1 95 | sw a5,-36(s0) 96 | .L4: 97 | lw a4,-36(s0) 98 | li a5,11 99 | bleu a4,a5,.L5 100 | li a5,0 101 | li a6,0 102 | sw a5,-48(s0) 103 | sw a6,-44(s0) 104 | sw zero,-36(s0) 105 | j .L6 106 | .L7: 107 | lw a5,-36(s0) 108 | addi a5,a5,1 109 | mv s2,a5 110 | li s3,0 111 | lw a5,-36(s0) 112 | slli a5,a5,3 113 | addi a4,s0,-32 114 | add a5,a4,a5 115 | lw a6,-684(a5) 116 | lw a5,-688(a5) 117 | mul a3,s3,a5 118 | mul a4,a6,s2 119 | add a4,a3,a4 120 | mul a3,s2,a5 121 | mulhu s5,s2,a5 122 | mv s4,a3 123 | add a5,a4,s5 124 | mv s5,a5 125 | lw a3,-48(s0) 126 | lw a4,-44(s0) 127 | add a5,a3,s4 128 | mv a2,a5 129 | sltu a2,a2,a3 130 | add a6,a4,s5 131 | add a4,a2,a6 132 | mv a6,a4 133 | sw a5,-48(s0) 134 | sw a6,-44(s0) 135 | lw a5,-36(s0) 136 | addi a5,a5,1 137 | sw a5,-36(s0) 138 | .L6: 139 | lw a4,-36(s0) 140 | li a5,11 141 | bleu a4,a5,.L7 142 | lw a4,-48(s0) 143 | li a5,76505088 144 | addi a5,a5,-96 145 | bne a4,a5,.L8 146 | lw a4,-44(s0) 147 | li a5,18 148 | bne a4,a5,.L8 149 | li a5,1611489280 150 | addi a5,a5,13 151 | j .L9 152 | .L8: 153 | li a5,195936256 154 | addi a5,a5,222 155 | .L9: 156 | mv s10,a5 157 | .L10: 158 | j .L10 159 | .size _start, .-_start 160 | .align 1 161 | .globl gcd 162 | .type gcd, @function 163 | gcd: 164 | addi sp,sp,-48 165 | sw s0,44(sp) 166 | addi s0,sp,48 167 | sw a0,-36(s0) 168 | sw a1,-40(s0) 169 | lw a5,-36(s0) 170 | bnez a5,.L12 171 | lw a5,-40(s0) 172 | bnez a5,.L12 173 | li a5,1 174 | j .L13 175 | .L12: 176 | lw a4,-36(s0) 177 | lw a5,-40(s0) 178 | bge a4,a5,.L15 179 | lw a5,-36(s0) 180 | sw a5,-20(s0) 181 | lw a5,-40(s0) 182 | sw a5,-36(s0) 183 | lw a5,-20(s0) 184 | sw a5,-40(s0) 185 | j .L15 186 | .L17: 187 | lw a4,-36(s0) 188 | lw a5,-40(s0) 189 | rem a5,a4,a5 190 | sw a5,-20(s0) 191 | lw a5,-40(s0) 192 | sw a5,-36(s0) 193 | lw a5,-20(s0) 194 | sw a5,-40(s0) 195 | .L15: 196 | lw a5,-36(s0) 197 | beqz a5,.L16 198 | lw a5,-40(s0) 199 | bnez a5,.L17 200 | .L16: 201 | lw a5,-36(s0) 202 | beqz a5,.L18 203 | lw a5,-36(s0) 204 | j .L13 205 | .L18: 206 | lw a5,-40(s0) 207 | .L13: 208 | mv a0,a5 209 | lw s0,44(sp) 210 | addi sp,sp,48 211 | jr ra 212 | .size gcd, .-gcd 213 | .align 1 214 | .globl lcm 215 | .type lcm, @function 216 | lcm: 217 | addi sp,sp,-48 218 | sw ra,44(sp) 219 | sw s0,40(sp) 220 | sw s2,36(sp) 221 | sw s3,32(sp) 222 | sw s4,28(sp) 223 | sw s5,24(sp) 224 | sw s6,20(sp) 225 | sw s7,16(sp) 226 | addi s0,sp,48 227 | sw a0,-36(s0) 228 | sw a1,-40(s0) 229 | lw a5,-36(s0) 230 | mv s4,a5 231 | srai a5,a5,31 232 | mv s5,a5 233 | lw a1,-40(s0) 234 | lw a0,-36(s0) 235 | call gcd 236 | mv a4,a0 237 | lw a5,-40(s0) 238 | div a5,a5,a4 239 | mv s2,a5 240 | srai a5,a5,31 241 | mv s3,a5 242 | mul a4,s5,s2 243 | mul a5,s3,s4 244 | add a5,a4,a5 245 | mul a4,s4,s2 246 | mulhu s7,s4,s2 247 | mv s6,a4 248 | add a5,a5,s7 249 | mv s7,a5 250 | mv a5,s6 251 | mv a6,s7 252 | mv a0,a5 253 | mv a1,a6 254 | lw ra,44(sp) 255 | lw s0,40(sp) 256 | lw s2,36(sp) 257 | lw s3,32(sp) 258 | lw s4,28(sp) 259 | lw s5,24(sp) 260 | lw s6,20(sp) 261 | lw s7,16(sp) 262 | addi sp,sp,48 263 | jr ra 264 | .size lcm, .-lcm 265 | .align 1 266 | .globl iter 267 | .type iter, @function 268 | iter: 269 | addi sp,sp,-48 270 | sw ra,44(sp) 271 | sw s0,40(sp) 272 | addi s0,sp,48 273 | sw a0,-36(s0) 274 | sw a1,-40(s0) 275 | lw a5,-40(s0) 276 | bnez a5,.L23 277 | li a5,-1 278 | li a6,-1 279 | j .L24 280 | .L23: 281 | lw a5,-36(s0) 282 | lw a5,0(a5) 283 | sw a5,-32(s0) 284 | srai a5,a5,31 285 | sw a5,-28(s0) 286 | li a5,1 287 | sw a5,-20(s0) 288 | j .L25 289 | .L26: 290 | lw a3,-32(s0) 291 | lw a5,-20(s0) 292 | slli a5,a5,2 293 | lw a4,-36(s0) 294 | add a5,a4,a5 295 | lw a5,0(a5) 296 | mv a1,a5 297 | mv a0,a3 298 | call lcm 299 | sw a0,-32(s0) 300 | sw a1,-28(s0) 301 | lw a5,-20(s0) 302 | addi a5,a5,1 303 | sw a5,-20(s0) 304 | .L25: 305 | lw a4,-20(s0) 306 | lw a5,-40(s0) 307 | blt a4,a5,.L26 308 | lw a5,-32(s0) 309 | lw a6,-28(s0) 310 | .L24: 311 | mv a0,a5 312 | mv a1,a6 313 | lw ra,44(sp) 314 | lw s0,40(sp) 315 | addi sp,sp,48 316 | jr ra 317 | .size iter, .-iter 318 | .align 1 319 | .globl __udivmodsi4 320 | .type __udivmodsi4, @function 321 | __udivmodsi4: 322 | addi sp,sp,-48 323 | sw s0,44(sp) 324 | addi s0,sp,48 325 | sw a0,-36(s0) 326 | sw a1,-40(s0) 327 | sw a2,-44(s0) 328 | li a5,1 329 | sw a5,-20(s0) 330 | sw zero,-24(s0) 331 | j .L28 332 | .L30: 333 | lw a5,-40(s0) 334 | slli a5,a5,1 335 | sw a5,-40(s0) 336 | lw a5,-20(s0) 337 | slli a5,a5,1 338 | sw a5,-20(s0) 339 | .L28: 340 | lw a4,-40(s0) 341 | lw a5,-36(s0) 342 | bgeu a4,a5,.L31 343 | lw a5,-20(s0) 344 | beqz a5,.L31 345 | lw a5,-40(s0) 346 | bgez a5,.L30 347 | j .L31 348 | .L33: 349 | lw a4,-36(s0) 350 | lw a5,-40(s0) 351 | bltu a4,a5,.L32 352 | lw a4,-36(s0) 353 | lw a5,-40(s0) 354 | sub a5,a4,a5 355 | sw a5,-36(s0) 356 | lw a4,-24(s0) 357 | lw a5,-20(s0) 358 | or a5,a4,a5 359 | sw a5,-24(s0) 360 | .L32: 361 | lw a5,-20(s0) 362 | srli a5,a5,1 363 | sw a5,-20(s0) 364 | lw a5,-40(s0) 365 | srli a5,a5,1 366 | sw a5,-40(s0) 367 | .L31: 368 | lw a5,-20(s0) 369 | bnez a5,.L33 370 | lw a5,-44(s0) 371 | beqz a5,.L34 372 | lw a5,-36(s0) 373 | j .L35 374 | .L34: 375 | lw a5,-24(s0) 376 | .L35: 377 | mv a0,a5 378 | lw s0,44(sp) 379 | addi sp,sp,48 380 | jr ra 381 | .size __udivmodsi4, .-__udivmodsi4 382 | .align 1 383 | .globl __divsi3 384 | .type __divsi3, @function 385 | __divsi3: 386 | addi sp,sp,-48 387 | sw ra,44(sp) 388 | sw s0,40(sp) 389 | addi s0,sp,48 390 | sw a0,-36(s0) 391 | sw a1,-40(s0) 392 | sw zero,-20(s0) 393 | lw a5,-36(s0) 394 | bgez a5,.L37 395 | lw a5,-36(s0) 396 | sub a5,zero,a5 397 | sw a5,-36(s0) 398 | lw a5,-20(s0) 399 | seqz a5,a5 400 | andi a5,a5,0xff 401 | sw a5,-20(s0) 402 | .L37: 403 | lw a5,-40(s0) 404 | bgez a5,.L38 405 | lw a5,-40(s0) 406 | sub a5,zero,a5 407 | sw a5,-40(s0) 408 | lw a5,-20(s0) 409 | seqz a5,a5 410 | andi a5,a5,0xff 411 | sw a5,-20(s0) 412 | .L38: 413 | lw a5,-36(s0) 414 | lw a4,-40(s0) 415 | li a2,0 416 | mv a1,a4 417 | mv a0,a5 418 | call __udivmodsi4 419 | mv a5,a0 420 | sw a5,-24(s0) 421 | lw a5,-20(s0) 422 | beqz a5,.L39 423 | lw a5,-24(s0) 424 | sub a5,zero,a5 425 | sw a5,-24(s0) 426 | .L39: 427 | lw a5,-24(s0) 428 | mv a0,a5 429 | lw ra,44(sp) 430 | lw s0,40(sp) 431 | addi sp,sp,48 432 | jr ra 433 | .size __divsi3, .-__divsi3 434 | .align 1 435 | .globl __modsi3 436 | .type __modsi3, @function 437 | __modsi3: 438 | addi sp,sp,-48 439 | sw ra,44(sp) 440 | sw s0,40(sp) 441 | addi s0,sp,48 442 | sw a0,-36(s0) 443 | sw a1,-40(s0) 444 | sw zero,-20(s0) 445 | lw a5,-36(s0) 446 | bgez a5,.L42 447 | lw a5,-36(s0) 448 | sub a5,zero,a5 449 | sw a5,-36(s0) 450 | li a5,1 451 | sw a5,-20(s0) 452 | .L42: 453 | lw a5,-40(s0) 454 | bgez a5,.L43 455 | lw a5,-40(s0) 456 | sub a5,zero,a5 457 | sw a5,-40(s0) 458 | .L43: 459 | lw a5,-36(s0) 460 | lw a4,-40(s0) 461 | li a2,1 462 | mv a1,a4 463 | mv a0,a5 464 | call __udivmodsi4 465 | mv a5,a0 466 | sw a5,-24(s0) 467 | lw a5,-20(s0) 468 | beqz a5,.L44 469 | lw a5,-24(s0) 470 | sub a5,zero,a5 471 | sw a5,-24(s0) 472 | .L44: 473 | lw a5,-24(s0) 474 | mv a0,a5 475 | lw ra,44(sp) 476 | lw s0,40(sp) 477 | addi sp,sp,48 478 | jr ra 479 | .size __modsi3, .-__modsi3 480 | .align 1 481 | .globl __udivsi3 482 | .type __udivsi3, @function 483 | __udivsi3: 484 | addi sp,sp,-32 485 | sw ra,28(sp) 486 | sw s0,24(sp) 487 | addi s0,sp,32 488 | sw a0,-20(s0) 489 | sw a1,-24(s0) 490 | lw a5,-20(s0) 491 | lw a4,-24(s0) 492 | li a2,0 493 | mv a1,a4 494 | mv a0,a5 495 | call __udivmodsi4 496 | mv a5,a0 497 | mv a0,a5 498 | lw ra,28(sp) 499 | lw s0,24(sp) 500 | addi sp,sp,32 501 | jr ra 502 | .size __udivsi3, .-__udivsi3 503 | .align 1 504 | .globl __umodsi3 505 | .type __umodsi3, @function 506 | __umodsi3: 507 | addi sp,sp,-32 508 | sw ra,28(sp) 509 | sw s0,24(sp) 510 | addi s0,sp,32 511 | sw a0,-20(s0) 512 | sw a1,-24(s0) 513 | lw a5,-20(s0) 514 | lw a4,-24(s0) 515 | li a2,1 516 | mv a1,a4 517 | mv a0,a5 518 | call __udivmodsi4 519 | mv a5,a0 520 | mv a0,a5 521 | lw ra,28(sp) 522 | lw s0,24(sp) 523 | addi sp,sp,32 524 | jr ra 525 | .size __umodsi3, .-__umodsi3 526 | .align 1 527 | .globl __muldi3 528 | .type __muldi3, @function 529 | __muldi3: 530 | addi sp,sp,-48 531 | sw s0,44(sp) 532 | addi s0,sp,48 533 | sw a0,-40(s0) 534 | sw a1,-36(s0) 535 | sw a2,-48(s0) 536 | sw a3,-44(s0) 537 | li a5,0 538 | li a6,0 539 | sw a5,-24(s0) 540 | sw a6,-20(s0) 541 | j .L51 542 | .L54: 543 | lw a5,-40(s0) 544 | andi t1,a5,1 545 | lw a5,-36(s0) 546 | andi t2,a5,0 547 | mv a5,t1 548 | or a5,a5,t2 549 | beqz a5,.L52 550 | lw a3,-24(s0) 551 | lw a4,-20(s0) 552 | lw a1,-48(s0) 553 | lw a2,-44(s0) 554 | add a5,a3,a1 555 | mv a0,a5 556 | sltu a0,a0,a3 557 | add a6,a4,a2 558 | add a4,a0,a6 559 | mv a6,a4 560 | sw a5,-24(s0) 561 | sw a6,-20(s0) 562 | .L52: 563 | lw a5,-36(s0) 564 | slli a5,a5,31 565 | lw a4,-40(s0) 566 | srli a4,a4,1 567 | or a5,a4,a5 568 | sw a5,-40(s0) 569 | lw a5,-36(s0) 570 | srli a5,a5,1 571 | sw a5,-36(s0) 572 | lw a5,-48(s0) 573 | srli a5,a5,31 574 | lw a4,-44(s0) 575 | slli a4,a4,1 576 | or a5,a4,a5 577 | sw a5,-44(s0) 578 | lw a5,-48(s0) 579 | slli a5,a5,1 580 | sw a5,-48(s0) 581 | .L51: 582 | lw a5,-40(s0) 583 | lw a4,-36(s0) 584 | or a5,a5,a4 585 | bnez a5,.L54 586 | lw a5,-24(s0) 587 | lw a6,-20(s0) 588 | mv a0,a5 589 | mv a1,a6 590 | lw s0,44(sp) 591 | addi sp,sp,48 592 | jr ra 593 | .size __muldi3, .-__muldi3 594 | .ident "GCC: (GNU) 7.2.0" 595 | -------------------------------------------------------------------------------- /testcode/mp4-cp1.s: -------------------------------------------------------------------------------- 1 | # mp4-cp1.s version 4.0 2 | .align 4 3 | .section .text 4 | .globl _start 5 | _start: 6 | pcrel_NEGTWO: auipc x10, %pcrel_hi(NEGTWO) 7 | pcrel_TWO: auipc x11, %pcrel_hi(TWO) 8 | pcrel_ONE: auipc x12, %pcrel_hi(ONE) 9 | nop 10 | nop 11 | nop 12 | nop 13 | nop 14 | nop 15 | nop 16 | lw x1, %pcrel_lo(pcrel_NEGTWO)(x10) 17 | lw x2, %pcrel_lo(pcrel_TWO)(x11) 18 | lw x4, %pcrel_lo(pcrel_ONE)(x12) 19 | nop 20 | nop 21 | nop 22 | nop 23 | nop 24 | nop 25 | nop 26 | beq x0, x0, LD_ST_TEST 27 | nop 28 | nop 29 | nop 30 | nop 31 | nop 32 | nop 33 | nop 34 | 35 | .section .rodata 36 | .balign 256 37 | ONE: .word 0x00000001 38 | TWO: .word 0x00000002 39 | NEGTWO: .word 0xFFFFFFFE 40 | TEMP1: .word 0x00000001 41 | GOOD: .word 0x600D600D 42 | BADD: .word 0xBADDBADD 43 | BYTES: .word 0x04030201 44 | HALF: .word 0x0020FFFF 45 | 46 | .section .text 47 | .align 4 48 | LD_ST_TEST: 49 | pcrel_BYTES: auipc x1, %pcrel_hi(BYTES) 50 | pcrel_HALF: auipc x2, %pcrel_hi(HALF) 51 | nop 52 | nop 53 | nop 54 | nop 55 | nop 56 | nop 57 | addi x1, x1, %pcrel_lo(pcrel_BYTES) 58 | addi x2, x2, %pcrel_lo(pcrel_HALF) 59 | nop 60 | nop 61 | nop 62 | nop 63 | nop 64 | nop 65 | lb x3, 0(x1) 66 | lb x4, 2(x1) 67 | lb x5, 3(x1) 68 | lh x6, 0(x2) 69 | lh x7, 2(x2) 70 | nop 71 | nop 72 | nop 73 | nop 74 | nop 75 | nop 76 | add x8, x3, x4 77 | bgt x6, x0, BADBAD 78 | nop 79 | nop 80 | nop 81 | nop 82 | nop 83 | nop 84 | bne x5, x8, BADBAD 85 | nop 86 | nop 87 | nop 88 | nop 89 | nop 90 | 91 | 92 | LOOP: 93 | pcrel_TEMP1_1: auipc x13, %pcrel_hi(TEMP1) 94 | pcrel_TEMP1_2: auipc x14, %pcrel_hi(TEMP1) 95 | add x3, x1, x2 # X3 <= X1 + X2 96 | and x5, x1, x4 # X5 <= X1 & X4 97 | not x6, x1 # X6 <= ~X1 98 | nop 99 | nop 100 | nop 101 | addi x9, x13, %pcrel_lo(pcrel_TEMP1_1) # X9 <= address of TEMP1 102 | nop 103 | nop 104 | nop 105 | nop 106 | nop 107 | nop 108 | sw x6, 0(x9) # TEMP1 <= x6 109 | lw x7, %pcrel_lo(pcrel_TEMP1_2)(x14) # X7 <= TEMP1 110 | add x1, x1, x4 # X1 <= X1 + X4 111 | nop 112 | nop 113 | nop 114 | nop 115 | nop 116 | nop 117 | nop 118 | blt x0, x1, DONEa 119 | nop 120 | nop 121 | nop 122 | nop 123 | nop 124 | nop 125 | nop 126 | beq x0, x0, LOOP 127 | nop 128 | nop 129 | nop 130 | nop 131 | nop 132 | nop 133 | nop 134 | BADBAD: 135 | pcrel_BADD: auipc x15, %pcrel_hi(BADD) 136 | nop 137 | nop 138 | nop 139 | nop 140 | nop 141 | nop 142 | nop 143 | 144 | lw x1, %pcrel_lo(pcrel_BADD)(x15) 145 | HALT: 146 | beq x0, x0, HALT 147 | nop 148 | nop 149 | nop 150 | nop 151 | nop 152 | nop 153 | nop 154 | 155 | DONEa: 156 | pcrel_GOOD: auipc x16, %pcrel_hi(GOOD) 157 | nop 158 | nop 159 | nop 160 | nop 161 | nop 162 | nop 163 | nop 164 | lw x1, %pcrel_lo(pcrel_GOOD)(x16) 165 | DONEb: 166 | beq x0, x0, DONEb 167 | nop 168 | nop 169 | nop 170 | nop 171 | nop 172 | nop 173 | nop 174 | -------------------------------------------------------------------------------- /testcode/mp4-cp2.s: -------------------------------------------------------------------------------- 1 | # mp4-cp2.s version 1.3 2 | .align 4 3 | .section .text 4 | .globl _start 5 | _start: 6 | 7 | # Your pipeline should be able to do hazard detection and forwarding. 8 | # Note that you should not stall or forward for dependencies on register x0 or when an 9 | # instruction does not use one of the source registers (such as rs2 for immediate instructions). 10 | 11 | # Mispredict taken branch flushing tests 12 | taken_branches: 13 | beq x0, x0, forward_br 14 | lw x7, BAD 15 | 16 | backward_br: 17 | beq x0, x0, not_taken_branches 18 | beq x0, x0, oof # Also, test back-to-back branches 19 | 20 | forward_br: 21 | beq x0, x0, backward_br 22 | lw x7, BAD 23 | 24 | # Mispredict not-taken branch flushing tests 25 | not_taken_branches: 26 | add x1, x0, 1 # Also, test branching on forwarded value :) 27 | beq x0, x1, oof # Don't take 28 | 29 | beq x0, x0, backward_br_nt # Take 30 | 31 | 32 | forwarding_tests: 33 | # Forwarding x0 test 34 | add x3, x3, 1 35 | add x0, x1, 0 36 | add x2, x0, 0 37 | 38 | beq x2, x3, oof 39 | 40 | # Forwarding sr2 imm test 41 | add x2, x1, 0 42 | add x3, x1, 2 # 2 immediate makes sr2 bits point to x2 43 | add x4, x0, 3 44 | 45 | bne x3, x4, oof # Also, test branching on 2 forwarded values :) 46 | 47 | # MEM -> EX forwarding with stall 48 | lw x1, NOPE 49 | lw x1, A 50 | add x5, x1, x0 # Necessary forwarding stall 51 | 52 | bne x5, x1, oof 53 | 54 | # WB -> MEM forwarding test 55 | add x3, x1, 1 #2 56 | la x8, TEST 57 | sw x3, 0(x8) 58 | lw x4, TEST 59 | 60 | bne x4, x3, oof 61 | 62 | 63 | # Half word forwarding test 64 | lh x2, FULL 65 | add x3, x0, -1 66 | 67 | bne x3, x2, oof 68 | 69 | # Cache miss control test 70 | add x4, x0, 3 71 | lw x2, B # Cache miss 72 | add x3, x2, 1 # Try to forward from cache miss load 73 | 74 | bne x4, x3, oof 75 | 76 | # Forwarding contention test 77 | add x2, x0, 1 78 | add x2, x0, 2 79 | add x3, x2, 1 80 | 81 | beq x3, x2, oof 82 | 83 | lw x7, GOOD 84 | 85 | halt: 86 | beq x0, x0, halt 87 | lw x7, BAD 88 | 89 | oof: 90 | lw x7, BAD 91 | lw x2, PAY_RESPECTS 92 | beq x0, x0, halt 93 | 94 | backward_br_nt: 95 | beq x0, x1, oof # Don't take 96 | 97 | beq x0, x0, forwarding_tests # Take 98 | 99 | 100 | 101 | .section .rodata 102 | .balign 256 103 | DataSeg: 104 | nop 105 | nop 106 | nop 107 | nop 108 | nop 109 | nop 110 | BAD: .word 0x00BADBAD 111 | PAY_RESPECTS: .word 0xFFFFFFFF 112 | # cache line boundary - this cache line should never be loaded 113 | 114 | A: .word 0x00000001 115 | GOOD: .word 0x600D600D 116 | NOPE: .word 0x00BADBAD 117 | TEST: .word 0x00000000 118 | FULL: .word 0xFFFFFFFF 119 | nop 120 | nop 121 | nop 122 | # cache line boundary 123 | 124 | B: .word 0x00000002 125 | nop 126 | nop 127 | nop 128 | nop 129 | nop 130 | nop 131 | nop 132 | # cache line boundary 133 | 134 | C: .word 0x00000003 135 | nop 136 | nop 137 | nop 138 | nop 139 | nop 140 | nop 141 | nop 142 | # cache line boundary 143 | 144 | D: .word 0x00000004 145 | nop 146 | nop 147 | nop 148 | nop 149 | nop 150 | nop 151 | nop 152 | -------------------------------------------------------------------------------- /testcode/src/comp1.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | COPYRIGHT 2020 University of Illinois at Urbana-Champaign 4 | All rights reserved. 5 | 6 | */ 7 | 8 | #include 9 | #include "target.h" 10 | 11 | #if TARGET == RISCV 12 | #include 13 | #endif 14 | 15 | int uncorrelated_branches_kernel(unsigned char test); 16 | int correlated_branches_kernel(unsigned char test); 17 | int test_uncorrelated_branches(); 18 | int test_correlated_branches(); 19 | int test_mixed(); 20 | int fib(int n); 21 | int test_function_call (); 22 | 23 | #if TARGET == EWS 24 | int main() 25 | #else 26 | int _start() 27 | #endif 28 | { 29 | #if TARGET == TARGET_RISCV 30 | volatile register unsigned status asm ("s10") = 0xDEFFDEFF; // default value 31 | #else 32 | register unsigned status = 0xDEFFDEFF; // default value 33 | #endif 34 | 35 | int error = 0; 36 | error |= test_uncorrelated_branches(); 37 | error |= test_correlated_branches(); 38 | error |= test_mixed(); 39 | error |= test_function_call(); 40 | 41 | if (error) { 42 | #if TARGET == EWS 43 | printf("something went wrong\n"); 44 | #endif 45 | status = 0x00BADBAD; 46 | goto done; 47 | } 48 | 49 | status = 0x600D600D; 50 | done: 51 | #if TARGET == EWS 52 | return 0; 53 | #else 54 | while(1); 55 | return status; 56 | #endif 57 | } 58 | 59 | int uncorrelated_branches_kernel(unsigned char test) { 60 | unsigned char out = 0; 61 | // here we have 8 branches at 8 distinc PC addresses 62 | if (test & 0x1) { 63 | out |= 0x1; 64 | } else { 65 | out = out; 66 | } 67 | if (test & 0x02) { 68 | out |= 0x02; 69 | } else { 70 | out = out; 71 | } 72 | if (test & 0x04) { 73 | out |= 0x04; 74 | } else { 75 | out = out; 76 | } 77 | if (test & 0x08) { 78 | out |= 0x08; 79 | } else { 80 | out = out; 81 | } 82 | if (test & 0x10) { 83 | out |= 0x10; 84 | } else { 85 | out = out; 86 | } 87 | if (test & 0x20) { 88 | out |= 0x20; 89 | } else { 90 | out = out; 91 | } 92 | if (test & 0x40) { 93 | out |= 0x40; 94 | } else { 95 | out = out; 96 | } 97 | if (test & 0x80) { 98 | out |= 0x80; 99 | } else { 100 | out = out; 101 | } 102 | return out; 103 | } 104 | 105 | int correlated_branches_kernel(unsigned char test) { 106 | unsigned char out = 0; 107 | if (test & 0x01) { 108 | out |= 0x01; 109 | } else { 110 | out = out; 111 | } 112 | if ((test & 0x03) == 0x03) { 113 | out |= 0x03; 114 | } else { 115 | out = out; 116 | } 117 | if ((test & 0x07) == 0x07) { 118 | out |= 0x07; 119 | } else { 120 | out = out; 121 | } 122 | if ((test & 0x0F) == 0x0F) { 123 | out |= 0x0F; 124 | } else { 125 | out = out; 126 | } 127 | if ((test & 0x1F) == 0x1F) { 128 | out |= 0x1F; 129 | } else { 130 | out = out; 131 | } 132 | if ((test & 0x3F) == 0x3F) { 133 | out |= 0x3F; 134 | } else { 135 | out = out; 136 | } 137 | if ((test & 0x7F) == 0x7F) { 138 | out |= 0x7F; 139 | } else { 140 | out = out; 141 | } 142 | if ((test & 0xFF) == 0xFF) { 143 | out |= 0xFF; 144 | } else { 145 | out = out; 146 | } 147 | return out; 148 | } 149 | 150 | int test_uncorrelated_branches() { 151 | unsigned char test = 0; 152 | unsigned char out = 0; 153 | // test local branch histroy table 154 | for (test = 0; test < 255; test ++) { 155 | out = uncorrelated_branches_kernel(test); 156 | //sanity check 157 | if (out != test) { 158 | return 1; 159 | } 160 | } 161 | return 0; 162 | } 163 | 164 | int test_correlated_branches() { 165 | unsigned char test = 0; 166 | unsigned char out = 0; 167 | unsigned char golden = 0; 168 | // test local branch histroy table 169 | for (test = 0; test < 255; test ++) { 170 | out = correlated_branches_kernel(test); 171 | //sanity check 172 | golden = ~test & (test + 1); 173 | golden --; 174 | //printf("0x%x 0x%x 0x%x\n", test, out, golden); 175 | if (out != golden) { 176 | return 1; 177 | } 178 | } 179 | return 0; 180 | } 181 | 182 | int test_mixed() { 183 | unsigned char test = 0; 184 | unsigned char out1 = 0, out2 = 0; 185 | unsigned char golden = 0; 186 | // test local branch histroy table 187 | for (test = 0; test < 255; test ++) { 188 | out1 = uncorrelated_branches_kernel(test); 189 | out2 = correlated_branches_kernel(test); 190 | //sanity check 191 | golden = ~test & (test + 1); 192 | golden --; 193 | //printf("0x%x 0x%x 0x%x\n", test, out, golden); 194 | if (out1 != test || out2 != golden) { 195 | return 1; 196 | } 197 | } 198 | return 0; 199 | } 200 | 201 | int fib(int n) { 202 | if (n <= 1) 203 | return n; 204 | return fib(n-1) + fib(n-2); 205 | } 206 | 207 | 208 | 209 | int test_function_call () 210 | { 211 | int n = 12; 212 | #if TARGET == EWS 213 | printf("fib(%d) = %d\n", n, fib(n)); 214 | #else 215 | fib(n); 216 | #endif 217 | return 0; 218 | } 219 | -------------------------------------------------------------------------------- /testcode/src/comp2.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | COPYRIGHT 2020 University of Illinois at Urbana-Champaign 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | 18 | */ 19 | 20 | #define TARGET_EWS 1 21 | #define TARGET_RISCV 2 22 | #define TARGET TARGET_RISCV 23 | 24 | #if TARGET == TARGET_EWS 25 | #include 26 | #endif 27 | 28 | #define PASS 0x600d600d 29 | #define FAIL 0x0badc0de 30 | 31 | #define N 12 32 | #define M 7 33 | #define INC 29 34 | #define MOD 41 35 | //#define EXPECTED 10403194620 36 | #define EXPECTED 77385916320 37 | 38 | int gcd(int a, int b); 39 | 40 | long long lcm(int a, int b); 41 | 42 | long long iter(int * arr, int n); 43 | 44 | #if TARGET == TARGET_EWS 45 | int main() { 46 | #else 47 | int _start() { 48 | #endif 49 | 50 | #if TARGET == TARGET_RISCV 51 | volatile register unsigned status asm ("s10") = 0xDEFFDEFF; // default value 52 | #else 53 | register unsigned status = 0xDEFFDEFF; // default value 54 | #endif 55 | 56 | unsigned i; 57 | int nums[N][N]; 58 | nums[0][0] = 60; 59 | for (i = 1; i < N * N; i++) { 60 | nums[i / N][i % N] = (M * nums[(i-1) / N][(i-1) % N] + INC) % MOD; 61 | } 62 | 63 | unsigned long long lcms[N]; 64 | for (i = 0; i < N; i++) { 65 | lcms[i] = iter(nums[i], N); 66 | } 67 | 68 | unsigned long long sum = 0; 69 | for (i = 0; i < N; i++) { 70 | sum += (i+1) * lcms[i]; 71 | } 72 | 73 | status = (sum == EXPECTED) ? PASS : FAIL; 74 | 75 | #if TARGET == TARGET_EWS 76 | printf("\n%llu\n", sum); 77 | printf("%x\n", status); 78 | return 0; 79 | #else 80 | while(1); 81 | #endif 82 | } 83 | 84 | int gcd(int a, int b) { 85 | if (a == 0 && b == 0) { 86 | return 1; 87 | } 88 | int rem; 89 | if (a < b) { 90 | rem = a; 91 | a = b; 92 | b = rem; 93 | } 94 | while (a != 0 && b != 0) { 95 | rem = a % b; 96 | a = b; 97 | b = rem; 98 | } 99 | return a ? a : b; 100 | } 101 | 102 | long long lcm(int a, int b) { 103 | return (long long)a * (b / gcd(a, b)); 104 | } 105 | 106 | long long iter(int * arr, int n) { 107 | if (n == 0) { 108 | return -1; 109 | } 110 | int i; 111 | long long curr = arr[0]; 112 | for (i = 1; i < n; i++) { 113 | curr = lcm(curr, arr[i]); 114 | } 115 | return curr; 116 | } 117 | 118 | unsigned long 119 | __udivmodsi4(unsigned long num, unsigned long den, int modwanted) 120 | { 121 | unsigned long bit = 1; 122 | unsigned long res = 0; 123 | 124 | while (den < num && bit && !(den & (1L<<31))) 125 | { 126 | den <<=1; 127 | bit <<=1; 128 | } 129 | while (bit) 130 | { 131 | if (num >= den) 132 | { 133 | num -= den; 134 | res |= bit; 135 | } 136 | bit >>=1; 137 | den >>=1; 138 | } 139 | if (modwanted) return num; 140 | return res; 141 | } 142 | 143 | long 144 | __divsi3 (long a, long b) 145 | { 146 | int neg = 0; 147 | long res; 148 | 149 | if (a < 0) 150 | { 151 | a = -a; 152 | neg = !neg; 153 | } 154 | 155 | if (b < 0) 156 | { 157 | b = -b; 158 | neg = !neg; 159 | } 160 | 161 | res = __udivmodsi4 (a, b, 0); 162 | 163 | if (neg) 164 | res = -res; 165 | 166 | return res; 167 | } 168 | 169 | long 170 | __modsi3 (long a, long b) 171 | { 172 | int neg = 0; 173 | long res; 174 | 175 | if (a < 0) 176 | { 177 | a = -a; 178 | neg = 1; 179 | } 180 | 181 | if (b < 0) 182 | b = -b; 183 | 184 | res = __udivmodsi4 (a, b, 1); 185 | 186 | if (neg) 187 | res = -res; 188 | 189 | return res; 190 | } 191 | 192 | long 193 | __udivsi3 (long a, long b) 194 | { 195 | return __udivmodsi4 (a, b, 0); 196 | } 197 | 198 | long 199 | __umodsi3 (long a, long b) 200 | { 201 | return __udivmodsi4 (a, b, 1); 202 | } 203 | 204 | unsigned long long 205 | __muldi3 (unsigned long long a, unsigned long long b) 206 | { 207 | unsigned long long r = 0; 208 | 209 | while (a) 210 | { 211 | if (a & 1) 212 | r += b; 213 | a >>= 1; 214 | b <<= 1; 215 | } 216 | return r; 217 | } 218 | -------------------------------------------------------------------------------- /testcode/src/comp3.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | COPYRIGHT 2020 University of Illinois at Urbana-Champaign 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 3 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | 18 | */ 19 | 20 | #include "target.h" 21 | #include "comp3_data.h" 22 | #include 23 | 24 | #if TARGET == TARGET_EWS 25 | #include 26 | #endif 27 | 28 | #define EXECUTION_TYPE 'N' 29 | #define EXECUTION_SUBTYPE 'E' 30 | #define TRADE_PUT 'P' 31 | #define TRADE_CALL 'C' 32 | #define SIDE_BUY 'B' 33 | #define SIDE_SELL 'S' 34 | 35 | #define LIQUIDITY_MAKER 1 36 | #define LIQUIDITY_TAKER 2 37 | 38 | #define RISK_THRESHOLD 100 39 | 40 | struct exec_notification 41 | { 42 | char type; 43 | char subtype; 44 | char trade_type; 45 | char side; 46 | uint32_t timestamp; 47 | uint32_t price; 48 | char symbol [5]; 49 | uint16_t contracts; 50 | uint8_t liquidity; 51 | uint16_t strike; 52 | uint16_t expiration; 53 | uint64_t message_id; 54 | } __attribute__ ((__packed__)); 55 | 56 | _Static_assert (sizeof(struct exec_notification) == 32, "Cacheline size mismatch"); 57 | 58 | unsigned long long old_message_id = 0; 59 | unsigned int contracts_processed = 0; 60 | int puts_count = 0; 61 | int calls_count = 0; 62 | 63 | unsigned int process_execution(struct exec_notification*); 64 | 65 | #define CHECK_EVERY 200 66 | #define STRIDE 3 67 | #define CHECK_STRIDE 80 68 | #define MESSAGE_STRIDE sizeof(struct exec_notification) * STRIDE 69 | 70 | #if TARGET == TARGET_EWS 71 | int main() 72 | #else 73 | int _start() 74 | #endif 75 | { 76 | //printf("%d\n", sizeof(struct exec_notification)); 77 | unsigned char* message_start = raw_data; 78 | struct exec_notification* trade; 79 | int ret_val; 80 | #if TARGET == TARGET_RISCV 81 | volatile register unsigned status asm ("s10") = 0xFEFEFEFE; 82 | #else 83 | register unsigned status = 0xFEFEFEFE; 84 | #endif 85 | 86 | for (int i = 0; i < CHECK_EVERY; i++) 87 | { 88 | trade = (struct exec_notification*) message_start; 89 | ret_val = process_execution(trade); 90 | if (ret_val) status = 0x00BADBAD; 91 | message_start += sizeof(struct exec_notification); 92 | } 93 | 94 | for (int i = 0; i < CHECK_STRIDE; i++) 95 | { 96 | trade = (struct exec_notification*) message_start; 97 | ret_val = process_execution(trade); 98 | if (ret_val) status = 0x00BADBAD; 99 | message_start += MESSAGE_STRIDE; 100 | } 101 | 102 | if (status == 0xFEFEFEFE) 103 | { 104 | status = 0x600D600D; 105 | } 106 | #if TARGET == TARGET_EWS 107 | return 0; 108 | #else 109 | while(1); 110 | #endif 111 | } 112 | 113 | unsigned int process_execution(struct exec_notification* trade) 114 | { 115 | if (trade->type != EXECUTION_TYPE && trade->subtype != EXECUTION_SUBTYPE) 116 | { 117 | // Not a notification we are interested in 118 | return 0; 119 | } 120 | 121 | uint32_t price = __builtin_bswap32(trade->price); 122 | uint16_t contracts = __builtin_bswap16(trade->contracts); 123 | uint16_t strike = __builtin_bswap16(trade->strike); 124 | uint16_t expiration = __builtin_bswap16(trade->expiration); 125 | uint64_t message_id = __builtin_bswap64(trade->message_id); 126 | 127 | #if TARGET == TARGET_EWS 128 | printf("Processing a trade involving %.5s side %c amount %d price %d\n", trade->symbol, trade->side, contracts, price); 129 | #endif 130 | 131 | if (message_id <= old_message_id) 132 | { 133 | // Out of order message, ignore 134 | return 0; 135 | } 136 | old_message_id = message_id; 137 | contracts_processed += contracts; 138 | if (trade->trade_type == TRADE_PUT) 139 | { 140 | puts_count += (trade->side == SIDE_BUY) ? contracts : -(contracts); 141 | } 142 | else if (trade->trade_type == TRADE_CALL) 143 | { 144 | calls_count += (trade->side == SIDE_SELL) ? -(contracts) : contracts; 145 | } 146 | 147 | int vol = price - strike; 148 | if (vol < 0) vol = -vol; 149 | 150 | int risk = vol << 2; 151 | if (expiration > 10) 152 | { 153 | // Long ways out means riskier 154 | risk += risk; 155 | } 156 | 157 | if (trade->liquidity == LIQUIDITY_MAKER) 158 | { 159 | //exchange gives us rebate on liquidity making, reflect that in risk 160 | risk -= 2; 161 | } 162 | 163 | if (risk > RISK_THRESHOLD) 164 | { 165 | //uhoh 166 | #if TARGET == TARGET_EWS 167 | printf("Trade breached risk threshold!!!\n"); 168 | #endif 169 | return 1; 170 | } 171 | return 0; 172 | } 173 | 174 | uint32_t __bswapsi2(uint32_t u) 175 | { 176 | return ((((u) & 0xff000000) >> 24) 177 | | (((u) & 0x00ff0000) >> 8) 178 | | (((u) & 0x0000ff00) << 8) 179 | | (((u) & 0x000000ff) << 24)); 180 | } 181 | 182 | uint64_t __bswapdi2(uint64_t u) 183 | { 184 | return ((((u) & 0xff00000000000000ull) >> 56) 185 | | (((u) & 0x00ff000000000000ull) >> 40) 186 | | (((u) & 0x0000ff0000000000ull) >> 24) 187 | | (((u) & 0x000000ff00000000ull) >> 8) 188 | | (((u) & 0x00000000ff000000ull) << 8) 189 | | (((u) & 0x0000000000ff0000ull) << 24) 190 | | (((u) & 0x000000000000ff00ull) << 40) 191 | | (((u) & 0x00000000000000ffull) << 56)); 192 | } 193 | -------------------------------------------------------------------------------- /testcode/src/target.h: -------------------------------------------------------------------------------- 1 | #ifndef TARGET_H 2 | #define TARGET_H 3 | 4 | #define TARGET_EWS 1 5 | #define TARGET_RISCV 2 6 | #define TARGET TARGET_RISCV 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /testcode/test_forwarding.s: -------------------------------------------------------------------------------- 1 | .align 4 2 | .section .text 3 | .globl _start 4 | _start: 5 | lw x1, ONE 6 | lw x2, TWO 7 | add x3, x1, x2 8 | add x4, x3, x3 9 | 10 | DONEb: 11 | beq x0, x0, DONEb 12 | 13 | .section .rodata 14 | ONE: .word 0x00000001 15 | TWO: .word 0x00000002 -------------------------------------------------------------------------------- /warn.config: -------------------------------------------------------------------------------- 1 | { 2 | +lint=none; 3 | +file=../hvl/rvfimon.v,../hvl/top.sv,../hvl/param_memory.sv; 4 | } --------------------------------------------------------------------------------