├── .gitignore ├── .gitmodules ├── .sv.format ├── .sv.style ├── .vscode └── c_cpp_properties.json ├── LICENSE ├── Makefile ├── README.md ├── aura-core.code-workspace ├── diff-ref-so └── riscv64-spike-so ├── doc ├── BTB.drawio.png ├── FTB.drawio.png ├── O3-memoryaccess.drawio.png ├── StoreSet.drawio.png ├── agiledesign.drawio.png ├── aura-backend.drawio.png ├── aura-frontend.drawio.png ├── aura.drawio.png ├── dataSet.drawio.png ├── difftest.drawio.png ├── dispQue.drawio.png ├── loadpipe.drawio.png ├── mem-cache.drawio.png ├── pipeline.drawio.png ├── png │ └── pipeview-sample.png └── uBTB.drawio.png ├── ready-to-run ├── copy.bin ├── fibo.bin ├── hello.bin ├── simpletest0.bin ├── simpletest1.bin └── sort.bin ├── rtl ├── common │ ├── base.svh │ ├── difftest_def.svh │ ├── dpic.svh │ ├── funcs.svh │ └── tilelink │ │ ├── tilelink.svh │ │ └── tilelink_if.sv ├── cpu │ ├── aura_core.sv │ ├── backend │ │ ├── aura_backend.sv │ │ ├── backend_define.svh │ │ ├── block │ │ │ ├── ctrlBlock.sv │ │ │ ├── exeBlock.sv │ │ │ ├── generateIntFu.svh.tmp │ │ │ ├── generateIntIQ.svh.tmp │ │ │ ├── generateMemFu.svh.tmp │ │ │ ├── generateMemIQ.svh.tmp │ │ │ ├── intBlock.sv │ │ │ └── memBlock.sv │ │ ├── commit │ │ │ ├── ROB.sv │ │ │ ├── csr_write.svh.tmp │ │ │ ├── newest_select.sv │ │ │ ├── oldest_select.sv │ │ │ └── priv_ctrl.sv │ │ ├── decode │ │ │ ├── decode.sv │ │ │ └── decoder.sv │ │ ├── decode_define.svh │ │ ├── dispatch │ │ │ ├── dataQue.sv │ │ │ ├── dispQue.sv │ │ │ └── dispatch.sv │ │ ├── fu │ │ │ ├── alu.sv │ │ │ ├── alu.svh.tmp │ │ │ ├── alu_bru.sv │ │ │ └── alu_scu.sv │ │ ├── issue │ │ │ ├── age_schedule.sv │ │ │ ├── issueQue.sv │ │ │ ├── issueQue_mem.sv │ │ │ └── issueport_if.sv │ │ ├── link │ │ │ ├── csrrw_if.sv │ │ │ ├── disp_if.sv │ │ │ ├── loadwake_if.sv │ │ │ └── syscall_if.sv │ │ ├── memfu │ │ │ ├── link │ │ │ │ ├── load2dcache_if.sv │ │ │ │ ├── load2que_if.sv │ │ │ │ ├── sta2ldque_if.sv │ │ │ │ ├── sta2mmu_if.sv │ │ │ │ ├── staviocheck_if.sv │ │ │ │ ├── stfwd_if.sv │ │ │ │ ├── store2dcache_if.sv │ │ │ │ └── store2que_if.sv │ │ │ ├── loadQue.sv │ │ │ ├── loadfu.sv │ │ │ ├── lsque.sv │ │ │ ├── mdp │ │ │ │ ├── StoreSet.sv │ │ │ │ └── memDepPred.sv │ │ │ ├── stafu.sv │ │ │ ├── stdfu.sv │ │ │ ├── storeQue.sv │ │ │ └── virtualLSQ.sv │ │ ├── regfile │ │ │ ├── bypass_sel.sv │ │ │ ├── regfile.sv │ │ │ └── simRegfile.sv │ │ └── rename │ │ │ ├── freelist.sv │ │ │ ├── rat_map.sv │ │ │ ├── rename.sv │ │ │ └── renametable.sv │ ├── core_comm.svh │ ├── core_config.svh │ ├── core_define.svh │ ├── core_priv.svh │ ├── frontend │ │ ├── aura_frontend.sv │ │ ├── bp │ │ │ ├── BPU.sv │ │ │ ├── FTB.sv │ │ │ ├── FTB_sram.sv │ │ │ ├── FTQ.sv │ │ │ ├── preDecode.sv │ │ │ └── uBTB.sv │ │ ├── fetcher.sv │ │ ├── frontend_config.svh │ │ └── frontend_define.svh │ └── mem │ │ ├── cache_sram.sv │ │ ├── core2icache_if.sv │ │ ├── dcache │ │ └── dcache.sv │ │ ├── icache │ │ └── icache.sv │ │ └── mem_define.svh ├── ip │ ├── sram_1r1w.sv │ └── sram_1rw.sv └── utils │ ├── array2vec.sv │ ├── bits_compare.sv │ ├── continuous_one.sv │ ├── count_one.sv │ ├── redirect.sv │ ├── reorder.sv │ ├── replacement │ ├── plru_rep.sv │ └── random_rep.sv │ └── struct │ ├── StoreBuffer.sv │ ├── bankedSet.sv │ ├── fifo.sv │ └── sramSet.sv ├── sim └── verilator │ ├── Makefile │ ├── inc │ ├── cmdline.hpp │ ├── debugflags.hpp │ ├── define.hpp │ ├── riscv-disasm │ │ ├── disasm.h │ │ └── encoding.h │ └── statistics.hpp │ ├── src │ ├── debugflags.cpp │ ├── difftest.cpp │ ├── main.cpp │ ├── memSim.cpp │ ├── riscv-disasm │ │ └── disasm.cpp │ └── statistics.cpp │ └── tb │ ├── bpu_test.sv │ ├── ctrl_test.sv │ └── tb.sv ├── synth └── yosys │ ├── Makefile │ └── tb.sv ├── tools ├── formatter.py ├── getlist_of_rtl.py └── pipeview.py └── vvls.sh /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | slpp_all 3 | *.dot* 4 | *.vcd 5 | temp.v 6 | *.txt 7 | run.sh -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "firmware"] 2 | path = firmware 3 | url = https://github.com/tastynoob/riscv-firmware.git 4 | -------------------------------------------------------------------------------- /.sv.format: -------------------------------------------------------------------------------- 1 | --column_limit=80 2 | --indentation_spaces=4 3 | --line_break_penalty=4 4 | --wrap_spaces=4 5 | 6 | # {true,false} 7 | --compact_indexing_and_selections=true 8 | --expand_coverpoints=false 9 | --port_declarations_right_align_packed_dimensions=false 10 | --port_declarations_right_align_unpacked_dimensions=false 11 | --wrap_end_else_clauses=true 12 | 13 | # {indent,wrap} 14 | --formal_parameters_indentation=indent 15 | --named_parameter_indentation=indent 16 | --named_port_indentation=indent 17 | --port_declarations_indentation=indent 18 | 19 | # {align,flush-left,preserve,infer} 20 | --assignment_statement_alignment=flush-left 21 | --case_items_alignment=align 22 | --class_member_variable_alignment=align 23 | --distribution_items_alignment=flush-left 24 | --formal_parameters_alignment=align 25 | --module_net_variable_alignment=flush-left 26 | --named_port_alignment=align 27 | --named_parameter_alignment=align 28 | --port_declarations_alignment=flush-left 29 | --struct_union_members_alignment=flush-left -------------------------------------------------------------------------------- /.sv.style: -------------------------------------------------------------------------------- 1 | -package-filename 2 | -enum-name-style 3 | -struct-union-name-style 4 | -line-length=150 5 | -no-tabs=false 6 | -explicit-function-lifetime=false 7 | -parameter-name-style 8 | -generate-label=false 9 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceFolder}/sim/verilator/inc", 7 | "${workspaceFolder}/build", 8 | "/usr/local/share/verilator/include", 9 | "/usr/local/share/verilator/include/vltstd" 10 | ], 11 | "defines": [ 12 | "USE_TRACE", 13 | "VTOP=Vtb", 14 | "Vname=\"tb\"", 15 | "Vheader=\"Vtb.h\"" 16 | ], 17 | "compilerPath": "/usr/bin/gcc", 18 | "cStandard": "c17", 19 | "cppStandard": "c++20", 20 | "intelliSenseMode": "linux-gcc-x64" 21 | } 22 | ], 23 | "version": 4 24 | } -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | aura: 4 | make -f sim/verilator/Makefile aura AURA_HOME=$(realpath .) 5 | 6 | format: 7 | python3 tools/formatter.py 8 | 9 | preprocess: 10 | make -f sim/verilator/Makefile preprocess AURA_HOME=$(realpath .) 11 | 12 | clean: 13 | rm -r build -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aura-core (my undergraduate graduation project) 2 | 3 | 4 | 5 | ## Architecture 6 | 7 | ![](doc/aura.drawio.png) 8 | 9 | 10 | ## develop-env 11 | - vscode 12 | - [Verilog-HDL/SystemVerilog](https://github.com/mshr-h/vscode-verilog-hdl-support) 13 | - ctags 14 | - [Verible](https://github.com/chipsalliance/verible) 15 | - verilator >= 5.012 (very important!!) 16 | - [yosys](https://github.com/YosysHQ/yosys) (with plugin [antmicro/yosys-systemverilog](https://github.com/antmicro/yosys-systemverilog)) 17 | 18 | ## doc and architecture 19 | plz see *.drawio.png in ./doc 20 | 21 | 22 | ## emulation with verilator 23 | 24 | aura support a serial of simple options 25 | ```sh 26 | # compile 27 | export AURA_HOME=`pwd` 28 | make aura # if enable wave trace: make aura USE_TRACE=1 29 | 30 | # for help 31 | ./build/aura -h 32 | 33 | # simple test 34 | ./build/aura -f ready-to-run/simpletest0.bin 35 | # if enable difftest 36 | ./build/aura -f ready-to-run/simpletest0.bin -d diff-ref-so/riscv64-spike-so 37 | # fully argument 38 | ./build/aura -f ready-to-run/simpletest0.bin -d diff-ref-so/riscv64-spike-so --debug-flags COMMIT -e t2000 39 | 40 | # enable debug flags 41 | ./build/aura -f ready-to-run/simpletest0.bin -d diff-ref-so/riscv64-spike-so --debug-flags FETCH,DECODE,COMMIT 42 | # all debug flags can be find at sim/verilator/inc/flags.hpp 43 | ``` 44 | 45 | ## statistics 46 | 47 | aura will dump some message when run completed 48 | 49 | all statistical keywords can be found at stats.txt 50 | 51 | ### O3PipeView 52 | 53 | ```sh 54 | # run with debug flag PIPELINE 55 | ./build/aura -f firmware/build/Debug/firmware.bin -d diff-ref-so/riscv64-spike-so --debug-flags PIPELINE > log.txt 56 | python3 tools/pipeview.py > pipeview.txt 57 | ``` 58 | open pipeview.txt 59 | 60 | ![sample](doc/png/pipeview-sample.png) 61 | 62 | 63 | ## difftest support 64 | 65 | now aura use spike to difftest 66 | ``` 67 | git clone https://github.com/tastynoob/riscv-isa-sim.git 68 | 69 | cd riscv-isa-sim && git checkout aura-difftest 70 | 71 | cd difftest && make CPU=AURA 72 | 73 | cp build/riscv64-spike-so $AURA_HOME/diff-ref-so 74 | ``` 75 | 76 | ## compile for aura firmware 77 | 78 | go to ./firmware 79 | install vscode plugin EIDE 80 | open firmware.code-workspace 81 | 82 | 83 | # thanks for any help! -------------------------------------------------------------------------------- /aura-core.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | } 6 | ], 7 | "settings": { 8 | "verilog.linting.linter": "verilator", 9 | "verilog.ctags.path": "ctags", 10 | "verilog.linting.verilator.arguments": "-sv -f test/verilator/tb.sv $(python3 tools/getlist_of_rtl.py -p rtl) ", 11 | "verilog.formatting.systemVerilog.formatter": "verible-verilog-format", 12 | "verilog.formatting.veribleVerilogFormatter.path": "verible-verilog-format", 13 | "verilog.formatting.veribleVerilogFormatter.arguments" : 14 | "--flagfile=/home/lurker/workspace/O3CPU/aura-core/.sv.format", 15 | //verilog language server use verible 16 | "verible.arguments": [ 17 | "--rules_config=.sv.style" 18 | ], 19 | "files.watcherExclude": { 20 | "**/target": true 21 | }, 22 | "files.associations": { 23 | "*.tmp": "systemverilog", 24 | "iosfwd": "cpp", 25 | "sstream": "cpp" 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /diff-ref-so/riscv64-spike-so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/diff-ref-so/riscv64-spike-so -------------------------------------------------------------------------------- /doc/BTB.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/BTB.drawio.png -------------------------------------------------------------------------------- /doc/FTB.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/FTB.drawio.png -------------------------------------------------------------------------------- /doc/O3-memoryaccess.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/O3-memoryaccess.drawio.png -------------------------------------------------------------------------------- /doc/StoreSet.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/StoreSet.drawio.png -------------------------------------------------------------------------------- /doc/agiledesign.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/agiledesign.drawio.png -------------------------------------------------------------------------------- /doc/aura-backend.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/aura-backend.drawio.png -------------------------------------------------------------------------------- /doc/aura-frontend.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/aura-frontend.drawio.png -------------------------------------------------------------------------------- /doc/aura.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/aura.drawio.png -------------------------------------------------------------------------------- /doc/dataSet.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/dataSet.drawio.png -------------------------------------------------------------------------------- /doc/difftest.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/difftest.drawio.png -------------------------------------------------------------------------------- /doc/dispQue.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/dispQue.drawio.png -------------------------------------------------------------------------------- /doc/loadpipe.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/loadpipe.drawio.png -------------------------------------------------------------------------------- /doc/mem-cache.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/mem-cache.drawio.png -------------------------------------------------------------------------------- /doc/pipeline.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/pipeline.drawio.png -------------------------------------------------------------------------------- /doc/png/pipeview-sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/png/pipeview-sample.png -------------------------------------------------------------------------------- /doc/uBTB.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/doc/uBTB.drawio.png -------------------------------------------------------------------------------- /ready-to-run/copy.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/ready-to-run/copy.bin -------------------------------------------------------------------------------- /ready-to-run/fibo.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/ready-to-run/fibo.bin -------------------------------------------------------------------------------- /ready-to-run/hello.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/ready-to-run/hello.bin -------------------------------------------------------------------------------- /ready-to-run/simpletest0.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/ready-to-run/simpletest0.bin -------------------------------------------------------------------------------- /ready-to-run/simpletest1.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/ready-to-run/simpletest1.bin -------------------------------------------------------------------------------- /ready-to-run/sort.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tastynoob/aura-core/389288250dcacbe95d0e20f344e68f12a1857f59/ready-to-run/sort.bin -------------------------------------------------------------------------------- /rtl/common/base.svh: -------------------------------------------------------------------------------- 1 | `ifndef __BASE_SVH__ 2 | `define __BASE_SVH__ 3 | 4 | typedef enum logic { 5 | true = 1'b1, 6 | false = 1'b0 7 | } bool_e; 8 | 9 | 10 | //bit width fast define 11 | `define WDEF(x) ((``x``) == 0 ? 0 : ((``x``)-1)):0 12 | //bit size fast define, actually it will allocate 1 more bit 13 | `define SDEF(x) $clog2(``x``):0 14 | 15 | `define MASK(s, e) (((1<<(``s``)) - 1) & (~((1<<(``e``)) - 1))) 16 | 17 | `define ASSERT(x) always_ff @(posedge clk) if (!rst) assert((``x``)) 18 | `define ORDER_CHECK(x) `ASSERT(funcs::continuous_one(``x``) == funcs::count_one(``x``)) 19 | 20 | `define PICK_ARRAY_MEMBER(pick_vec, array, member, size) \ 21 | generate \ 22 | for(genvar tmp_expand=0;tmp_expand<``size``;tmp_expand=tmp_expand+1) begin \ 23 | assign ``pick_vec``[tmp_expand] = ``array``[tmp_expand].``member``; \ 24 | end \ 25 | endgenerate 26 | 27 | `define ARRAY_TO_VECTOR(vector, array) \ 28 | for (genvar tmp_expand=0; tmp_expand<`SIZE; tmp_expand=tmp_expand+1) begin \ 29 | assign vector[tmp_expand] = array[tmp_expand]; \ 30 | end 31 | 32 | `define DEBUG_EXP(x) ``x`` 33 | `undef DEBUG_EXP 34 | 35 | `define SET_TRACE_OFF /*verilator tracing_off*/ 36 | `define SET_TRACE_ON /*verilator tracing_on*/ 37 | 38 | typedef longint unsigned uint64_t; 39 | 40 | `include "difftest_def.svh" 41 | 42 | `endif 43 | -------------------------------------------------------------------------------- /rtl/common/difftest_def.svh: -------------------------------------------------------------------------------- 1 | `ifndef __DIFFTEST_DEF_SVH__ 2 | `define __DIFFTEST_DEF_SVH__ 3 | 4 | 5 | package difftest_def; 6 | 7 | typedef enum int { 8 | AT_fetch, 9 | AT_decode, 10 | AT_rename, 11 | AT_dispQue, 12 | AT_issueQue, 13 | AT_fu, 14 | AT_wb, 15 | AT_lq, 16 | AT_sq, 17 | NUMPOS 18 | } InstPos; 19 | 20 | 21 | typedef enum int { 22 | META_ISBRANCH, 23 | META_ISLOAD, 24 | META_ISSTORE, 25 | META_ISMV, 26 | META_MISPRED, // branch only 27 | META_NPC, // branch only 28 | META_VADDR, // load/store only 29 | META_PADDR, // load/store only 30 | NUM_META 31 | } MetaKeys; 32 | 33 | endpackage 34 | 35 | 36 | 37 | `endif 38 | -------------------------------------------------------------------------------- /rtl/common/dpic.svh: -------------------------------------------------------------------------------- 1 | `ifndef __DPIC_SVH__ 2 | `define __DPIC_SVH__ 3 | 4 | `include "base.svh" 5 | 6 | import "DPI-C" function byte read_rom(uint64_t addr); 7 | 8 | // should call update_instMeta first 9 | import "DPI-C" function void update_instMeta( 10 | uint64_t instmeta, 11 | uint64_t key, 12 | uint64_t value 13 | ); 14 | import "DPI-C" function void update_instPos( 15 | uint64_t instmeta, 16 | uint64_t pos 17 | ); 18 | import "DPI-C" function void goto_fu( 19 | uint64_t instmeta, 20 | uint64_t fu_id 21 | ); 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | `endif 30 | -------------------------------------------------------------------------------- /rtl/common/funcs.svh: -------------------------------------------------------------------------------- 1 | `ifndef __FUNCS_SVH__ 2 | `define __FUNCS_SVH__ 3 | 4 | `include "base.svh" 5 | 6 | package funcs; 7 | 8 | function automatic int get_last_one_index(logic [31:0] a); 9 | for (int i = 31; i >= 0; i = i - 1) begin 10 | if (a[i]) begin 11 | return i + 1; 12 | end 13 | end 14 | return 0; 15 | endfunction 16 | 17 | function automatic int continuous_one(logic [31:0] a); 18 | int c = 0; 19 | for (int i = 0; i < 32; i = i + 1) begin 20 | if (a[i] == 0) begin 21 | return i; 22 | end 23 | end 24 | return 32; 25 | endfunction 26 | 27 | function automatic int count_one(logic [31:0] a); 28 | int c = 0; 29 | for (int i = 0; i < 32; i = i + 1) begin 30 | if (a[i]) begin 31 | c = c + 1; 32 | end 33 | end 34 | return c; 35 | endfunction 36 | 37 | 38 | endpackage 39 | 40 | 41 | 42 | `endif 43 | -------------------------------------------------------------------------------- /rtl/common/tilelink/tilelink.svh: -------------------------------------------------------------------------------- 1 | `ifndef __TILELINK_SVH__ 2 | `define __TILELINK_SVH__ 3 | 4 | `include "base.svh" 5 | 6 | 7 | 8 | package tilelink_enum; 9 | const logic [`WDEF(3)] Aopcode_get = 4; 10 | const logic [`WDEF(3)] Aopcode_putf = 0; 11 | const logic [`WDEF(3)] Aopcode_putp = 1; 12 | 13 | const logic [`WDEF(3)] Dopcode_ack = 0; // access ack 14 | const logic [`WDEF(3)] Dopcode_ackd = 1; // access ack data 15 | endpackage 16 | 17 | 18 | 19 | `endif 20 | -------------------------------------------------------------------------------- /rtl/common/tilelink/tilelink_if.sv: -------------------------------------------------------------------------------- 1 | `include "tilelink.svh" 2 | 3 | 4 | interface tilelink_if #( 5 | parameter int MASTERS = 2, 6 | parameter int SLAVES = 2, 7 | parameter int ADDR_WIDTH = 32, // bit 8 | parameter int DATA_WIDTH = 32 // Byte 9 | ); 10 | // A channel 11 | logic [`WDEF(3)] a_code; 12 | logic [`WDEF(3)] a_param; 13 | logic [`WDEF($clog2(DATA_WIDTH))] a_size; 14 | logic [`WDEF($clog2(MASTERS))] a_source; 15 | logic [`WDEF(ADDR_WIDTH)] a_address; 16 | logic [`WDEF(DATA_WIDTH)] a_mask; 17 | logic [`WDEF(DATA_WIDTH*8)] a_data; 18 | logic a_corrupt; 19 | logic a_valid; 20 | logic a_ready; 21 | 22 | // D channel 23 | logic [`WDEF(3)] d_opcode; 24 | logic [`WDEF(2)] d_param; 25 | logic [`WDEF($clog2(DATA_WIDTH))] d_size; 26 | logic [`WDEF($clog2(MASTERS))] d_source; 27 | logic [`WDEF($clog2(SLAVES))] d_sink; 28 | logic d_denied; 29 | logic [`WDEF(DATA_WIDTH*8)] d_data; 30 | logic d_corrupt; 31 | logic d_valid; 32 | logic d_ready; 33 | 34 | 35 | modport m( 36 | output a_code, 37 | output a_param, 38 | output a_size, 39 | output a_source, 40 | output a_address, 41 | output a_mask, 42 | output a_data, 43 | output a_corrupt, 44 | output a_valid, 45 | input a_ready, 46 | 47 | input d_opcode, 48 | input d_param, 49 | input d_size, 50 | input d_source, 51 | input d_sink, 52 | input d_denied, 53 | input d_data, 54 | input d_corrupt, 55 | input d_valid, 56 | output d_ready 57 | ); 58 | 59 | modport s( 60 | input a_code, 61 | input a_param, 62 | input a_size, 63 | input a_source, 64 | input a_address, 65 | input a_mask, 66 | input a_data, 67 | input a_corrupt, 68 | input a_valid, 69 | output a_ready, 70 | 71 | output d_opcode, 72 | output d_param, 73 | output d_size, 74 | output d_source, 75 | output d_sink, 76 | output d_denied, 77 | output d_data, 78 | output d_corrupt, 79 | output d_valid, 80 | input d_ready 81 | ); 82 | 83 | function int Ahandshake(); 84 | Ahandshake = a_valid && a_ready; 85 | endfunction 86 | 87 | function int Dhandshake(); 88 | Dhandshake = d_valid && d_ready; 89 | endfunction 90 | 91 | endinterface 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /rtl/cpu/aura_core.sv: -------------------------------------------------------------------------------- 1 | `include "core_define.svh" 2 | `include "backend_define.svh" 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | module aura_core ( 11 | input wire clk, 12 | input wire rst, 13 | 14 | // tilelink 0 15 | tilelink_if.m if_tilelink_bus0, 16 | // tilelink 1 17 | tilelink_if.m if_tilelink_bus1 18 | ); 19 | 20 | 21 | wire squash_vld; 22 | squashInfo_t squashInfo; 23 | 24 | wire [`WDEF(`BRU_NUM)] branchwb_vld; 25 | branchwbInfo_t branchwb_info[`BRU_NUM]; 26 | ftqIdx_t read_ftqIdx[`BRU_NUM + `LDU_NUM + `STU_NUM]; 27 | wire [`XDEF] read_ftqStartAddr[`BRU_NUM + `LDU_NUM + `STU_NUM]; 28 | wire [`XDEF] read_ftqNextAddr[`BRU_NUM + `LDU_NUM + `STU_NUM]; 29 | wire backend_stall; 30 | wire [`WDEF(`FETCH_WIDTH)] fetch_inst_vld; 31 | fetchEntry_t fetch_inst[`FETCH_WIDTH]; 32 | 33 | wire commit_ftq_vld; 34 | ftqIdx_t commit_ftqIdx; 35 | 36 | aura_frontend u_aura_frontend ( 37 | .clk(clk), 38 | .rst(rst), 39 | 40 | .i_squash_vld(squash_vld), 41 | .i_squashInfo(squashInfo), 42 | 43 | .i_branchwb_vld(branchwb_vld), 44 | .i_branchwbInfo(branchwb_info), 45 | 46 | .i_read_ftqIdx (read_ftqIdx), 47 | .o_read_ftqStartAddr(read_ftqStartAddr), 48 | .o_read_ftqNextAddr (read_ftqNextAddr), 49 | 50 | .i_backend_stall (backend_stall), 51 | .o_fetch_inst_vld(fetch_inst_vld), 52 | .o_fetch_inst (fetch_inst), 53 | 54 | .i_commit_vld (commit_ftq_vld), 55 | .i_commit_ftqIdx(commit_ftqIdx), 56 | 57 | .if_fetch_bus(if_tilelink_bus0) 58 | ); 59 | 60 | 61 | aura_backend u_aura_backend ( 62 | .clk(clk), 63 | .rst(rst), 64 | 65 | .o_squash_vld(squash_vld), 66 | .o_squashInfo(squashInfo), 67 | 68 | .o_branchwb_vld(branchwb_vld), 69 | .o_branchwbInfo(branchwb_info), 70 | 71 | .o_read_ftqIdx (read_ftqIdx), 72 | .i_read_ftqStartAddr(read_ftqStartAddr), 73 | .i_read_ftqNextAddr (read_ftqNextAddr), 74 | 75 | .o_stall (backend_stall), 76 | .i_inst_vld(fetch_inst_vld), 77 | .i_inst (fetch_inst), 78 | 79 | .o_commit_ftq_vld(commit_ftq_vld), 80 | .o_commit_ftqIdx (commit_ftqIdx) 81 | ); 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | endmodule 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /rtl/cpu/backend/block/generateIntFu.svh.tmp: -------------------------------------------------------------------------------- 1 | `ifdef YOU_NEED_DEFINE_THIS_MACRO 2 | // you must defined parameters outside: 3 | // IQ_FUID, BLK_FUID 4 | // optional macro: 5 | // HAS_SCU, HAS_BRU, HAS_MDU 6 | // you must assign here: 7 | // issueStall, wakeFromFu 8 | 9 | wire[`WDEF(`NUMSRCS_INT)] srcBypassed; 10 | wire[`XDEF] bypassedData[`NUMSRCS_INT]; 11 | wire[`XDEF] finalData[`NUMSRCS_INT]; 12 | wire[`XDEF] extendImm = {{44{s1_irob_imm[BLK_FUID][19]}},s1_irob_imm[BLK_FUID]}; 13 | 14 | // scu needed signals 15 | `ifdef HAS_SCU 16 | csrIdx_t scu_csrIdx; 17 | assign scu_csrIdx = s1_irob_imm[BLK_FUID][16:5]; 18 | wire[`WDEF(5)] scu_zimm = s1_irob_imm[BLK_FUID][4:0]; 19 | wire scu_write_csr = 20 | (s1_issueState[IQ_FUID].issueQueId == `SCUIQ_ID) && 21 | (s1_issueState[IQ_FUID].micOp >= MicOp_t::csrrw); 22 | 23 | assign if_csrrw.access = 24 | s1_issueVec[IQ_FUID] && (s1_issueState[IQ_FUID].issueQueId == `SCUIQ_ID) && 25 | (s1_issueState[IQ_FUID].micOp >= MicOp_t::csrrw); 26 | assign if_csrrw.read_idx = scu_csrIdx; 27 | `endif 28 | 29 | // bypass 30 | for (i=0;i<`NUMSRCS_INT;i=i+1) begin : gen_srcBypass 31 | bypass_sel 32 | #( 33 | .WIDTH ( `BYPASS_WIDTH ) 34 | ) 35 | u_bypass_sel( 36 | .rst ( rst ), 37 | .i_src_vld ( i_glob_bp_vec ), 38 | .i_src_idx ( i_glob_bp_iprd ), 39 | .i_src_data ( i_glob_bp_data ), 40 | .i_target_idx ( s1_issueState[IQ_FUID].iprs[i] ), 41 | .o_target_vld ( srcBypassed[i] ), 42 | .o_target_data ( bypassedData[i] ) 43 | ); 44 | end 45 | 46 | // select final data 47 | assign finalData[0] = 48 | srcBypassed[0] ? bypassedData[0] : 49 | i_iprs_data[BLK_FUID][0]; 50 | `ifdef HAS_SCU 51 | assign finalData[1] = 52 | s1_issueState[IQ_FUID].issueQueId == `SCUIQ_ID ? if_csrrw.read_val : 53 | s1_issueState[IQ_FUID].useImm ? extendImm : 54 | srcBypassed[1] ? bypassedData[1] : 55 | i_iprs_data[BLK_FUID][1]; 56 | `elsif HAS_MDU 57 | assign finalData[1] = 58 | srcBypassed[1] ? bypassedData[1] : 59 | i_iprs_data[BLK_FUID][1]; 60 | `else 61 | assign finalData[1] = 62 | (s1_issueState[IQ_FUID].useImm && s1_issueState[IQ_FUID].issueQueId == `ALUIQ_ID) ? extendImm : 63 | srcBypassed[1] ? bypassedData[1] : 64 | i_iprs_data[BLK_FUID][1]; 65 | `endif 66 | 67 | `ifdef HAS_BRU 68 | // read ftqStartAddr & nextAddr 69 | assign o_read_ftqIdx[IQ_FUID] = issueState[IQ_FUID].ftqIdx; 70 | // read ftqoffset 71 | assign o_read_robIdx[IQ_FUID] = issueState[IQ_FUID].robIdx; 72 | `endif 73 | 74 | `ifndef HAS_MDU 75 | // clear imm immediately after issue 76 | assign o_immB_clear_vld[BLK_FUID] = s1_issueVec[IQ_FUID] && s1_issueState[IQ_FUID].useImm; 77 | assign o_immB_clear_idx[BLK_FUID] = s1_issueState[IQ_FUID].irobIdx; 78 | `endif 79 | 80 | exeInfo_t exeInfo; 81 | assign exeInfo = '{ 82 | default : 0, 83 | ftqIdx : s1_issueState[IQ_FUID].ftqIdx, 84 | robIdx : s1_issueState[IQ_FUID].robIdx, 85 | irobIdx : s1_issueState[IQ_FUID].irobIdx, 86 | rdwen : s1_issueState[IQ_FUID].rdwen, 87 | iprd : s1_issueState[IQ_FUID].iprd, 88 | useImm : s1_issueState[IQ_FUID].useImm, 89 | issueQueId : s1_issueState[IQ_FUID].issueQueId, 90 | micOp : s1_issueState[IQ_FUID].micOp, 91 | srcs : finalData, 92 | `ifndef HAS_MDU 93 | imm20 : s1_irob_imm[BLK_FUID], 94 | `endif 95 | `ifdef HAS_BRU 96 | ftqOffset : i_read_ftqOffset[IQ_FUID], 97 | pc : i_read_ftqStartAddr[IQ_FUID] + i_read_ftqOffset[IQ_FUID], 98 | npc : i_read_ftqNextAddr[IQ_FUID], 99 | `endif 100 | seqNum : s1_issueState[IQ_FUID].seqNum 101 | }; 102 | 103 | // generate fu 104 | `ifdef HAS_SCU 105 | assign issueStall[IQ_FUID] = 0; 106 | assign wakeFromFu[IQ_FUID] = 0; 107 | alu_scu u_alu_scu( 108 | .clk ( clk ), 109 | .rst ( rst || i_squash_vld ), 110 | 111 | .o_fu_stall ( ), 112 | .i_vld ( s1_issueComplete[IQ_FUID] ), 113 | .i_fuInfo ( exeInfo ), 114 | 115 | .i_csr_pack ( i_csr_pack ), 116 | .i_illegal_access_csr ( if_csrrw.illegal ), 117 | .i_zimm ( scu_zimm ), 118 | .i_write_csr ( scu_write_csr ), 119 | .i_csrIdx ( scu_csrIdx ), 120 | 121 | .o_willwrite_vld ( bypass_vld[BLK_FUID] ), 122 | .o_willwrite_rdIdx ( bypass_iprd[BLK_FUID] ), 123 | .o_willwrite_data ( bypass_data[BLK_FUID] ), 124 | 125 | .o_has_except ( o_exceptwb_vld ), 126 | .o_exceptwbInfo ( o_exceptwb_info ), 127 | 128 | .i_wb_stall ( 0 ), 129 | .o_fu_finished ( fu_finished[BLK_FUID] ), 130 | .o_comwbInfo ( comwbInfo[BLK_FUID] ), 131 | 132 | .if_syscall ( if_syscall ), 133 | .o_write_csr ( if_csrrw.write ), 134 | .o_write_csrIdx ( if_csrrw.write_idx ), 135 | .o_write_new_csr ( if_csrrw.write_val ) 136 | ); 137 | `elsif HAS_BRU 138 | assign issueStall[IQ_FUID] = 0; 139 | assign wakeFromFu[IQ_FUID] = 0; 140 | alu_bru u_alu_bru( 141 | .clk ( clk ), 142 | .rst ( rst || i_squash_vld ), 143 | 144 | .o_fu_stall ( ), 145 | .i_vld ( s1_issueComplete[IQ_FUID] ), 146 | .i_fuInfo ( exeInfo ), 147 | 148 | .o_willwrite_vld ( bypass_vld[BLK_FUID] ), 149 | .o_willwrite_rdIdx ( bypass_iprd[BLK_FUID] ), 150 | .o_willwrite_data ( bypass_data[BLK_FUID] ), 151 | 152 | .i_wb_stall ( 0 ), 153 | .o_fu_finished ( fu_finished[BLK_FUID] ), 154 | .o_comwbInfo ( comwbInfo[BLK_FUID] ), 155 | 156 | .o_branchwb_vld ( o_branchWB_vld[IQ_FUID] ), 157 | .o_branchwbInfo ( o_branchwb_info[IQ_FUID] ) 158 | ); 159 | `elsif HAS_MDU 160 | unimplemented 161 | `else 162 | assign issueStall[IQ_FUID] = 0; 163 | assign wakeFromFu[IQ_FUID] = 0; 164 | alu u_alu( 165 | .clk ( clk ), 166 | .rst ( rst || i_squash_vld ), 167 | 168 | .o_fu_stall ( ), 169 | .i_vld ( s1_issueComplete[IQ_FUID] ), 170 | .i_fuInfo ( exeInfo ), 171 | 172 | .o_willwrite_vld ( bypass_vld[BLK_FUID] ), 173 | .o_willwrite_rdIdx ( bypass_iprd[BLK_FUID] ), 174 | .o_willwrite_data ( bypass_data[BLK_FUID] ), 175 | 176 | .i_wb_stall ( 0 ), 177 | .o_fu_finished ( fu_finished[BLK_FUID] ), 178 | .o_comwbInfo ( comwbInfo[BLK_FUID] ) 179 | ); 180 | `endif 181 | 182 | `endif 183 | -------------------------------------------------------------------------------- /rtl/cpu/backend/block/generateIntIQ.svh.tmp: -------------------------------------------------------------------------------- 1 | `ifdef YOU_NEED_DEFINE_THIS_MACRO 2 | // must defined parameters outside: 3 | // IQ_SIZE, IQ_INOUT, PORT_OFFSET 4 | // you must defined signals outside: 5 | // canEnq, enqReq, enqMicroOp, enqIprsRdy 6 | // optional macro: 7 | // NEED_IMM 8 | 9 | wire[`WDEF(IQ_INOUT)] issueStall; 10 | wire[`WDEF(IQ_INOUT)] issueVec; 11 | issueState_t issueState[IQ_INOUT]; 12 | 13 | wire[`WDEF(IQ_INOUT)] issueSuccess; 14 | wire[`WDEF(IQ_INOUT)] issueReplay; 15 | wire[`WDEF($clog2(IQ_SIZE))] feedbackIdx[IQ_INOUT]; 16 | 17 | reg[`WDEF(IQ_INOUT)] s1_issueComplete; 18 | reg[`WDEF(IQ_INOUT)] s1_issueVec; 19 | issueState_t s1_issueState[IQ_INOUT]; 20 | 21 | logic[`WDEF(IQ_INOUT)] cancelled; 22 | logic[`WDEF(IQ_INOUT)] s1_cancelled; 23 | 24 | wire[`WDEF(IQ_INOUT)] wakeFromFu; 25 | iprIdx_t wakeFromFuIprd[IQ_INOUT]; 26 | 27 | issueQue 28 | #( 29 | .DEPTH ( IQ_SIZE ), 30 | .INOUTPORT_NUM ( IQ_INOUT ), 31 | .EXTERNAL_WAKEUPNUM ( `INTWAKE_WIDTH ) 32 | ) 33 | u_issueQue ( 34 | .clk ( clk ), 35 | .rst ( rst || i_squash_vld ), 36 | 37 | .o_can_enq ( canEnq ), 38 | .i_enq_req ( enqReq ), 39 | .i_microOp ( enqMicroOp ), 40 | .i_enq_iprs_rdy ( enqIprsRdy ), 41 | 42 | .i_fu_busy ( issueStall ), 43 | .o_can_issue ( issueVec ), 44 | .o_issueState ( issueState ), 45 | 46 | .i_issueSuccess ( issueSuccess ), 47 | .i_issueReplay ( issueReplay ), 48 | .i_feedbackIdx ( feedbackIdx ), 49 | 50 | .if_loadwake ( if_loadwake ), 51 | .i_ext_wk_vec ( wake_vec ), 52 | .i_ext_wk_iprd ( wake_iprd ), 53 | .i_ext_wk_lpv ( wake_lpv ) 54 | ); 55 | 56 | 57 | for (i=0;i cur_mode); 109 | 110 | assign o_read_val = (i_access && (`GETMODE(i_read_csrIdx) <= cur_mode)) ? csr_mapping[i_read_csrIdx] : 0; 111 | 112 | 113 | assign o_priv_sysInfo = '{ 114 | mode : cur_mode, 115 | status : mstatus, 116 | epc : mepc, 117 | interrupt_vectored : (mtvec.mode == 1), 118 | tvec : {mtvec.base, 2'b00} 119 | }; 120 | 121 | endmodule 122 | -------------------------------------------------------------------------------- /rtl/cpu/backend/decode/decode.sv: -------------------------------------------------------------------------------- 1 | `include "core_define.svh" 2 | 3 | 4 | // DESIGN: 5 | // (1) if we found one inst is unknow: 6 | // let inst take the except code 7 | // check except at commit 8 | // (2) if we found one inst need serialize: 9 | // let inst take the serialize code 10 | // at dispatch: wait for rob is empty 11 | // stall pipeline, wait for rob commit signal 12 | 13 | //TODO: finish above 14 | 15 | 16 | // TODO: 17 | // we may need to implement lui-load imm bypassing 18 | // lui x1,123; ld x2,1(x1) => ld x2,(123<<12)+1 19 | module decode ( 20 | input wire clk, 21 | input wire rst, 22 | 23 | // from rename 24 | input wire i_stall, 25 | // squash 26 | input wire i_squash_vld, 27 | 28 | // from fetchBuffer 29 | // which inst need to deq from fetchbuffer 30 | output wire [`WDEF(`DECODE_WIDTH)] o_can_deq, 31 | input wire [`WDEF(`DECODE_WIDTH)] i_inst_vld, 32 | input fetchEntry_t i_inst[`DECODE_WIDTH], 33 | // to rename 34 | output reg [`WDEF(`DECODE_WIDTH)] o_decinfo_vld, 35 | output decInfo_t o_decinfo[`DECODE_WIDTH] 36 | ); 37 | genvar i; 38 | 39 | wire [`WDEF(`DECODE_WIDTH)] unKnown_inst; 40 | decInfo_t temp[`DECODE_WIDTH]; 41 | wire [`WDEF(`DECODE_WIDTH)] temp_val; 42 | generate 43 | for (i = 0; i < `DECODE_WIDTH; i = i + 1) begin : gen_decode 44 | decoder u_decoder ( 45 | .i_inst (i_inst[i].inst), 46 | .o_unkown_inst(unKnown_inst[i]), 47 | .o_decinfo (temp[i]) 48 | ); 49 | assign temp_val[i] = i_inst[i].has_except; 50 | end 51 | endgenerate 52 | 53 | 54 | reg [`WDEF(`RENAME_WIDTH)] decinfo_vld; 55 | decInfo_t decinfo[`DECODE_WIDTH]; 56 | always_ff @(posedge clk) begin 57 | int fa; 58 | if (rst || i_squash_vld) begin 59 | decinfo_vld <= 0; 60 | end 61 | else if (!i_stall) begin 62 | decinfo_vld <= i_inst_vld; 63 | for (fa = 0; fa < `DECODE_WIDTH; fa = fa + 1) begin 64 | decinfo[fa] <= '{ 65 | foldpc : i_inst[fa].foldpc, 66 | ftq_idx : i_inst[fa].ftq_idx, 67 | ftqOffset : i_inst[fa].ftqOffset, 68 | has_except : (unKnown_inst[fa] || temp_val[fa]), 69 | except : i_inst[fa].has_except ? i_inst[fa].except : rv_trap_t::instIllegal, 70 | isRVC : temp[fa].isRVC, 71 | ismv : temp[fa].ismv, 72 | imm20 : temp[fa].imm20, 73 | need_serialize : temp[fa].need_serialize, 74 | rd_wen : temp[fa].rd_wen, 75 | ilrd_idx : temp[fa].ilrd_idx, 76 | ilrs_idx : temp[fa].ilrs_idx, 77 | use_imm : temp[fa].use_imm, 78 | dispQue_id : temp[fa].dispQue_id, 79 | issueQue_id : temp[fa].issueQue_id, 80 | micOp_type : temp[fa].micOp_type, 81 | isStore : temp[fa].isStore, 82 | 83 | instmeta : i_inst[fa].instmeta 84 | }; 85 | if (i_inst_vld[fa]) begin 86 | update_instMeta(i_inst[fa].instmeta, difftest_def::META_ISBRANCH, 87 | (temp[fa].dispQue_id == `INTBLOCK_ID) && (temp[fa].issueQue_id == `BRUIQ_ID) && (temp[fa].micOp_type > MicOp_t::auipc && temp[fa].micOp_type <= MicOp_t::bgeu)); 88 | update_instMeta(i_inst[fa].instmeta, difftest_def::META_ISLOAD, 89 | (temp[fa].dispQue_id == `MEMBLOCK_ID) && (temp[fa].issueQue_id == `LDUIQ_ID)); 90 | update_instMeta(i_inst[fa].instmeta, difftest_def::META_ISSTORE, 91 | (temp[fa].dispQue_id == `MEMBLOCK_ID) && (temp[fa].issueQue_id == `STUIQ_ID)); 92 | update_instMeta(i_inst[fa].instmeta, difftest_def::META_ISMV, temp[fa].ismv); 93 | 94 | update_instPos(i_inst[fa].instmeta, difftest_def::AT_decode); 95 | end 96 | end 97 | end 98 | end 99 | assign o_can_deq = i_stall ? 0 : i_inst_vld; 100 | 101 | assign o_decinfo_vld = decinfo_vld; 102 | assign o_decinfo = decinfo; 103 | 104 | endmodule 105 | 106 | -------------------------------------------------------------------------------- /rtl/cpu/backend/decode_define.svh: -------------------------------------------------------------------------------- 1 | `ifndef __DECODE_DEFINE_SVH__ 2 | `define __DECODE_DEFINE_SVH__ 3 | 4 | `include "core_config.svh" 5 | 6 | //addi xn,xn,0 空指令 7 | 8 | //32位指令开头 9 | `define OPC_TYPE32 2'b11 10 | 11 | //需要计算 12 | //需要写rd 13 | //alu_b位为imm 14 | `define OPC_LUI 5'b01101 // rd = imm 15 | `define OPC_AUIPC 5'b00101 // rd = pc + imm 16 | /*****************************************************/ //无条件跳转 17 | `define OPC_JAL 5'b11011 // rd = pc + 4; pc += imm 18 | `define OPC_JALR 5'b11001 // rd = pc+4;pc= ( rs1 + imm ) & ~1; 19 | /*****************************************************/ //branch 20 | `define OPC_BRANCH 5'b11000 21 | `define FUNC_BEQ 3'b000 // if(rs1 == rs2) pc += imm; => if(rs1-rs2=0) 22 | `define FUNC_BNE 3'b001 // if(rs1 != rs2) pc += imm; => if(rs1-rs2) 23 | `define FUNC_BLT 3'b100 // if(rs1 < rs2) => if(rs1 < rs2) 24 | `define FUNC_BGE 3'b101 // if(rs1 >= rs2) pc += imm; => if(!(rs1 < rs2)) 25 | `define FUNC_BLTU 3'b110 // if(rs1 if(rs1 =u rs2) => if(!(rs1 > shifter); 9 | wire[`XDEF] sra = (({64{src0[63]}} << (7'd64 - {1'b0, shifter})) | (src0 >> shifter)); 10 | 11 | wire[`WDEF(32)] sllw_ = (src0[31:0] << shifter[4:0]); 12 | wire[`WDEF(32)] srlw_ = (src0[31:0] >> shifter[4:0]); 13 | 14 | wire[`XDEF] sllw = {{32{sllw_[31]}},sllw_[31:0]}; 15 | wire[`XDEF] srlw = {{32{srlw_[31]}},srlw_[31:0]}; 16 | wire[`XDEF] sraw = (({64{src0[31]}} << (6'd31 - {1'b0, shifter[4:0]})) | (src0[31:0] >> shifter[4:0])); 17 | 18 | wire[`XDEF] _xor = src0 ^ src1; 19 | wire[`XDEF] _or = src0 | src1; 20 | wire[`XDEF] _and = src0 & src1; 21 | // signed 22 | // src0 < src1 (src0 - src1 < 0) 23 | wire[`XDEF] slt = {63'd0,sub[63]}; 24 | // unsigned 25 | // src0 > src1 : fasle : src0 - src1 > 0 26 | wire[`XDEF] sltu = src0 < src1; 27 | 28 | wire[`XDEF] calc_data = 29 | (saved_fuInfo.micOp == MicOp_t::lui) ? lui : 30 | (saved_fuInfo.micOp == MicOp_t::add) ? add : 31 | (saved_fuInfo.micOp == MicOp_t::sub) ? sub : 32 | (saved_fuInfo.micOp == MicOp_t::addw) ? addw : 33 | (saved_fuInfo.micOp == MicOp_t::subw) ? subw : 34 | (saved_fuInfo.micOp == MicOp_t::sll) ? sll : 35 | (saved_fuInfo.micOp == MicOp_t::srl) ? srl : 36 | (saved_fuInfo.micOp == MicOp_t::sra) ? sra : 37 | (saved_fuInfo.micOp == MicOp_t::sllw) ? sllw : 38 | (saved_fuInfo.micOp == MicOp_t::srlw) ? srlw : 39 | (saved_fuInfo.micOp == MicOp_t::sraw) ? sraw : 40 | (saved_fuInfo.micOp == MicOp_t::_xor) ? _xor : 41 | (saved_fuInfo.micOp == MicOp_t::_or) ? _or : 42 | (saved_fuInfo.micOp == MicOp_t::_and) ? _and : 43 | (saved_fuInfo.micOp == MicOp_t::slt) ? slt : 44 | (saved_fuInfo.micOp == MicOp_t::sltu) ? sltu : 45 | 0; 46 | -------------------------------------------------------------------------------- /rtl/cpu/backend/fu/alu_bru.sv: -------------------------------------------------------------------------------- 1 | 2 | `include "core_define.svh" 3 | 4 | module alu_bru ( 5 | input wire clk, 6 | input wire rst, 7 | 8 | output wire o_fu_stall, 9 | //ctrl info 10 | input wire i_vld, 11 | input exeInfo_t i_fuInfo, 12 | 13 | // export bypass 14 | output wire o_willwrite_vld, 15 | output iprIdx_t o_willwrite_rdIdx, 16 | output wire [`XDEF] o_willwrite_data, 17 | 18 | //wb, rd_idx will be used to fast bypass 19 | input wire i_wb_stall, 20 | output wire o_fu_finished, 21 | output comwbInfo_t o_comwbInfo, 22 | output wire o_branchwb_vld, 23 | output branchwbInfo_t o_branchwbInfo 24 | ); 25 | reg saved_vld; 26 | exeInfo_t saved_fuInfo; 27 | 28 | always_ff @(posedge clk) begin : blockName 29 | if (rst == true) begin 30 | saved_vld <= 0; 31 | end 32 | else if (!i_wb_stall) begin 33 | saved_vld <= i_vld; 34 | saved_fuInfo <= i_fuInfo; 35 | if (i_vld) begin 36 | update_instPos(i_fuInfo.seqNum, difftest_def::AT_fu); 37 | end 38 | end 39 | end 40 | 41 | 42 | wire [`XDEF] src0 = saved_fuInfo.srcs[0]; 43 | wire [`XDEF] src1 = saved_fuInfo.srcs[1]; 44 | 45 | /****************************************************************************************************/ 46 | // alu 47 | /****************************************************************************************************/ 48 | 49 | `include "alu.svh.tmp" 50 | 51 | /****************************************************************************************************/ 52 | // bru 53 | /****************************************************************************************************/ 54 | wire isauipc = (saved_fuInfo.issueQueId == `BRUIQ_ID) && (saved_fuInfo.micOp == MicOp_t::auipc); 55 | wire isbranch = (saved_fuInfo.issueQueId == `BRUIQ_ID) && (saved_fuInfo.micOp > MicOp_t::auipc && saved_fuInfo.micOp <= MicOp_t::bgeu); 56 | 57 | 58 | wire [`XDEF] pc = saved_fuInfo.pc; 59 | wire [`XDEF] pred_npc = saved_fuInfo.npc; 60 | wire [`XDEF] fallthru = saved_fuInfo.pc + 4; 61 | wire [`XDEF] imm20 = {{44{saved_fuInfo.imm20[19]}}, saved_fuInfo.imm20}; 62 | wire [`XDEF] auipc_imm = {{32{saved_fuInfo.imm20[19]}}, saved_fuInfo.imm20, 12'b0}; 63 | wire [`XDEF] auipc = pc + auipc_imm; 64 | 65 | wire [`XDEF] jal_target = pc + imm20; 66 | wire [`XDEF] jalr_target = src0 + imm20; 67 | wire [`XDEF] br_target = pc + imm20; 68 | 69 | wire beq_taken = (src0 == src1); 70 | wire bne_taken = !beq_taken; 71 | wire blt_taken = slt; 72 | wire bge_taken = !blt_taken; 73 | wire bltu_taken = sltu; 74 | wire bgeu_taken = !bltu_taken; 75 | 76 | wire taken = 77 | (saved_fuInfo.micOp == MicOp_t::jal) ? 1 : 78 | (saved_fuInfo.micOp == MicOp_t::jalr) ? 1 : 79 | (saved_fuInfo.micOp == MicOp_t::beq) ? beq_taken : 80 | (saved_fuInfo.micOp == MicOp_t::bne) ? bne_taken : 81 | (saved_fuInfo.micOp == MicOp_t::blt) ? blt_taken : 82 | (saved_fuInfo.micOp == MicOp_t::bge) ? bge_taken : 83 | (saved_fuInfo.micOp == MicOp_t::bltu) ? bltu_taken : 84 | (saved_fuInfo.micOp == MicOp_t::bgeu) ? bgeu_taken : 85 | 0; 86 | 87 | wire[`XDEF] target = 88 | (saved_fuInfo.micOp == MicOp_t::jal) ? jal_target : 89 | (saved_fuInfo.micOp == MicOp_t::jalr) ? jalr_target : 90 | br_target; 91 | 92 | wire [`XDEF] npc = taken ? target : fallthru; 93 | 94 | wire mispred = isbranch && (npc != pred_npc); 95 | //TODO: remove it 96 | BranchType::_ branch_type; 97 | assign branch_type = 98 | ((saved_fuInfo.micOp == MicOp_t::jalr) && (saved_fuInfo.iprd == 1)) ? BranchType::isCall : 99 | ((saved_fuInfo.micOp == MicOp_t::jalr) && (saved_fuInfo.iprd == 0)) ? BranchType::isRet : //FIXME: iprs[0] should is 1 100 | (saved_fuInfo.micOp == MicOp_t::jalr) ? BranchType::isIndirect : 101 | (saved_fuInfo.micOp == MicOp_t::jal) ? BranchType::isDirect : 102 | ((saved_fuInfo.micOp >= MicOp_t::beq) && (saved_fuInfo.micOp <= MicOp_t::bgeu)) ? BranchType::isCond : 103 | BranchType::isNone; 104 | 105 | reg fu_finished; 106 | comwbInfo_t comwbInfo; 107 | reg branchwb_vld; 108 | branchwbInfo_t branchwb_info; 109 | always_ff @(posedge clk) begin 110 | if (rst) begin 111 | fu_finished <= 0; 112 | branchwb_vld <= 0; 113 | end 114 | else if (!i_wb_stall) begin 115 | fu_finished <= saved_vld; 116 | comwbInfo.rob_idx <= saved_fuInfo.robIdx; 117 | comwbInfo.irob_idx <= saved_fuInfo.irobIdx; 118 | comwbInfo.use_imm <= saved_fuInfo.useImm; 119 | comwbInfo.rd_wen <= saved_fuInfo.rdwen; 120 | comwbInfo.iprd_idx <= saved_fuInfo.iprd; 121 | comwbInfo.result <= o_willwrite_data; 122 | if (saved_vld) begin 123 | assert (saved_fuInfo.issueQueId == `ALUIQ_ID || saved_fuInfo.issueQueId == `BRUIQ_ID); 124 | update_instPos(saved_fuInfo.seqNum, difftest_def::AT_wb); 125 | end 126 | 127 | // jal must be not mispred 128 | assert ((saved_vld && mispred) ? (saved_fuInfo.micOp != MicOp_t::jal) : 1); 129 | // only writeback when mispred 130 | branchwb_vld <= saved_vld && isbranch; 131 | branchwb_info <= '{ 132 | branch_type : branch_type, 133 | rob_idx : saved_fuInfo.robIdx, 134 | ftq_idx : saved_fuInfo.ftqIdx, 135 | has_mispred : mispred, 136 | branch_taken : taken, 137 | //FIXME: fallthruAddr should always point to branch_pc + 4/2 138 | fallthruOffset : 139 | saved_fuInfo.ftqOffset 140 | + 4, 141 | target_pc : target, 142 | branch_npc : npc 143 | }; 144 | if (saved_vld && isbranch) begin 145 | update_instMeta(saved_fuInfo.seqNum, difftest_def::META_NPC, npc); 146 | end 147 | if (saved_vld && mispred) begin 148 | update_instMeta(saved_fuInfo.seqNum, difftest_def::META_MISPRED, 1); 149 | end 150 | end 151 | end 152 | 153 | assign o_willwrite_vld = saved_vld && saved_fuInfo.rdwen; 154 | assign o_willwrite_rdIdx = saved_fuInfo.iprd; 155 | assign o_willwrite_data = isbranch ? fallthru : isauipc ? auipc : calc_data; 156 | 157 | assign o_fu_stall = i_wb_stall; 158 | assign o_fu_finished = fu_finished; 159 | assign o_comwbInfo = comwbInfo; 160 | assign o_branchwb_vld = branchwb_vld; 161 | assign o_branchwbInfo = branchwb_info; 162 | 163 | 164 | 165 | endmodule 166 | -------------------------------------------------------------------------------- /rtl/cpu/backend/fu/alu_scu.sv: -------------------------------------------------------------------------------- 1 | 2 | `include "core_define.svh" 3 | 4 | module alu_scu ( 5 | input wire clk, 6 | input wire rst, 7 | 8 | output wire o_fu_stall, 9 | //ctrl info 10 | input wire i_vld, 11 | input exeInfo_t i_fuInfo, 12 | 13 | input csr_in_pack_t i_csr_pack, 14 | input wire i_illegal_access_csr, // illegal access csr 15 | input wire [`WDEF(5)] i_zimm, 16 | input wire i_write_csr, 17 | input csrIdx_t i_csrIdx, 18 | 19 | // export bypass 20 | output wire o_willwrite_vld, 21 | output iprIdx_t o_willwrite_rdIdx, 22 | output wire [`XDEF] o_willwrite_data, 23 | 24 | // exception wb 25 | output wire o_has_except, 26 | output exceptwbInfo_t o_exceptwbInfo, 27 | 28 | //wb, rd_idx will be used to fast bypass 29 | input wire i_wb_stall, 30 | output wire o_fu_finished, 31 | output comwbInfo_t o_comwbInfo, 32 | 33 | syscall_if.m if_syscall, 34 | output wire o_write_csr, 35 | output csrIdx_t o_write_csrIdx, 36 | output wire [`XDEF] o_write_new_csr 37 | ); 38 | reg illegal_csr; 39 | 40 | reg [`WDEF(5)] zimm; 41 | reg write_csr; // rs1 != 0 42 | csrIdx_t saved_csrIdx; 43 | reg saved_vld; 44 | exeInfo_t saved_fuInfo; 45 | 46 | always_ff @(posedge clk) begin : blockName 47 | if (rst) begin 48 | illegal_csr <= 0; 49 | write_csr <= 0; 50 | saved_vld <= 0; 51 | end 52 | else if (!i_wb_stall) begin 53 | illegal_csr <= i_illegal_access_csr; 54 | 55 | zimm <= i_zimm; 56 | write_csr <= i_write_csr && !i_illegal_access_csr; 57 | saved_csrIdx <= i_csrIdx; 58 | 59 | saved_vld <= i_vld; 60 | saved_fuInfo <= i_fuInfo; 61 | if (i_vld) begin 62 | update_instPos(i_fuInfo.seqNum, difftest_def::AT_fu); 63 | end 64 | end 65 | end 66 | 67 | 68 | wire [`XDEF] src0 = saved_fuInfo.srcs[0]; 69 | wire [`XDEF] src1 = saved_fuInfo.srcs[1]; 70 | 71 | `include "alu.svh.tmp" 72 | 73 | wire [`XDEF] csr_val = src1; 74 | wire use_zimm = (saved_fuInfo.micOp > MicOp_t::csrrs); 75 | wire [`XDEF] n_src0 = use_zimm ? {59'd0, zimm} : src0; 76 | wire [`XDEF] new_csr; 77 | wire [`XDEF] csr_w = n_src0; 78 | wire [`XDEF] csr_c = csr_val & (~n_src0); 79 | wire [`XDEF] csr_s = csr_val | n_src0; 80 | 81 | assign new_csr = 82 | (saved_fuInfo.micOp == MicOp_t::csrrw) || (saved_fuInfo.micOp == MicOp_t::csrrwi) ? csr_w : 83 | (saved_fuInfo.micOp == MicOp_t::csrrc) || (saved_fuInfo.micOp == MicOp_t::csrrci) ? csr_c : 84 | (saved_fuInfo.micOp == MicOp_t::csrrs) || (saved_fuInfo.micOp == MicOp_t::csrrsi) ? csr_s : 85 | 0; 86 | 87 | wire[`XDEF] final_result = 88 | (saved_fuInfo.issueQueId == `ALUIQ_ID) ? calc_data : 89 | (saved_fuInfo.issueQueId == `SCUIQ_ID) ? csr_val : 0; 90 | 91 | wire ecall = (saved_fuInfo.issueQueId == `SCUIQ_ID) && (saved_fuInfo.micOp == MicOp_t::ecall); 92 | wire ebreak = (saved_fuInfo.issueQueId == `SCUIQ_ID) && (saved_fuInfo.micOp == MicOp_t::ebreak); 93 | // NOTE: mret/sret do not cause except if permission is legal 94 | wire mret = (saved_fuInfo.issueQueId == `SCUIQ_ID) && (saved_fuInfo.micOp == MicOp_t::mret); 95 | wire sret = (saved_fuInfo.issueQueId == `SCUIQ_ID) && (saved_fuInfo.micOp == MicOp_t::sret); 96 | wire illegal_eret = mret ? i_csr_pack.mode < `MODE_M : sret ? i_csr_pack.mode < `MODE_S : 0; 97 | 98 | wire sysexcept = (saved_fuInfo.issueQueId == `SCUIQ_ID) && (ecall || ebreak); 99 | rv_trap_t::exception syscall_except; 100 | assign syscall_except = 101 | ecall ? (rv_trap_t::ucall + i_csr_pack.mode) : 102 | ebreak ? rv_trap_t::breakpoint : 103 | rv_trap_t::breakpoint; 104 | 105 | wire instIllegal = illegal_csr || illegal_eret; 106 | 107 | reg _has_except; 108 | exceptwbInfo_t exceptwbInfo; 109 | 110 | reg fu_finished; 111 | comwbInfo_t comwbInfo; 112 | reg _write_csr; 113 | csrIdx_t _write_csrIdx; 114 | reg [`XDEF] _new_csr; 115 | always_ff @(posedge clk) begin 116 | if (rst) begin 117 | _has_except <= 0; 118 | _write_csr <= 0; 119 | fu_finished <= 0; 120 | end 121 | else if (!i_wb_stall) begin 122 | fu_finished <= saved_vld; 123 | comwbInfo.rob_idx <= saved_fuInfo.robIdx; 124 | comwbInfo.irob_idx <= saved_fuInfo.irobIdx; 125 | comwbInfo.use_imm <= saved_fuInfo.useImm; 126 | comwbInfo.rd_wen <= saved_fuInfo.rdwen; 127 | comwbInfo.iprd_idx <= saved_fuInfo.iprd; 128 | comwbInfo.result <= final_result; 129 | 130 | _has_except <= saved_vld && (instIllegal || sysexcept); 131 | exceptwbInfo <= '{ 132 | default: 0, 133 | rob_idx : saved_fuInfo.robIdx, 134 | except_type : instIllegal ? rv_trap_t::instIllegal : sysexcept ? syscall_except : 0 135 | }; 136 | 137 | _write_csr <= saved_vld && write_csr; 138 | _write_csrIdx <= saved_csrIdx; 139 | _new_csr <= new_csr; 140 | if (saved_vld) begin 141 | assert (saved_fuInfo.issueQueId == `ALUIQ_ID || saved_fuInfo.issueQueId == `SCUIQ_ID); 142 | update_instPos(saved_fuInfo.seqNum, difftest_def::AT_wb); 143 | end 144 | end 145 | end 146 | 147 | assign o_willwrite_vld = saved_vld && saved_fuInfo.rdwen; 148 | assign o_willwrite_rdIdx = saved_fuInfo.iprd; 149 | assign o_willwrite_data = calc_data; 150 | 151 | assign o_fu_stall = i_wb_stall; 152 | assign o_fu_finished = fu_finished; 153 | assign o_comwbInfo = comwbInfo; 154 | 155 | assign o_has_except = _has_except; 156 | assign o_exceptwbInfo = exceptwbInfo; 157 | 158 | assign o_write_csr = _write_csr; 159 | assign o_write_csrIdx = _write_csrIdx; 160 | assign o_write_new_csr = _new_csr; 161 | 162 | 163 | // system call/ret 164 | reg _mret; 165 | reg _sret; 166 | reg [`XDEF] eret_pc; 167 | 168 | 169 | always_ff @(posedge clk) begin 170 | if (rst) begin 171 | _mret <= 0; 172 | _sret <= 0; 173 | end 174 | else if (saved_vld) begin 175 | _mret <= saved_vld && (saved_fuInfo.issueQueId == `SCUIQ_ID) && (saved_fuInfo.micOp == MicOp_t::mret); 176 | _sret <= saved_vld && (saved_fuInfo.issueQueId == `SCUIQ_ID) && (saved_fuInfo.micOp == MicOp_t::sret); 177 | eret_pc <= i_csr_pack.epc; 178 | end 179 | else begin 180 | _mret <= 0; 181 | _sret <= 0; 182 | end 183 | end 184 | 185 | assign if_syscall.rob_idx = comwbInfo.rob_idx; 186 | assign if_syscall.mret = _mret; 187 | assign if_syscall.sret = _sret; 188 | assign if_syscall.npc = eret_pc; 189 | 190 | endmodule 191 | -------------------------------------------------------------------------------- /rtl/cpu/backend/issue/age_schedule.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | `include "funcs.svh" 3 | 4 | 5 | module age_schedule #( 6 | parameter int WIDTH = 16, 7 | parameter int OUTS = 2 8 | ) ( 9 | input wire clk, 10 | input wire rst, 11 | 12 | input wire [`WDEF(WIDTH)] i_vld, 13 | input robIdx_t i_ages[WIDTH], 14 | 15 | output wire [`WDEF(OUTS)] o_vld, 16 | output wire [`WDEF($clog2(WIDTH))] o_sel_idx[OUTS] 17 | ); 18 | genvar i; 19 | /* verilator lint_off UNOPTFLAT */ 20 | logic [`WDEF(WIDTH)] entry_selected[OUTS]; 21 | logic [`WDEF($clog2(WIDTH))] find_idx[OUTS]; 22 | 23 | 24 | generate 25 | for (i = 0; i < OUTS; i = i + 1) begin : gen_select 26 | wire [`WDEF(WIDTH)] tofind_vld; 27 | if (i == 0) begin 28 | assign tofind_vld = i_vld; 29 | end 30 | else begin 31 | assign tofind_vld = i_vld & (~entry_selected[i-1]); 32 | end 33 | robIdx_t rob_idx; 34 | logic [`WDEF($clog2(WIDTH))] sel_idx; 35 | logic find_vld; 36 | 37 | oldest_select #( 38 | .WIDTH(WIDTH), 39 | .dtype(robIdx_t) 40 | ) u_oldest_select ( 41 | .i_vld (tofind_vld), 42 | .i_rob_idx (i_ages), 43 | .i_datas (i_ages), 44 | .o_oldest_rob_idx(rob_idx) 45 | ); 46 | assign o_vld[i] = find_vld; 47 | assign o_sel_idx[i] = sel_idx; 48 | 49 | logic [`WDEF(WIDTH)] temp; 50 | always_comb begin 51 | int ca; 52 | if (i == 0) begin 53 | entry_selected[i] = 0; 54 | end 55 | else begin 56 | entry_selected[i] = entry_selected[i-1]; 57 | end 58 | sel_idx = 0; 59 | find_vld = 0; 60 | temp = 0; 61 | for (ca = 0; ca <= WIDTH; ca = ca + 1) begin 62 | if (tofind_vld[ca] && (i_ages[ca] == rob_idx)) begin 63 | entry_selected[i][ca] = 1; 64 | sel_idx = ca; 65 | find_vld = 1; 66 | temp[ca] = 1; 67 | end 68 | end 69 | end 70 | `ASSERT(funcs::count_one(temp) < 2); 71 | end 72 | endgenerate 73 | 74 | 75 | 76 | endmodule 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /rtl/cpu/backend/issue/issueport_if.sv: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | interface issueport_if; 6 | 7 | 8 | 9 | 10 | endinterface 11 | -------------------------------------------------------------------------------- /rtl/cpu/backend/link/csrrw_if.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | // scu -> csr regs 4 | interface csrrw_if; 5 | // read channel 6 | logic access; 7 | csrIdx_t read_idx; 8 | logic illegal; 9 | logic [`XDEF] read_val; 10 | // write channel 11 | logic write; 12 | csrIdx_t write_idx; 13 | logic [`XDEF] write_val; 14 | 15 | modport m( 16 | output access, 17 | output read_idx, 18 | input illegal, 19 | input read_val, 20 | 21 | output write, 22 | output write_idx, 23 | output write_val 24 | ); 25 | 26 | modport s( 27 | input access, 28 | input read_idx, 29 | output illegal, 30 | output read_val, 31 | 32 | input write, 33 | input write_idx, 34 | input write_val 35 | ); 36 | 37 | endinterface 38 | 39 | -------------------------------------------------------------------------------- /rtl/cpu/backend/link/disp_if.sv: -------------------------------------------------------------------------------- 1 | 2 | `include "backend_define.svh" 3 | 4 | 5 | 6 | 7 | // dispatch -> exeBlock 8 | interface disp_if; 9 | // req -> exeBlock 10 | // rdy -> dispatch 11 | 12 | // from/to int block 13 | logic [`WDEF(`INTDQ_DISP_WID)] int_req; 14 | logic [`WDEF(`INTDQ_DISP_WID)] int_rdy; 15 | microOp_t int_info[`INTDQ_DISP_WID]; 16 | 17 | // from/to mem block 18 | logic [`WDEF(`MEMDQ_DISP_WID)] mem_req; 19 | logic [`WDEF(`MEMDQ_DISP_WID)] mem_rdy; 20 | microOp_t mem_info[`MEMDQ_DISP_WID]; 21 | 22 | modport m(output int_req, input int_rdy, output int_info, output mem_req, input mem_rdy, output mem_info); 23 | 24 | modport s(input int_req, output int_rdy, input int_info, input mem_req, output mem_rdy, input mem_info); 25 | endinterface 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /rtl/cpu/backend/link/loadwake_if.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | // load wake channel 4 | interface loadwake_if; 5 | logic [`WDEF(`LDU_NUM)] wk; 6 | iprIdx_t wkIprd[`LDU_NUM]; 7 | lpv_t cl[`LDU_NUM]; 8 | 9 | modport m(output wk, output wkIprd, output cl); 10 | 11 | 12 | modport s(input wk, input wkIprd, input cl); 13 | 14 | endinterface 15 | -------------------------------------------------------------------------------- /rtl/cpu/backend/link/syscall_if.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | // scu -> priv_ctrl/rob 4 | interface syscall_if; 5 | robIdx_t rob_idx; 6 | logic mret; 7 | logic sret; 8 | 9 | logic [`XDEF] npc; 10 | 11 | modport m(output rob_idx, output mret, output sret, output npc); 12 | 13 | modport s(input rob_idx, input mret, input sret, input npc); 14 | 15 | endinterface 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/link/load2dcache_if.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | /* 5 | 6 | | agu | get paddr, ptag | get data | 7 | | | 8 | V match? 9 | vaddr V 10 | s1_miss 11 | 12 | */ 13 | 14 | 15 | interface load2dcache_if; 16 | // s0: 17 | // send request, read tag sram, translate vaddr 18 | logic s0_req; 19 | logic s0_gnt; 20 | lqIdx_t s0_lqIdx; 21 | logic [`XDEF] s0_vaddr; 22 | 23 | // s1: 24 | // check dcache/tlb miss 25 | logic s1_req; 26 | logic s1_rdy; // used for pipeline align 27 | logic s1_cft; // bank conflict, replay 28 | logic s1_miss; // tlbmiss or cache miss 29 | logic s1_pagefault; // mmu page fault 30 | logic s1_illegaAddr; // mmu check failed 31 | logic s1_mmio; // mmio space 32 | paddr_t s1_paddr; // translated paddr 33 | 34 | // s2: 35 | logic s2_req; 36 | logic s2_rdy; 37 | logic [`WDEF(`CACHELINE_SIZE*8)] s2_data; // return one cacheline 38 | 39 | modport m( 40 | output s0_req, 41 | input s0_gnt, 42 | output s0_lqIdx, 43 | output s0_vaddr, 44 | 45 | output s1_req, 46 | input s1_rdy, 47 | input s1_cft, 48 | input s1_miss, 49 | input s1_pagefault, 50 | input s1_illegaAddr, 51 | input s1_mmio, 52 | input s1_paddr, 53 | 54 | output s2_req, 55 | input s2_rdy, 56 | input s2_data 57 | ); 58 | 59 | modport s( 60 | input s0_req, 61 | output s0_gnt, 62 | input s0_lqIdx, 63 | input s0_vaddr, 64 | 65 | input s1_req, 66 | output s1_rdy, 67 | output s1_cft, 68 | output s1_miss, 69 | output s1_pagefault, 70 | output s1_illegaAddr, 71 | output s1_mmio, 72 | output s1_paddr, 73 | 74 | input s2_req, 75 | output s2_rdy, 76 | output s2_data 77 | ); 78 | endinterface 79 | 80 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/link/load2que_if.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | 5 | // loadpipe to load/storeQue 6 | interface load2que_if; 7 | // load s2 8 | logic vld; 9 | lqIdx_t lqIdx; 10 | sqIdx_t sqIdx; 11 | logic [`XDEF] vaddr; 12 | paddr_t paddr; 13 | logic [`WDEF(`XLEN/8)] loadmask; // 8 byte aligned 14 | 15 | robIdx_t robIdx; 16 | logic [`XDEF] pc; 17 | 18 | 19 | modport m( 20 | output vld, 21 | output lqIdx, 22 | output sqIdx, 23 | output vaddr, 24 | output paddr, 25 | output loadmask, 26 | output robIdx, 27 | output pc 28 | ); 29 | 30 | modport s( 31 | input vld, 32 | input lqIdx, 33 | input sqIdx, 34 | input vaddr, 35 | input paddr, 36 | input loadmask, 37 | input robIdx, 38 | input pc 39 | ); 40 | endinterface 41 | 42 | 43 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/link/sta2ldque_if.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | 5 | // staFu to loadQue 6 | // store-load violation check 7 | interface sta2ldque_if; 8 | 9 | logic s0_vld; 10 | sqIdx_t s0_sqIdx; 11 | logic [`XDEF] s0_sta_vaddr; 12 | logic [`WDEF(`XLEN/8)] s0_store_vec; 13 | 14 | modport m(output s0_vld, output s0_sqIdx, output s0_sta_vaddr, output s0_store_vec); 15 | 16 | modport s(input s0_vld, input s0_sqIdx, input s0_sta_vaddr, input s0_store_vec); 17 | endinterface 18 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/link/sta2mmu_if.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | 5 | interface sta2mmu_if; 6 | logic s0_req; 7 | logic [`XDEF] s0_vaddr; 8 | 9 | logic s1_miss;// tlb miss 10 | logic s1_pagefault;// store page fault 11 | logic s1_illegaAddr;// store illegal address 12 | logic s1_mmio;// store mmio 13 | paddr_t s1_paddr; 14 | modport m( 15 | output s0_req, 16 | output s0_vaddr, 17 | 18 | input s1_miss, 19 | input s1_pagefault, 20 | input s1_illegaAddr, 21 | input s1_mmio, 22 | input s1_paddr 23 | ); 24 | 25 | modport s ( 26 | input s0_req, 27 | input s0_vaddr, 28 | 29 | output s1_miss, 30 | output s1_pagefault, 31 | output s1_illegaAddr, 32 | output s1_mmio, 33 | output s1_paddr 34 | ); 35 | endinterface 36 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/link/staviocheck_if.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | 5 | 6 | interface staviocheck_if; 7 | // s1 8 | logic vld; 9 | sqIdx_t sqIdx; 10 | paddr_t paddr; 11 | logic [`WDEF(`XLEN/8)] mask; 12 | // s2 13 | logic vio; 14 | robIdx_t vioload_robIdx; 15 | logic [`XDEF] vioload_pc; 16 | 17 | modport m ( 18 | output vld, 19 | output sqIdx, 20 | output paddr, 21 | output mask, 22 | 23 | input vio, 24 | input vioload_robIdx, 25 | input vioload_pc 26 | ); 27 | 28 | modport s ( 29 | input vld, 30 | input sqIdx, 31 | input paddr, 32 | input mask, 33 | 34 | output vio, 35 | output vioload_robIdx, 36 | output vioload_pc 37 | ); 38 | 39 | endinterface 40 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/link/stfwd_if.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | // use virtual addr forward 5 | // use physical addr check 6 | // master: loadpipe 7 | // slave: storeQue/sbuffer 8 | 9 | interface stfwd_if; 10 | // s0: send forward request 11 | // m->s 12 | logic s0_vld; 13 | lqIdx_t s0_lqIdx; 14 | sqIdx_t s0_sqIdx; // store age small than load 15 | logic [`XDEF] s0_vaddr; 16 | logic [`WDEF(`XLEN/8)] s0_load_vec; 17 | 18 | // s1: match check 19 | // m->s 20 | logic s1_vaddr_match; 21 | logic s1_data_rdy; // match and data ready 22 | logic s1_vld; 23 | paddr_t s1_paddr; 24 | 25 | // s2: send forward response 26 | // m<-s 27 | logic s2_paddr_match; 28 | logic s2_match_failed; 29 | logic [`WDEF(`XLEN/8)] s2_match_vec; // which byte was forward matched 30 | logic [`XDEF] s2_fwd_data; 31 | 32 | modport m( 33 | output s0_vld, 34 | output s0_lqIdx, 35 | output s0_sqIdx, 36 | output s0_vaddr, 37 | output s0_load_vec, 38 | 39 | input s1_vaddr_match, 40 | input s1_data_rdy, 41 | output s1_vld, 42 | output s1_paddr, 43 | 44 | input s2_paddr_match, 45 | input s2_match_failed, 46 | input s2_match_vec, 47 | input s2_fwd_data 48 | ); 49 | 50 | modport s( 51 | input s0_vld, 52 | input s0_lqIdx, 53 | input s0_sqIdx, 54 | input s0_vaddr, 55 | input s0_load_vec, 56 | 57 | output s1_vaddr_match, 58 | output s1_data_rdy, 59 | input s1_vld, 60 | input s1_paddr, 61 | 62 | output s2_paddr_match, 63 | output s2_match_failed, 64 | output s2_match_vec, 65 | output s2_fwd_data 66 | ); 67 | 68 | endinterface 69 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/link/store2dcache_if.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | interface store2dcache_if; 5 | // s0: 6 | logic req; 7 | logic gnt; 8 | paddr_t paddr; 9 | logic [`XDEF] storedata; 10 | logic [`WDEF(`XLEN/8)] storemask; 11 | // s2: 12 | logic s2_finish; 13 | 14 | modport m( 15 | output req, 16 | input gnt, 17 | output paddr, 18 | output storedata, 19 | output storemask, 20 | 21 | input s2_finish 22 | ); 23 | 24 | modport s( 25 | input req, 26 | output gnt, 27 | input paddr, 28 | input storedata, 29 | input storemask, 30 | 31 | output s2_finish 32 | ); 33 | endinterface 34 | 35 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/link/store2que_if.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | interface store2que_if; 10 | // stau 11 | logic vld; 12 | sqIdx_t sqIdx; 13 | robIdx_t robIdx; 14 | logic [`XDEF] vaddr; 15 | paddr_t paddr; 16 | logic[`WDEF(`XLEN/8)] storemask; 17 | // only for stdu 18 | logic [`XDEF] data; 19 | 20 | modport m( 21 | output vld, 22 | output sqIdx, 23 | output robIdx, 24 | output vaddr, 25 | output paddr, 26 | output storemask, 27 | output data 28 | ); 29 | modport s( 30 | input vld, 31 | input sqIdx, 32 | input robIdx, 33 | input vaddr, 34 | input paddr, 35 | input storemask, 36 | input data 37 | ); 38 | 39 | endinterface 40 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/lsque.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | 5 | module lsque ( 6 | load2que_if.s if_load2que[2], 7 | stfwd_if.s if_stfwd[2] 8 | ); 9 | genvar i; 10 | for (i=0;i<2;i=i+1) begin 11 | assign if_stfwd[i].s1_vaddr_match = 0; 12 | assign if_stfwd[i].s1_data_rdy = 0; 13 | assign if_stfwd[i].s2_rdy = 0; 14 | assign if_stfwd[i].s2_match_failed = 0; 15 | assign if_stfwd[i].s2_match_vec = 0; 16 | end 17 | endmodule 18 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/mdp/memDepPred.sv: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | `include "backend_define.svh" 5 | 6 | 7 | 8 | 9 | 10 | module memDepPred ( 11 | input wire clk, 12 | input wire rst, 13 | 14 | input wire i_stall, 15 | 16 | // insert new inst 17 | // rename stage, lookup SSIT 18 | input wire [`WDEF(`RENAME_WIDTH)] i_lookup_ssit_vld, 19 | input wire [`WDEF(`MEMDEP_FOLDPC_WIDTH)] i_foldpc[`RENAME_WIDTH], 20 | 21 | // dispatch stage check inst dep and insert store 22 | input wire [`WDEF(`RENAME_WIDTH)] i_insert_store, 23 | input robIdx_t i_allocated_robIdx[`RENAME_WIDTH], 24 | output wire [`WDEF(`RENAME_WIDTH)] o_shouldwait, 25 | output robIdx_t o_dep_robIdx[`RENAME_WIDTH], 26 | 27 | // store issued 28 | input wire [`WDEF(`STORE_ISSUE_WIDTH)] i_store_issued, 29 | input wire [`WDEF(`MEMDEP_FOLDPC_WIDTH)] i_issue_foldpc[`STORE_ISSUE_WIDTH], 30 | input robIdx_t i_store_robIdx[`STORE_ISSUE_WIDTH], 31 | 32 | // violation update 33 | input wire i_violation, 34 | input wire [`WDEF(`MEMDEP_FOLDPC_WIDTH)] i_vio_store_foldpc, 35 | input wire [`WDEF(`MEMDEP_FOLDPC_WIDTH)] i_vio_load_foldpc, 36 | 37 | // dispatch->IQ, read busytable 38 | input robIdx_t i_read_robIdx[`MEMDQ_DISP_WID], 39 | output wire [`WDEF(`MEMDQ_DISP_WID)] o_memdep_rdy 40 | ); 41 | 42 | genvar i; 43 | 44 | logic [`WDEF(`ROB_SIZE)] nxt_rdy_bits; 45 | reg [`WDEF(`ROB_SIZE)] rdy_bits; 46 | 47 | always_ff @(posedge clk) begin 48 | int fa, fb; 49 | if (rst || i_violation) begin 50 | for (fa = 0; fa < `ROB_SIZE; fa = fa + 1) begin 51 | rdy_bits[fa] <= 1; 52 | end 53 | end 54 | else begin 55 | // for (fa = 0; fa < `RENAME_WIDTH; fa = fa + 1) begin 56 | // if (i_insert_store[fa]) begin 57 | // assert (rdy_bits[i_allocated_robIdx[fa].idx]); 58 | // rdy_bits[i_allocated_robIdx[fa].idx] <= 0; 59 | // end 60 | // end 61 | // for (fa = 0; fa < `STORE_ISSUE_WIDTH; fa = fa + 1) begin 62 | // if (i_store_issued[fa]) begin 63 | // assert (rdy_bits[i_store_robIdx[fa].idx] == 0); 64 | // rdy_bits[i_store_robIdx[fa].idx] <= 1; 65 | 66 | // // assert check 67 | // for (fb = 0; fb < `RENAME_WIDTH; fb = fb + 1) begin 68 | // if (i_insert_store[fb]) begin 69 | // assert (i_allocated_robIdx[fa].idx != i_store_robIdx[fa]); 70 | // end 71 | // end 72 | // end 73 | // end 74 | end 75 | end 76 | 77 | always_comb begin 78 | int ca; 79 | nxt_rdy_bits = rdy_bits; 80 | for (ca = 0; ca < `STORE_ISSUE_WIDTH; ca = ca + 1) begin 81 | if (i_store_issued[ca]) begin 82 | nxt_rdy_bits[i_store_robIdx[ca].idx] = 1; 83 | end 84 | end 85 | end 86 | 87 | generate 88 | for (i = 0; i < `MEMDQ_DISP_WID; i = i + 1) begin 89 | assign o_memdep_rdy[i] = nxt_rdy_bits[i_read_robIdx[i].idx]; 90 | end 91 | endgenerate 92 | 93 | 94 | 95 | `ifdef ENABLE_MEMPRED 96 | StoreSet #( 97 | .SSIT_SIZE(`SSIT_SIZE), 98 | .LFST_SIZE(`LFST_SIZE) 99 | ) u_StoreSet ( 100 | .clk (clk), 101 | .rst (rst), 102 | .i_stall(i_stall), 103 | 104 | .i_lookup_ssit_vld(i_lookup_ssit_vld), 105 | .i_foldpc (i_foldpc), 106 | 107 | .i_insert_store (i_insert_store), 108 | .i_allocated_robIdx(i_allocated_robIdx), 109 | .o_shouldwait (o_shouldwait), 110 | .o_dep_robIdx (o_dep_robIdx), 111 | 112 | .i_store_issued(i_store_issued), 113 | .i_issue_foldpc(i_issue_foldpc), 114 | .i_store_robIdx(i_store_robIdx), 115 | 116 | .i_violation (i_violation), 117 | .i_vio_store_foldpc(i_vio_store_foldpc), 118 | .i_vio_load_foldpc (i_vio_load_foldpc) 119 | ); 120 | 121 | `else 122 | assign o_shouldwait = 0; 123 | `endif 124 | 125 | endmodule 126 | 127 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/stafu.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | 5 | import "DPI-C" function void memory_violation_find( 6 | uint64_t ldpc, 7 | uint64_t stpc 8 | ); 9 | 10 | import "DPI-C" function void set_store_load_info( 11 | uint64_t seqNum, 12 | uint64_t isload, 13 | uint64_t paddr, 14 | uint64_t size 15 | ); 16 | 17 | // NOTE: 18 | // if ld0 has dep on st0 19 | // ld0 can't execute parallel with st0 20 | module stafu ( 21 | input wire clk, 22 | input wire rst, 23 | 24 | output wire o_stall, 25 | input wire i_vld, 26 | input exeInfo_t i_fuInfo, 27 | 28 | output wire o_issue_success, 29 | output wire o_issue_replay, 30 | output iqIdx_t o_feedback_iqIdx, 31 | 32 | sta2mmu_if.m if_sta2mmu, 33 | staviocheck_if.m if_staviocheck, 34 | store2que_if.m if_sta2que, 35 | 36 | output wire o_fu_finished, 37 | output comwbInfo_t o_comwbInfo, 38 | 39 | output wire o_has_except, 40 | output exceptwbInfo_t o_exceptwbInfo 41 | ); 42 | // calculate store addr 43 | // check memory violation 44 | genvar i; 45 | 46 | reg s0_vld; 47 | exeInfo_t s0_fuInfo; 48 | 49 | always_ff @(posedge clk) begin 50 | if (rst) begin 51 | s0_vld <= 0; 52 | end 53 | else begin 54 | s0_vld <= i_vld; 55 | s0_fuInfo <= i_fuInfo; 56 | if (i_vld) begin 57 | update_instPos(i_fuInfo.seqNum, difftest_def::AT_fu); 58 | end 59 | end 60 | end 61 | 62 | // s0: calculate addr, mmu check 63 | wire [`XDEF] s0_vaddr; 64 | assign s0_vaddr = s0_fuInfo.srcs[0] + s0_fuInfo.srcs[1]; 65 | 66 | wire [`WDEF(`XLEN/8)] s0_store_vec; // 8 byte aligned 67 | wire [`WDEF($clog2(8))] s0_store_size; 68 | wire store_misaligned; 69 | assign s0_store_vec = 70 | (s0_fuInfo.micOp == MicOp_t::sb) ? (8'b0000_0001 << s0_vaddr[2:0]) : 71 | (s0_fuInfo.micOp == MicOp_t::sh) ? (8'b0000_0011 << s0_vaddr[2:0]) : 72 | (s0_fuInfo.micOp == MicOp_t::sw) ? (8'b0000_1111 << s0_vaddr[2:0]) : 73 | 8'b1111_1111; 74 | 75 | assign s0_store_size = 76 | (s0_fuInfo.micOp == MicOp_t::sb) ? 1 : 77 | (s0_fuInfo.micOp == MicOp_t::sh) ? 2 : 78 | (s0_fuInfo.micOp == MicOp_t::sw) ? 4 : 79 | 8 ; 80 | 81 | assign store_misaligned = (s0_vaddr[2:0] & (s0_store_size - 1)) != 0; 82 | 83 | assign if_sta2mmu.s0_req = s0_vld && !store_misaligned; 84 | assign if_sta2mmu.s0_vaddr = s0_vaddr; 85 | 86 | // s1: get paddr 87 | reg s1_vld; 88 | reg s1_misaligned; 89 | logic [`XDEF] s1_vaddr; 90 | reg [`WDEF(`XLEN/8)] s1_storemask; 91 | exeInfo_t s1_fuInfo; 92 | always_ff @(posedge clk) begin 93 | if (rst) begin 94 | s1_vld <= 0; 95 | s1_misaligned <= 0; 96 | end 97 | else begin 98 | s1_vld <= s0_vld; 99 | s1_vaddr <= s0_vaddr; 100 | s1_storemask <= s0_store_vec; 101 | s1_fuInfo <= s0_fuInfo; 102 | s1_misaligned <= store_misaligned; 103 | end 104 | end 105 | 106 | wire s1_replay = if_sta2mmu.s1_miss | if_sta2mmu.s1_mmio; 107 | wire s1_fault = s1_misaligned | if_sta2mmu.s1_pagefault | if_sta2mmu.s1_illegaAddr; 108 | 109 | // notify IQ 110 | assign o_issue_success = s1_vld && (!s1_replay); 111 | assign o_issue_replay = s1_vld && s1_replay; 112 | assign o_feedback_iqIdx = s1_fuInfo.iqIdx; 113 | 114 | // write back storeque 115 | assign if_sta2que.vld = s1_vld && !s1_replay && !s1_fault; 116 | assign if_sta2que.sqIdx = s1_fuInfo.sqIdx; 117 | assign if_sta2que.robIdx = s1_fuInfo.robIdx; 118 | assign if_sta2que.vaddr = s1_vaddr; 119 | assign if_sta2que.paddr = if_sta2mmu.s1_paddr; 120 | assign if_sta2que.storemask = s1_storemask; 121 | 122 | // check violation 123 | assign if_staviocheck.vld = s1_vld && !s1_replay && !s1_fault; 124 | assign if_staviocheck.sqIdx = s1_fuInfo.sqIdx; 125 | assign if_staviocheck.paddr = if_sta2mmu.s1_paddr; 126 | assign if_staviocheck.mask = s1_storemask; 127 | 128 | // s2: get vio result, notify rob 129 | wire violation = if_staviocheck.vio; 130 | robIdx_t vioload_robIdx = if_staviocheck.vioload_robIdx; 131 | robIdx_t viostore_robIdx = s2_fuInfo.robIdx; 132 | wire [`XDEF] vioload_pc = if_staviocheck.vioload_pc; 133 | wire [`XDEF] viostore_pc = s2_fuInfo.pc; 134 | reg s2_vld; 135 | exeInfo_t s2_fuInfo; 136 | reg prev_has_except; 137 | rv_trap_t::exception prev_except; 138 | always_ff @(posedge clk) begin 139 | if (rst) begin 140 | s2_vld <= 0; 141 | prev_has_except <= 0; 142 | end 143 | else begin 144 | s2_vld <= s1_vld; 145 | s2_fuInfo <= s1_fuInfo; 146 | prev_has_except <= s1_vld && s1_fault; 147 | prev_except <= s1_misaligned ? rv_trap_t::storeMisaligned : 148 | if_sta2mmu.s1_pagefault ? rv_trap_t::storePageFault : 149 | rv_trap_t::storeFault; 150 | 151 | if (violation) begin 152 | memory_violation_find(vioload_pc, viostore_pc); 153 | end 154 | 155 | if (s1_vld) begin 156 | set_store_load_info(s1_fuInfo.seqNum, 0, if_sta2mmu.s1_paddr, count_one(s1_storemask)); 157 | end 158 | end 159 | end 160 | 161 | // s2: write except 162 | assign o_has_except = prev_has_except || violation; 163 | assign o_exceptwbInfo = '{ 164 | rob_idx : prev_has_except ? s2_fuInfo.robIdx : vioload_robIdx, 165 | except_type : prev_has_except ? prev_except : rv_trap_t::reExec, 166 | stpc: viostore_pc, 167 | ldpc: vioload_pc 168 | }; 169 | 170 | // s3: store finish 171 | reg store_finished; 172 | comwbInfo_t commwbInfo; 173 | always_ff @(posedge clk) begin 174 | if (rst) begin 175 | store_finished <= 0; 176 | end 177 | else begin 178 | store_finished <= s2_vld; 179 | commwbInfo <= '{ 180 | rob_idx : s2_fuInfo.robIdx, 181 | irob_idx : s2_fuInfo.irobIdx, 182 | use_imm : s2_fuInfo.useImm, 183 | rd_wen : 0, 184 | iprd_idx : 0, 185 | result : 0 186 | }; 187 | if (s2_vld) begin 188 | update_instPos(s2_fuInfo.seqNum, difftest_def::AT_wb); 189 | end 190 | end 191 | end 192 | 193 | assign o_fu_finished = store_finished; 194 | assign o_comwbInfo = commwbInfo; 195 | 196 | 197 | endmodule 198 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/stdfu.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | 5 | 6 | 7 | // NOTE: 8 | // if ld0 has dep on st0 9 | // ld0 can't execute parallel with st0 10 | module stdfu ( 11 | input wire clk, 12 | input wire rst, 13 | 14 | input wire i_vld, 15 | input exeInfo_t i_fuInfo, 16 | 17 | store2que_if.m if_std2que 18 | ); 19 | 20 | reg s0_vld; 21 | exeInfo_t s0_fuInfo; 22 | 23 | always_ff @(posedge clk) begin 24 | if (rst) begin 25 | s0_vld <= 0; 26 | end 27 | else begin 28 | s0_vld <= i_vld; 29 | s0_fuInfo <= i_fuInfo; 30 | end 31 | end 32 | 33 | 34 | assign if_std2que.vld = s0_vld; 35 | assign if_std2que.sqIdx = s0_fuInfo.sqIdx; 36 | assign if_std2que.data = s0_fuInfo.srcs[0]; 37 | endmodule 38 | -------------------------------------------------------------------------------- /rtl/cpu/backend/memfu/virtualLSQ.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | module virtualLSQ #( 11 | parameter int INPORTS = `MEMDQ_DISP_WID, 12 | parameter int LD_ISSUE_WIDTH = 2, 13 | parameter int ST_ISSUE_WIDTH = 2, 14 | parameter int LD_COMMIT_WIDTH = `COMMIT_WIDTH, 15 | parameter int ST_COMMIT_WIDTH = `COMMIT_WIDTH 16 | // INPORTS should be equal to LD_ISSUE_WIDTH + ST_ISSUE_WIDTH 17 | ) ( 18 | input wire clk, 19 | input wire rst, 20 | 21 | output wire o_can_enq, 22 | input wire[`WDEF(INPORTS)] i_disp_load, 23 | input wire[`WDEF(INPORTS)] i_disp_store, 24 | 25 | output lqIdx_t o_alloc_lqIdx[INPORTS], 26 | output sqIdx_t o_alloc_sqIdx[INPORTS], 27 | 28 | input wire[`SDEF(`COMMIT_WIDTH)] i_ld_commit_num, 29 | input wire[`SDEF(`COMMIT_WIDTH)] i_st_commit_num 30 | ); 31 | genvar i; 32 | wire [`WDEF(INPORTS)] isLoad; 33 | wire [`WDEF(INPORTS)] isStore; 34 | wire [`SDEF(INPORTS)] enqLoadNum; 35 | wire [`SDEF(INPORTS)] enqStoreNum; 36 | generate 37 | for (i = 0; i < INPORTS; i = i + 1) begin 38 | assign isLoad[i] = o_can_enq && i_disp_load[i]; 39 | assign isStore[i] = o_can_enq && i_disp_store[i]; 40 | end 41 | endgenerate 42 | count_one #( 43 | .WIDTH(INPORTS) 44 | ) u_count_one0 ( 45 | .i_a (isLoad), 46 | .o_sum(enqLoadNum) 47 | ); 48 | count_one #( 49 | .WIDTH(INPORTS) 50 | ) u_count_one1 ( 51 | .i_a (isStore), 52 | .o_sum(enqStoreNum) 53 | ); 54 | 55 | wire [`SDEF(`COMMIT_WIDTH)] deqLoadNum = i_ld_commit_num; 56 | wire [`SDEF(`COMMIT_WIDTH)] deqStoreNum = i_st_commit_num; 57 | 58 | 59 | lqIdx_t lqhead[INPORTS]; 60 | sqIdx_t sqhead[INPORTS]; 61 | reg [`SDEF(`LQSIZE)] ldNum; 62 | reg [`SDEF(`SQSIZE)] stNum; 63 | 64 | assign o_can_enq = (ldNum <= (`LQSIZE - LD_ISSUE_WIDTH)) && (stNum <= (`SQSIZE - ST_ISSUE_WIDTH)); 65 | 66 | always_ff @(posedge clk) begin 67 | int fa; 68 | if (rst) begin 69 | ldNum <= 0; 70 | stNum <= 0; 71 | for (fa = 0; fa < INPORTS; fa = fa + 1) begin 72 | lqhead[fa] <= fa; 73 | sqhead[fa] <= fa; 74 | end 75 | end 76 | else begin 77 | ldNum <= ldNum + enqLoadNum - deqLoadNum; 78 | stNum <= stNum + enqStoreNum - deqStoreNum; 79 | 80 | for (fa = 0; fa < INPORTS; fa = fa + 1) begin 81 | lqhead[fa].idx <= (lqhead[fa].idx + enqLoadNum) < `LQSIZE ? (lqhead[fa].idx + enqLoadNum) : (lqhead[fa].idx + enqLoadNum - `LQSIZE); 82 | if ((lqhead[fa].idx + enqLoadNum) >= `LQSIZE) begin 83 | lqhead[fa].flipped <= ~lqhead[fa].flipped; 84 | end 85 | sqhead[fa].idx <= (sqhead[fa].idx + enqStoreNum) < `SQSIZE ? (sqhead[fa].idx + enqStoreNum) : (sqhead[fa].idx + enqStoreNum - `SQSIZE); 86 | if ((sqhead[fa].idx + enqStoreNum) >= `SQSIZE) begin 87 | sqhead[fa].flipped <= ~sqhead[fa].flipped; 88 | end 89 | end 90 | end 91 | end 92 | 93 | /* 94 | inst lqIdx sqIdx 95 | 3 load 1 2 96 | 2 store 1 1 97 | 1 load 0 1 98 | 0 store 0 0 99 | */ 100 | 101 | redirect #( 102 | .dtype (lqIdx_t), 103 | .NUM (INPORTS) 104 | ) u_redirect0( 105 | .i_arch_vld ( isLoad ), 106 | .i_arch_datas ( lqhead ), 107 | .o_redirect_datas ( o_alloc_lqIdx ) 108 | ); 109 | 110 | redirect #( 111 | .dtype (sqIdx_t), 112 | .NUM (INPORTS) 113 | ) u_redirect1( 114 | .i_arch_vld ( isStore ), 115 | .i_arch_datas ( sqhead ), 116 | .o_redirect_datas ( o_alloc_sqIdx ) 117 | ); 118 | 119 | endmodule 120 | -------------------------------------------------------------------------------- /rtl/cpu/backend/regfile/bypass_sel.sv: -------------------------------------------------------------------------------- 1 | `include "core_define.svh" 2 | 3 | 4 | module bypass_sel #( 5 | parameter int WIDTH = 4 6 | ) ( 7 | input wire rst, 8 | input wire [`WDEF(WIDTH)] i_src_vld, 9 | input iprIdx_t i_src_idx[WIDTH], 10 | input wire [`XDEF] i_src_data[WIDTH], 11 | input iprIdx_t i_target_idx, 12 | output wire o_target_vld, 13 | output wire [`XDEF] o_target_data 14 | ); 15 | always_comb begin 16 | int j, temp; 17 | temp = 0; 18 | o_target_vld = 0; 19 | o_target_data = 0; 20 | for (j = 0; j < WIDTH; j = j + 1) begin 21 | if (i_src_vld[j] && (i_src_idx[j] == i_target_idx)) begin 22 | temp = temp + 1; 23 | o_target_data = i_src_data[j]; 24 | o_target_vld = true; 25 | end 26 | end 27 | assert ((rst ? 0 : temp) < 2); 28 | end 29 | 30 | endmodule 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /rtl/cpu/backend/regfile/regfile.sv: -------------------------------------------------------------------------------- 1 | `include "core_define.svh" 2 | 3 | 4 | module regfile #( 5 | parameter int READPORT_NUM = 10, 6 | parameter int WBPORT_NUM = 6, 7 | parameter int DISPWIDTH = 8, 8 | parameter int SIZE = 80, 9 | parameter int HAS_ZERO = 1 10 | ) ( 11 | input wire clk, 12 | input wire rst, 13 | // rename to rob mark not ready 14 | input wire [`WDEF(`RENAME_WIDTH)] i_notready_mark, 15 | input iprIdx_t i_notready_iprIdx[`RENAME_WIDTH], 16 | 17 | // dispatch to issueQue read src is or not ready 18 | input iprIdx_t i_disp_check_iprsIdx[DISPWIDTH * `NUMSRCS_INT], 19 | output wire [`WDEF(DISPWIDTH * `NUMSRCS_INT)] o_disp_check_iprs_vld, 20 | 21 | input wire [`WDEF($clog2(SIZE))] i_read_idx[READPORT_NUM], 22 | output wire [`WDEF(READPORT_NUM)] o_data_rdy, 23 | output wire [`XDEF] o_read_data[READPORT_NUM], 24 | 25 | input wire [`WDEF(WBPORT_NUM)] i_write_en, 26 | input wire [`WDEF($clog2(SIZE))] i_write_idx[WBPORT_NUM], 27 | input wire [`XDEF] i_write_data[WBPORT_NUM] 28 | ); 29 | genvar i; 30 | generate 31 | if (HAS_ZERO != 0) begin : gen_has_zero 32 | import "DPI-C" function void write_int_physicRegfile( 33 | uint64_t idx, 34 | uint64_t value 35 | ); 36 | import "DPI-C" function void count_regfilewrite(uint64_t n); 37 | 38 | reg [`XDEF] buffer[1:SIZE-1]; 39 | reg [`WDEF(SIZE)] rdy_bit; 40 | logic [`WDEF(SIZE)] rdy_bit_bypass; 41 | 42 | always_ff @(posedge clk) begin 43 | int fa; 44 | if (rst) begin 45 | rdy_bit <= 0; 46 | end 47 | else begin 48 | rdy_bit <= rdy_bit_bypass; 49 | for (fa = 0; fa < WBPORT_NUM; fa = fa + 1) begin 50 | if (i_write_en[fa]) begin 51 | buffer[i_write_idx[fa]] <= i_write_data[fa]; 52 | write_int_physicRegfile(i_write_idx[fa], i_write_data[fa]); 53 | assert (rdy_bit[i_write_idx[fa]] == 0); 54 | end 55 | end 56 | count_regfilewrite(count_one(i_write_en)); 57 | end 58 | end 59 | 60 | always_comb begin 61 | int ca; 62 | rdy_bit_bypass = rdy_bit; 63 | for (ca = 0; ca < `RENAME_WIDTH; ca = ca + 1) begin 64 | if (i_notready_mark[ca]) begin 65 | rdy_bit_bypass[i_notready_iprIdx[ca]] = 0; 66 | end 67 | end 68 | for (ca = 0; ca < WBPORT_NUM; ca = ca + 1) begin 69 | if (i_write_en[ca]) begin 70 | rdy_bit_bypass[i_write_idx[ca]] = 1; 71 | end 72 | end 73 | end 74 | 75 | reg [`XDEF] read_data[READPORT_NUM]; 76 | reg [`WDEF(READPORT_NUM)] data_rdy; 77 | always_ff @(posedge clk) begin 78 | int fa; 79 | for (fa = 0; fa < READPORT_NUM; fa = fa + 1) begin 80 | read_data[fa] <= (i_read_idx[fa] == 0) ? 0 : buffer[i_read_idx[fa]]; 81 | data_rdy[fa] <= (i_read_idx[fa] == 0) ? 1 : rdy_bit[i_read_idx[fa]]; 82 | end 83 | end 84 | 85 | assign o_read_data = read_data; 86 | assign o_data_rdy = data_rdy; 87 | // disp to IQ check 88 | for (i = 0; i < DISPWIDTH * `NUMSRCS_INT; i = i + 1) begin 89 | // this should use rdy_bit_bypass; 90 | assign o_disp_check_iprs_vld[i] = (i_disp_check_iprsIdx[i] == 0) ? 1 : rdy_bit_bypass[i_disp_check_iprsIdx[i]]; 91 | end 92 | end 93 | else begin : gen_no_zero 94 | // reg[`XDEF] buffer[SIZE]; 95 | 96 | // always_ff @(posedge clk) begin 97 | // int fa; 98 | // for (fa=0;fa= 0; ca = ca - 1) begin 26 | if (i_wb_vld[ca]) begin 27 | regfile_temp[i_wb_idx[ca]] = i_wb_data[ca]; 28 | end 29 | end 30 | end 31 | 32 | always_ff @(posedge clk) begin 33 | int fa; 34 | if (rst) begin 35 | for (fa = 0; fa < 32; fa = fa + 1) begin 36 | regfile[fa] = 0; 37 | end 38 | clk_count <= 0; 39 | end 40 | else begin 41 | regfile <= regfile_temp; 42 | clk_count <= clk_count + 1; 43 | end 44 | end 45 | `SET_TRACE_ON 46 | wire [`XDEF] A_clk_count = clk_count; 47 | wire [`XDEF] x0_zero = 0; 48 | wire [`XDEF] x1_ra = regfile_temp[1]; 49 | wire [`XDEF] x2_sp = regfile_temp[2]; 50 | wire [`XDEF] x3_gp = regfile_temp[3]; 51 | wire [`XDEF] x4_tp = regfile_temp[4]; 52 | wire [`XDEF] x5_t0 = regfile_temp[5]; 53 | wire [`XDEF] x6_t1 = regfile_temp[6]; 54 | wire [`XDEF] x7_t2 = regfile_temp[7]; 55 | wire [`XDEF] x8_s0 = regfile_temp[8]; 56 | wire [`XDEF] x9_s1 = regfile_temp[9]; 57 | wire [`XDEF] x10_a0 = regfile_temp[10]; 58 | wire [`XDEF] x11_a1 = regfile_temp[11]; 59 | wire [`XDEF] x12_a2 = regfile_temp[12]; 60 | wire [`XDEF] x13_a3 = regfile_temp[13]; 61 | wire [`XDEF] x14_a4 = regfile_temp[14]; 62 | wire [`XDEF] x15_a5 = regfile_temp[15]; 63 | wire [`XDEF] x16_a6 = regfile_temp[16]; 64 | wire [`XDEF] x17_a7 = regfile_temp[17]; 65 | wire [`XDEF] x18_s2 = regfile_temp[18]; 66 | wire [`XDEF] x19_s3 = regfile_temp[19]; 67 | wire [`XDEF] x20_s4 = regfile_temp[20]; 68 | wire [`XDEF] x21_s5 = regfile_temp[21]; 69 | wire [`XDEF] x22_s6 = regfile_temp[22]; 70 | wire [`XDEF] x23_s7 = regfile_temp[23]; 71 | wire [`XDEF] x24_s8 = regfile_temp[24]; 72 | wire [`XDEF] x25_s9 = regfile_temp[25]; 73 | wire [`XDEF] x26_s10 = regfile_temp[26]; 74 | wire [`XDEF] x27_s11 = regfile_temp[27]; 75 | wire [`XDEF] x28_t3 = regfile_temp[28]; 76 | wire [`XDEF] x29_t4 = regfile_temp[29]; 77 | wire [`XDEF] x30_t5 = regfile_temp[30]; 78 | wire [`XDEF] x31_t6 = regfile_temp[31]; 79 | 80 | 81 | endmodule 82 | 83 | 84 | -------------------------------------------------------------------------------- /rtl/cpu/backend/rename/freelist.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | //unordered in,out 5 | module freelist ( 6 | input wire clk, 7 | input wire rst, 8 | //alloc physic reg 9 | //free regs must lager than RENAME_WIDTH 10 | output wire o_can_alloc, 11 | input wire [`WDEF(`RENAME_WIDTH)] i_alloc_req, 12 | output iprIdx_t o_alloc_prIdx[`RENAME_WIDTH], 13 | //dealloc physic reg (it must have enough spec to dealloc) 14 | input wire [`WDEF(`COMMIT_WIDTH)] i_dealloc_req, 15 | input iprIdx_t i_dealloc_prIdx[`COMMIT_WIDTH], 16 | 17 | // from commit 18 | input wire i_resteer_vld, 19 | input wire [`WDEF(`COMMIT_WIDTH)] i_commit_vld 20 | ); 21 | 22 | wire [`WDEF(`COMMIT_WIDTH)] reorder_dealloc_req; 23 | 24 | iprIdx_t reorder_dealloc_prIdx[`COMMIT_WIDTH]; 25 | 26 | reorder #( 27 | .dtype(iprIdx_t), 28 | .NUM (`COMMIT_WIDTH) 29 | ) u_reorder ( 30 | .i_data_vld (i_dealloc_req), 31 | .i_datas (i_dealloc_prIdx), 32 | .o_data_vld (reorder_dealloc_req), 33 | .o_reorder_datas(reorder_dealloc_prIdx) 34 | ); 35 | 36 | 37 | wire [`WDEF(`RENAME_WIDTH)] real_alloc_req; 38 | iprIdx_t deq_data[`RENAME_WIDTH]; 39 | 40 | wire [`SDEF(`RENAME_WIDTH)] alloc_num; 41 | count_one #( 42 | .WIDTH(`RENAME_WIDTH) 43 | ) u_count_one_0 ( 44 | .i_a (i_alloc_req), 45 | .o_sum(alloc_num) 46 | ); 47 | 48 | //reorder the alloc_vld bits: 1001 - > 0011 49 | assign real_alloc_req = ((|i_alloc_req) & (o_can_alloc)) ? (`RENAME_WIDTH'd1 << alloc_num) - 1 : 0; 50 | 51 | // the reg x0 is no need to save to freelist 52 | iprIdx_t free_list_init_data[`IPHYREG_NUM - 1]; 53 | generate 54 | genvar i; 55 | for (i = 0; i < `IPHYREG_NUM - 1; i = i + 1) begin : gen_init 56 | assign free_list_init_data[i] = i + 1; 57 | end 58 | endgenerate 59 | 60 | wire [`WDEF(`RENAME_WIDTH)] can_deq; 61 | wire can_enq; 62 | `ASSERT((reorder_dealloc_req != 0) ? (can_enq == true) : 1); 63 | fifo #( 64 | .dtype (iprIdx_t), 65 | .INPORT_NUM (`COMMIT_WIDTH), 66 | .OUTPORT_NUM(`RENAME_WIDTH), 67 | .DEPTH (`IPHYREG_NUM - 1), 68 | .USE_INIT (1), 69 | // only for rename 70 | .USE_RENAME (1), 71 | .COMMIT_WID (`COMMIT_WIDTH) 72 | ) u_fifo ( 73 | .init_data(free_list_init_data), 74 | .clk (clk), 75 | .rst (rst), 76 | .i_flush (0), 77 | 78 | .o_can_enq (can_enq), //dont care, it must have enough free entry to write 79 | .i_enq_vld (|reorder_dealloc_req), 80 | .i_enq_req (reorder_dealloc_req), 81 | .i_enq_data(reorder_dealloc_prIdx), 82 | 83 | .o_can_deq (can_deq), 84 | .i_deq_req (real_alloc_req), 85 | .o_deq_data(deq_data), 86 | 87 | .i_resteer_vld(i_resteer_vld), 88 | .i_commit_vld (i_commit_vld) 89 | ); 90 | 91 | 92 | //redirect fifo output to alloc_data 93 | //xxab -(redirect bits: 1001)> axxb 94 | redirect #( 95 | .dtype(iprIdx_t), 96 | .NUM (`RENAME_WIDTH) 97 | ) u_redirect ( 98 | .i_arch_vld (i_alloc_req), 99 | .i_arch_datas (deq_data), 100 | .o_redirect_datas(o_alloc_prIdx) 101 | ); 102 | 103 | wire [`SDEF(`RENAME_WIDTH)] can_deq_num; 104 | 105 | count_one #( 106 | .WIDTH(`RENAME_WIDTH) 107 | ) u_count_one_1 ( 108 | .i_a (can_deq), 109 | .o_sum(can_deq_num) 110 | ); 111 | 112 | assign o_can_alloc = can_deq_num >= alloc_num; 113 | 114 | endmodule 115 | -------------------------------------------------------------------------------- /rtl/cpu/backend/rename/rename.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | import "DPI-C" function void rename_alloc( 5 | uint64_t seq, 6 | uint64_t logic_idx, 7 | uint64_t physcial_idx, 8 | uint64_t ismv 9 | ); 10 | 11 | 12 | module rename ( 13 | input wire rst, 14 | input wire clk, 15 | // to decode 16 | output wire o_stall, 17 | // from dispatch 18 | input wire i_stall, 19 | // squash 20 | input wire i_squash_vld, 21 | // from commit 22 | input wire [`WDEF(`COMMIT_WIDTH)] i_commit_vld, 23 | input renameCommitInfo_t i_commitInfo[`COMMIT_WIDTH], 24 | // from decode 25 | input wire [`WDEF(`DECODE_WIDTH)] i_decinfo_vld, 26 | input decInfo_t i_decinfo[`DECODE_WIDTH], 27 | // to dispatch 28 | output wire [`WDEF(`RENAME_WIDTH)] o_rename_vld, 29 | output renameInfo_t o_renameInfo[`RENAME_WIDTH] 30 | ); 31 | genvar i; 32 | 33 | wire can_rename; 34 | wire [`WDEF(`RENAME_WIDTH)] ismv; 35 | wire [`WDEF(`RENAME_WIDTH)] has_rd; 36 | ilrIdx_t ilrd_idx[`RENAME_WIDTH]; 37 | iprIdx_t iprd_idx[`RENAME_WIDTH]; 38 | iprIdx_t prev_iprd_idx[`RENAME_WIDTH]; 39 | 40 | ilrIdx_t ilrs_idx[`RENAME_WIDTH][`NUMSRCS_INT]; 41 | iprIdx_t iprs_idx[`RENAME_WIDTH][`NUMSRCS_INT]; 42 | 43 | generate 44 | for (i = 0; i < `RENAME_WIDTH; i = i + 1) begin 45 | assign ismv[i] = i_decinfo_vld[i] & i_decinfo[i].ismv; 46 | assign has_rd[i] = i_decinfo_vld[i] & i_decinfo[i].rd_wen & (!i_stall); 47 | assign ilrd_idx[i] = i_decinfo[i].ilrd_idx; 48 | end 49 | endgenerate 50 | 51 | always_comb begin 52 | int ca, cb; 53 | for (ca = 0; ca < `RENAME_WIDTH; ca = ca + 1) begin 54 | for (cb = 0; cb < `NUMSRCS_INT; cb = cb + 1) begin 55 | ilrs_idx[ca][cb] = i_decinfo[ca].ilrs_idx[cb]; 56 | end 57 | end 58 | end 59 | 60 | assign o_stall = (!can_rename) || i_stall; 61 | 62 | renameInfo_t wireInfo[`RENAME_WIDTH]; 63 | renametable u_renametable ( 64 | .clk(clk), 65 | .rst(rst), 66 | 67 | .o_can_rename(can_rename), 68 | 69 | .i_ismv (ismv), 70 | .i_has_rd (has_rd), 71 | .i_ilrd_idx (ilrd_idx), 72 | .o_renamed_iprd_idx (iprd_idx), 73 | .o_prevRenamed_iprd_idx(prev_iprd_idx), 74 | 75 | .i_ilrs_idx (ilrs_idx), 76 | .o_renamed_iprs_idx(iprs_idx), 77 | 78 | .i_squash_vld(i_squash_vld), 79 | .i_commit_vld(i_commit_vld), 80 | .i_commitInfo(i_commitInfo) 81 | ); 82 | 83 | generate 84 | for (i = 0; i < `RENAME_WIDTH; i = i + 1) begin 85 | assign wireInfo[i] = '{ 86 | ftq_idx : i_decinfo[i].ftq_idx, 87 | ftqOffset : i_decinfo[i].ftqOffset, 88 | has_except : i_decinfo[i].has_except, 89 | except : i_decinfo[i].except, 90 | isRVC : i_decinfo[i].isRVC, 91 | ismv : i_decinfo[i].ismv, 92 | imm20 : i_decinfo[i].imm20, 93 | need_serialize : i_decinfo[i].need_serialize, 94 | rd_wen : i_decinfo[i].rd_wen, 95 | ilrd_idx : i_decinfo[i].ilrd_idx, 96 | iprd_idx : iprd_idx[i], 97 | prev_iprd_idx : prev_iprd_idx[i], 98 | 99 | iprs_idx : iprs_idx[i], 100 | 101 | use_imm : i_decinfo[i].use_imm, 102 | dispQue_id : i_decinfo[i].dispQue_id, 103 | issueQue_id : i_decinfo[i].issueQue_id, 104 | micOp_type : i_decinfo[i].micOp_type, 105 | isStore : i_decinfo[i].isStore, 106 | 107 | instmeta : i_decinfo[i].instmeta 108 | }; 109 | end 110 | endgenerate 111 | 112 | reg [`WDEF(`RENAME_WIDTH)] rename_vld; 113 | renameInfo_t renameInfo[`RENAME_WIDTH]; 114 | 115 | always_ff @(posedge clk) begin 116 | int fa, fb; 117 | if (rst || i_squash_vld) begin 118 | rename_vld <= 0; 119 | end 120 | else if (!i_stall) begin 121 | rename_vld <= can_rename ? i_decinfo_vld : 0; 122 | renameInfo <= wireInfo; 123 | for (fa = 0; fa < `RENAME_WIDTH; fa = fa + 1) begin 124 | if (can_rename ? i_decinfo_vld[fa] : 0) begin 125 | update_instPos(i_decinfo[fa].instmeta, difftest_def::AT_rename); 126 | if (i_decinfo[fa].ilrd_idx != 0) begin 127 | rename_alloc(i_decinfo[fa].instmeta, i_decinfo[fa].ilrd_idx, iprd_idx[fa], i_decinfo[fa].ismv); 128 | end 129 | if (ilrs_idx[fa][0] != 0) begin 130 | rename_alloc(i_decinfo[fa].instmeta, ilrs_idx[fa][0], iprs_idx[fa][0], 0); 131 | end 132 | if (ilrs_idx[fa][1] != 0) begin 133 | rename_alloc(i_decinfo[fa].instmeta, ilrs_idx[fa][1], iprs_idx[fa][1], 0); 134 | end 135 | end 136 | end 137 | end 138 | end 139 | 140 | assign o_rename_vld = rename_vld; 141 | assign o_renameInfo = renameInfo; 142 | 143 | 144 | endmodule 145 | 146 | -------------------------------------------------------------------------------- /rtl/cpu/backend/rename/renametable.sv: -------------------------------------------------------------------------------- 1 | `include "backend_define.svh" 2 | 3 | 4 | 5 | 6 | //TODO: how about MEMartix implement? 7 | //TODO: how about spec-arch mv elim ( we can use the traditional rename and save space ) 8 | 9 | module renametable ( 10 | input wire clk, 11 | input wire rst, 12 | 13 | output wire o_can_rename, 14 | 15 | // int rename dest 16 | input wire [`WDEF(`RENAME_WIDTH)] i_ismv, 17 | input wire [`WDEF(`RENAME_WIDTH)] i_has_rd, 18 | input ilrIdx_t i_ilrd_idx[`RENAME_WIDTH], 19 | output iprIdx_t o_renamed_iprd_idx[`RENAME_WIDTH], 20 | output iprIdx_t o_prevRenamed_iprd_idx[`RENAME_WIDTH], 21 | 22 | // int rename srcs 23 | input ilrIdx_t i_ilrs_idx[`RENAME_WIDTH][`NUMSRCS_INT], 24 | output iprIdx_t o_renamed_iprs_idx[`RENAME_WIDTH][`NUMSRCS_INT], 25 | 26 | // from commit 27 | input wire i_squash_vld, 28 | input wire [`WDEF(`COMMIT_WIDTH)] i_commit_vld, 29 | input renameCommitInfo_t i_commitInfo[`COMMIT_WIDTH] 30 | ); 31 | genvar i; 32 | 33 | wire [`WDEF(`COMMIT_WIDTH)] int_dealloc_vld; 34 | iprIdx_t int_dealloc_iprd_idx[`COMMIT_WIDTH]; 35 | iprIdx_t int_alloc_iprd_idx[`COMMIT_WIDTH]; 36 | rat_map #( 37 | .COMMIT_WID (`COMMIT_WIDTH), 38 | .WIDTH (`RENAME_WIDTH), 39 | .NUMSRCS (`NUMSRCS_INT), 40 | .PHYREG_TYPE(0), 41 | .lrIdx_t (ilrIdx_t), 42 | .prIdx_t (iprIdx_t) 43 | ) u_rat_map ( 44 | .clk(clk), 45 | .rst(rst), 46 | 47 | .i_ismv (o_can_rename ? i_ismv : 0), 48 | .i_has_rd (o_can_rename ? i_has_rd : 0), 49 | .i_lrd_idx (i_ilrd_idx), 50 | .i_alloc_prd_idx (int_alloc_iprd_idx), 51 | .o_renamed_prd_idx (o_renamed_iprd_idx), 52 | .o_prevRenamed_prd_idx(o_prevRenamed_iprd_idx), 53 | 54 | .i_lrs_idx (i_ilrs_idx), 55 | .o_renamed_prs_idx(o_renamed_iprs_idx), 56 | 57 | .o_dealloc_vld (int_dealloc_vld), 58 | .o_dealloc_prd_idx(int_dealloc_iprd_idx), 59 | 60 | .i_squash_vld(i_squash_vld), 61 | .i_commit_vld(i_commit_vld), 62 | .i_commitInfo(i_commitInfo) 63 | ); 64 | 65 | wire [`WDEF(`COMMIT_WIDTH)] commit_has_rd, commit_ismv; 66 | freelist u_freelist ( 67 | .clk(clk), 68 | .rst(rst), 69 | 70 | .o_can_alloc (o_can_rename), 71 | .i_alloc_req ((i_has_rd & (~i_ismv))), 72 | .o_alloc_prIdx(int_alloc_iprd_idx), 73 | 74 | .i_dealloc_req (int_dealloc_vld), 75 | .i_dealloc_prIdx(int_dealloc_iprd_idx), 76 | 77 | .i_resteer_vld(i_squash_vld), 78 | // this commit vld = i_commit_vld & commitInfo.has_rd & (~commitInfo.ismv) 79 | // it muse be update in one cycle with commit 80 | .i_commit_vld ((i_commit_vld & commit_has_rd & (~commit_ismv))) 81 | ); 82 | 83 | generate 84 | for (i = 0; i < `COMMIT_WIDTH; i = i + 1) begin 85 | assign commit_has_rd[i] = i_commitInfo[i].has_rd; 86 | assign commit_ismv[i] = i_commitInfo[i].ismv; 87 | end 88 | endgenerate 89 | 90 | endmodule 91 | -------------------------------------------------------------------------------- /rtl/cpu/core_comm.svh: -------------------------------------------------------------------------------- 1 | `ifndef __CORE_COMM_SVH__ 2 | `define __CORE_COMM_SVH__ 3 | 4 | `include "base.svh" 5 | 6 | `define FTB_PREDICT_WIDTH 24 // byte 7 | `define CACHELINE_SIZE 32 // Byte 8 | `define XLEN 64 9 | `define XLEN_64 10 | `define INIT_PC 64'h0000000080000000 11 | 12 | // cache region fast define 13 | `define BLKDEF `WDEF(`XLEN - $clog2(`CACHELINE_SIZE)) 14 | `define BLK_RANGE `XLEN - 1 : $clog2(`CACHELINE_SIZE) 15 | 16 | `define BLOCKADDR(x) ((``x``)>>$clog2(`CACHELINE_SIZE)) 17 | `define PADDR(x) ``x``[`PALEN-1:0] 18 | 19 | //int logic register index def 20 | `define ILRIDX_DEF `WDEF($clog2(32)) 21 | //flt logic register index def 22 | `define FLRIDX_DEF `ILRIDX_DEF 23 | //xlen fast define 24 | `define XDEF `WDEF(`XLEN) 25 | //instruction fast define 26 | `define IDEF `WDEF(32) 27 | 28 | `define CSRIDX_DEF `WDEF(12) 29 | `define PCDEF `WDEF(64) 30 | `define IMMDEF `WDEF(20) 31 | 32 | `define FTQ_SIZE 32 33 | `define IPHYREG_NUM 80 34 | `define IMMBUFFER_SIZE 60 35 | `define ROB_SIZE 128 36 | `define INTDQ_SIZE 16 37 | `define MEMDQ_SIZE 16 38 | `define LDIQ_SIZE 16 39 | `define LQSIZE 64 40 | `define SQSIZE 64 41 | 42 | `define SSIT_SIZE 1024 43 | `define MEMDEP_FOLDPC_WIDTH $clog2(`SSIT_SIZE) 44 | `define LFST_SIZE 32 45 | 46 | `include "core_priv.svh" 47 | 48 | `define OLDER_THAN(a, b) ((``a``.flipped == ``b``.flipped) ? (``a``.idx < ``b``.idx) : (``a``.idx > ``b``.idx)) 49 | 50 | typedef logic [`WDEF(`PALEN)] paddr_t; 51 | 52 | typedef logic [`WDEF($clog2(`FTQ_SIZE))] ftqIdx_t; 53 | typedef logic [`WDEF($clog2(`FTB_PREDICT_WIDTH))] ftqOffset_t; 54 | typedef struct packed { 55 | logic flipped; 56 | logic [`WDEF($clog2(`ROB_SIZE))] idx; 57 | } robIdx_t; 58 | // typedef logic [`WDEF($clog2(`ROB_SIZE))] robIdx_t; 59 | typedef logic [`WDEF($clog2(`IMMBUFFER_SIZE))] irobIdx_t; // the immBuffer idx 60 | 61 | //[int/fp][logic/physic]r[dest/src]Idx 62 | typedef logic [`WDEF($clog2(32))] ilrIdx_t; //the int logic regfile idx 63 | typedef logic [ 64 | `WDEF($clog2(`IPHYREG_NUM)) 65 | ] iprIdx_t; //the int physic regfile idx 66 | typedef logic [`WDEF(12)] csrIdx_t; //the csr regfile idx 67 | 68 | typedef logic [`IMMDEF] imm_t; 69 | 70 | typedef struct packed { 71 | logic flipped; 72 | logic [`WDEF($clog2(`LQSIZE))] idx; 73 | } lqIdx_t; 74 | 75 | typedef struct packed { 76 | logic flipped; 77 | logic [`WDEF($clog2(`SQSIZE))] idx; 78 | } sqIdx_t; 79 | 80 | package rv_trap_t; 81 | //mtvec mode: 82 | //0:Direct All exceptions set pc to BASE. 83 | //1:Vectored Asynchronous interrupts set pc to BASE+4×cause. 84 | `define TRAPCODE_WIDTH 16 85 | // mcause (actually, 16bits mcause reg is enough) 86 | typedef enum logic [ 87 | `WDEF(`TRAPCODE_WIDTH) 88 | ] { 89 | //instruction fetch and decode 90 | pcMisaligned = 0, // instruction address misaligned 91 | fetchFault = 1, // instruction access fault 92 | instIllegal = 2, // Illegal instruction 93 | breakpoint = 3, 94 | //load, store/AMO 95 | loadMisaligned = 4, 96 | loadFault = 5, 97 | storeMisaligned = 6, 98 | storeFault = 7, 99 | //env call 100 | ucall = 8, 101 | scall = 9, 102 | mcall = 11, 103 | fetchPageFault = 12, 104 | loadPageFault = 13, 105 | storePageFault = 15, 106 | //NOTE:24-31/48-63, designated for custom use 107 | reExec = 128, 108 | reserved_exception 109 | } exception; 110 | typedef enum logic [ 111 | `WDEF(`TRAPCODE_WIDTH) 112 | ] { 113 | sSoft = 1, // Supervisor software interrupt 114 | mSoft = 3, 115 | sTimer = 5, // Supervisor timer interrupt 116 | mTimer = 7, 117 | sExter = 9, // Supervisor external interrupt 118 | mExter = 11, 119 | //>=16 Designated for platform use 120 | reserved_interrupts 121 | } interrupt; 122 | 123 | endpackage 124 | 125 | 126 | `endif 127 | -------------------------------------------------------------------------------- /rtl/cpu/core_config.svh: -------------------------------------------------------------------------------- 1 | `ifndef __CORE_CONFIG_SVH__ 2 | `define __CORE_CONFIG_SVH__ 3 | 4 | `include "core_comm.svh" 5 | 6 | 7 | `define FETCH_WIDTH `FTB_PREDICT_WIDTH/2 8 | 9 | // decode rename 10 | `define DECODE_WIDTH 4 11 | `define RENAME_WIDTH `DECODE_WIDTH 12 | 13 | `define ENABLE_MEMPRED 1 14 | 15 | `define STORE_ISSUE_WIDTH 2 16 | 17 | // commit 18 | `define COMMIT_WIDTH 4 19 | 20 | 21 | `endif 22 | 23 | -------------------------------------------------------------------------------- /rtl/cpu/core_define.svh: -------------------------------------------------------------------------------- 1 | `ifndef __CORE_DEFINE_SVH__ 2 | `define __CORE_DEFINE_SVH__ 3 | 4 | `include "core_config.svh" 5 | `include "decode_define.svh" 6 | 7 | package BranchType; 8 | typedef enum logic [2:0] { 9 | isNone = 0, 10 | isCond, 11 | isDirect, 12 | isIndirect, 13 | isCall, 14 | isRet 15 | } _; 16 | endpackage 17 | 18 | 19 | typedef struct packed { 20 | logic [`IDEF] inst; 21 | ftqIdx_t ftq_idx; 22 | ftqOffset_t ftqOffset; 23 | logic [`WDEF(`MEMDEP_FOLDPC_WIDTH)] foldpc; 24 | logic has_except; 25 | rv_trap_t::exception except; 26 | logic [`XDEF] instmeta; 27 | } fetchEntry_t; 28 | 29 | 30 | typedef struct { 31 | BranchType::_ branch_type; 32 | robIdx_t rob_idx; 33 | ftqIdx_t ftq_idx; 34 | // the branchInst is mispred taken 35 | logic has_mispred; 36 | // is branchInst actually taken ? (the jal inst must taken) 37 | logic branch_taken; 38 | // branchInst's fallthruOffset 39 | // NOTE: fallthruOffset may >= FTB_PREDICT_WIDTH 40 | logic [`WDEF($clog2(`FTB_PREDICT_WIDTH) + 1)] fallthruOffset; 41 | // branchInst's taken pc 42 | logic [`XDEF] target_pc; 43 | // branchInst's nextpc 44 | logic [`XDEF] branch_npc; 45 | } branchwbInfo_t; // writeback to rob and ftq 46 | 47 | 48 | // DESIGN: 49 | // only when branch retired, rob can send squashInfo 50 | // and squashInfo priority is greater than commitInfo 51 | // when squashed 52 | // set the spec-status to arch-status 53 | 54 | // commit do something: 55 | // check csr permission 56 | // check exception 57 | // use spec-arch to restore core status 58 | 59 | 60 | typedef struct { 61 | logic dueToBranch; 62 | logic dueToViolation; 63 | logic branch_taken; 64 | logic [`XDEF] arch_pc; 65 | 66 | // violation info 67 | logic [`WDEF(`MEMDEP_FOLDPC_WIDTH)] stpc; 68 | logic [`WDEF(`MEMDEP_FOLDPC_WIDTH)] ldpc; 69 | } squashInfo_t; 70 | 71 | 72 | `endif 73 | -------------------------------------------------------------------------------- /rtl/cpu/core_priv.svh: -------------------------------------------------------------------------------- 1 | `ifndef __CORE_PRIV_SVH__ 2 | `define __CORE_PRIV_SVH__ 3 | 4 | `include "core_config.svh" 5 | 6 | `define SV39_SUPPORT 1 7 | 8 | `define PALEN 36 9 | 10 | `define VADDR(x) ``x``[39-1:0] 11 | 12 | 13 | `define CSR_MHARTID 'hf14 14 | `define CSR_MSTATUS 'h300 15 | `define CSR_MIE 'h304 16 | `define CSR_MTVEC 'h305 17 | `define CSR_MEPC 'h341 18 | `define CSR_MCAUSE 'h342 19 | `define CSR_MTVAL 'h343 20 | `define CSR_MIP 'h344 21 | 22 | `define MODE_M 3 23 | `define MODE_S 1 24 | `define MODE_U 0 25 | 26 | `define GETMODE(x) ``x``[9:8] 27 | `define CSR_READONLY(x) (``x``[11:10] == 2'b11) 28 | 29 | 30 | typedef struct { 31 | // trap info 32 | logic [`WDEF(2)] mode; 33 | logic [`XDEF] status; 34 | logic [`XDEF] epc; 35 | logic interrupt_vectored; 36 | logic [`XDEF] tvec; 37 | } csr_in_pack_t; 38 | 39 | typedef struct { 40 | // trap handle 41 | logic has_trap; 42 | logic [`XDEF] epc; 43 | logic [`XDEF] cause; 44 | logic [`XDEF] tval; 45 | } trap_pack_t; 46 | 47 | 48 | `define INIT_MSTATUS (64'h0000000a_00000000) 49 | `define MSTATUS_READ_MASK (64'h8000003F_007FFFEA) 50 | `define MSTATUS_WRITE_MASK (64'h80000030_007FFFEA) 51 | typedef struct packed { 52 | logic sd; 53 | logic [`WDEF(25)] wpri4; 54 | logic mbe; 55 | logic sbe; 56 | logic [`WDEF(2)] sxl; 57 | logic [`WDEF(2)] uxl; 58 | logic [`WDEF(9)] wpri3; 59 | logic tsr; 60 | logic tw; 61 | logic tvm; 62 | logic mxr; 63 | logic sum; 64 | logic mprv; 65 | logic [`WDEF(2)] xs; 66 | logic [`WDEF(2)] fs; 67 | logic [`WDEF(2)] mpp; 68 | logic [`WDEF(2)] vs; 69 | logic spp; 70 | logic mpie; 71 | logic ube; 72 | logic spie; 73 | logic wpri2; 74 | logic mie; 75 | logic wpri1; 76 | logic sie; 77 | logic wpri0; 78 | } mstatus_csr_t; 79 | 80 | typedef struct packed { 81 | logic [`WDEF(`XLEN-2)] base; 82 | logic [`WDEF(2)] mode; 83 | } mtvec_csr_t; 84 | 85 | `define MIP_MIE_WRITE_MASK (64'h555) 86 | typedef struct packed { 87 | logic meip; 88 | logic zero5; 89 | logic seip; 90 | logic zero4; 91 | logic mtip; 92 | logic zero3; 93 | logic stip; 94 | logic zero2; 95 | logic msip; 96 | logic zero1; 97 | logic ssip; 98 | logic zero0; 99 | } mip_csr_t; 100 | 101 | typedef struct packed { 102 | logic meie; 103 | logic zero5; 104 | logic seie; 105 | logic zero4; 106 | logic mtie; 107 | logic zero3; 108 | logic stie; 109 | logic zero2; 110 | logic msie; 111 | logic zero1; 112 | logic ssie; 113 | logic zero0; 114 | } mie_csr_t; 115 | 116 | typedef struct packed { 117 | logic inter; 118 | logic [`WDEF(63)] except_code; 119 | } mcause_csr_t; 120 | 121 | 122 | `endif 123 | -------------------------------------------------------------------------------- /rtl/cpu/frontend/aura_frontend.sv: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | // cpu frontend 7 | // storage <-tilelink-> frontend <--> backend 8 | 9 | 10 | 11 | 12 | module aura_frontend ( 13 | input wire clk, 14 | input wire rst, 15 | 16 | input wire i_squash_vld, 17 | input squashInfo_t i_squashInfo, 18 | 19 | // from backend 20 | input wire [`WDEF(`BRU_NUM)] i_branchwb_vld, 21 | input branchwbInfo_t i_branchwbInfo[`BRU_NUM], 22 | 23 | input ftqIdx_t i_read_ftqIdx[`BRU_NUM + `LDU_NUM + `STU_NUM], 24 | output wire [`XDEF] o_read_ftqStartAddr[`BRU_NUM + `LDU_NUM + `STU_NUM], 25 | output wire [`XDEF] o_read_ftqNextAddr[`BRU_NUM + `LDU_NUM + `STU_NUM], 26 | 27 | // to backend 28 | input wire i_backend_stall, 29 | output wire [`WDEF(`FETCH_WIDTH)] o_fetch_inst_vld, 30 | output fetchEntry_t o_fetch_inst[`FETCH_WIDTH], 31 | 32 | input wire i_commit_vld, 33 | input ftqIdx_t i_commit_ftqIdx, 34 | 35 | 36 | // to next level storage 37 | tilelink_if.m if_fetch_bus 38 | ); 39 | 40 | 41 | 42 | core2icache_if if_toIcache (); 43 | 44 | fetcher u_fetcher ( 45 | .clk (clk), 46 | .rst (rst), 47 | .i_squash_vld(i_squash_vld), 48 | .i_squashInfo(i_squashInfo), 49 | 50 | .i_branchwb_vld(i_branchwb_vld), 51 | .i_branchwbInfo(i_branchwbInfo), 52 | 53 | .i_read_ftqIdx (i_read_ftqIdx), 54 | .o_read_ftqStartAddr(o_read_ftqStartAddr), 55 | .o_read_ftqNextAddr (o_read_ftqNextAddr), 56 | 57 | .i_backend_stall (i_backend_stall), 58 | .o_fetch_inst_vld(o_fetch_inst_vld), 59 | .o_fetch_inst (o_fetch_inst), 60 | 61 | .i_commit_vld (i_commit_vld), 62 | .i_commit_ftqIdx(i_commit_ftqIdx), 63 | 64 | .if_core_fetch(if_toIcache) 65 | ); 66 | 67 | icache #( 68 | .BANKS(1), 69 | .SETS (32), 70 | .WAYS (4) 71 | ) u_icache ( 72 | .clk (clk), 73 | .rst (rst), 74 | .if_core_fetch(if_toIcache) 75 | ); 76 | 77 | 78 | 79 | 80 | endmodule 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /rtl/cpu/frontend/bp/FTB.sv: -------------------------------------------------------------------------------- 1 | `include "frontend_define.svh" 2 | 3 | import "DPI-C" function void ftb_update_new_block( 4 | uint64_t startAddr, 5 | uint64_t fallthru, 6 | uint64_t target 7 | ); 8 | 9 | // do predict 10 | // s0: send req | s1: get 4 way datas | s2: output the ftbInfo 11 | // do update or alloc 12 | // s0: send req | s1: get 4 way datas | s2: select and update | s3: write back to ftb 13 | 14 | 15 | package FTB_status_t; 16 | typedef enum logic { 17 | normal, 18 | updating 19 | } _; 20 | endpackage 21 | 22 | module FTB ( 23 | input wire clk, 24 | input wire rst, 25 | input wire i_squash_vld, 26 | 27 | // do predict 28 | input wire i_lookup_req, 29 | output wire o_lookup_gnt, 30 | input wire [`XDEF] i_lookup_pc, 31 | output wire o_lookup_hit, // s1 32 | output wire o_lookup_hit_rdy, // s1 33 | output ftbInfo_t o_lookup_ftbInfo, // s2 34 | 35 | // do update 36 | input wire i_update_req, 37 | output wire o_update_finished, 38 | input wire [`XDEF] i_update_pc, 39 | input ftbInfo_t i_update_ftbInfo 40 | ); 41 | 42 | 43 | FTB_status_t::_ status; 44 | 45 | wire [`WDEF(`FTB_WAYS)] s1_update_sel_vec; 46 | reg s1_update_vld; 47 | FTB_sram #( 48 | .SETS(`FTB_SETS), 49 | .WAYS(`FTB_WAYS) 50 | ) u_FTB_sram ( 51 | .clk (clk), 52 | .rst (rst), 53 | .i_squash_vld (i_squash_vld), 54 | .i_lookup_req (i_lookup_req), 55 | .o_lookup_gnt (), // dont care 56 | .i_lookup_pc (i_lookup_pc), 57 | .o_lookup_hit (o_lookup_hit), 58 | .o_lookup_hit_rdy(o_lookup_hit_rdy), 59 | .o_lookup_info (o_lookup_ftbInfo), 60 | 61 | .i_update_req (i_update_req), 62 | .i_update_pc (i_update_pc), 63 | .o_update_sel_vec(s1_update_sel_vec), 64 | 65 | .i_write_req (s1_update_vld), 66 | .i_write_way_vec(s1_update_sel_vec), 67 | .i_write_info (i_update_ftbInfo) 68 | ); 69 | 70 | 71 | // global status 72 | always_ff @(posedge clk) begin 73 | if (rst) begin 74 | status <= FTB_status_t::normal; 75 | s1_update_vld <= 0; 76 | end 77 | else begin 78 | if ((status == FTB_status_t::normal) && i_update_req) begin // s0 79 | status <= FTB_status_t::updating; 80 | s1_update_vld <= 1; 81 | ftb_update_new_block(i_update_pc, ftbFuncs::calcFallthruAddr(i_update_pc, i_update_ftbInfo), 82 | ftbFuncs::calcTargetAddr(i_update_pc, i_update_ftbInfo)); 83 | end 84 | else if (status == FTB_status_t::updating) begin // s1 85 | s1_update_vld <= 0; 86 | status <= FTB_status_t::normal; 87 | end 88 | end 89 | end 90 | 91 | assign o_lookup_gnt = i_lookup_req && (!i_update_req) && (status == FTB_status_t::normal); 92 | assign o_update_finished = (status == FTB_status_t::updating); 93 | 94 | endmodule 95 | -------------------------------------------------------------------------------- /rtl/cpu/frontend/bp/FTB_sram.sv: -------------------------------------------------------------------------------- 1 | `include "frontend_define.svh" 2 | `include "funcs.svh" 3 | import funcs::*; 4 | 5 | typedef struct packed { 6 | logic [`WDEF(`FTB_TAG_WIDTH)] tag; 7 | logic vld; 8 | ftbInfo_t info; 9 | } ftbEntry_t; 10 | 11 | module FTB_sram #( 12 | parameter int SETS = 32, 13 | parameter int WAYS = 4 14 | ) ( 15 | input wire clk, 16 | input wire rst, 17 | input wire i_squash_vld, 18 | 19 | // lookup 20 | input wire i_lookup_req, 21 | output wire o_lookup_gnt, // s0 22 | input wire [`XDEF] i_lookup_pc, 23 | output wire o_lookup_hit, // s1 24 | output wire o_lookup_hit_rdy, // s1 25 | output ftbInfo_t o_lookup_info, // s2 26 | 27 | // update 28 | input wire i_update_req, // s0: lookup for update, s1: write for update 29 | input wire [`XDEF] i_update_pc, 30 | output wire [`WDEF(WAYS)] o_update_sel_vec, // the wayIdx needed update which was select 31 | 32 | // write 33 | input wire i_write_req, 34 | input wire [`WDEF(WAYS)] i_write_way_vec, 35 | input ftbInfo_t i_write_info 36 | ); 37 | genvar i; 38 | localparam int INDEX_WIDTH = $clog2(SETS); // 5 39 | 40 | `define INDEX_RANGE INDEX_WIDTH+1 - 1 : 1 41 | `define TAG_RANGE `FTB_TAG_WIDTH + (INDEX_WIDTH+1)-1 : INDEX_WIDTH+1 42 | 43 | // send response 44 | wire sram_read_req = i_lookup_req || i_update_req; 45 | assign o_lookup_gnt = sram_read_req; 46 | wire [`WDEF(WAYS)] write_vec = i_write_way_vec; 47 | wire [`XDEF] access_addr = i_update_req ? i_update_pc : i_lookup_pc; 48 | wire [`WDEF(WAYS)] s1_req_hit; 49 | 50 | reg s1_req; 51 | reg s1_islookup; 52 | reg [`XDEF] s1_access_addr; 53 | wire [`WDEF(`FTB_TAG_WIDTH)] s1_tag = s1_access_addr[`TAG_RANGE]; 54 | 55 | ftbEntry_t read_data[WAYS], write_data[WAYS]; 56 | 57 | wire [`WDEF(INDEX_WIDTH)] index = access_addr[`INDEX_RANGE]; 58 | sramSet #( 59 | .SETS (SETS), 60 | .WAYS (WAYS), 61 | .dtype (ftbEntry_t), 62 | .NEEDRESET(1) 63 | ) u_sramSet ( 64 | .clk(clk), 65 | .rst(rst), 66 | 67 | .i_addr (index), 68 | .i_read_en (sram_read_req), 69 | .i_write_en_vec(i_write_req ? i_write_way_vec : 0), 70 | .o_read_data (read_data), 71 | .i_write_data (write_data) 72 | ); 73 | generate 74 | for (i = 0; i < WAYS; i = i + 1) begin 75 | assign write_data[i] = '{tag: s1_access_addr[`TAG_RANGE], vld: 1, info: i_write_info}; 76 | end 77 | endgenerate 78 | 79 | // replacement 80 | 81 | wire [`WDEF($clog2(SETS))] rep_setIdx = access_addr[`INDEX_RANGE]; 82 | wire [`WDEF(WAYS)] rep_replace_vec; 83 | wire rep_update = (|s1_req_hit) && s1_islookup; 84 | wire [`WDEF(WAYS)] rep_wayhit_vec = s1_req_hit; 85 | 86 | random_rep #( 87 | .SETS(SETS), 88 | .WAYS(WAYS) 89 | ) u_random_rep ( 90 | .clk (clk), 91 | .rst (rst), 92 | .i_setIdx (rep_setIdx), 93 | .o_replace_vec(rep_replace_vec), 94 | .i_update_req (rep_update), 95 | .i_wayhit_vec (rep_wayhit_vec) 96 | ); 97 | 98 | // hit check 99 | ftbInfo_t s2_lookup_info; 100 | always_ff @(posedge clk) begin 101 | int fa; 102 | if (rst) begin 103 | s1_req <= 0; 104 | s1_islookup <= 1; 105 | end 106 | else begin 107 | if (i_squash_vld) begin 108 | s1_islookup <= 0; 109 | end 110 | else begin 111 | s1_islookup <= i_lookup_req && (!i_update_req); 112 | end 113 | 114 | s1_req <= sram_read_req; 115 | s1_access_addr <= access_addr; 116 | 117 | for (fa = 0; fa < WAYS; fa = fa + 1) begin 118 | if (s1_req_hit[fa]) begin 119 | s2_lookup_info <= read_data[fa].info; 120 | end 121 | end 122 | end 123 | end 124 | 125 | generate 126 | for (i = 0; i < WAYS; i = i + 1) begin 127 | assign s1_req_hit[i] = (read_data[i].tag == s1_access_addr[`TAG_RANGE]) && read_data[i].vld && s1_req; 128 | end 129 | endgenerate 130 | `ASSERT(count_one(s1_req_hit) == 1 || count_one(s1_req_hit) == 0); 131 | 132 | assign o_lookup_info = s2_lookup_info; 133 | assign o_lookup_hit = |s1_req_hit; 134 | assign o_lookup_hit_rdy = s1_req && s1_islookup; 135 | 136 | assign o_update_sel_vec = |s1_req_hit ? s1_req_hit : rep_replace_vec; 137 | 138 | endmodule 139 | 140 | 141 | -------------------------------------------------------------------------------- /rtl/cpu/frontend/bp/preDecode.sv: -------------------------------------------------------------------------------- 1 | `include "frontend_define.svh" 2 | 3 | 4 | module preDecode ( 5 | input wire [`IDEF] i_inst, 6 | input wire [`XDEF] i_pc, 7 | output preDecInfo_t o_info 8 | ); 9 | wire isRVC = (i_inst[1:0] != 2'b11); 10 | 11 | wire inst_JALR = (i_inst ==? 32'b?????????????????000?????1100111); 12 | wire inst_JAL = (i_inst ==? 32'b?????????????????????????1101111); 13 | wire inst_BEQ = (i_inst ==? 32'b?????????????????000?????1100011); 14 | wire inst_BGE = (i_inst ==? 32'b?????????????????101?????1100011); 15 | wire inst_BGEU = (i_inst ==? 32'b?????????????????111?????1100011); 16 | wire inst_BLT = (i_inst ==? 32'b?????????????????100?????1100011); 17 | wire inst_BLTU = (i_inst ==? 32'b?????????????????110?????1100011); 18 | wire inst_BNE = (i_inst ==? 32'b?????????????????001?????1100011); 19 | wire [19:0] inst_i_type_imm = {{8{i_inst[31]}}, i_inst[31:20]}; // jalr 20 | wire [19:0] inst_j_type_imm = {i_inst[19:12], i_inst[20], i_inst[30:21], 1'b0}; // jal 21 | wire [19:0] inst_b_type_imm = {{8{i_inst[31]}}, i_inst[7], i_inst[30:25], i_inst[11:8], 1'b0}; // branch 22 | 23 | wire [`XDEF] condTarget = i_pc + {{44{inst_b_type_imm[19]}}, inst_b_type_imm}; 24 | wire [`XDEF] directTarget = i_pc + {{44{inst_j_type_imm[19]}}, inst_j_type_imm}; 25 | wire [`XDEF] indirectTarget = i_pc + {{44{inst_i_type_imm[19]}}, inst_i_type_imm}; // just predicted 26 | 27 | wire isDirect = inst_JAL; 28 | wire isIndirect = inst_JALR; 29 | wire isCond = (inst_BEQ || inst_BGE || inst_BGEU || inst_BLT || inst_BLTU || inst_BNE); 30 | 31 | // condBranch's probability of jumping backward is large than jumping forward 32 | wire condBr_jump_back = isCond && (inst_b_type_imm[19]); 33 | 34 | wire [`XDEF] target = isDirect ? directTarget : isIndirect ? indirectTarget : condTarget; 35 | 36 | wire [`XDEF] fallthru = i_pc + (isRVC ? 2 : 4); 37 | 38 | wire[`XDEF] simplePredNPC = 39 | isDirect ? directTarget : 40 | isIndirect ? indirectTarget : 41 | condBr_jump_back ? condTarget :// a simple predict 42 | fallthru; 43 | 44 | assign o_info = '{ 45 | fallthru : fallthru, 46 | isCond : isCond, 47 | isDirect : isDirect, 48 | isIndirect : isIndirect, 49 | isBr : (isCond || isDirect || isIndirect), 50 | target : target, 51 | simplePredNPC : simplePredNPC 52 | }; 53 | 54 | 55 | endmodule 56 | 57 | 58 | -------------------------------------------------------------------------------- /rtl/cpu/frontend/bp/uBTB.sv: -------------------------------------------------------------------------------- 1 | `include "frontend_define.svh" 2 | 3 | import "DPI-C" function void ubtb_update_new_block( 4 | uint64_t uindex, 5 | uint64_t startAddr, 6 | uint64_t fallthru, 7 | uint64_t target, 8 | uint64_t scnt, 9 | uint64_t phtindex 10 | ); 11 | 12 | import "DPI-C" function void ubtb_loookup( 13 | uint64_t lookup_pc, 14 | uint64_t endAddr, 15 | uint64_t targetAddr, 16 | uint64_t hit, 17 | uint64_t taken, 18 | uint64_t index, 19 | uint64_t phtindex 20 | ); 21 | 22 | `define TAG_WIDTH 9 23 | `define TARGET_WIDTH 11 // actually is (11+1) 24 | 25 | typedef struct packed { 26 | logic vld; 27 | logic [`WDEF(`TAG_WIDTH)] tag; 28 | logic [`WDEF($clog2(`FTB_PREDICT_WIDTH))] fallthruOffset; 29 | logic [`WDEF(`TARGET_WIDTH)] targetAddr; 30 | BranchType::_ branch_type; 31 | } uFTBEntry_t; 32 | 33 | module uBTB #( 34 | parameter int DEPTH = 32 35 | ) ( 36 | input wire clk, 37 | input wire rst, 38 | 39 | input wire [`XDEF] i_lookup_pc, 40 | input wire [`WDEF(`BRHISTORYLENGTH)] i_gbh, 41 | 42 | output uBTBInfo_t o_uBTBInfo, 43 | 44 | input wire i_update, 45 | input wire [`XDEF] i_update_pc, 46 | input wire [`WDEF(`BRHISTORYLENGTH)] i_arch_gbh, 47 | input uBTBInfo_t i_updateInfo 48 | ); 49 | localparam int PHTDEPTH = DEPTH * 4; 50 | 51 | uFTBEntry_t uftb[DEPTH]; 52 | reg [`WDEF(2)] pht[PHTDEPTH]; 53 | 54 | // lookup 55 | wire [`WDEF($clog2(DEPTH))] index_btb; 56 | wire [`WDEF($clog2(PHTDEPTH))] index_pht; 57 | wire [`WDEF(`TAG_WIDTH)] tag; 58 | assign index_btb = i_lookup_pc[$clog2(DEPTH)+1:2]; 59 | assign index_pht = i_lookup_pc[$clog2(PHTDEPTH)+1:2] ^ i_gbh[$clog2(PHTDEPTH)-1:0]; 60 | assign tag = (i_lookup_pc[`TAG_WIDTH:1] ^ i_lookup_pc[2*`TAG_WIDTH:`TAG_WIDTH+1]); 61 | 62 | uFTBEntry_t indexed_data; 63 | wire [`WDEF(2)] indexed_scnt; 64 | assign indexed_data = uftb[index_btb]; 65 | assign indexed_scnt = pht[index_pht]; 66 | 67 | wire hit = (indexed_data.tag == tag) && indexed_data.vld; 68 | wire taken = hit && ((indexed_scnt >= 2) || (indexed_data.branch_type > BranchType::isCond)); 69 | wire [`XDEF] fallthruAddr = (i_lookup_pc + indexed_data.fallthruOffset); 70 | wire [`XDEF] targetAddr = {i_lookup_pc[`XLEN-1:`TARGET_WIDTH+1], indexed_data.targetAddr, 1'b0}; 71 | wire [`XDEF] nextAddr = (taken ? targetAddr : fallthruAddr); 72 | 73 | assign o_uBTBInfo = '{ 74 | hit : hit, 75 | taken : taken, 76 | fallthruAddr : fallthruAddr, 77 | targetAddr : targetAddr, 78 | nextAddr : nextAddr, 79 | branch_type : indexed_data.branch_type 80 | }; 81 | 82 | // update 83 | wire [`WDEF($clog2(DEPTH))] uindex_btb; 84 | wire [`WDEF($clog2(PHTDEPTH))] uindex_pht; 85 | wire [`WDEF(`TAG_WIDTH)] utag; 86 | wire [`WDEF($clog2(`FTB_PREDICT_WIDTH))] ufallthruOffset; 87 | wire [`WDEF(`TARGET_WIDTH)] utargetAddr; 88 | assign uindex_btb = i_update_pc[$clog2(DEPTH)+1:2]; 89 | assign uindex_pht = i_update_pc[$clog2(PHTDEPTH)+1:2] ^ i_arch_gbh[$clog2(PHTDEPTH)-1:0]; 90 | assign utag = (i_update_pc[`TAG_WIDTH:1] ^ i_update_pc[2*`TAG_WIDTH:`TAG_WIDTH+1]); 91 | 92 | assign ufallthruOffset = (i_updateInfo.fallthruAddr - i_update_pc); 93 | assign utargetAddr = i_updateInfo.targetAddr[`TARGET_WIDTH:1]; 94 | 95 | always_ff @(posedge clk) begin 96 | int fa; 97 | if (rst) begin 98 | for (fa = 0; fa < DEPTH; fa = fa + 1) begin 99 | uftb[fa].vld = 0; 100 | end 101 | for (fa = 0; fa < PHTDEPTH; fa = fa + 1) begin 102 | pht[fa] = 1; 103 | end 104 | end 105 | else begin 106 | ubtb_loookup(i_lookup_pc, fallthruAddr, targetAddr, hit, taken, index_btb, index_pht); 107 | if (i_update) begin 108 | uftb[uindex_btb] <= '{ 109 | vld : 1, 110 | tag : utag, 111 | fallthruOffset : ufallthruOffset, 112 | targetAddr : utargetAddr, 113 | branch_type : i_updateInfo.branch_type 114 | }; 115 | if (i_updateInfo.branch_type == BranchType::isCond) begin 116 | pht[uindex_pht] <= ftbFuncs::counterUpdate(pht[uindex_pht], i_updateInfo.taken); 117 | end 118 | ubtb_update_new_block(uindex_btb, i_update_pc, i_updateInfo.fallthruAddr, i_updateInfo.targetAddr, 119 | ftbFuncs::counterUpdate(pht[uindex_pht], i_updateInfo.taken), uindex_pht); 120 | end 121 | end 122 | end 123 | 124 | endmodule 125 | 126 | 127 | -------------------------------------------------------------------------------- /rtl/cpu/frontend/frontend_config.svh: -------------------------------------------------------------------------------- 1 | `ifndef __FRONTEND_CONFIG_SVH__ 2 | `define __FRONTEND_CONFIG_SVH__ 3 | 4 | 5 | `include "core_define.svh" 6 | 7 | /* FTB config */ 8 | 9 | 10 | `define FTB_TAG_WIDTH 11 11 | `define FTB_FALLTHRU_WIDTH ($clog2(`FTB_PREDICT_WIDTH) - 1) // 12 | `define FTB_TARGET_WIDTH 11 // actually is (11+1) 13 | 14 | `define FTB_SETS 128 15 | `define FTB_WAYS 4 16 | 17 | `define BRHISTORYLENGTH 40 18 | 19 | 20 | 21 | `endif 22 | -------------------------------------------------------------------------------- /rtl/cpu/frontend/frontend_define.svh: -------------------------------------------------------------------------------- 1 | `ifndef __FORNTEND_DEFINE_SVH__ 2 | `define __FORNTEND_DEFINE_SVH__ 3 | 4 | 5 | `include "frontend_config.svh" 6 | 7 | 8 | package tarStat_t; 9 | typedef enum logic [2:0] { 10 | FIT, // {higher_bits, targte} 11 | OVF, // {higher_bits + 1, targte} 12 | UDF // {higher_bits - 1, targte} 13 | } _; 14 | endpackage 15 | 16 | // uBTB 17 | typedef struct { 18 | logic hit; 19 | logic taken; 20 | logic [`XDEF] fallthruAddr; 21 | logic [`XDEF] targetAddr; 22 | logic [`XDEF] nextAddr; 23 | BranchType::_ branch_type; 24 | } uBTBInfo_t; 25 | 26 | // FTB 27 | typedef struct packed { 28 | logic carry; 29 | logic [`WDEF(`FTB_FALLTHRU_WIDTH)] fallthruAddr; 30 | tarStat_t::_ tarStat; 31 | logic [`WDEF(`FTB_TARGET_WIDTH)] targetAddr; 32 | BranchType::_ branch_type; 33 | } ftbInfo_t; 34 | 35 | //ftq 36 | typedef struct { 37 | logic [`XDEF] startAddr; 38 | logic [`XDEF] endAddr; 39 | logic [`XDEF] nextAddr; 40 | logic taken; 41 | logic [`XDEF] targetAddr; 42 | // ubtb meta 43 | logic hit_on_ubtb; 44 | // ftb meta 45 | logic hit_on_ftb; 46 | BranchType::_ branch_type; 47 | } BPInfo_t; 48 | 49 | typedef struct { 50 | logic [`XDEF] startAddr; 51 | logic [`XDEF] fallthruAddr; 52 | logic [`XDEF] targetAddr; 53 | BranchType::_ branch_type; 54 | logic taken; 55 | logic mispred; 56 | // original ubtb meta 57 | logic hit_on_ubtb; 58 | // original ftb meta 59 | logic hit_on_ftb; 60 | } BPupdateInfo_t; 61 | 62 | typedef struct { 63 | logic [`XDEF] startAddr; 64 | logic [`SDEF(`FTB_PREDICT_WIDTH)] fetchBlock_size; 65 | logic taken; 66 | logic [`XDEF] nextAddr; 67 | } ftq2icacheInfo_t; 68 | 69 | 70 | typedef struct { 71 | logic [`XDEF] fallthru; 72 | logic isCond; 73 | logic isDirect; 74 | logic isIndirect; 75 | logic isBr; 76 | logic [`XDEF] target; 77 | logic [`XDEF] simplePredNPC; 78 | } preDecInfo_t; 79 | 80 | package ftbFuncs; 81 | function automatic logic [`XDEF] calcFallthruAddr(logic [`XDEF] base_pc, ftbInfo_t ftbInfo); 82 | calcFallthruAddr = {base_pc[`XLEN-1 : `FTB_FALLTHRU_WIDTH+1] + ftbInfo.carry, ftbInfo.fallthruAddr, 1'b0}; 83 | endfunction 84 | 85 | function automatic logic [`XDEF] calcTargetAddr(logic [`XDEF] base_pc, ftbInfo_t ftbInfo); 86 | logic [`WDEF(`XLEN - `FTB_TARGET_WIDTH - 1)] higher; 87 | higher = ftbInfo.tarStat == tarStat_t::FIT ? base_pc[`XLEN-1 : `FTB_TARGET_WIDTH+1] : 88 | ftbInfo.tarStat == tarStat_t::OVF ? base_pc[`XLEN-1 : `FTB_TARGET_WIDTH+1] + 1 : 89 | ftbInfo.tarStat == tarStat_t::UDF ? base_pc[`XLEN-1 : `FTB_TARGET_WIDTH+1] - 1 : 90 | base_pc[`XLEN-1 : `FTB_TARGET_WIDTH+1]; 91 | calcTargetAddr = {higher, ftbInfo.targetAddr, 1'b0}; 92 | endfunction 93 | 94 | function automatic logic [`XDEF] calcNPC(logic [`XDEF] base_pc, logic taken, ftbInfo_t ftbInfo); 95 | logic [`XDEF] fallthruAddr = calcFallthruAddr(base_pc, ftbInfo); 96 | logic [`XDEF] targetAddr = calcTargetAddr(base_pc, ftbInfo); 97 | calcNPC = taken ? targetAddr : fallthruAddr; 98 | endfunction 99 | 100 | function automatic logic [`WDEF(2)] counterUpdate(logic [`WDEF(2)] source, logic taken); 101 | logic [`WDEF(2)] counter_0 = ((source == 0) ? 0 : source - 1); 102 | logic [`WDEF(2)] counter_1 = ((source == 3) ? 3 : source + 1); 103 | counterUpdate = taken ? counter_1 : counter_0; 104 | endfunction 105 | 106 | function automatic tarStat_t::_ calcuTarStat(logic [`XDEF] start, logic [`XDEF] target); 107 | calcuTarStat = 108 | target[`FTB_TARGET_WIDTH+3:`FTB_TARGET_WIDTH+1] == start[`FTB_TARGET_WIDTH+3:`FTB_TARGET_WIDTH+1] ? tarStat_t::FIT : 109 | target[`FTB_TARGET_WIDTH+3:`FTB_TARGET_WIDTH+1] > start[`FTB_TARGET_WIDTH+3:`FTB_TARGET_WIDTH+1] ? tarStat_t::OVF : 110 | tarStat_t::UDF; 111 | endfunction 112 | endpackage 113 | 114 | 115 | `endif 116 | -------------------------------------------------------------------------------- /rtl/cpu/mem/cache_sram.sv: -------------------------------------------------------------------------------- 1 | `include "core_define.svh" 2 | 3 | 4 | 5 | 6 | // read: s0: send req | s1: read data and select | s2: output 7 | // write: s0: send req | s1: read data and select | s2: output and modify | s3: writeback to cache 8 | module cache_sram #( 9 | parameter int BANK_TYPE = 1, // 0: none bank, 1: 2banks, 2: 4banks 10 | parameter int SETS = 32, 11 | parameter int WAYS = 4, 12 | parameter int ADDR_WIDTH = 64, 13 | parameter int CACHELINE_SIZE = 64 14 | ) ( 15 | input wire clk, 16 | input wire rst, 17 | 18 | // lookup 19 | input wire i_lookup_req, 20 | output wire o_lookup_gnt, 21 | input wire [`WDEF(ADDR_WIDTH)] i_lookup_addr, 22 | output wire o_lookup_hit, 23 | output wire o_lookup_hit_rdy, 24 | output wire [`WDEF(WAYS)] o_lookup_sel_vec, // if not hit, sel_vec is pointed to which need replace 25 | output wire [ 26 | `WDEF(CACHELINE_SIZE) 27 | ] o_lookup_data, // if hit, send data at next cycle, if not hit, send data which need to be replaced 28 | 29 | // write 30 | input wire i_write_req, 31 | input wire [`WDEF(ADDR_WIDTH)] i_write_addr, // we only use index 32 | input wire [`WDEF(WAYS)] i_write_way_vec, 33 | input wire [`WDEF(CACHELINE_SIZE)] i_write_data 34 | ); 35 | genvar i; 36 | localparam int INDEX_WIDTH = $clog2(SETS); 37 | 38 | `ASSERT(count_one(i_write_way_vec) == 1 || count_one(i_write_way_vec) == 0); 39 | `define INDEX_RANGE INDEX_WIDTH + $clog2(CACHELINE_SIZE) + BANK_TYPE - 1 : $clog2(CACHELINE_SIZE) + BANK_TYPE 40 | `define TAG_RANGE ADDR_WIDTH-1 : INDEX_WIDTH + $clog2(CACHELINE_SIZE) + BANK_TYPE 41 | 42 | // send response 43 | wire sram_read_req = i_lookup_req && (!i_write_req); 44 | assign o_lookup_gnt = sram_read_req; 45 | wire [`WDEF(WAYS)] write_vec = i_write_way_vec; 46 | wire [`XDEF] access_addr = i_write_req ? i_write_addr : i_lookup_addr; 47 | wire [`WDEF(WAYS)] s1_req_hit; 48 | 49 | reg s1_req; 50 | reg s1_islookup; 51 | reg [`XDEF] s1_access_addr; 52 | 53 | wire [`WDEF(CACHELINE_SIZE)] read_data[WAYS], write_data[WAYS]; 54 | 55 | sramSet #( 56 | .SETS (SETS), 57 | .WAYS (WAYS), 58 | .dtype (logic [`WDEF(CACHELINE_SIZE)]), 59 | .NEEDRESET(1) 60 | ) u_sramSet ( 61 | .clk(clk), 62 | .rst(rst), 63 | 64 | .i_addr (access_addr[`INDEX_RANGE]), 65 | .i_read_en (sram_read_req), 66 | .i_write_en_vec(i_write_req ? i_write_way_vec : 0), 67 | .o_read_data (read_data), 68 | .i_write_data (write_data) 69 | ); 70 | 71 | generate 72 | for (i = 0; i < WAYS; i = i + 1) begin 73 | assign write_data[i] = i_write_data; 74 | end 75 | endgenerate 76 | 77 | // replacement 78 | 79 | wire [`WDEF($clog2(SETS))] rep_setIdx = access_addr[`INDEX_RANGE]; 80 | wire [`WDEF(WAYS)] rep_replace_vec; 81 | wire rep_update = (|s1_req_hit) && s1_islookup; 82 | wire [`WDEF(WAYS)] rep_wayhit_vec = s1_req_hit; 83 | 84 | random_rep #( 85 | .SETS(SETS), 86 | .WAYS(WAYS) 87 | ) u_replace_policy ( 88 | .clk (clk), 89 | .rst (rst), 90 | .i_setIdx (rep_setIdx), 91 | .o_replace_vec(rep_replace_vec), 92 | .i_update_req (rep_update), 93 | .i_wayhit_vec (rep_wayhit_vec) 94 | ); 95 | 96 | // hit check 97 | reg [`WDEF(CACHELINE_SIZE)] s2_lookup_data; 98 | always_ff @(posedge clk) begin 99 | int fa; 100 | if (rst) begin 101 | s1_req <= 0; 102 | s1_islookup <= 1; 103 | end 104 | else begin 105 | if (i_squash_vld) begin 106 | s1_islookup <= 0; 107 | end 108 | else begin 109 | s1_islookup <= i_lookup_req && (!i_write_req); 110 | end 111 | 112 | s1_req <= sram_read_req; 113 | s1_access_addr <= access_addr; 114 | 115 | for (fa = 0; fa < WAYS; fa = fa + 1) begin 116 | if (rep_replace_vec[fa]) begin 117 | s2_lookup_data <= read_data[fa]; 118 | end 119 | end 120 | for (fa = 0; fa < WAYS; fa = fa + 1) begin 121 | if (s1_req_hit[fa]) begin 122 | s2_lookup_data <= read_data[fa]; 123 | end 124 | end 125 | 126 | end 127 | end 128 | 129 | generate 130 | for (i = 0; i < WAYS; i = i + 1) begin 131 | // FIXME: use meta sram 132 | assign s1_req_hit[i] = (read_data[i].tag == s1_access_addr[`TAG_RANGE]) && read_data[i].vld && s1_req; 133 | end 134 | endgenerate 135 | `ASSERT(count_one(s1_req_hit) == 1 || count_one(s1_req_hit) == 0); 136 | 137 | assign o_lookup_hit = |s1_req_hit; 138 | assign o_lookup_hit_rdy = s1_req && s1_islookup; 139 | assign o_lookup_sel_vec = |s1_req_hit ? s1_req_hit : rep_replace_vec; 140 | assign o_lookup_data = s2_lookup_data; 141 | 142 | endmodule 143 | 144 | 145 | -------------------------------------------------------------------------------- /rtl/cpu/mem/core2icache_if.sv: -------------------------------------------------------------------------------- 1 | `include "core_define.svh" 2 | 3 | 4 | 5 | // if fetch addr is not aligned by 4 bytes 6 | // core will send 2 request for 2 cacheline 7 | 8 | interface core2icache_if (); 9 | logic req; //M->S 10 | logic get2; //M->S 11 | logic gnt; //S->M 12 | logic [`BLKDEF] addr; //M->S 13 | logic [`WDEF(`CACHELINE_SIZE*8)] line0; //S->M 14 | logic [`WDEF(`CACHELINE_SIZE*8)] line1; //S->M 15 | logic rsp; //S->M 16 | modport m(output req, input gnt, output get2, output addr, input line0, input line1, input rsp); 17 | modport s(input req, output gnt, input get2, input addr, output line0, output line1, output rsp); 18 | 19 | 20 | function logic handshaked(); 21 | handshaked = req && gnt; 22 | endfunction 23 | 24 | endinterface 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /rtl/cpu/mem/dcache/dcache.sv: -------------------------------------------------------------------------------- 1 | `include "core_define.svh" 2 | `include "dpic.svh" 3 | 4 | 5 | // use physic tag virtual index 6 | // | req -> icache | select data | output 7 | // tlb | 8 | module dcache #( 9 | parameter int BANKS = 0, 10 | parameter int SETS = 32, 11 | parameter int WAYS = 4 12 | ) ( 13 | input wire clk, 14 | input wire rst, 15 | 16 | // from cpu 17 | load2dcache_if.s if_core[2], 18 | sta2mmu_if.s if_sta[2] 19 | ); 20 | genvar i, j; 21 | 22 | generate 23 | for (i = 0; i < 2; i = i + 1) begin : gen_load 24 | // s0: 25 | assign if_core[i].s0_gnt = 1; 26 | // s1 27 | reg s1_req; 28 | logic [`XDEF] s1_vaddr; 29 | logic [`XDEF] s1_paddr; 30 | // s2 31 | reg s2_req; 32 | always_ff @(posedge clk) begin 33 | int fa; 34 | if (rst) begin 35 | s1_req <= 0; 36 | end 37 | else begin 38 | // s1: read tlb 39 | s1_req <= if_core[i].s0_req; 40 | s1_paddr <= (if_core[i].s0_vaddr >> $clog2(`CACHELINE_SIZE)); 41 | s1_vaddr <= if_core[i].s0_vaddr; 42 | 43 | s2_req <= if_core[i].s1_req; 44 | end 45 | end 46 | // s1: read data sram 47 | assign if_core[i].s1_rdy = s1_req; 48 | assign if_core[i].s1_cft = 0; 49 | assign if_core[i].s1_miss = 0; 50 | assign if_core[i].s1_pagefault = 0; 51 | assign if_core[i].s1_illegaAddr = 0; 52 | assign if_core[i].s1_mmio = 0; 53 | assign if_core[i].s1_paddr = s1_vaddr; 54 | 55 | // s2: output 56 | assign if_core[i].s2_rdy = s2_req; 57 | for (j = 0; j < `CACHELINE_SIZE; j = j + 1) begin 58 | always_ff @(posedge clk) begin 59 | if (if_core[i].s1_req) begin 60 | if_core[i].s2_data[j*8+7 : j*8] <= read_rom((s1_paddr << $clog2(`CACHELINE_SIZE)) + j); 61 | end 62 | else begin 63 | if_core[i].s2_data[j*8+7 : j*8] <= 0; 64 | end 65 | end 66 | end 67 | end 68 | 69 | for (i = 0; i < 2; i = i + 1) begin : gen_store 70 | reg s1_req; 71 | logic[`XDEF] s1_paddr; 72 | 73 | always_ff @( posedge clk ) begin 74 | if (rst) begin 75 | s1_req <= 0; 76 | end 77 | else begin 78 | s1_req <= if_sta[i].s0_req; 79 | s1_paddr <= if_sta[i].s0_vaddr; 80 | end 81 | end 82 | 83 | assign if_sta[i].s1_miss = 0; 84 | assign if_sta[i].s1_pagefault = 0; 85 | assign if_sta[i].s1_illegaAddr = 0; 86 | assign if_sta[i].s1_mmio = 0; 87 | assign if_sta[i].s1_paddr = s1_paddr; 88 | 89 | end 90 | endgenerate 91 | 92 | endmodule 93 | 94 | 95 | -------------------------------------------------------------------------------- /rtl/cpu/mem/icache/icache.sv: -------------------------------------------------------------------------------- 1 | `include "core_define.svh" 2 | `include "dpic.svh" 3 | 4 | 5 | // use physic tag virtual index 6 | // | req -> icache | select data | output 7 | // tlb | 8 | module icache #( 9 | parameter int BANKS = 0, 10 | parameter int SETS = 32, 11 | parameter int WAYS = 4 12 | ) ( 13 | input wire clk, 14 | input wire rst, 15 | 16 | // from cpu 17 | core2icache_if.s if_core_fetch 18 | 19 | // from/to next level storage 20 | ); 21 | 22 | genvar i; 23 | 24 | // 3 stage icache simulate 25 | assign if_core_fetch.gnt = if_core_fetch.req; 26 | reg s1_req; 27 | reg s1_get2; 28 | reg [`BLKDEF] s1_addr; 29 | 30 | always_ff @(posedge clk) begin 31 | int fa; 32 | if (rst) begin 33 | s1_req <= 0; 34 | if_core_fetch.rsp <= 0; 35 | end 36 | else begin 37 | // s1: read sram 38 | s1_req <= if_core_fetch.req; 39 | s1_get2 <= if_core_fetch.get2; 40 | s1_addr <= if_core_fetch.addr; 41 | 42 | if_core_fetch.rsp <= s1_req; 43 | end 44 | end 45 | 46 | generate 47 | // s2: select 48 | for (i = 0; i < `CACHELINE_SIZE; i = i + 1) begin 49 | always_ff @(posedge clk) begin 50 | if (s1_req) begin 51 | if_core_fetch.line0[i*8+7 : i*8] <= read_rom((s1_addr << $clog2(`CACHELINE_SIZE)) + i); 52 | if (s1_get2) begin 53 | if_core_fetch.line1[i*8+7 : i*8] <= read_rom(((s1_addr + 1) << $clog2(`CACHELINE_SIZE)) + i); 54 | end 55 | end 56 | else begin 57 | if_core_fetch.line0[i*8+7 : i*8] <= 0; 58 | if_core_fetch.line1[i*8+7 : i*8] <= 0; 59 | end 60 | end 61 | end 62 | endgenerate 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | endmodule 72 | 73 | 74 | -------------------------------------------------------------------------------- /rtl/cpu/mem/mem_define.svh: -------------------------------------------------------------------------------- 1 | `ifndef __MEM_DEFINE_SVH__ 2 | `define __MEM_DEFINE_SVH__ 3 | 4 | `include "core_define.svh" 5 | 6 | 7 | typedef struct packed { 8 | paddr_t paddr; 9 | logic dirty; 10 | logic accessed; 11 | logic g; 12 | logic user; 13 | logic r; 14 | logic w; 15 | logic x; 16 | logic vld; 17 | } pageTableEntry_t; 18 | 19 | 20 | `endif 21 | -------------------------------------------------------------------------------- /rtl/ip/sram_1r1w.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | 4 | 5 | module sram_1r1w #( 6 | parameter int DEPTH = 1024, 7 | parameter int WIDTH = 64 8 | ) ( 9 | input wire clk, 10 | input wire rst, 11 | 12 | input wire [`WDEF($clog2(DEPTH))] i_read_addr, 13 | output wire [`WDEF(WIDTH)] o_read_data, 14 | 15 | input wire i_write_en, 16 | input wire [`WDEF($clog2(DEPTH))] i_write_addr, 17 | input wire [`WDEF(WIDTH)] i_write_data 18 | ); 19 | 20 | 21 | `ifdef SIMULATION 22 | reg [`WDEF(WIDTH)] buffer[DEPTH]; 23 | reg [`WDEF(WIDTH)] out_buf; 24 | always_ff @(posedge clk) begin 25 | if (i_write_en) begin 26 | buffer[i_write_addr] <= i_write_data; 27 | end 28 | out_buf <= buffer[i_read_addr]; 29 | end 30 | assign o_read_data = out_buf; 31 | `endif 32 | 33 | endmodule 34 | 35 | -------------------------------------------------------------------------------- /rtl/ip/sram_1rw.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | 4 | 5 | module sram_1rw #( 6 | parameter int DEPTH = 1024, 7 | parameter int WIDTH = 64, 8 | parameter int NEEDRESET = 0 9 | ) ( 10 | input wire clk, 11 | input wire rst, 12 | input wire i_read_en, 13 | input wire i_write_en, 14 | input wire [`WDEF($clog2(DEPTH))] i_addr, 15 | output wire [`WDEF(WIDTH)] o_read_data, 16 | input wire [`WDEF(WIDTH)] i_write_data 17 | ); 18 | 19 | 20 | `ifdef SIMULATION 21 | reg [`WDEF(WIDTH)] buffer[DEPTH]; 22 | reg [`WDEF(WIDTH)] out_buf; 23 | always_ff @(posedge clk) begin 24 | int fa; 25 | if (rst) begin 26 | for (fa = 0; fa < DEPTH; fa = fa + 1) begin 27 | buffer[fa] = 0; 28 | end 29 | end 30 | else begin 31 | if (i_read_en) begin 32 | out_buf <= buffer[i_addr]; 33 | end 34 | if (i_write_en) begin 35 | buffer[i_addr] <= i_write_data; 36 | end 37 | end 38 | end 39 | assign o_read_data = out_buf; 40 | `endif 41 | 42 | endmodule 43 | 44 | -------------------------------------------------------------------------------- /rtl/utils/array2vec.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | 4 | 5 | 6 | 7 | module array2vec #( 8 | parameter int ARRAYLENGTH = 1, 9 | parameter type dtype = logic 10 | ) ( 11 | input dtype i_array[ARRAYLENGTH], 12 | output dtype [ARRAYLENGTH:0] o_vec 13 | ); 14 | genvar i; 15 | 16 | generate 17 | for (i = 0; i < ARRAYLENGTH; i = i + 1) begin 18 | assign o_vec[i] = i_array[i]; 19 | end 20 | endgenerate 21 | endmodule 22 | -------------------------------------------------------------------------------- /rtl/utils/bits_compare.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | 4 | // vld = a.len<=b.len 5 | module bits_compare #( 6 | parameter int LENGTH = 32 7 | ) ( 8 | input wire [`WDEF(LENGTH)] i_a, 9 | input wire [`WDEF(LENGTH)] i_b, 10 | output wire o_vld 11 | ); 12 | 13 | wire [`SDEF(LENGTH)] alen, blen; 14 | 15 | count_one #( 16 | .WIDTH(LENGTH) 17 | ) u_count_one_0 ( 18 | .i_a (i_a), 19 | .o_sum(alen) 20 | ); 21 | 22 | count_one #( 23 | .WIDTH(LENGTH) 24 | ) u_count_one_1 ( 25 | .i_a (i_b), 26 | .o_sum(blen) 27 | ); 28 | 29 | assign o_vld = alen <= blen; 30 | 31 | endmodule 32 | 33 | -------------------------------------------------------------------------------- /rtl/utils/continuous_one.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | //get the continuous one of begin of logic 4 | //0011 => 2 5 | //0101 => 1 6 | 7 | module continuous_one #( 8 | parameter int WIDTH = 4 9 | ) ( 10 | input wire [`WDEF(WIDTH)] i_a, 11 | output wire [`SDEF(WIDTH)] o_sum 12 | ); 13 | /* verilator lint_off UNOPTFLAT */ 14 | wire [`SDEF(WIDTH)] map[WIDTH]; 15 | assign map[0] = i_a[0]; 16 | generate 17 | genvar i; 18 | for (i = 1; i < WIDTH; i = i + 1) begin : gen_count 19 | assign map[i] = &i_a[i:0] ? i + 1 : map[i-1]; 20 | end 21 | endgenerate 22 | assign o_sum = map[WIDTH-1]; 23 | endmodule 24 | 25 | -------------------------------------------------------------------------------- /rtl/utils/count_one.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | //get the number of 1 of logic 4 | //0101 => 2 5 | module count_one #( 6 | parameter int WIDTH = 4 7 | ) ( 8 | input wire [`WDEF(WIDTH)] i_a, 9 | output wire [`SDEF(WIDTH)] o_sum 10 | ); 11 | /* verilator lint_off UNOPTFLAT */ 12 | wire [`SDEF(WIDTH)] buffer[WIDTH+1]; 13 | assign buffer[0] = 0; 14 | generate 15 | genvar i; 16 | for (i = 0; i < WIDTH; i = i + 1) begin : gen_count 17 | assign buffer[i+1] = i_a[i] ? buffer[i] + 1 : buffer[i]; 18 | end 19 | endgenerate 20 | assign o_sum = buffer[WIDTH]; 21 | endmodule 22 | 23 | -------------------------------------------------------------------------------- /rtl/utils/redirect.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | 4 | //input_vld : 1001 5 | //input : dcba 6 | //output : bxxa 7 | 8 | //ordered in 9 | //unordered out 10 | module redirect #( 11 | parameter type dtype = logic, 12 | parameter int NUM = 4 13 | ) ( 14 | input wire [`WDEF(NUM)] i_arch_vld, 15 | input dtype i_arch_datas[NUM], 16 | output dtype o_redirect_datas[NUM] 17 | ); 18 | wire [`SDEF(NUM)] sel_offset[NUM]; 19 | 20 | generate 21 | genvar i; 22 | //todo: finish it 23 | for (i = 0; i < NUM; i = i + 1) begin : gen_countone 24 | if (i == 0) begin 25 | assign sel_offset[0] = 0; 26 | end 27 | else begin 28 | count_one #( 29 | .WIDTH(i + 1) 30 | ) u_count_one ( 31 | .i_a (i_arch_vld[i-1:0]), 32 | .o_sum(sel_offset[i]) 33 | ); 34 | end 35 | 36 | assign o_redirect_datas[i] = i_arch_datas[sel_offset[i]]; 37 | end 38 | endgenerate 39 | endmodule 40 | -------------------------------------------------------------------------------- /rtl/utils/reorder.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | 4 | 5 | //reorder the data and output 6 | //0101 -> 0011 7 | //1001 -> 0011 8 | 9 | //unordered in 10 | //ordered out 11 | module reorder #( 12 | parameter type dtype = logic, 13 | parameter int NUM = 4 14 | ) ( 15 | input wire [`WDEF(NUM)] i_data_vld, 16 | input dtype i_datas[NUM], 17 | output wire [`WDEF(NUM)] o_data_vld, 18 | output dtype o_reorder_datas[NUM] 19 | ); 20 | wire [`SDEF(NUM)] count_vld; 21 | wire [`SDEF(NUM)] sel_offset[NUM]; 22 | count_one #( 23 | .WIDTH(NUM) 24 | ) u_count_one ( 25 | .i_a (i_data_vld), 26 | .o_sum(count_vld) 27 | ); 28 | assign o_data_vld = count_vld == 0 ? 0 : ((1 << count_vld) - 1); 29 | generate 30 | genvar i, j; 31 | for (i = 0; i < NUM; i = i + 1) begin : gen_countone 32 | count_one #( 33 | .WIDTH(i + 1) 34 | ) u_count_one ( 35 | .i_a (i_data_vld[i:0]), 36 | .o_sum(sel_offset[i]) 37 | ); 38 | always_comb begin 39 | o_reorder_datas[i] = i_datas[i]; 40 | if (i_data_vld[i]) begin 41 | o_reorder_datas[sel_offset[i]-1] = i_datas[i]; 42 | end 43 | end 44 | end 45 | endgenerate 46 | 47 | 48 | endmodule 49 | -------------------------------------------------------------------------------- /rtl/utils/replacement/plru_rep.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | 4 | 5 | 6 | 7 | // s0: read plru select 8 | // s1: cache hit and update plru 9 | 10 | module plru_rep #( 11 | parameter int SETS = 32, 12 | parameter int WAYS = 4 13 | ) ( 14 | input wrie clk, 15 | input wire rst, 16 | 17 | input wire [`WDEF($clog2(SETS))] i_setIdx, 18 | output wire [`WDEF(WAYS)] o_replace_vec, 19 | input wire i_update_req, 20 | input wire [`WDEF(WAYS)] i_wayhit_vec 21 | ); 22 | localparam int plru_wid = WAYS - 1; 23 | 24 | reg [`WDEF(plru_wid)] plru_bits[SETS]; 25 | 26 | 27 | 28 | endmodule 29 | -------------------------------------------------------------------------------- /rtl/utils/replacement/random_rep.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | 4 | 5 | module random_rep #( 6 | parameter int SETS = 32, 7 | parameter int WAYS = 4 8 | 9 | ) ( 10 | input wire clk, 11 | input wire rst, 12 | 13 | input wire [`WDEF($clog2(SETS))] i_setIdx, 14 | output wire [`WDEF(WAYS)] o_replace_vec, 15 | input wire i_update_req, 16 | input wire [`WDEF(WAYS)] i_wayhit_vec 17 | ); 18 | reg [`WDEF(WAYS)] rand_bits; 19 | 20 | 21 | always_ff @(posedge clk) begin 22 | if (rst) begin 23 | rand_bits <= 1; 24 | end 25 | else begin 26 | rand_bits <= {rand_bits[0], rand_bits[WAYS-1:1]}; 27 | end 28 | end 29 | 30 | assign o_replace_vec = rand_bits; 31 | 32 | 33 | 34 | endmodule 35 | 36 | -------------------------------------------------------------------------------- /rtl/utils/struct/StoreBuffer.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | // write data to Dcache 4 | // we need to copy data and wait for write-finished signal 5 | // then we can release this data 6 | 7 | 8 | // link storeQue to Dcache 9 | module StoreBuffer #( 10 | parameter int SIZE = 16, 11 | parameter int DATAWIDTH = 32 * 8 //32Byte 12 | ) ( 13 | input wire clk, 14 | input wire rst 15 | ); 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | endmodule 29 | -------------------------------------------------------------------------------- /rtl/utils/struct/bankedSet.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | 4 | 5 | 6 | // {set index, offset} 7 | module bankedSet #( 8 | parameter int BANKS = 4, 9 | parameter int SETS = 64, 10 | parameter int WAYS = 4, 11 | parameter type dtype = logic 12 | ) ( 13 | input wire clk, 14 | input wire rst, 15 | 16 | input wire [`WDEF(BANKS)] i_write, 17 | input wire [`WDEF(BANKS)] i_read, 18 | input wire [`WDEF(WAYS)] i_way_sel[BANKS], 19 | input wire [`WDEF($clog2(SETS))] i_addr[BANKS], 20 | input wire [`WDEF(DATASIZE)] i_data[BANKS], 21 | output wire [`WDEF(DATASIZE)] o_data[BANKS] 22 | ); 23 | genvar i; 24 | 25 | generate 26 | for (i = 0; i < BANKS; i = i + 1) begin 27 | dtype read_datas[WAYS]; 28 | dtype write_datas[WAYS]; 29 | genvar j; 30 | for (j = 0; j < WAYS; j = j + 1) begin 31 | assign write_datas[j] = i_data[i]; 32 | end 33 | 34 | sramSet #( 35 | .SETS (SETS / BANKS), 36 | .WAYS (WAYS), 37 | .dtype(dtype) 38 | ) u_sramSet ( 39 | .clk (clk), 40 | .rst (rst), 41 | .i_addr (i_addr[i]), 42 | .i_read_en (i_read[i]), 43 | .i_write_en_vec(i_write ? i_way_sel[i] : 0), 44 | .o_read_data (read_datas), 45 | .i_write_data (write_datas) 46 | ); 47 | dtype read_temp; 48 | always_comb begin 49 | int ca; 50 | for (ca = 0; ca < WAYS; ca = ca + 1) begin 51 | if (i_way_sel[i][ca]) begin 52 | read_temp = read_datas[ca]; 53 | end 54 | end 55 | end 56 | `ASSET(func::count_one(i_way_sel) < 2); 57 | assign o_data[i] = read_temp; 58 | end 59 | endgenerate 60 | 61 | endmodule 62 | 63 | -------------------------------------------------------------------------------- /rtl/utils/struct/fifo.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | `include "funcs.svh" 3 | import funcs::*; 4 | 5 | //unsafed fifo 6 | //ordered in out 7 | module fifo #( 8 | parameter type dtype = logic, 9 | parameter int INPORT_NUM = 4, 10 | parameter int OUTPORT_NUM = 4, 11 | parameter int DEPTH = 32, 12 | parameter int USE_INIT = 0, 13 | // only for rename 14 | parameter int USE_RENAME = 0, 15 | parameter int COMMIT_WID = 0 16 | ) ( 17 | input dtype init_data[DEPTH], 18 | input wire clk, 19 | input wire rst, 20 | input wire i_flush, 21 | // enq 22 | output wire o_can_enq, 23 | input wire i_enq_vld, // only when enq_vld is true, can enq 24 | input wire [`WDEF(INPORT_NUM)] i_enq_req, 25 | input dtype i_enq_data[INPORT_NUM], 26 | // deq 27 | output wire [`WDEF(OUTPORT_NUM)] o_can_deq, 28 | input wire [`WDEF(OUTPORT_NUM)] i_deq_req, 29 | output dtype o_deq_data[OUTPORT_NUM], 30 | // DESIGN: rename restore 31 | // resteer (only for rename restore) 32 | input wire i_resteer_vld, 33 | // commit (only for rename restore) 34 | input wire [`WDEF(COMMIT_WID)] i_commit_vld 35 | ); 36 | genvar i; 37 | 38 | wire [`WDEF(INPORT_NUM)] real_enq_vld = (o_can_enq && i_enq_vld) ? i_enq_req : 0; 39 | wire [`WDEF(INPORT_NUM)] real_deq_vld = i_deq_req & o_can_deq; 40 | wire [`SDEF(DEPTH)] enq_num, real_enq_num, deq_num; 41 | count_one #( 42 | .WIDTH(INPORT_NUM) 43 | ) u_count_one_0 ( 44 | .i_a (i_enq_req), 45 | .o_sum(enq_num) 46 | ); 47 | assign o_can_enq = enq_num <= remaining; 48 | 49 | count_one #( 50 | .WIDTH(INPORT_NUM) 51 | ) u_count_one_1 ( 52 | .i_a (real_enq_vld), 53 | .o_sum(real_enq_num) 54 | ); 55 | count_one #( 56 | .WIDTH(OUTPORT_NUM) 57 | ) u_count_one_2 ( 58 | .i_a (real_deq_vld), 59 | .o_sum(deq_num) 60 | ); 61 | 62 | dtype buffer[DEPTH]; 63 | reg [`WDEF($clog2(DEPTH))] enq_ptr[INPORT_NUM], deq_ptr[OUTPORT_NUM]; 64 | reg [`WDEF($clog2(DEPTH))] arch_deq_ptr; 65 | reg [`SDEF(DEPTH)] count, arch_count; 66 | 67 | if (USE_RENAME) begin : gen_freelist 68 | // DESIGN: 69 | // commit ont inst with rd 70 | // the arch_deq_ptr increment by 1 71 | 72 | wire [`SDEF(DEPTH)] commit_num; // the arch_read_num 73 | count_one #( 74 | .WIDTH(COMMIT_WID) 75 | ) u_count_one_3 ( 76 | .i_a (i_commit_vld), 77 | .o_sum(commit_num) 78 | ); 79 | always_ff @(posedge clk) begin 80 | int fa; 81 | if (rst == true) begin 82 | arch_count <= DEPTH; 83 | arch_deq_ptr <= 0; 84 | end 85 | else begin 86 | arch_count <= arch_count - commit_num + enq_num; 87 | arch_deq_ptr <= (arch_deq_ptr + commit_num) < DEPTH ? (arch_deq_ptr + commit_num) : (arch_deq_ptr + commit_num - DEPTH); 88 | for (fa = 0; fa < INPORT_NUM; fa = fa + 1) begin 89 | if (real_enq_vld[fa]) begin 90 | assert (arch_deq_ptr != enq_ptr[fa]); 91 | end 92 | end 93 | end 94 | end 95 | end 96 | 97 | 98 | 99 | 100 | always_ff @(posedge clk) begin 101 | int fa; 102 | if ((rst == true) || (i_flush == true)) begin 103 | if (USE_RENAME) begin 104 | for (fa = 0; fa < DEPTH; fa = fa + 1) begin 105 | buffer[fa] = fa + 1; 106 | end 107 | count <= DEPTH; 108 | end 109 | else begin 110 | count <= 0; 111 | end 112 | for (fa = 0; fa < INPORT_NUM; fa = fa + 1) begin 113 | enq_ptr[fa] <= fa; 114 | end 115 | for (fa = 0; fa < OUTPORT_NUM; fa = fa + 1) begin 116 | deq_ptr[fa] <= fa; 117 | end 118 | end 119 | else begin 120 | // enq 121 | for (fa = 0; fa < INPORT_NUM; fa = fa + 1) begin 122 | if (real_enq_vld[fa] == true) begin 123 | buffer[enq_ptr[fa]] <= i_enq_data[fa]; 124 | end 125 | 126 | enq_ptr[fa] <= (enq_ptr[fa] + real_enq_num) < DEPTH ? (enq_ptr[fa] + real_enq_num) : (enq_ptr[fa] + real_enq_num - DEPTH); 127 | end 128 | 129 | // deq 130 | if ((USE_RENAME != 0) && i_resteer_vld) begin 131 | for (fa = 0; fa < OUTPORT_NUM; fa = fa + 1) begin 132 | deq_ptr[fa] <= (arch_deq_ptr + fa) < DEPTH ? (arch_deq_ptr + fa) : (arch_deq_ptr + fa - DEPTH); 133 | end 134 | count <= arch_count + real_enq_num; 135 | end 136 | else begin 137 | for (fa = 0; fa < OUTPORT_NUM; fa = fa + 1) begin 138 | deq_ptr[fa] <= ((deq_ptr[fa] + deq_num) < DEPTH) ? (deq_ptr[fa] + deq_num) : (deq_ptr[fa] + deq_num - DEPTH); 139 | end 140 | count <= count + real_enq_num - deq_num; 141 | end 142 | end 143 | end 144 | 145 | wire [`SDEF(DEPTH)] existing, remaining; 146 | assign existing = count; 147 | assign remaining = DEPTH - count; 148 | 149 | generate 150 | for (i = 0; i < OUTPORT_NUM; i = i + 1) begin 151 | assign o_can_deq[i] = ((i + 1) <= existing); 152 | assign o_deq_data[i] = buffer[deq_ptr[i]]; 153 | end 154 | endgenerate 155 | 156 | 157 | // use for waveform debug 158 | wire [`SDEF(DEPTH)] AAA_count = count; 159 | if (USE_RENAME) begin 160 | wire [`SDEF(DEPTH)] AAA_arch_count = arch_count; 161 | end 162 | 163 | wire [`SDEF(DEPTH)] AAA_enq_num = real_enq_num; 164 | wire [`SDEF(DEPTH)] AAA_deq_num = deq_num; 165 | 166 | `ASSERT(count <= DEPTH); 167 | 168 | `ORDER_CHECK(real_deq_vld); 169 | 170 | `ORDER_CHECK(real_enq_vld); 171 | 172 | endmodule 173 | -------------------------------------------------------------------------------- /rtl/utils/struct/sramSet.sv: -------------------------------------------------------------------------------- 1 | `include "base.svh" 2 | 3 | 4 | 5 | 6 | 7 | 8 | module sramSet #( 9 | parameter int SETS = 32, 10 | parameter int WAYS = 4, 11 | parameter type dtype = logic, 12 | parameter int NEEDRESET = 0 13 | ) ( 14 | input wire clk, 15 | input wire rst, 16 | 17 | input wire [`WDEF($clog2(SETS))] i_addr, 18 | input wire i_read_en, 19 | input wire [`WDEF(WAYS)] i_write_en_vec, 20 | output dtype o_read_data[WAYS], 21 | input dtype i_write_data[WAYS] 22 | ); 23 | localparam int WIDTH = $bits(dtype); 24 | 25 | genvar i; 26 | 27 | wire [`WDEF(WIDTH)] read_bits[WAYS]; 28 | wire [`WDEF(WIDTH)] write_bits[WAYS]; 29 | 30 | generate 31 | for (i = 0; i < WAYS; i = i + 1) begin 32 | assign write_bits[i] = i_write_data[i]; 33 | assign o_read_data[i] = read_bits[i]; 34 | end 35 | endgenerate 36 | 37 | generate 38 | for (i = 0; i < WAYS; i = i + 1) begin : gen_sram1rw 39 | sram_1rw #( 40 | .DEPTH (SETS), 41 | .WIDTH (WIDTH), 42 | .NEEDRESET(NEEDRESET) 43 | ) u_sram_1rw ( 44 | .clk (clk), 45 | .rst (rst), 46 | .i_read_en (i_read_en), 47 | .i_write_en (i_write_en_vec[i]), 48 | .i_addr (i_addr), 49 | .o_read_data (read_bits[i]), 50 | .i_write_data(write_bits[i]) 51 | ); 52 | end 53 | endgenerate 54 | 55 | endmodule 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /sim/verilator/Makefile: -------------------------------------------------------------------------------- 1 | TOP ?= tb 2 | 3 | ADDITIONAL_PARAM = --x-assign unique --x-initial unique --assert --trace-max-array 64 4 | 5 | EMU_DEFINES = -DSIMULATION -DDEBUG 6 | WARNING_OFF = -Wno-WIDTH -Wno-PINMISSING -Wno-TIMESCALEMOD -Wno-ENUMVALUE 7 | CXX_FLAGS = -std=c++20 -DVTOP=V$(TOP) -DVname=\\\"$(TOP)\\\" -DVheader=\\\"V$(TOP).h\\\" 8 | 9 | TB_PATH = $(AURA_HOME)/sim/verilator/tb 10 | CXX_SOURCES := $(shell find $(AURA_HOME)/sim/verilator/src -type f -name "*.cpp") 11 | CXX_INCLUDE_PATH := $(AURA_HOME)/sim/verilator/inc 12 | SV_INCLUDE_PATH := $(shell find $(AURA_HOME)/rtl -type d) 13 | SV_INCLUDE_PATH_PARAM := $(addprefix -y ,$(SV_INCLUDE_PATH)) 14 | 15 | 16 | CXX_FLAGS += -I $(CXX_INCLUDE_PATH) 17 | ifeq ($(USE_TRACE),1) 18 | ADDITIONAL_PARAM += --trace --trace-structs 19 | EMU_DEFINES += -DUSE_TRACE 20 | CXX_FLAGS += -DUSE_TRACE 21 | endif 22 | ifdef THREAD 23 | ADDITIONAL_PARAM += --threads $(THREAD) 24 | endif 25 | CXX_FLAGS := --CFLAGS "$(CXX_FLAGS)" 26 | 27 | aura: 28 | @echo "**********verilator generating**********" 29 | verilator \ 30 | --cc $(TB_PATH)/$(TOP).sv --top-module $(TOP) --exe \ 31 | $(CXX_SOURCES) \ 32 | $(CXX_FLAGS) \ 33 | $(SV_INCLUDE_PATH_PARAM) \ 34 | $(ADDITIONAL_PARAM) \ 35 | $(EMU_DEFINES) \ 36 | $(WARNING_OFF) \ 37 | -Mdir $(AURA_HOME)/build -o aura 38 | 39 | @if [ $$? -ne 0 ]; then \ 40 | echo "**********verilator generate failed**********"; \ 41 | exit 1; \ 42 | else \ 43 | echo "**********verilator generate successfully**********"; \ 44 | fi 45 | 46 | @echo "**********make building**********" 47 | @make -C $(AURA_HOME)/build -f V$(TOP).mk 48 | 49 | @if [ $$? -ne 0 ]; then \ 50 | echo "**********make build failed**********"; \ 51 | exit 1; \ 52 | else \ 53 | echo "**********make build successfully**********"; \ 54 | fi 55 | 56 | preprocess: 57 | @echo "**********verilator generating**********" 58 | verilator \ 59 | rtl/cpu/backend/block/intBlock.sv -E \ 60 | $(CXX_SOURCES) \ 61 | $(CXX_FLAGS) \ 62 | $(SV_INCLUDE_PATH_PARAM) \ 63 | $(ADDITIONAL_PARAM) \ 64 | $(EMU_DEFINES) \ 65 | $(WARNING_OFF) \ 66 | -Mdir $(AURA_HOME)/build -o aura -------------------------------------------------------------------------------- /sim/verilator/inc/debugflags.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | enum DebugFlag { 10 | UBTB, 11 | FTB, 12 | BPU, 13 | BPU_GBH, 14 | FTQ, 15 | FTQCOMMIT, 16 | 17 | FETCH, 18 | DECODE, 19 | 20 | RENAME, 21 | RENAME_ALLOC, 22 | 23 | EXECUTE, 24 | COMMIT, 25 | 26 | MEMDEP, 27 | LDQUE, 28 | STQUE, 29 | 30 | PIPELINE, 31 | 32 | ROM, 33 | NUM_DEBUGFLAGS 34 | }; 35 | 36 | extern std::map debugflag_name; 37 | extern uint64_t curTick(); 38 | 39 | class DebugChecker { 40 | bool enable_flag = false; 41 | uint64_t debug_start = 0; 42 | uint64_t debug_end = UINT64_MAX; 43 | std::vector tmp_debug_flags; 44 | std::vector debug_flags; 45 | std::vector dprint_buf; 46 | public: 47 | std::stringstream dprinta_buf; // not controlled by debugflag 48 | char strBuf[1024]; 49 | DebugChecker(); 50 | void setTime(uint64_t start, uint64_t end) 51 | { 52 | debug_start = start; 53 | debug_end = end; 54 | } 55 | // such as: FETCH,DECODE 56 | void parseFlags(std::string flags); 57 | void enableFlags(); 58 | void clearFlags(); 59 | bool checkFlag(DebugFlag flag); 60 | 61 | void putin(DebugFlag flag, const char * str); 62 | void printAll(uint64_t tick); 63 | }; 64 | 65 | extern DebugChecker debugChecker; 66 | 67 | #define DPRINTF(flag, args...) \ 68 | if (debugChecker.checkFlag(DebugFlag::flag)) { \ 69 | sprintf(debugChecker.strBuf, "%lu DebugFlag-" #flag ": ", curTick()); \ 70 | debugChecker.putin(flag, debugChecker.strBuf); \ 71 | sprintf(debugChecker.strBuf, args); \ 72 | debugChecker.putin(flag, debugChecker.strBuf); \ 73 | } 74 | 75 | #define DPRINTFD(flag, args...) \ 76 | if (debugChecker.checkFlag(DebugFlag::flag)) { \ 77 | sprintf(debugChecker.strBuf, args); \ 78 | debugChecker.putin(flag, debugChecker.strBuf); \ 79 | } 80 | 81 | #define DPRINTFA(args...) \ 82 | sprintf(debugChecker.strBuf, args); \ 83 | debugChecker.dprinta_buf << debugChecker.strBuf; \ 84 | 85 | 86 | extern void mark_exit(bool failed); 87 | extern uint32_t force_exit(); -------------------------------------------------------------------------------- /sim/verilator/inc/define.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #define PMEM_BASE 0x80000000 -------------------------------------------------------------------------------- /sim/verilator/inc/statistics.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | extern uint64_t curTick(); 9 | 10 | enum InstPos { 11 | AT_fetch, 12 | AT_decode, 13 | AT_rename, 14 | AT_dispQue, 15 | AT_issueQue, 16 | AT_fu, 17 | AT_wb, 18 | AT_lq, 19 | AT_sq, 20 | NUMPOS 21 | }; 22 | 23 | enum MetaKeys { 24 | META_ISBRANCH, 25 | META_ISLOAD, 26 | META_ISSTORE, 27 | META_ISMV, 28 | META_MISPRED,// branch only 29 | META_NPC,// branch only 30 | META_PADDR,// load/store only 31 | META_SIZE, // load/stores only 32 | NUM_META 33 | }; 34 | 35 | struct InstMeta 36 | { 37 | uint32_t code; 38 | uint64_t seq = ~0; 39 | uint64_t pc = ~0; 40 | 41 | // pos 42 | uint64_t issue_tick = ~0; 43 | uint64_t finished_tick = ~0; 44 | uint64_t commit_tick = ~0; 45 | uint64_t ready_tick = ~0; 46 | bool is_first_issue = false; 47 | std::vector pos; 48 | std::vector active_tick; 49 | 50 | // meta 51 | std::vector meta; 52 | 53 | std::vector::iterator it; 54 | InstMeta() : pos(InstPos::NUMPOS, false), active_tick(InstPos::NUMPOS, 0), meta(MetaKeys::NUM_META, 0) {} 55 | 56 | std::string base() { return std::format("[sn {:d} pc {:x}]", seq, pc); } 57 | 58 | void print(); 59 | 60 | std::string cachedDisasm; 61 | std::string disassembly(); 62 | }; 63 | 64 | 65 | 66 | void dumpStats(); 67 | 68 | InstMeta* read_instmeta(uint64_t ptr); 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /sim/verilator/src/debugflags.cpp: -------------------------------------------------------------------------------- 1 | #include "debugflags.hpp" 2 | 3 | #include 4 | #include 5 | 6 | std::map debugflag_name = { 7 | {"UBTB", DebugFlag::UBTB}, 8 | {"FTB", DebugFlag::FTB}, 9 | {"BPU" , DebugFlag::BPU}, 10 | {"BPU_GBH", DebugFlag::BPU_GBH}, 11 | {"FTQ", DebugFlag::FTQ}, 12 | {"FTQCOMMIT", DebugFlag::FTQCOMMIT}, 13 | {"FETCH" , DebugFlag::FETCH}, 14 | {"DECODE" , DebugFlag::DECODE}, 15 | 16 | {"RENAME" , DebugFlag::RENAME}, 17 | {"RENAME_ALLOC" , DebugFlag::RENAME_ALLOC}, 18 | 19 | {"EXECUTE" , DebugFlag::EXECUTE}, 20 | 21 | {"MEMDEP", DebugFlag::MEMDEP}, 22 | {"LDQUE", DebugFlag::LDQUE}, 23 | {"STQUE", DebugFlag::STQUE}, 24 | 25 | {"COMMIT" , DebugFlag::COMMIT}, 26 | {"PIPELINE", DebugFlag::PIPELINE}, 27 | {"ROM" , DebugFlag::ROM} 28 | }; 29 | 30 | DebugChecker debugChecker; 31 | 32 | DebugChecker::DebugChecker() 33 | { 34 | tmp_debug_flags.resize(DebugFlag::NUM_DEBUGFLAGS, false); 35 | debug_flags.resize(DebugFlag::NUM_DEBUGFLAGS, false); 36 | dprint_buf.resize(DebugFlag::NUM_DEBUGFLAGS); 37 | } 38 | 39 | void DebugChecker::parseFlags(std::string flags) 40 | { 41 | char flag[20]; 42 | int pos = 0; 43 | for (int i=0; isecond] = true; 51 | } 52 | else { 53 | printf("can not find flag: %s!\n", flag); 54 | exit(1); 55 | } 56 | } 57 | else { 58 | flag[pos++] = flags[i]; 59 | } 60 | } 61 | } 62 | 63 | void DebugChecker::enableFlags() 64 | { 65 | debug_flags = tmp_debug_flags; 66 | enable_flag = true; 67 | } 68 | 69 | void DebugChecker::clearFlags() 70 | { 71 | for (auto it = debug_flags.begin(); it!= debug_flags.end(); it++) { 72 | (*it) = false; 73 | } 74 | enable_flag = false; 75 | } 76 | 77 | bool DebugChecker::checkFlag(DebugFlag flag) 78 | { 79 | return debug_flags[flag]; 80 | } 81 | 82 | void DebugChecker::putin(DebugFlag flag, const char * str) 83 | { 84 | dprint_buf[flag] << str; 85 | } 86 | 87 | void DebugChecker::printAll(uint64_t tick) 88 | { 89 | if (!enable_flag && tick >= debug_start) [[unlikely]] { 90 | enableFlags(); 91 | } 92 | if (enable_flag) [[likely]] { 93 | if (tick > debug_end) [[unlikely]] { 94 | clearFlags(); 95 | } 96 | for (auto& it : dprint_buf) { 97 | if (it.rdbuf()->in_avail()) { 98 | std::cout << it.str(); 99 | it.str(""); 100 | it.clear(); 101 | } 102 | } 103 | } 104 | 105 | if (dprinta_buf.rdbuf()->in_avail()) { 106 | std::cout << dprinta_buf.str(); 107 | dprinta_buf.str(""); 108 | dprinta_buf.clear(); 109 | } 110 | } 111 | 112 | 113 | bool forceExit = false; 114 | bool runningfail = false; 115 | 116 | void mark_exit(bool failed) { 117 | runningfail = failed; 118 | forceExit = true; 119 | } 120 | 121 | uint32_t force_exit() { 122 | uint32_t type = 123 | runningfail ? 1 : 2; 124 | return forceExit ? type : 0; 125 | } -------------------------------------------------------------------------------- /sim/verilator/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include Vheader 6 | #include "cmdline.hpp" 7 | #include "statistics.hpp" 8 | #include "debugflags.hpp" 9 | 10 | uint64_t trace_start = 0; 11 | uint64_t max_simTime = UINT64_MAX; 12 | uint64_t main_time = 0; 13 | VTOP* top; 14 | VerilatedVcdC* tfp; 15 | char buffer[100]; 16 | 17 | uint64_t curTick() { return main_time; } 18 | 19 | extern void diff_init(const char* ref_path); 20 | extern void init_workload(std::string path); 21 | 22 | #ifdef USE_TRACE 23 | #define TraceDump if (main_time >= trace_start) tfp->dump(main_time) 24 | #else 25 | #define TraceDump 26 | #endif 27 | void tick_init_top() { 28 | top->clk = 0; 29 | top->rst = 1; 30 | top->eval(); 31 | TraceDump; 32 | 33 | main_time++; 34 | top->clk = 1; 35 | top->rst = 1; 36 | top->eval(); 37 | TraceDump; 38 | 39 | main_time++; 40 | top->rst = 0; 41 | } 42 | 43 | void tick_step() { 44 | top->clk = !top->clk; 45 | top->eval(); 46 | TraceDump; 47 | ++main_time; 48 | } 49 | 50 | 51 | int main(int argc, char** argv) 52 | { 53 | for (int i = 0; i < argc; i++) 54 | { 55 | std::cout << argv[i] << " "; 56 | } 57 | std::cout << std::endl; 58 | cmdline::parser parser; 59 | parser.add("exec-file", 'f', "the riscv executable binary file path", true); 60 | parser.add("end", 'e', "end simulation by specific conditions\n" 61 | " e.g\n" 62 | " -e i100t25\n" 63 | " end simulation at 100th instruction or 25th tick", 64 | false); 65 | parser.add("seed", 's', "the seed of x-assign random init", false); 66 | parser.add("diff-so", 'd', "the so of difftest ref", false); 67 | 68 | parser.add("trace-start", 0, "the trace start tick", false); 69 | parser.add("debug-start", 0, "the debug start tick", false); 70 | parser.add("debug-end", 0, "the debug end tick", false); 71 | parser.add("debug-flags", 0, "the debug flags", false); 72 | 73 | #ifdef USE_TRACE 74 | parser.add("trace", 0, "enable trace by specific conditions\n" 75 | " e.g\n" 76 | " --trace i100t25\n" 77 | " enable trace starting at 100th instruction or 25th tick", 78 | false); 79 | #endif 80 | 81 | parser.parse_check(argc, argv); 82 | 83 | if (parser.exist("debug-flags")) { 84 | debugChecker.parseFlags(parser.get("debug-flags")); 85 | } 86 | if (parser.exist("exec-file")) 87 | { 88 | std::string workload_path = parser.get("exec-file"); 89 | init_workload(workload_path); 90 | } 91 | if (parser.exist("diff-so")) 92 | { 93 | diff_init(parser.get("diff-so").c_str()); 94 | } 95 | 96 | int verilated_seed; 97 | if (parser.exist("seed")) 98 | { 99 | verilated_seed = parser.get("seed"); 100 | } 101 | else { 102 | std::random_device rd; 103 | verilated_seed = rd() % 10000; 104 | } 105 | if (parser.exist("trace-start")) 106 | { 107 | #ifndef USE_TRACE 108 | std::cout << "trace-start is not supported in this build" << std::endl; 109 | return 1; 110 | #endif 111 | trace_start = parser.get("trace-start"); 112 | } 113 | uint64_t debug_start = 0; 114 | uint64_t debug_end = UINT64_MAX; 115 | if (parser.exist("debug-start")) 116 | { 117 | debug_start = parser.get("debug-start"); 118 | } 119 | if (parser.exist("debug-end")) 120 | { 121 | debug_end = parser.get("debug-end"); 122 | } 123 | if (debug_end < debug_start) { 124 | std::cout << "debug-end should be larger than debug-start" << std::endl; 125 | return 1; 126 | } 127 | debugChecker.setTime(debug_start, debug_end); 128 | if (parser.exist("end")) 129 | { 130 | std::string cmd = parser.get("end"); 131 | uint64_t i, t; 132 | int count = sscanf(cmd.c_str(), "t%lu", &t); 133 | if (count) 134 | { 135 | max_simTime = t; 136 | } 137 | } 138 | 139 | 140 | std::cout << "verilated random seed: " << verilated_seed << std::endl; 141 | 142 | int verilated_argc = 3; 143 | char const* verilated_argv[3]; 144 | sprintf(buffer, "+verilator+seed+%d", verilated_seed); 145 | // veriator simulate runtime args 146 | verilated_argv[0] = argv[0]; 147 | verilated_argv[1] = buffer; 148 | verilated_argv[2] = "+verilator+rand+reset+2"; 149 | Verilated::commandArgs(verilated_argc, verilated_argv); 150 | Verilated::traceEverOn(true); 151 | Verilated::addExitCb([](void*) 152 | { std::cout << "Exiting tick at: " << main_time << std::endl; }, 153 | nullptr); 154 | top = new VTOP(Vname); 155 | 156 | #ifdef USE_TRACE 157 | tfp = new VerilatedVcdC(); 158 | top->trace(tfp, 0); 159 | tfp->open("wave.vcd"); 160 | printf("Start trace at: %d\n", 0); 161 | #endif 162 | 163 | std::cout << "**** MAX EMULATION TICK: " << max_simTime << " ****\n"; 164 | std::cout << "**** REAL EMULATION ****\n"; 165 | 166 | tick_init_top(); 167 | 168 | // Simulate until $finish 169 | while ((main_time < max_simTime) && !force_exit()) 170 | { 171 | // Evaluate model 172 | tick_step(); 173 | debugChecker.printAll(main_time); 174 | } 175 | top->final(); 176 | 177 | #ifdef USE_TRACE 178 | tfp->close(); 179 | #endif 180 | 181 | delete top; 182 | 183 | int ret_code = 0; 184 | std::cout << std::endl; 185 | if (force_exit() == 1) { 186 | std::cout << "**** [" << main_time << "] RUN FAILED! ****\n"; 187 | ret_code = 1; 188 | } 189 | else { 190 | std::cout << "**** [" << main_time << "] END EMULATION, DUMP STATS ****\n"; 191 | if (force_exit() == 2) { 192 | std::cout << "[active exit] Exit due to call quit\n"; 193 | } 194 | dumpStats(); 195 | } 196 | 197 | return ret_code; 198 | } -------------------------------------------------------------------------------- /sim/verilator/src/memSim.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "define.hpp" 7 | #include "debugflags.hpp" 8 | 9 | 10 | class MemSim { 11 | public: 12 | uint64_t pmem_size = 24 * 1024 * 1024; // 24M size 13 | char *pmem; 14 | 15 | MemSim() { 16 | pmem = new char[pmem_size]; 17 | } 18 | void loadBinary(std::string path) { 19 | std::string workload_path = path; 20 | std::ifstream workload_fs(workload_path, std::ios::in | std::ios::binary); 21 | if (workload_fs.is_open()) 22 | { 23 | std::cout << "load binary file to rom" << std::endl; 24 | workload_fs.seekg(0, workload_fs.end); 25 | uint64_t filesize = workload_fs.tellg(); 26 | workload_fs.seekg(0, workload_fs.beg); 27 | workload_fs.read(pmem, filesize); 28 | workload_fs.close(); 29 | std::cout << "execute binary file size: " << filesize << std::endl; 30 | std::cout << "load successed" << std::endl; 31 | } 32 | else 33 | { 34 | throw std::invalid_argument("can't open file: " + workload_path + "\n"); 35 | } 36 | } 37 | char readByte(uint64_t addr) { 38 | if (addr < pmem_size) { 39 | unsigned char a; 40 | a = pmem[addr]; 41 | return a; 42 | } 43 | return 0; 44 | } 45 | 46 | void writeByte(uint64_t addr, char val) { 47 | if (addr < pmem_size) { 48 | pmem[addr] = val; 49 | } 50 | } 51 | }memSim; 52 | 53 | 54 | void init_workload(std::string path) { 55 | memSim.loadBinary(path); 56 | } 57 | 58 | 59 | char* get_pmem(uint64_t& size) { 60 | size = memSim.pmem_size; 61 | return memSim.pmem; 62 | } 63 | 64 | extern "C" char read_rom(uint64_t addr) { 65 | uint64_t paddr = addr - PMEM_BASE; 66 | unsigned char byte = memSim.readByte(paddr); 67 | DPRINTF(ROM, "read rom addr: %lx, data: %#02x\n", addr, byte); 68 | return byte; 69 | } 70 | 71 | extern "C" void pmem_write(uint64_t paddr, uint64_t data) { 72 | DPRINTF(ROM, "write rom addr: %lx, data: %#02x\n", paddr, (char)data); 73 | uint64_t addr = paddr - PMEM_BASE; 74 | memSim.writeByte(addr, (char)data); 75 | } 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /sim/verilator/tb/bpu_test.sv: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | module bpu_test ( 5 | input wire clk, 6 | input rst 7 | ); 8 | 9 | 10 | reg close; 11 | int count; 12 | reg update_vld; 13 | wire update_finished; 14 | always_ff @( posedge clk ) begin 15 | if (rst) begin 16 | count <= 0; 17 | update_vld <= 0; 18 | close <= 0; 19 | end 20 | else begin 21 | count <= count + 1; 22 | if (update_finished) begin 23 | update_vld <= 0; 24 | end 25 | 26 | if (count >= 10 && (!close)) begin 27 | update_vld <= 1; 28 | close <= 1; 29 | end 30 | end 31 | end 32 | 33 | BPupdateInfo_t ftb_update = '{ 34 | startAddr : `INIT_PC + 20*64, 35 | ftb_update : '{ 36 | carry : 0, 37 | fallthruAddr : 16, 38 | tarStat : tarStat_t::FIT, 39 | targetAddr : 0, 40 | branch_type : BranchType::isCond, 41 | counter : 2 42 | } 43 | }; 44 | 45 | 46 | BPU u_BPU( 47 | .clk ( clk ), 48 | .rst ( rst ), 49 | 50 | .i_squash_vld ( 0 ), 51 | .i_squashInfo ( ), 52 | 53 | .i_update_vld ( update_vld ), 54 | .o_update_finished ( update_finished ), 55 | .i_BPupdateInfo ( ftb_update ), 56 | 57 | .o_pred_vld ( ), 58 | .o_pred_ftqInfo ( ) 59 | ); 60 | 61 | 62 | 63 | 64 | endmodule 65 | 66 | -------------------------------------------------------------------------------- /sim/verilator/tb/ctrl_test.sv: -------------------------------------------------------------------------------- 1 | module ctrl_test #( 2 | parameter int WIDTH = 4 3 | )( 4 | input wire clk, 5 | input wire rst 6 | ); 7 | 8 | fetchEntry_t temp = '{ 9 | inst : 32'b00000000000000001000000010110011,// mv x1,x1 10 | ftq_idx:0, 11 | ftqOffset:0, 12 | has_except:0, 13 | except:0 14 | }; 15 | 16 | 17 | ctrlBlock u_ctrlBlock( 18 | .clk (clk ), 19 | .rst (rst ), 20 | 21 | .i_inst_vld (4'b0011), 22 | .i_inst ({temp,temp,temp,temp}), 23 | 24 | .i_immB_clear_vld (0), 25 | .i_wb_vld (0), 26 | .i_branchwb_vld (0), 27 | .i_exceptwb_vld (0), 28 | 29 | .i_intBlock_stall (0) 30 | ); 31 | 32 | 33 | 34 | 35 | 36 | 37 | endmodule 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sim/verilator/tb/tb.sv: -------------------------------------------------------------------------------- 1 | 2 | `include "core_define.svh" 3 | `include "frontend_define.svh" 4 | 5 | module tb ( 6 | input wire clk, 7 | input wire rst 8 | ); 9 | 10 | tilelink_if #( 11 | .MASTERS(2), 12 | .SLAVES(1), 13 | .ADDR_WIDTH(64), 14 | .DATA_WIDTH(`CACHELINE_SIZE) 15 | ) if_ibus(), if_dbus(); 16 | 17 | 18 | aura_core u_aura_core( 19 | .clk (clk ), 20 | .rst (rst ), 21 | .if_tilelink_bus0 (if_ibus ), 22 | .if_tilelink_bus1 (if_dbus ) 23 | ); 24 | 25 | 26 | 27 | endmodule 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /synth/yosys/Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SV_FILES := $(shell find ../../rtl -name "*.sv") 7 | SV_PATHS := $(shell find ../../rtl -type d) 8 | SV_PATHS := $(addprefix -I ,$(SV_PATHS)) 9 | aura: 10 | touch temp.v 11 | #convert sv to v 12 | @sv2v -v -E Always $(SV_PATHS) $(SV_FILES) -w temp.v 13 | yosys -p "plugin -i systemverilog" \ 14 | -p "read_verilog -top tb tb.sv $(SV_FILES)" \ 15 | -p "proc; proc_mux; memory; proc_clean; proc_rmdead; proc_prune; opt; opt_clean; opt_dff; opt_demorgan; opt_dff; opt_expr; opt_mem; opt_muxtree; opt_reduce" \ 16 | -p "show -colors 2 -width -signed -enum -prefix out tb" 17 | rm temp.v 18 | 19 | tb: 20 | touch temp.v 21 | sv2v -v -E Always tb.sv -w temp.v 22 | yosys \ 23 | -p "read_verilog -sv temp.v" \ 24 | -p "proc; proc_mux; memory; proc_clean; proc_rmdead; proc_prune; opt; opt_clean; opt_dff; opt_demorgan; opt_dff; opt_expr; opt_mem; opt_muxtree; opt_reduce" \ 25 | -p "synth_xilinx" \ 26 | -p "show -colors 2 -width -signed -enum -prefix out tb" 27 | rm temp.v 28 | 29 | sv2v: 30 | touch temp.v 31 | #convert sv to v 32 | sv2v -v -E Always $(SV_PATHS) $(SV_FILES) -w temp.v -------------------------------------------------------------------------------- /synth/yosys/tb.sv: -------------------------------------------------------------------------------- 1 | 2 | `define WDEF(x) ((``x``) == 0 ? 0 : ((``x``)-1)):0 3 | 4 | interface tilelink_if #( 5 | parameter int MASTERS = 2, 6 | parameter int SLAVES = 2, 7 | parameter int ADDR_WIDTH = 32,// bit 8 | parameter int DATA_WIDTH = 32// Byte 9 | ); 10 | // A channel 11 | logic[`WDEF(3)] a_code; 12 | logic[`WDEF(3)] a_param; 13 | logic[`WDEF($clog2(DATA_WIDTH))] a_size; 14 | logic[`WDEF($clog2(MASTERS))] a_source; 15 | logic[`WDEF(ADDR_WIDTH)] a_address; 16 | logic[`WDEF(DATA_WIDTH)] a_mask; 17 | logic[`WDEF(DATA_WIDTH*8)] a_data; 18 | logic a_corrupt; 19 | logic a_valid; 20 | logic a_ready; 21 | 22 | // D channel 23 | logic[`WDEF(3)] d_opcode; 24 | logic[`WDEF(2)] d_param; 25 | logic[`WDEF($clog2(DATA_WIDTH))] d_size; 26 | logic[`WDEF($clog2(MASTERS))] d_source; 27 | logic[`WDEF($clog2(SLAVES))] d_sink; 28 | logic d_denied; 29 | logic[`WDEF(DATA_WIDTH*8)] d_data; 30 | logic d_corrupt; 31 | logic d_valid; 32 | logic d_ready; 33 | 34 | 35 | modport m ( 36 | output a_code, 37 | output a_param, 38 | output a_size, 39 | output a_source, 40 | output a_address, 41 | output a_mask, 42 | output a_data, 43 | output a_corrupt, 44 | output a_valid, 45 | input a_ready, 46 | 47 | input d_opcode, 48 | input d_param, 49 | input d_size, 50 | input d_source, 51 | input d_sink, 52 | input d_denied, 53 | input d_data, 54 | input d_corrupt, 55 | input d_valid, 56 | output d_ready 57 | ); 58 | 59 | modport s ( 60 | input a_code, 61 | input a_param, 62 | input a_size, 63 | input a_source, 64 | input a_address, 65 | input a_mask, 66 | input a_data, 67 | input a_corrupt, 68 | input a_valid, 69 | output a_ready, 70 | 71 | output d_opcode, 72 | output d_param, 73 | output d_size, 74 | output d_source, 75 | output d_sink, 76 | output d_denied, 77 | output d_data, 78 | output d_corrupt, 79 | output d_valid, 80 | input d_ready 81 | ); 82 | 83 | function int Ahandshake(); 84 | Ahandshake = a_valid && a_ready; 85 | endfunction; 86 | 87 | function int Dhandshake(); 88 | Dhandshake = d_valid && d_ready; 89 | endfunction; 90 | 91 | endinterface 92 | 93 | 94 | 95 | 96 | module tb(); 97 | 98 | intf #(4) myi(); 99 | mod m(myi); 100 | // hello world 101 | int a = myi.WWW(); 102 | 103 | endmodule 104 | 105 | module mod ( 106 | tilelink_if.m m 107 | ); 108 | always begin 109 | m.AputData(23); 110 | end 111 | endmodule 112 | -------------------------------------------------------------------------------- /tools/formatter.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | svfiles = [] 4 | def get_svfiles(path): 5 | global svfiles 6 | subfolders = os.listdir(path) 7 | for i in subfolders: 8 | subpath = os.path.join(path,i) 9 | if os.path.isdir(subpath): 10 | get_svfiles(subpath) 11 | if os.path.isfile(subpath): 12 | if subpath.endswith('.sv') or subpath.endswith('.svh'): 13 | svfiles.append(subpath) 14 | 15 | def is_modified(file): 16 | return os.system('git diff --quiet ' + file) != 0 17 | 18 | 19 | aura_home = os.environ.get('AURA_HOME') 20 | rtlpath = (aura_home + '/' if aura_home else '') + 'rtl' 21 | get_svfiles(rtlpath) 22 | 23 | 24 | formatCommand = 'verible-verilog-format --flagfile .sv.format --inplace' 25 | for svfile in svfiles: 26 | if is_modified(svfile): 27 | command = formatCommand + ' ' + svfile 28 | print(command) 29 | os.system(command) 30 | 31 | -------------------------------------------------------------------------------- /tools/getlist_of_rtl.py: -------------------------------------------------------------------------------- 1 | import os 2 | import argparse 3 | 4 | folders = "" 5 | def get_list_of(path): 6 | global folders 7 | subfolders = os.listdir(path) 8 | for i in subfolders: 9 | subpath = os.path.join(path,i) 10 | if os.path.isdir(subpath): 11 | folders+=" -y " + subpath 12 | get_list_of(subpath) 13 | 14 | 15 | 16 | parser = argparse.ArgumentParser() 17 | parser.add_argument("-p", "--path", action="store", 18 | help="the path which you want to list reduce") 19 | args = parser.parse_args() 20 | get_list_of(args.path) 21 | print(folders,end='') 22 | -------------------------------------------------------------------------------- /tools/pipeview.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | 4 | debugFlag_pipeline_re = r"\d+ DebugFlag-PIPELINE: \[sn (\d+) pc ([\da-zA-Z]+)\] ([\(\)a-zA-z ,.0-9-+]+) F(\d+) ([\d:]+C)" 5 | 6 | debugFlag_pipeline_pattern = re.compile(debugFlag_pipeline_re) 7 | 8 | 9 | def printPipe(res): 10 | stage = ['f', 'd', 'r', 'D', 'i', 'e', 'c'] 11 | sn, pc, disass, ftime, pipe = res 12 | i = 0 13 | line = ['.'] * 100 14 | ti = int(ftime) 15 | for c in pipe.split(':'): 16 | if c != 'C': 17 | c = int(c) 18 | s = stage[i] 19 | for j in range(c): 20 | line[ti % 100] = s 21 | ti+=1 22 | else : 23 | line[ti % 100] = 'C' 24 | i+=1 25 | print('[' + ''.join(line) + ']', '[sn %s pc %s]' % (sn, pc), disass) 26 | 27 | def fparser(file): 28 | fs = open(file, 'r') 29 | for line in fs.readlines(): 30 | line = line.strip() 31 | if 'DebugFlag-PIPELINE' in line: 32 | res = debugFlag_pipeline_pattern.findall(line)[0] 33 | printPipe(res) 34 | 35 | 36 | fparser('log.txt') 37 | -------------------------------------------------------------------------------- /vvls.sh: -------------------------------------------------------------------------------- 1 | # verible-verilog-ls language server style 2 | verible-verilog-ls --rules_config /media/lurker/files/O3CPU/aura-core/.sv.style --------------------------------------------------------------------------------