├── .gitignore ├── Makefile ├── README.md ├── cache ├── .gitignore ├── Makefile ├── README.md ├── assets │ ├── architecture.drawio │ ├── architecture.png │ └── icache.drawio ├── build │ └── .gitkeeper ├── sources-cache.tcl ├── sources.tcl ├── src │ ├── CacheBuffer.sv │ ├── CacheLayer.sv │ ├── DCache.sv │ ├── DCache.top │ ├── ICache.sv │ ├── ICache.top │ ├── LoadStoreBuffer.sv │ ├── LoadStoreBuffer.top │ ├── MMU.sv │ ├── OneLineBuffer.sv │ ├── OneLineBuffer.top │ ├── PLRU.sv │ ├── PLRU.top │ ├── PrefixSum.sv │ ├── PrefixSum.top │ ├── TranslationUnit.sv │ ├── include │ │ ├── axi.svh │ │ ├── cache.svh │ │ ├── cache_bus.svh │ │ ├── data_bus.svh │ │ ├── defs.svh │ │ ├── disable_tu.svh │ │ ├── instr_bus.svh │ │ ├── sramx.svh │ │ ├── tu.svh │ │ └── tu_addr.svh │ ├── ip │ │ ├── .gitignore │ │ └── AXICrossbar │ │ │ └── AXICrossbar.xci │ ├── ram │ │ ├── DualPortBRAM.sv │ │ ├── FFRAM.sv │ │ ├── LUTRAM.sv │ │ ├── SimpleDualPortBRAM.sv │ │ ├── SimpleDualPortFFRAM.sv │ │ └── SimpleDualPortLUTRAM.sv │ ├── synth │ │ ├── DCacheTop.sv │ │ └── ICacheTop.sv │ ├── top │ │ └── mycpu_top.sv │ ├── util │ │ ├── AXIWrap.sv │ │ ├── CacheBusToAXI.sv │ │ ├── CrossbarWrap.sv │ │ ├── DirectMappedAddr.sv │ │ ├── InstrBusToSRAMx.sv │ │ ├── OneHotToBinary.sv │ │ ├── RequestBuffer.sv │ │ ├── SRAMxToAXI.sv │ │ ├── SRAMxToDataBus.sv │ │ ├── SRAMxToInstrBus.sv │ │ └── StrobeTranslator.sv │ └── xsim │ │ ├── CacheBusToAXITest.sv │ │ ├── DualPortBRAMTest.sv │ │ ├── LUTRAMTest.sv │ │ ├── SRAMxToAXITest.sv │ │ ├── SimpleDualPortBRAMTest.sv │ │ └── global.svh ├── test │ ├── DCache.cpp │ ├── DCache.h │ ├── ICache.cpp │ ├── ICache.h │ ├── LoadStoreBuffer.cpp │ ├── LoadStoreBuffer.h │ ├── OneLineBuffer.cpp │ ├── OneLineBuffer.h │ ├── PLRU.cpp │ ├── PLRU.h │ ├── PrefixSum.cpp │ ├── PrefixSum.h │ └── util │ │ ├── CacheBusMemory.h │ │ ├── ICacheBus.h │ │ ├── SimpleTopBase.h │ │ ├── TopBase.h │ │ ├── main.cpp │ │ ├── util.cpp │ │ └── util.h ├── trace │ ├── .gitkeeper │ ├── dcache.gtkw │ ├── icache.gtkw │ ├── ls-buffer.gtkw │ ├── partial-write.gtkw │ ├── random-read-write.gtkw │ ├── sequential-read.gtkw │ ├── sequential-write.gtkw │ ├── single-read.gtkw │ └── single-write.gtkw └── wrap.py ├── scripts ├── Jenkinsfile ├── add_directory.tcl ├── build_bitstream.tcl ├── check_simulation.sh ├── dynamic_pll.sh ├── generate_all_ips.tcl ├── run_implementation.tcl └── run_simulation.tcl ├── sources └── superscalar-inorder.tcl ├── superscalar_inorder_bpb ├── ALU.sv ├── DIVU.sv ├── FU.sv ├── JUDGE.sv ├── MULU.sv ├── adder.sv ├── bpb │ ├── bpb0.sv │ ├── bpb1.sv │ ├── bpb2.sv │ ├── bpb_decode.sv │ ├── bpb_line0.sv │ ├── bpb_line1.sv │ ├── bpb_line2.sv │ └── branchpredict.sv ├── bypass.sv ├── commit.sv ├── control.sv ├── cp0.sv ├── cp0bypass.sv ├── cp0status_bypass.sv ├── cpu_axi_interface.v ├── datapath.sv ├── decode.sv ├── decode.svh ├── decode_to_issue_t.sv ├── exception.sv ├── exception_checker.sv ├── exec_to_commit_t.sv ├── exec_to_exec_t.sv ├── execute.sv ├── extend.sv ├── fetch.sv ├── global.svh ├── handshake.sv ├── hilo.sv ├── hlbypass.sv ├── issue.sv ├── maindecode.sv ├── mem_to_reg.sv ├── mips.svh ├── mult │ ├── .gitignore │ ├── divider.sv │ ├── divider.svh │ ├── mult.sv │ ├── mult_gen_0 │ │ └── mult_gen_0.xci │ └── multplier.sv ├── mycpu.sv ├── pcselect.sv ├── pipelinereg.sv ├── regbypass.sv ├── regfile.sv ├── retire.sv ├── signalcommit.sv ├── signaldecode.sv ├── top │ ├── readdata_format.sv │ └── rfwrite_queue.sv └── writedata_format.sv ├── superscalar_inorder_dual ├── ALU.sv ├── DIVU.sv ├── FU.sv ├── JUDGE.sv ├── MULU.sv ├── README.md ├── adder.sv ├── assets │ ├── commit.png │ ├── fetch.png │ ├── issue.png │ ├── pipeline.JPG │ └── simplified_pipeline.png ├── bpb │ ├── bpb0.sv │ ├── bpb1.sv │ ├── bpb2.sv │ ├── bpb_decode.sv │ ├── bpb_line0.sv │ ├── bpb_line1.sv │ ├── bpb_line2.sv │ ├── bpbdecode.sv │ ├── branchpredict.sv │ ├── jrpredict.sv │ └── jrstack.sv ├── bypass.sv ├── commit.sv ├── commit │ ├── datacommit.sv │ ├── exceptioncommit.sv │ └── quickcommit.sv ├── control.sv ├── cp0.sv ├── cp0bypass.sv ├── cp0status_bypass.sv ├── cpu_axi_interface.v ├── datapath.sv ├── decode.sv ├── decode.svh ├── decode_to_issue_t.sv ├── exception.sv ├── exception_checker.sv ├── exec_to_commit_t.sv ├── exec_to_exec_t.sv ├── execute.sv ├── extend.sv ├── fetch.sv ├── fetch │ ├── instrfetch.sv │ ├── pc_cmtselect.sv │ ├── pcfetch.sv │ └── quickfetch.sv ├── global.svh ├── handshake.sv ├── hilo.sv ├── hlbypass.sv ├── issue.sv ├── maindecode.sv ├── mem_to_reg.sv ├── mips.svh ├── mult │ ├── .gitignore │ ├── divider.sv │ ├── divider.svh │ ├── mult.sv │ ├── mult_gen_0 │ │ └── mult_gen_0.xci │ └── multplier.sv ├── mycpu.sv ├── pcselect.sv ├── pipelinereg.sv ├── regbypass.sv ├── regfile.sv ├── retire.sv ├── sbuffer │ ├── sbuffer.sv │ └── sbuffer.svh ├── signalcommit.sv ├── signaldecode.sv ├── sources.tcl ├── top │ ├── readdata_format.sv │ └── rfwrite_queue.sv └── writedata_format.sv └── superscalar_inorder_signal ├── ALU.sv ├── DIVU.sv ├── FU.sv ├── JUDGE.sv ├── MULU.sv ├── adder.sv ├── bypass.sv ├── commit.sv ├── control.sv ├── cp0.sv ├── cp0bypass.sv ├── cp0status_bypass.sv ├── cpu_axi_interface.v ├── datapath.sv ├── decode.sv ├── decode.svh ├── decode_to_issue_t.sv ├── exception.sv ├── exception_checker.sv ├── exec_to_commit_t.sv ├── exec_to_exec_t.sv ├── execute.sv ├── extend.sv ├── fetch.sv ├── global.svh ├── handshake.sv ├── hilo.sv ├── hlbypass.sv ├── issue.sv ├── maindecode.sv ├── mem_to_reg.sv ├── mips.svh ├── mycpu.sv ├── mycpu_top.sv ├── pcselect.sv ├── pipelinereg.sv ├── regbypass.sv ├── regfile.sv ├── retire.sv ├── signalcommit.sv ├── signaldecode.sv ├── top ├── readdata_format.sv └── rfwrite_queue.sv └── writedata_format.sv /.gitignore: -------------------------------------------------------------------------------- 1 | benchtest/* 2 | 5-stage/ 3 | *.log 4 | *.jou 5 | vivado/* 6 | .vscode/ 7 | .Xil/ 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL: help 2 | 3 | .PHONY: help 4 | help: 5 | @echo "See README & Makefile." -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 一个朴素的顺序双发射MIPS处理器 2 | 3 | 本项目为复旦大学FDU1.1队在第四届“龙芯杯”的参赛作品。 4 | 5 | 6 | 7 | 我们的成绩如下: 8 | 9 | | | 频率(MHZ) | 性能分 | IPC分 | 10 | | -------- | ----------- | ------ | ----- | 11 | | 初赛提交 | 110 | 74 | | 12 | | 决赛提交 | 95 | | 34 | 13 | 14 | `master`分支为我们的初赛提交,供大家参考。我们决赛提交的CPU在流水线架构上相对初赛提交几乎没有改进,且存在一些bug而无法启动Linux。虽然比赛已经结束,但我们不想留下遗憾,仍在其他分支上进行debug工作。如能启动Linux,我们会把能启Linux的版本更新到`master`分支上。 15 | 16 | 17 | 18 | ------ 19 | 20 | Cache部分详见`cache/`。 21 | 22 | CPU主体部分详见`superscalar_inorder_dual/`。 23 | 24 | 可用`scripts/superscalar-inorder.tcl`在大赛提供的func test或perf test工程中快速添加源代码及IP核的配置文件。 -------------------------------------------------------------------------------- /cache/.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | !build/.gitkeeper 3 | *.out 4 | 5 | .top 6 | *.bak 7 | *.vcd 8 | *.fst 9 | *.hier -------------------------------------------------------------------------------- /cache/assets/architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSCSCC-2020-Fudan/FDU1.1-NSCSCC/6c751483f2b8467548fb216fb23b995cd6ce8897/cache/assets/architecture.png -------------------------------------------------------------------------------- /cache/build/.gitkeeper: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSCSCC-2020-Fudan/FDU1.1-NSCSCC/6c751483f2b8467548fb216fb23b995cd6ce8897/cache/build/.gitkeeper -------------------------------------------------------------------------------- /cache/sources-cache.tcl: -------------------------------------------------------------------------------- 1 | cd [file dirname [info script]] 2 | source sources.tcl 3 | add_files [glob src/synth/*.sv] 4 | add_files [glob src/xsim/*.svh] 5 | set_property is_global_include true [get_files src/xsim/global.svh] -------------------------------------------------------------------------------- /cache/sources.tcl: -------------------------------------------------------------------------------- 1 | cd [file dirname [info script]] 2 | add_files [glob src/include/*.svh] 3 | add_files [glob src/ip/*/*.xci] 4 | add_files [glob src/ram/*.sv] 5 | add_files [glob src/util/*.sv] 6 | add_files [glob src/*.sv] -------------------------------------------------------------------------------- /cache/src/CacheBuffer.sv: -------------------------------------------------------------------------------- 1 | `include "data_bus.svh" 2 | 3 | /** 4 | * to include vaddr in buffer requests 5 | */ 6 | module CacheBuffer #( 7 | parameter type req_t = dbus_req_t, 8 | parameter type resp_t = dbus_resp_t 9 | ) ( 10 | input logic clk, resetn, 11 | 12 | input addr_t m_req_vaddr, 13 | input req_t m_req, 14 | output resp_t m_resp, 15 | output addr_t s_req_vaddr, 16 | output req_t s_req, 17 | input resp_t s_resp 18 | ); 19 | typedef struct packed { 20 | logic req; 21 | addr_t vaddr; 22 | req_t payload; 23 | } buf_req_t; 24 | 25 | buf_req_t i_req, o_req; 26 | 27 | assign i_req.req = m_req.req; 28 | assign i_req.vaddr = m_req_vaddr; 29 | assign i_req.payload = m_req; 30 | 31 | assign s_req = o_req.payload; 32 | assign s_req_vaddr = o_req.vaddr; 33 | 34 | RequestBuffer #( 35 | .req_t(buf_req_t), 36 | .resp_t(resp_t) 37 | ) req_buf_inst( 38 | .clk, .resetn, 39 | .m_req(i_req), .m_resp, 40 | .s_req(o_req), .s_resp 41 | ); 42 | 43 | logic __unused_ok = &{1'b0, o_req.req, 1'b0}; 44 | endmodule -------------------------------------------------------------------------------- /cache/src/DCache.top: -------------------------------------------------------------------------------- 1 | # ports 2 | //bram_inst.mem 3 | bram_inst.new_data_1 4 | bram_inst.new_data_2 5 | bram_inst.write_en_1 6 | bram_inst.write_en_2 7 | bram_inst.addr_1 8 | bram_inst.addr_2 9 | 10 | req_hit 11 | req_idx 12 | req_in_miss 13 | req_miss_ready 14 | //req_ready 15 | req_to_hit 16 | req_to_miss 17 | req_victim_idx 18 | req_new_select 19 | 20 | miss_addr 21 | miss_avail 22 | miss_busy 23 | miss_is_dirty 24 | miss_pos 25 | miss_rdata 26 | miss_ready 27 | miss_state 28 | miss_victim 29 | miss_voffset 30 | miss_vwrten 31 | miss_wdata 32 | miss_write_en 33 | 34 | hit_data_ok 35 | hit_pos 36 | hit_rdata 37 | hit_wdata 38 | hit_write_en -------------------------------------------------------------------------------- /cache/src/ICache.top: -------------------------------------------------------------------------------- 1 | # ports 2 | //bram_inst.mem 3 | //sets 4 | //req_ready 5 | req_hit 6 | miss_busy 7 | miss_avail 8 | req_to_miss 9 | req_to_hit 10 | bram_inst.addr_1 11 | bram_inst.write_en_1 12 | bram_inst.data_in_1 13 | bram_inst.data_out_1 14 | bram_inst.addr_2 15 | bram_inst.write_en_2 16 | bram_inst.data_in_2 17 | bram_inst.data_out_2 18 | req_in_miss 19 | req_miss_ready 20 | miss_ready 21 | miss_mark 22 | miss_count 23 | req_iaddr 24 | req_paddr 25 | req_hit_bits 26 | ram_new_meta 27 | -------------------------------------------------------------------------------- /cache/src/LoadStoreBuffer.top: -------------------------------------------------------------------------------- 1 | # ports 2 | fifo 3 | fifo_avail 4 | fifo_empty 5 | fifo_pop 6 | fifo_push 7 | //req_is_wr 8 | //req_ff_ok 9 | head 10 | meta 11 | tail -------------------------------------------------------------------------------- /cache/src/OneLineBuffer.top: -------------------------------------------------------------------------------- 1 | # ports 2 | mem: mem 3 | valid 4 | tag 5 | state 6 | tag_hit 7 | offset_hit 8 | req_addr 9 | saved_addr 10 | dirty 11 | offset 12 | req_strb 13 | saved_strb -------------------------------------------------------------------------------- /cache/src/PLRU.sv: -------------------------------------------------------------------------------- 1 | module PLRU #( 2 | parameter int NUM_WAYS = 8, 3 | 4 | localparam int IDX_BITS = $clog2(NUM_WAYS), 5 | localparam int NUM_SELECT = NUM_WAYS - 1, 6 | 7 | localparam type idx_t = logic [IDX_BITS - 1:0], 8 | localparam type select_t = logic [NUM_SELECT - 1:0] 9 | ) ( 10 | input select_t select, 11 | output idx_t victim_idx, 12 | input idx_t idx, 13 | output select_t new_select 14 | ); 15 | /** 16 | * select idx for replacement 17 | */ 18 | typedef logic [NUM_SELECT:1] mask_t; 19 | mask_t s, bits; 20 | mask_t mask /* verilator split_var */; 21 | 22 | // mask tree root 23 | assign mask[1] = 1; 24 | 25 | // propagation to leaves 26 | assign s = select; 27 | for (genvar i = 1; i < NUM_WAYS / 2; i++) begin: plru_mask 28 | assign mask[2 * i ] = mask[i] && !s[i]; 29 | assign mask[2 * i + 1] = mask[i] && s[i]; 30 | end 31 | 32 | // generate idx 33 | assign bits = s & mask; 34 | for (genvar i = 0; i < IDX_BITS; i++) begin: plru_idx 35 | localparam int lo = 2**i; 36 | localparam int hi = 2 * lo - 1; 37 | assign victim_idx[IDX_BITS - i - 1] = |bits[hi:lo]; 38 | end 39 | 40 | /** 41 | * calculate new select vector 42 | */ 43 | mask_t rax; 44 | assign new_select = rax; 45 | 46 | assign rax[1] = ~idx[IDX_BITS - 1]; 47 | for (genvar i = 2; i <= NUM_SELECT; i++) begin: calc_new_select 48 | localparam int n = $clog2(i + 1) - 1; // number of bits from idx 49 | localparam int t = IDX_BITS - n - 1; // target bit index 50 | 51 | idx_t v; 52 | assign v = {{(IDX_BITS - n - 1){1'b0}}, 1'b1, idx[IDX_BITS - 1 -: n]}; 53 | assign rax[i] = (i == v) ? ~idx[t] : s[i]; 54 | end 55 | endmodule -------------------------------------------------------------------------------- /cache/src/PLRU.top: -------------------------------------------------------------------------------- 1 | # ports 2 | -------------------------------------------------------------------------------- /cache/src/PrefixSum.sv: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * NOTE: be careful about endianness 4 | * 5 | * although it's named "PrefixSum", it was intended to calculate 6 | * suffix sums. 7 | */ 8 | module PrefixSum #( 9 | parameter int ARRAY_LENGTH = 8, 10 | 11 | localparam type array_t = logic [ARRAY_LENGTH - 1:0] 12 | ) ( 13 | input array_t arr, 14 | output array_t sum 15 | ); 16 | array_t partial; 17 | 18 | function int lowbit(input int x); 19 | return x & (-x); 20 | endfunction 21 | 22 | function int prev(input int x); 23 | return x - lowbit(x); 24 | endfunction 25 | 26 | always_comb begin 27 | partial = arr; 28 | for (int i = 1; i <= ARRAY_LENGTH; i++) begin 29 | for (int j = i - 1; j > 0; j = prev(j)) begin 30 | partial[ARRAY_LENGTH - i] &= partial[ARRAY_LENGTH - j]; 31 | end 32 | end 33 | end 34 | 35 | always_comb begin 36 | sum = partial; 37 | for (int i = 1; i <= ARRAY_LENGTH; i++) begin 38 | for (int j = prev(i); j > 0; j = prev(j)) begin 39 | sum[ARRAY_LENGTH - i] &= partial[ARRAY_LENGTH - j]; 40 | end 41 | end 42 | end 43 | endmodule -------------------------------------------------------------------------------- /cache/src/PrefixSum.top: -------------------------------------------------------------------------------- 1 | # ports 2 | -------------------------------------------------------------------------------- /cache/src/TranslationUnit.sv: -------------------------------------------------------------------------------- 1 | `ifndef DISABLE_DEFAULT_TU 2 | 3 | `include "defs.svh" 4 | `include "tu.svh" 5 | `include "tu_addr.svh" 6 | 7 | module TranslationUnit( 8 | input logic clk, resetn, 9 | 10 | // address translation requests 11 | input tu_addr_req_t i_req, d_req, 12 | output tu_addr_resp_t i_resp, d_resp, 13 | 14 | // TU interactions 15 | input tu_op_req_t op_req, 16 | output tu_op_resp_t op_resp 17 | ); 18 | DirectMappedAddr i_map_inst( 19 | .vaddr(i_req.vaddr), 20 | .paddr(i_resp.paddr), 21 | .is_uncached(i_resp.is_uncached) 22 | ); 23 | 24 | DirectMappedAddr d_map_inst( 25 | .vaddr(d_req.vaddr), 26 | .paddr(d_resp.paddr), 27 | .is_uncached(d_resp.is_uncached) 28 | ); 29 | 30 | assign op_resp = 0; 31 | logic __unused_ok = &{1'b0, clk, resetn, op_req, 1'b0}; 32 | endmodule 33 | 34 | `endif -------------------------------------------------------------------------------- /cache/src/include/cache.svh: -------------------------------------------------------------------------------- 1 | `ifndef __CACHE_CACHE_SVH__ 2 | `define __CACHE_CACHE_SVH__ 3 | 4 | `include "defs.svh" 5 | 6 | // 8-way 32KB 64bytes-line dual-fetch 7 | parameter int ICACHE_IDX_BITS = 3; // id bits 8 | parameter int ICACHE_INDEX_BITS = 6; // index bits (set) 9 | parameter int ICACHE_OFFSET_BITS = 3; // offset bits 10 | parameter int ICACHE_ALIGN_BITS = 3; // aligned bits 11 | 12 | // 4-way 16KB 64bytes-line 13 | parameter int DCACHE_IDX_BITS = 2; // id bits 14 | parameter int DCACHE_INDEX_BITS = 6; // index bits (set) 15 | parameter int DCACHE_OFFSET_BITS = 4; // offset bits 16 | 17 | parameter int LSBUF_LENGTH = 8; // length of load-store buffer for uncached ops 18 | 19 | `endif -------------------------------------------------------------------------------- /cache/src/include/cache_bus.svh: -------------------------------------------------------------------------------- 1 | `ifndef __CACHE_CACHE_BUS_SVH__ 2 | `define __CACHE_CACHE_BUS_SVH__ 3 | 4 | `include "defs.svh" 5 | 6 | // NOTE: `CBUS_LEN_BITS` must be greater than `AXI_LEN_BITS`. 7 | parameter int CBUS_DATA_WIDTH = 32; 8 | parameter int CBUS_DATA_BYTES = CBUS_DATA_WIDTH / 8; // 4 9 | parameter int CBUS_LEN_BITS = 16; 10 | parameter int CBUS_MAXLEN = 2**(CBUS_LEN_BITS - 1); // 2^15 = 32768 11 | parameter int CBUS_ORDER_BITS = $clog2(CBUS_LEN_BITS); // 4 12 | 13 | typedef logic [CBUS_DATA_WIDTH - 1:0] cbus_word_t; 14 | typedef logic [CBUS_LEN_BITS - 1:0] cbus_len_t; 15 | typedef logic [CBUS_ORDER_BITS - 1:0] cbus_order_t; 16 | 17 | typedef union packed { 18 | byte_t [CBUS_DATA_BYTES - 1:0] bytes; 19 | cbus_word_t word; 20 | } cbus_view_t; 21 | 22 | typedef struct packed { 23 | logic valid; 24 | logic is_write; 25 | addr_t addr; 26 | cbus_order_t order; 27 | cbus_view_t wdata; 28 | } cbus_req_t; 29 | 30 | typedef struct packed { 31 | logic okay; 32 | logic last; 33 | cbus_view_t rdata; 34 | } cbus_resp_t; 35 | 36 | `endif -------------------------------------------------------------------------------- /cache/src/include/data_bus.svh: -------------------------------------------------------------------------------- 1 | `ifndef __CACHE_DATA_BUS_SVH__ 2 | `define __CACHE_DATA_BUS_SVH__ 3 | 4 | `include "defs.svh" 5 | 6 | parameter int DBUS_DATA_WIDTH = 32; 7 | parameter int DBUS_DATA_BYTES = DBUS_DATA_WIDTH / 8; 8 | 9 | typedef logic [DBUS_DATA_BYTES - 1:0] dbus_wrten_t; 10 | typedef byte_t [DBUS_DATA_BYTES - 1:0] dbus_bytes_t; 11 | typedef logic [DBUS_DATA_WIDTH - 1:0] dbus_word_t; 12 | 13 | typedef union packed { 14 | dbus_bytes_t bytes; 15 | dbus_word_t word; 16 | } dbus_view_t; 17 | 18 | typedef struct packed { 19 | logic req; 20 | logic is_write; 21 | dbus_wrten_t write_en; 22 | addr_t addr; 23 | dbus_view_t data; 24 | } dbus_req_t; 25 | 26 | typedef struct packed { 27 | logic addr_ok; 28 | logic data_ok; 29 | dbus_view_t data; 30 | } dbus_resp_t; 31 | 32 | `endif -------------------------------------------------------------------------------- /cache/src/include/defs.svh: -------------------------------------------------------------------------------- 1 | `ifndef CACHE_WITHOUT_MIPS 2 | `include "mips.svh" 3 | `endif 4 | 5 | `ifndef __CACHE_DEFS_SVH__ 6 | `define __CACHE_DEFS_SVH__ 7 | 8 | parameter int BYTES_PER_WORD = 4; 9 | parameter int BITS_PER_WORD = BYTES_PER_WORD * 8; 10 | 11 | /** 12 | * utility macros 13 | */ 14 | 15 | `ifdef CACHE_WITHOUT_MIPS 16 | `define ASSERT(expr, message) \ 17 | if (!(expr)) \ 18 | $error(message); 19 | `else 20 | `define ASSERT(expr, message) /* nothing */ 21 | `endif 22 | 23 | /** 24 | * primitive datatypes 25 | */ 26 | 27 | // nibble: half byte 28 | typedef logic [3 :0] nibble_t; 29 | 30 | /** 31 | * since both `byte_t` and `word_t` have been defined in MIPS source 32 | * in `global.svh`, we cannot have duplicate definitions of them. 33 | * 34 | * Remark: ******* VIVADO. 35 | */ 36 | `ifdef CACHE_WITHOUT_MIPS 37 | typedef logic [7 :0] byte_t; 38 | typedef logic [31:0] word_t; 39 | `endif 40 | 41 | typedef word_t addr_t; 42 | 43 | // Vivado Synthesis does not support string parameters. 44 | `ifdef VERILATOR 45 | `define STRING string 46 | `else 47 | `define STRING /* f**k vivado */ 48 | `endif 49 | 50 | `endif -------------------------------------------------------------------------------- /cache/src/include/disable_tu.svh: -------------------------------------------------------------------------------- 1 | // NOTE: set as "global include" 2 | 3 | `ifndef DISABLE_DEFAULT_TU 4 | `define DISABLE_DEFAULT_TU 5 | `endif -------------------------------------------------------------------------------- /cache/src/include/instr_bus.svh: -------------------------------------------------------------------------------- 1 | `ifndef __CACHE_INSTR_BUS_SVH__ 2 | `define __CACHE_INSTR_BUS_SVH__ 3 | 4 | `include "defs.svh" 5 | 6 | parameter int IBUS_DATA_WIDTH = 64; 7 | parameter int IBUS_WORD_WIDTH = 32; 8 | parameter int IBUS_WORD_PER_BUS = IBUS_DATA_WIDTH / IBUS_WORD_WIDTH; 9 | parameter int IBUS_INDEX_WIDTH = $clog2(IBUS_WORD_PER_BUS); 10 | 11 | typedef logic [IBUS_DATA_WIDTH - 1:0] ibus_data_t; 12 | typedef logic [IBUS_INDEX_WIDTH - 1:0] ibus_index_t; 13 | 14 | typedef struct packed { 15 | logic req; 16 | addr_t addr; 17 | } ibus_req_t; 18 | 19 | typedef struct packed { 20 | logic addr_ok; 21 | logic data_ok; 22 | ibus_data_t data; 23 | ibus_index_t index; 24 | } ibus_resp_t; 25 | 26 | `endif -------------------------------------------------------------------------------- /cache/src/include/sramx.svh: -------------------------------------------------------------------------------- 1 | `ifndef __CACHE_SRAMX_SVH__ 2 | `define __CACHE_SRAMX_SVH__ 3 | 4 | `include "defs.svh" 5 | 6 | parameter int SRAMX_DATA_WIDTH = 32; 7 | parameter int SRAMX_SIZE_WIDTH = 2; 8 | parameter int SRAMX_DATA_BYTES = SRAMX_DATA_WIDTH / 8; // 4 9 | parameter int SRAMX_MAX_SIZE = $clog2(SRAMX_DATA_BYTES); // 2 10 | parameter int SRAMX_DATA_BITS = $clog2(SRAMX_DATA_WIDTH); // 5 11 | 12 | typedef logic [SRAMX_DATA_WIDTH - 1:0] sramx_word_t; 13 | typedef logic [SRAMX_SIZE_WIDTH - 1:0] sramx_size_t; 14 | 15 | typedef union packed { 16 | byte_t [SRAMX_DATA_BYTES - 1:0] bytes; 17 | sramx_word_t word; 18 | } sramx_view_t; 19 | 20 | typedef struct packed { 21 | logic req; 22 | logic wr; 23 | sramx_size_t size; 24 | addr_t addr; 25 | sramx_view_t wdata; 26 | } sramx_req_t; 27 | 28 | typedef struct packed { 29 | logic addr_ok; 30 | logic data_ok; 31 | sramx_view_t rdata; 32 | } sramx_resp_t; 33 | 34 | `endif -------------------------------------------------------------------------------- /cache/src/include/tu.svh: -------------------------------------------------------------------------------- 1 | `ifndef DISABLE_DEFAULT_TU 2 | 3 | `ifndef __CACHE_TU_SVH__ 4 | `define __CACHE_TU_SVH__ 5 | 6 | typedef struct packed { 7 | logic __reserved; 8 | } tu_op_req_t; 9 | 10 | typedef struct packed { 11 | logic __reserved; 12 | } tu_op_resp_t; 13 | 14 | `endif 15 | 16 | `endif -------------------------------------------------------------------------------- /cache/src/include/tu_addr.svh: -------------------------------------------------------------------------------- 1 | `ifndef __CACHE_TU_ADDR_SVH__ 2 | `define __CACHE_TU_ADDR_SVH__ 3 | 4 | `include "defs.svh" 5 | 6 | typedef struct packed { 7 | addr_t vaddr; 8 | } tu_addr_req_t; 9 | 10 | typedef struct packed { 11 | logic is_uncached; 12 | addr_t paddr; 13 | } tu_addr_resp_t; 14 | 15 | `endif -------------------------------------------------------------------------------- /cache/src/ip/.gitignore: -------------------------------------------------------------------------------- 1 | */* 2 | !*.xci -------------------------------------------------------------------------------- /cache/src/ram/FFRAM.sv: -------------------------------------------------------------------------------- 1 | /** 2 | * RAM with full reset support 3 | * 4 | * it's likely implemented in flip-flops. 5 | */ 6 | module FFRAM #( 7 | parameter int DATA_WIDTH = 32, 8 | parameter int ADDR_WIDTH = 10, 9 | 10 | localparam int MEM_NUM_WORDS = 2**ADDR_WIDTH, 11 | localparam int MEM_NUM_BITS = MEM_NUM_WORDS * DATA_WIDTH, 12 | 13 | localparam type addr_t = logic [ADDR_WIDTH - 1:0], 14 | localparam type word_t = logic [DATA_WIDTH - 1:0] 15 | ) ( 16 | input logic clk, resetn, write_en, 17 | input addr_t addr, 18 | input word_t data_in, 19 | output word_t data_out 20 | ); 21 | word_t [MEM_NUM_WORDS - 1:0] mem; 22 | assign data_out = mem[addr]; 23 | 24 | always_ff @(posedge clk) 25 | if (resetn) begin 26 | if (write_en) begin 27 | for (int i = 0; i < MEM_NUM_WORDS; i++) begin 28 | mem[i] <= addr == addr_t'(i) ? data_in : mem[i]; 29 | end 30 | end else 31 | mem <= mem; 32 | end else begin 33 | mem <= 0; 34 | end 35 | endmodule -------------------------------------------------------------------------------- /cache/src/ram/SimpleDualPortFFRAM.sv: -------------------------------------------------------------------------------- 1 | /** 2 | * RAM with full reset support 3 | * 4 | * it's likely implemented in flip-flops. 5 | */ 6 | module SimpleDualPortFFRAM #( 7 | parameter int DATA_WIDTH = 32, 8 | parameter int ADDR_WIDTH = 10, 9 | 10 | localparam int MEM_NUM_WORDS = 2**ADDR_WIDTH, 11 | localparam int MEM_NUM_BITS = MEM_NUM_WORDS * DATA_WIDTH, 12 | 13 | localparam type addr_t = logic [ADDR_WIDTH - 1:0], 14 | localparam type word_t = logic [DATA_WIDTH - 1:0] 15 | ) ( 16 | input logic clk, resetn, write_en, 17 | input addr_t raddr, waddr, 18 | input word_t data_in, 19 | output word_t data_out 20 | ); 21 | word_t [MEM_NUM_WORDS - 1:0] mem; 22 | assign data_out = mem[raddr]; 23 | 24 | always_ff @(posedge clk) 25 | if (resetn) begin 26 | if (write_en) begin 27 | for (int i = 0; i < MEM_NUM_WORDS; i++) begin 28 | mem[i] <= waddr == addr_t'(i) ? data_in : mem[i]; 29 | end 30 | end else 31 | mem <= mem; 32 | end else begin 33 | mem <= 0; 34 | end 35 | endmodule -------------------------------------------------------------------------------- /cache/src/synth/DCacheTop.sv: -------------------------------------------------------------------------------- 1 | `include "data_bus.svh" 2 | `include "cache_bus.svh" 3 | 4 | module DCacheTop( 5 | input logic clk, resetn, 6 | 7 | input addr_t _dbus_req_vaddr, 8 | input dbus_req_t _dbus_req, 9 | output dbus_resp_t _dbus_resp, 10 | output cbus_req_t _cbus_req, 11 | input cbus_resp_t _cbus_resp 12 | ); 13 | addr_t dbus_req_vaddr; 14 | dbus_req_t dbus_req; 15 | dbus_resp_t dbus_resp; 16 | cbus_req_t cbus_req; 17 | cbus_resp_t cbus_resp; 18 | 19 | always_ff @(posedge clk) begin 20 | dbus_req_vaddr <= _dbus_req_vaddr; 21 | dbus_req <= _dbus_req; 22 | cbus_resp <= _cbus_resp; 23 | _dbus_resp <= dbus_resp; 24 | _cbus_req <= cbus_req; 25 | end 26 | 27 | DCache inst(.*); 28 | endmodule -------------------------------------------------------------------------------- /cache/src/synth/ICacheTop.sv: -------------------------------------------------------------------------------- 1 | `include "instr_bus.svh" 2 | `include "cache_bus.svh" 3 | 4 | module ICacheTop( 5 | input logic clk, resetn, 6 | 7 | input addr_t _ibus_req_vaddr, 8 | input ibus_req_t _ibus_req, 9 | output ibus_resp_t _ibus_resp, 10 | output cbus_req_t _cbus_req, 11 | input cbus_resp_t _cbus_resp 12 | ); 13 | addr_t ibus_req_vaddr; 14 | ibus_req_t ibus_req; 15 | ibus_resp_t ibus_resp; 16 | cbus_req_t cbus_req; 17 | cbus_resp_t cbus_resp; 18 | 19 | always_ff @(posedge clk) begin 20 | ibus_req_vaddr <= _ibus_req_vaddr; 21 | ibus_req <= _ibus_req; 22 | cbus_resp <= _cbus_resp; 23 | _ibus_resp <= ibus_resp; 24 | _cbus_req <= cbus_req; 25 | end 26 | 27 | ICache inst(.*); 28 | endmodule -------------------------------------------------------------------------------- /cache/src/util/DirectMappedAddr.sv: -------------------------------------------------------------------------------- 1 | `include "defs.svh" 2 | 3 | module DirectMappedAddr( 4 | input addr_t vaddr, 5 | output addr_t paddr, 6 | output logic is_uncached 7 | ); 8 | // 0x8/0x9: 1000/1001, 0xa/0xb: 1010/1011 9 | assign is_uncached = vaddr[BITS_PER_WORD - 3]; 10 | assign paddr = {3'b000, vaddr[BITS_PER_WORD - 4:0]}; 11 | endmodule -------------------------------------------------------------------------------- /cache/src/util/InstrBusToSRAMx.sv: -------------------------------------------------------------------------------- 1 | `include "sramx.svh" 2 | `include "instr_bus.svh" 3 | 4 | /** 5 | * NOTE: this bus converter does not fully utilize 6 | * the maximum bandwidth of IBus. 7 | */ 8 | module InstrBusToSRAMx( 9 | input ibus_req_t ibus_req, 10 | output ibus_resp_t ibus_resp, 11 | output sramx_req_t sramx_req, 12 | input sramx_resp_t sramx_resp 13 | ); 14 | assign sramx_req.req = ibus_req.req; 15 | assign sramx_req.wr = 0; 16 | assign sramx_req.size = sramx_size_t'(SRAMX_MAX_SIZE); 17 | assign sramx_req.addr = ibus_req.addr; 18 | assign sramx_req.wdata = 0; 19 | 20 | assign ibus_resp.addr_ok = sramx_resp.addr_ok; 21 | assign ibus_resp.data_ok = sramx_resp.data_ok; 22 | assign ibus_resp.index = {IBUS_INDEX_WIDTH{1'b1}}; 23 | assign ibus_resp.data = { 24 | sramx_resp.rdata, 25 | {(IBUS_DATA_WIDTH - SRAMX_DATA_WIDTH){1'b0}} 26 | }; 27 | endmodule -------------------------------------------------------------------------------- /cache/src/util/OneHotToBinary.sv: -------------------------------------------------------------------------------- 1 | module OneHotToBinary #( 2 | parameter int SIZE = 8, 3 | 4 | localparam int IDX_BITS = $clog2(SIZE), 5 | localparam type vec_t = logic [SIZE - 1:0], 6 | localparam type idx_t = logic [IDX_BITS - 1:0] 7 | ) ( 8 | input vec_t vec, 9 | output idx_t idx 10 | ); 11 | always_comb begin 12 | idx = 0; 13 | for (int i = 0; i < SIZE; i++) begin 14 | idx |= vec[i] ? idx_t'(i) : 0; 15 | end 16 | end 17 | endmodule -------------------------------------------------------------------------------- /cache/src/util/RequestBuffer.sv: -------------------------------------------------------------------------------- 1 | `include "sramx.svh" 2 | 3 | /** 4 | * to remove combinatorial circuits between requests & "addr_ok". 5 | */ 6 | module RequestBuffer #( 7 | parameter type req_t = sramx_req_t, 8 | parameter type resp_t = sramx_resp_t 9 | ) ( 10 | input logic clk, resetn, 11 | 12 | input req_t m_req, 13 | output resp_t m_resp, 14 | output req_t s_req, 15 | input resp_t s_resp 16 | ); 17 | logic avail; 18 | req_t buf_req; 19 | 20 | assign s_req = avail ? m_req : buf_req; 21 | 22 | always_comb begin 23 | m_resp = s_resp; 24 | m_resp.addr_ok = avail; 25 | end 26 | 27 | always_ff @(posedge clk) 28 | if (resetn) begin 29 | if (s_resp.addr_ok) 30 | avail <= 1; 31 | else if (m_req.req && avail) begin 32 | avail <= 0; 33 | buf_req <= m_req; 34 | end 35 | end else 36 | avail <= 1; 37 | endmodule -------------------------------------------------------------------------------- /cache/src/util/SRAMxToDataBus.sv: -------------------------------------------------------------------------------- 1 | `include "sramx.svh" 2 | `include "data_bus.svh" 3 | 4 | module SRAMxToDataBus( 5 | input sramx_req_t sramx_req, 6 | output sramx_resp_t sramx_resp, 7 | output dbus_req_t dbus_req, 8 | input dbus_resp_t dbus_resp 9 | ); 10 | assign dbus_req.req = sramx_req.req; 11 | assign dbus_req.is_write = sramx_req.wr; 12 | assign dbus_req.addr = sramx_req.addr; 13 | assign dbus_req.data = sramx_req.wdata; 14 | 15 | // convert first, since StrobeTranslator has no idea 16 | // with "is_write". 17 | dbus_wrten_t cvt_wrten; 18 | StrobeTranslator _strobe_inst( 19 | .size(sramx_req.size), 20 | .offset(sramx_req.addr[1:0]), 21 | .strobe(cvt_wrten) 22 | ); 23 | assign dbus_req.write_en = sramx_req.wr ? cvt_wrten : 0; 24 | 25 | assign sramx_resp.addr_ok = dbus_resp.addr_ok; 26 | assign sramx_resp.data_ok = dbus_resp.data_ok; 27 | assign sramx_resp.rdata = dbus_resp.data; 28 | endmodule -------------------------------------------------------------------------------- /cache/src/util/SRAMxToInstrBus.sv: -------------------------------------------------------------------------------- 1 | `include "sramx.svh" 2 | `include "instr_bus.svh" 3 | 4 | /** 5 | * NOTE: IBus does not allow write operations 6 | */ 7 | module SRAMxToInstrBus( 8 | input sramx_req_t sramx_req, 9 | output sramx_resp_t sramx_resp, 10 | output ibus_req_t ibus_req, 11 | input ibus_resp_t ibus_resp 12 | ); 13 | assign ibus_req.req = sramx_req.req; 14 | assign ibus_req.addr = sramx_req.addr; 15 | assign sramx_resp.addr_ok = ibus_resp.addr_ok; 16 | assign sramx_resp.data_ok = ibus_resp.data_ok; 17 | assign sramx_resp.rdata = ibus_resp.data[ 18 | {ibus_resp.index, {SRAMX_DATA_BITS{1'b1}}} -: SRAMX_DATA_WIDTH 19 | ]; 20 | 21 | logic __unused_ok = &{1'b0, sramx_req, 1'b0}; 22 | endmodule -------------------------------------------------------------------------------- /cache/src/util/StrobeTranslator.sv: -------------------------------------------------------------------------------- 1 | /** 2 | * translate to AXI strobe mask for 32bit data. 3 | */ 4 | module StrobeTranslator #( 5 | // use parameter: https://www.xilinx.com/support/answers/73178.html 6 | /*localparam*/ parameter type size_t = logic [1:0], 7 | /*localparam*/ parameter type offset_t = logic [1:0], 8 | /*localparam*/ parameter type strobe_t = logic [3:0] 9 | ) ( 10 | input size_t size, 11 | input offset_t offset, 12 | output strobe_t strobe 13 | ); 14 | always_comb 15 | unique case ({size, offset}) 16 | 4'b00_00: strobe = 4'b0001; 17 | 4'b00_01: strobe = 4'b0010; 18 | 4'b00_10: strobe = 4'b0100; 19 | 4'b00_11: strobe = 4'b1000; 20 | 4'b01_00: strobe = 4'b0011; 21 | 4'b01_10: strobe = 4'b1100; 22 | 4'b10_00: strobe = 4'b1111; 23 | default: strobe = 4'b0000; 24 | endcase 25 | endmodule -------------------------------------------------------------------------------- /cache/src/xsim/DualPortBRAMTest.sv: -------------------------------------------------------------------------------- 1 | `ifndef VERILATOR 2 | 3 | module DualPortBRAMTest(); 4 | logic clk = 0; 5 | always 6 | #5 clk = ~clk; 7 | 8 | logic reset, resetn, en; 9 | logic [3:0] write_en_1, write_en_2; 10 | logic [9:0] addr_1, addr_2; 11 | logic [31:0] data_in_1, data_in_2, data_out_1, data_out_2; 12 | assign resetn = ~reset; 13 | 14 | DualPortBRAM #( 15 | .RESET_VALUE("23333333"), 16 | .WRITE_MODE("read_first") 17 | ) inst(.*); 18 | 19 | initial begin 20 | en = 1; 21 | reset = 1; 22 | {write_en_1, write_en_2, addr_1, addr_2} = 0; 23 | {data_in_1, data_in_2} = 0; 24 | #200 25 | reset = 0; 26 | #10 27 | write_en_1 = 4'b1111; 28 | addr_1 = 0; 29 | addr_2 = 0; 30 | data_in_1 = 32'h12345678; 31 | #10 32 | write_en_1 = 0; 33 | #20 34 | write_en_1 = 4'b1111; 35 | addr_1 = 1; 36 | data_in_1 = 32'h87654321; 37 | #10 38 | addr_1 = 4; 39 | data_in_1 = 32'haaaaaaaa; 40 | addr_2 = 2; 41 | data_in_2 = 32'hcccccccc; 42 | write_en_2 = 4'b0011; 43 | #10 44 | write_en_1 = 0; 45 | write_en_2 = 0; 46 | addr_2 = 0; 47 | #10 48 | addr_2 = 1; 49 | #10 50 | addr_2 = 2; 51 | #10 52 | addr_2 = 3; 53 | #10 54 | addr_2 = 4; 55 | #10 56 | en = 0; 57 | #10 58 | reset = 1; 59 | #200 60 | reset = 0; 61 | #10 62 | en = 1; 63 | #10 64 | addr_1 = 1; 65 | addr_2 = 2; 66 | #10 67 | reset = 1; 68 | #200 69 | reset = 0; 70 | #20 71 | addr_1 = 0; 72 | addr_2 = 4; 73 | #10 74 | en = 0; 75 | write_en_2 = 4'b1111; 76 | addr_2 = 3; 77 | data_in_2 = 32'h12121212; 78 | #10 79 | en = 1; 80 | #10 81 | write_en_2 = 0; 82 | en = 0; 83 | #10 84 | addr_2 = 0; 85 | #10 86 | en = 1; 87 | #20 $finish; 88 | end 89 | endmodule 90 | 91 | `endif -------------------------------------------------------------------------------- /cache/src/xsim/LUTRAMTest.sv: -------------------------------------------------------------------------------- 1 | `ifndef VERILATOR 2 | 3 | module LUTRAMTest(); 4 | logic clk = 0; 5 | always #5 clk = ~clk; 6 | 7 | logic [3:0] write_en = 0; 8 | logic [31:0] addr = 0; 9 | logic [31:0] data_in = 0; 10 | logic [31:0] data_out; 11 | 12 | LUTRAM #(.DATA_WIDTH(33), .ENABLE_BYTE_WRITE(0)) inst33(.*); 13 | LUTRAM inst(.*); 14 | 15 | initial begin 16 | #8 17 | write_en = 4'b1111; 18 | data_in = 32'h12345678; 19 | #10 20 | addr = 1; 21 | data_in = 32'h87654321; 22 | #10 23 | addr = 2; 24 | data_in = 32'hdeadbeef; 25 | #10 26 | addr = 3; 27 | write_en = 4'b1010; 28 | data_in = 32'hcccccccc; 29 | #10 30 | write_en = 0; 31 | #2 32 | addr = 0; 33 | data_in = 32'habcdef99; 34 | #3 35 | addr = 1; 36 | #3 37 | write_en = 4'b1111; 38 | addr = 2; 39 | #2 40 | addr = 3; 41 | #40 $finish; 42 | end 43 | endmodule 44 | 45 | `endif -------------------------------------------------------------------------------- /cache/src/xsim/SimpleDualPortBRAMTest.sv: -------------------------------------------------------------------------------- 1 | `ifndef VERILATOR 2 | 3 | module SimpleDualPortBRAMTest(); 4 | logic clk = 0; 5 | always #5 clk = ~clk; 6 | 7 | logic reset, en; 8 | logic [3:0] write_en; 9 | logic [31:0] raddr, waddr, wdata; 10 | logic [31:0] rdata; 11 | SimpleDualPortBRAM inst(.*); 12 | 13 | initial begin 14 | en = 1; 15 | reset = 1; 16 | write_en = 0; 17 | raddr = 0; 18 | waddr = 0; 19 | wdata = 0; 20 | #200 21 | reset = 0; 22 | #17 23 | waddr = 0; 24 | wdata = 32'h12345678; 25 | write_en = 4'b1111; 26 | #20 27 | waddr = 1; 28 | wdata = 32'h87654321; 29 | write_en = 4'b1100; 30 | #20 31 | raddr = 1; 32 | #20 33 | write_en = 0; 34 | #40 $finish; 35 | end 36 | endmodule 37 | 38 | `endif -------------------------------------------------------------------------------- /cache/src/xsim/global.svh: -------------------------------------------------------------------------------- 1 | `define CACHE_WITHOUT_MIPS -------------------------------------------------------------------------------- /cache/test/ICache.cpp: -------------------------------------------------------------------------------- 1 | #include "ICache.h" 2 | 3 | static auto top = new Top; 4 | 5 | PRETEST_HOOK [] { 6 | top->reset(); 7 | }; 8 | 9 | WITH { 10 | top->reset(false); 11 | top->issue_read(4); 12 | top->tick(256); 13 | assert(top->inst->ibus_resp_x_addr_ok == 1); 14 | assert(top->inst->ibus_resp_x_data_ok == 1); 15 | assert(top->inst->ibus_resp_x_index == 1); 16 | assert(top->inst->ibus_resp_x_data == ((u64(remap(1)) << 32) | remap(0))); 17 | } AS("single read"); 18 | 19 | WITH LOG { 20 | Pipeline p(top); 21 | p.expect32(123 * 4, remap(123)); 22 | p.wait(256); 23 | p.expect(124); 24 | p.expect(126); 25 | p.expect64(122 * 4, remap(122, 123)); 26 | p.wait(256); 27 | p.expect(122); 28 | p.expect(124); 29 | p.expect(126); 30 | p.wait(256); 31 | } AS("on pipeline"); 32 | 33 | WITH { 34 | for (int addr = 0; addr < 8192; addr++) { 35 | top->issue_read(addr * 4); 36 | top->inst->ibus_req_x_req = 0; 37 | top->eval(); 38 | for (int i = 0; i < 256; i++) { 39 | assert(top->inst->req_hit == 0); 40 | assert(top->inst->ibus_resp_x_data_ok == 0); 41 | top->tick(); 42 | } 43 | } 44 | } AS("fake read"); 45 | 46 | WITH { 47 | Pipeline p(top); 48 | for (int i = 0; i < MEMORY_SIZE; i += 2) { 49 | p.expect(i); 50 | } 51 | p.wait(); 52 | } AS("sequential read 1"); 53 | 54 | WITH { 55 | Pipeline p(top); 56 | for (int i = 1; i < MEMORY_SIZE; i += 2) { 57 | p.expect(i); 58 | } 59 | p.wait(); 60 | } AS("sequential read 2"); 61 | 62 | WITH SKIP { 63 | constexpr int T = 100000; 64 | 65 | Pipeline p(top); 66 | for (int _t = 0; _t < T; _t++) { 67 | int n = randu(1, 128); 68 | int addr = randu(0, MEMORY_SIZE - n - 1); 69 | for (int i = 0; i < n; i++) { 70 | p.expect(addr + i); 71 | } 72 | p.wait(); 73 | } 74 | } AS("random block read"); 75 | 76 | WITH SKIP { 77 | constexpr int T = 500000; 78 | 79 | Pipeline p(top); 80 | for (int i = 0; i < T; i++) { 81 | int addr = randu(0, MEMORY_SIZE - 1); 82 | p.expect(addr); 83 | } 84 | 85 | p.wait(); 86 | } AS("random read"); 87 | 88 | WITH { 89 | Pipeline p(top); 90 | for (int i = MEMORY_SIZE - 2; i >= 0; i -= 2) { 91 | p.expect(i); 92 | } 93 | p.wait(); 94 | } AS("backward read 1"); 95 | 96 | WITH { 97 | Pipeline p(top); 98 | for (int i = MEMORY_SIZE - 1; i >= 0; i -= 2) { 99 | p.expect(i); 100 | } 101 | p.wait(); 102 | } AS("backward read 2"); -------------------------------------------------------------------------------- /cache/test/LoadStoreBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "LoadStoreBuffer.h" 2 | 3 | static auto top = new Top; 4 | static Pipeline p(top); 5 | 6 | PRETEST_HOOK [] { 7 | top->reset(); 8 | }; 9 | 10 | WITH { 11 | for (int i = 0; i < 32; i++) { 12 | top->issue_load(0x12345678); 13 | top->tick(); 14 | } 15 | top->reset(); 16 | for (int i = 0; i < 256; i++) { 17 | assert(top->inst->s_req_x_req == 0); 18 | top->tick(); 19 | } 20 | } AS("nop"); 21 | 22 | WITH LOG { 23 | p.write(0x12345678, 0x87654321); 24 | p.inspect(0x11223344); 25 | p.wait(256); 26 | } AS("simple test"); 27 | 28 | WITH { 29 | for (int i = 0; i < 256; i++) { 30 | p.write(randu(), randu()); 31 | } 32 | p.inspect(randu()); 33 | p.wait(8192); 34 | } AS("full store"); 35 | 36 | WITH { 37 | for (int i = 0; i < 8; i++) { 38 | p.write(randu(), randu()); 39 | } 40 | for (int i = 0; i < 256; i++) { 41 | p.inspect(randu()); 42 | } 43 | p.wait(8192); 44 | } AS("full load"); 45 | 46 | WITH { 47 | for (int i = 0; i < 256; i++) { 48 | p.write(randu(), randu()); 49 | p.inspect(randu()); 50 | } 51 | p.wait(8192); 52 | } AS("interleave 1"); 53 | 54 | WITH { 55 | for (int i = 0; i < 256; i++) { 56 | p.inspect(randu()); 57 | p.write(randu(), randu()); 58 | } 59 | p.wait(8192); 60 | } AS("interleave 2"); 61 | 62 | WITH SKIP { 63 | constexpr int T = 1000000; 64 | 65 | for (int _t = 0; _t < T; _t++) { 66 | int op = randu(0, 1); 67 | 68 | if (op == 0) 69 | p.write(randu(), randu()); 70 | if (op == 1) 71 | p.inspect(randu()); 72 | } 73 | 74 | p.wait(T * 16); 75 | } AS("random"); 76 | 77 | WITH SKIP { 78 | constexpr int T = 3000000; 79 | 80 | for (int _t = 0; _t < T; _t++) { 81 | int op = randu(0, 2); 82 | 83 | if (op == 0) 84 | p.write(randu(), randu()); 85 | if (op == 1) 86 | p.inspect(randu()); 87 | if (op == 2) 88 | p.tick(); 89 | } 90 | 91 | p.wait(T * 16); 92 | } AS("random with tick"); 93 | 94 | WITH { 95 | for (int i = 0; i < 256; i++) { 96 | top->issue_load(randu()); 97 | top->inst->m_req_x_req = 0; 98 | top->eval(); 99 | 100 | for (int j = 0; j < 256; j++) { 101 | assert(top->inst->m_resp_x_data_ok == 0); 102 | } 103 | } 104 | } AS("fake load"); 105 | 106 | WITH { 107 | for (int i = 0; i < 256; i++) { 108 | top->issue_store(randu(), randu()); 109 | top->inst->m_req_x_req = 0; 110 | top->eval(); 111 | 112 | for (int j = 0; j < 256; j++) { 113 | assert(top->inst->m_resp_x_data_ok == 0); 114 | } 115 | } 116 | } AS("fake store"); -------------------------------------------------------------------------------- /cache/test/PLRU.cpp: -------------------------------------------------------------------------------- 1 | #include "PLRU.h" 2 | 3 | static auto top = new Top; 4 | 5 | auto random_select(int n = 7) -> select_t { 6 | select_t s; 7 | s.resize(n); 8 | for (int i = 0; i < n; i++) { 9 | s[i] = randu(0, 1); 10 | } 11 | return s; 12 | } 13 | 14 | WITH { 15 | for (int S = 0; S < (1 << 7); S++) { 16 | auto s = to_vec(S); 17 | int got = top->query_idx(s); 18 | int ans = 0, x = 1; 19 | for (int i = 0; i < 3; i++) { 20 | ans |= s[x - 1] << (2 - i); 21 | x = 2 * x + s[x - 1]; 22 | } 23 | 24 | assert(got == ans); 25 | } 26 | } AS("replace test"); 27 | 28 | WITH { 29 | constexpr int T = 100000; 30 | 31 | for (int _t = 0; _t < T; _t++) { 32 | auto s = random_select(); 33 | int got = top->query_idx(s); 34 | int ans = 0, x = 1; 35 | for (int i = 0; i < 3; i++) { 36 | ans |= s[x - 1] << (2 - i); 37 | x = 2 * x + s[x - 1]; 38 | } 39 | 40 | assert(got == ans); 41 | } 42 | } AS("random replace test"); 43 | 44 | WITH { 45 | for (int S = 0; S < (1 << 7); S++) 46 | for (int idx = 0; idx < 7; idx++) { 47 | auto s = to_vec(S); 48 | auto got = top->query_next(s, idx); 49 | auto ans = s; 50 | 51 | int x = 1; 52 | for (int i = 2; i >= 0; i--) { 53 | int b = (idx >> i) & 1; 54 | ans[x - 1] = !b; 55 | x = 2 * x + b; 56 | } 57 | 58 | assert(got == ans); 59 | } 60 | } AS("hit test"); 61 | 62 | WITH { 63 | constexpr int T = 100000; 64 | 65 | for (int _t = 0; _t < T; _t++) { 66 | auto s = random_select(); 67 | int idx = randu(0, 7); 68 | 69 | auto got = top->query_next(s, idx); 70 | auto ans = s; 71 | 72 | int x = 1; 73 | for (int i = 2; i >= 0; i--) { 74 | int b = (idx >> i) & 1; 75 | ans[x - 1] = !b; 76 | x = 2 * x + b; 77 | } 78 | 79 | assert(got == ans); 80 | } 81 | } AS("random hit test"); -------------------------------------------------------------------------------- /cache/test/PLRU.h: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include "SimpleTopBase.h" 3 | 4 | #include 5 | 6 | using select_t = std::vector; 7 | 8 | auto to_bits(const select_t &a) -> u32 { 9 | u32 r = 0; 10 | for (int i = 0; i < a.size(); i++) { 11 | r |= u32(a[i]) << i; 12 | } 13 | return r; 14 | } 15 | 16 | auto to_vec(u32 v, int n = 7) -> select_t { 17 | select_t r; 18 | r.resize(n); 19 | for (int i = 0; i < n; i++) { 20 | r[i] = v & 1; 21 | v >>= 1; 22 | } 23 | return r; 24 | } 25 | 26 | class Top : public SimpleTopBase { 27 | public: 28 | auto query_idx(const select_t &a) -> int { 29 | inst->select = to_bits(a); 30 | inst->idx = randu(0, 7); 31 | inst->eval(); 32 | return inst->victim_idx; 33 | } 34 | 35 | auto query_next(const select_t &a, int idx) -> select_t { 36 | inst->select = to_bits(a); 37 | inst->idx = idx; 38 | inst->eval(); 39 | return to_vec(inst->new_select); 40 | } 41 | }; -------------------------------------------------------------------------------- /cache/test/PrefixSum.cpp: -------------------------------------------------------------------------------- 1 | #include "PrefixSum.h" 2 | 3 | static auto top = new Top; 4 | 5 | WITH { 6 | vec_t in = {0, 1, 1, 0, 1, 1, 1, 1}; 7 | vec_t out = {0, 0, 0, 0, 1, 1, 1, 1}; 8 | auto ret = top->test(in); 9 | assert(ret == out); 10 | } AS("simple test"); 11 | 12 | WITH { 13 | constexpr int T = 1000000; 14 | for (int _t = 0; _t < T; _t++) { 15 | vec_t in; 16 | in.resize(8); 17 | for (int i = 0; i < 8; i++) { 18 | in[i] = randu(0, 1); 19 | } 20 | vec_t out = in; 21 | for (int i = 6; i >= 0; i--) { 22 | out[i] &= out[i + 1]; 23 | } 24 | auto ret = top->test(in); 25 | assert(ret == out); 26 | } 27 | } AS("random test"); -------------------------------------------------------------------------------- /cache/test/PrefixSum.h: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | #include "SimpleTopBase.h" 3 | 4 | #include 5 | 6 | typedef std::vector vec_t; 7 | 8 | class Top : public SimpleTopBase { 9 | public: 10 | auto test(const vec_t &in) -> vec_t { 11 | u32 bits = 0; 12 | for (int i = 0; i < in.size(); i++) { 13 | bits |= static_cast(in[i]) << i; 14 | } 15 | 16 | inst->arr = bits; 17 | inst->eval(); 18 | 19 | u32 ret = inst->sum; 20 | vec_t rax; 21 | for (int i = 0; i < in.size(); i++) { 22 | rax.push_back(ret & 1); 23 | ret >>= 1; 24 | } 25 | 26 | return rax; 27 | } 28 | }; -------------------------------------------------------------------------------- /cache/test/util/ICacheBus.h: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | class ICacheBusMaster { 4 | public: 5 | virtual auto valid() -> u8& = 0; 6 | virtual auto is_write() -> u8& = 0; 7 | virtual auto addr() -> u32& = 0; 8 | virtual auto order() -> u32& = 0; 9 | virtual auto wdata() -> u32& = 0; 10 | 11 | virtual auto okay() -> u8 = 0; 12 | virtual auto last() -> u8 = 0; 13 | virtual auto rdata() -> u32 = 0; 14 | }; 15 | 16 | class ICacheBusSlave { 17 | public: 18 | virtual auto valid() -> u8 = 0; 19 | virtual auto is_write() -> u8 = 0; 20 | virtual auto addr() -> u32 = 0; 21 | virtual auto order() -> u32 = 0; 22 | virtual auto wdata() -> u32 = 0; 23 | 24 | virtual auto okay() -> u8& = 0; 25 | virtual auto last() -> u8& = 0; 26 | virtual auto rdata() -> u32& = 0; 27 | }; -------------------------------------------------------------------------------- /cache/test/util/SimpleTopBase.h: -------------------------------------------------------------------------------- 1 | #include "VTop.h" 2 | 3 | class SimpleTopBase { 4 | public: 5 | VTop *inst; 6 | 7 | SimpleTopBase() : inst(new VTop) {} 8 | ~SimpleTopBase() { 9 | delete inst; 10 | } 11 | 12 | void eval() { 13 | inst->eval(); 14 | } 15 | 16 | void eval_step() { 17 | inst->eval_step(); 18 | } 19 | 20 | void eval_end_step() { 21 | inst->eval_end_step(); 22 | } 23 | }; -------------------------------------------------------------------------------- /cache/test/util/main.cpp: -------------------------------------------------------------------------------- 1 | #include "verilated.h" 2 | #include "util.h" 3 | 4 | int main(int argc, char *argv[]) { 5 | Verilated::commandArgs(argc, argv); 6 | Verilated::traceEverOn(true); 7 | run_tests(); 8 | return 0; 9 | } -------------------------------------------------------------------------------- /cache/trace/.gitkeeper: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSCSCC-2020-Fudan/FDU1.1-NSCSCC/6c751483f2b8467548fb216fb23b995cd6ce8897/cache/trace/.gitkeeper -------------------------------------------------------------------------------- /cache/trace/single-read.gtkw: -------------------------------------------------------------------------------- 1 | [*] 2 | [*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI 3 | [*] Thu Jul 16 08:24:23 2020 4 | [*] 5 | [dumpfile] "./single-read.fst" 6 | [dumpfile_mtime] "Thu Jul 16 08:08:02 2020" 7 | [dumpfile_size] 3913 8 | [savefile] "./single-read.gtkw" 9 | [timestart] 0 10 | [size] 1920 1048 11 | [pos] -1 -1 12 | *-5.075328 32 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 13 | [treeopen] TOP. 14 | [treeopen] TOP.OneLineBufferTop. 15 | [treeopen] TOP.OneLineBufferTop.cbus_resp. 16 | [treeopen] TOP.OneLineBufferTop.sramx_req. 17 | [treeopen] TOP.OneLineBufferTop.sramx_resp. 18 | [signals_width] 348 19 | @28 20 | TOP.OneLineBufferTop.clk 21 | TOP.OneLineBufferTop.reset 22 | @22 23 | TOP.OneLineBufferTop.cbus_req.addr[31:0] 24 | @28 25 | TOP.OneLineBufferTop.cbus_req.is_write 26 | @22 27 | TOP.OneLineBufferTop.cbus_req.order[3:0] 28 | @28 29 | TOP.OneLineBufferTop.cbus_req.valid 30 | @22 31 | TOP.OneLineBufferTop.cbus_req.wdata.word[31:0] 32 | @28 33 | TOP.OneLineBufferTop.cbus_resp.last 34 | TOP.OneLineBufferTop.cbus_resp.okay 35 | @22 36 | TOP.OneLineBufferTop.cbus_resp.rdata.word[31:0] 37 | TOP.OneLineBufferTop.sramx_req.addr[31:0] 38 | @28 39 | TOP.OneLineBufferTop.sramx_req.req 40 | TOP.OneLineBufferTop.sramx_req.size[1:0] 41 | TOP.OneLineBufferTop.sramx_req.wr 42 | @22 43 | TOP.OneLineBufferTop.sramx_req.wdata.word[31:0] 44 | @28 45 | TOP.OneLineBufferTop.sramx_resp.addr_ok 46 | TOP.OneLineBufferTop.sramx_resp.data_ok 47 | @23 48 | TOP.OneLineBufferTop.sramx_resp.rdata.word[31:0] 49 | [pattern_trace] 1 50 | [pattern_trace] 0 51 | -------------------------------------------------------------------------------- /scripts/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent any 3 | 4 | stages { 5 | stage('Add directory') { 6 | steps { 7 | deleteDir() // clean up workspace 8 | // git 'https://github.com/NSCSCC-2020-Fudan/FDU1.1-MIPS' 9 | git credentialsId: 'b18376fc-d1e2-453b-b019-5f4d587dcd5b', 10 | url: 'https://github.com/NSCSCC-2020-Fudan/FDU1.1-MIPS' 11 | // 'https://git@github.com:NSCSCC-2020-Fudan/FDU1.1-MIPS.git' 12 | sh 'vivado -mode tcl -source scripts/add_directory.tcl ../loongson/soc_sram_func/run_vivado/mycpu_prj1/mycpu.xpr' 13 | } 14 | } 15 | stage('Run sram_func_test') { 16 | environment { 17 | SIMULATION="sim_1" 18 | LOG_PATH="../loongson/soc_sram_func/run_vivado/mycpu_prj1/mycpu.sim/${SIMULATION}/behav/xsim/simulate.log" 19 | FLAG="\\-\\-\\-\\-PASS!!!" 20 | } 21 | steps { 22 | sh 'vivado -mode tcl -source scripts/run_simulation.tcl ../loongson/soc_sram_func/run_vivado/mycpu_prj1/mycpu.xpr' 23 | sh 'bash scripts/check_simulation.sh' 24 | } 25 | } 26 | } 27 | post { 28 | failure { 29 | emailext attachLog: true, 30 | body: '''Project name: $PROJECT_NAME 31 | Build number: $BUILD_NUMBER 32 | Build Status: $BUILD_STATUS 33 | Build URL: $BUILD_URL''', 34 | recipientProviders: [culprits()], 35 | subject: 'Project \'$PROJECT_NAME\' is broken' 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /scripts/add_directory.tcl: -------------------------------------------------------------------------------- 1 | add_files code 2 | exit 0 -------------------------------------------------------------------------------- /scripts/build_bitstream.tcl: -------------------------------------------------------------------------------- 1 | set ncpu [exec nproc] 2 | set project_file [glob -directory vivado *.xpr] 3 | set utilisation_file utilisation.csv 4 | open_project ${project_file} 5 | launch_runs impl_1 -to_step write_bitstream -jobs ${ncpu} 6 | wait_on_run impl_1 7 | namespace import ::tclapp::xilinx::designutils::report_failfast 8 | open_run [current_run -implementation -quiet] 9 | report_failfast -csv -transpose -no_header -file ${utilisation_file} 10 | exec sed /^#/d -i ${utilisation_file} 11 | exec sed /^"Description"/d -i ${utilisation_file} 12 | exec sed /^$/d -i ${utilisation_file} 13 | exec sed s/\"//g -i ${utilisation_file} 14 | close_design 15 | -------------------------------------------------------------------------------- /scripts/check_simulation.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | grep $FLAG $LOG_PATH > /dev/null 4 | 5 | if [ $? -eq 0 ]; then 6 | echo "Simulation ${SIMULATION} succeeded." 7 | else 8 | echo "Simulation ${SIMULATION} failed. Please check log ${LOG_PATH} for more information." 9 | exit 1 10 | fi 11 | -------------------------------------------------------------------------------- /scripts/dynamic_pll.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function help_function() 4 | { 5 | echo "" 6 | echo "Usage: $0 (--frq=FRQ) (--vivado=VIVADO_PATH) (--prj=PRJ_PATH)" 7 | echo -e "\t--frq Description of what is FRQ" 8 | echo -e "\t--vivado Description of what is VIVADO_PATH" 9 | echo -e "\t--prj Description of what is PRJ_PATH" 10 | exit 1 # Exit script after printing help 11 | } 12 | 13 | while [ $# -gt 0 ]; do 14 | case "$1" in 15 | --frq=*) 16 | FRQ="${1#*=}" 17 | ;; 18 | --vivado=*) 19 | VIVADO_PATH="${1#*=}" 20 | ;; 21 | --prj=*) 22 | PRJ_PATH="${1#*=}" 23 | ;; 24 | *) 25 | help_function 26 | esac 27 | shift 28 | done 29 | 30 | BEFORE_FRQ=${BEFORE_FRQ:=50} 31 | FRQ=${FRQ:=100} 32 | VIVADO_PATH=${VIVADO_PATH:=vivado} 33 | PRJ_PATH=${PRJ_PATH:="../nscscc2020_group_v0.01/perf_test_v0.01/soc_axi_perf/run_vivado/mycpu_prj1"} 34 | THRESHOLD=${THRESHOLD:=0.3} 35 | LOG_PATH="$PRJ_PATH/mycpu.runs/impl_1/runme.log" 36 | XPR_PATH="$PRJ_PATH/mycpu.xpr" 37 | 38 | function run_iterations { 39 | DIVIDE=$(echo "scale=2; 900/$FRQ" | bc) 40 | tmpfile=$(mktemp) 41 | echo "[DYNAMIC] Alter clk freq to $FRQ" 42 | echo "[DYNAMIC] Using temp file as tcl source: $tmpfile" 43 | echo "set_property -dict [list CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {$FRQ} CONFIG.MMCM_CLKOUT0_DIVIDE_F {$DIVIDE}] [get_ips clk_pll]" 44 | echo "exit" >> $tmpfile 45 | $VIVADO_PATH -mode tcl -source $tmpfile $XPR_PATH 46 | echo "[DYNAMIC] generate all IP" 47 | $VIVADO_PATH -mode tcl -source scripts/generate_all_ips.tcl $XPR_PATH 48 | echo "[DYNAMIC] run implementation" 49 | $VIVADO_PATH -mode tcl -source scripts/run_implementation.tcl $XPR_PATH 50 | } 51 | 52 | while : 53 | do 54 | run_iterations 55 | WNS=$(grep -oP 'Post Routing Timing Summary \| WNS=\K[^ ]+' $LOG_PATH) 56 | echo "frequency:$FRQ WNS: $WNS" >> freq.log 57 | if [$WNS -lt $THRESHOLD] 58 | then 59 | break 60 | fi 61 | BEFORE_FRQ=$FRQ 62 | FRQ=$(echo "scale=2; 1000 / ((1000 / $FRQ) - $WNS)" | bc) 63 | done 64 | -------------------------------------------------------------------------------- /scripts/generate_all_ips.tcl: -------------------------------------------------------------------------------- 1 | update_compile_order -fileset sources_1 2 | 3 | # If IP cores are used 4 | if { [llength [get_ips]] != 0} { 5 | upgrade_ip [get_ips] 6 | 7 | foreach ip [get_ips] { 8 | create_ip_run [get_ips $ip] 9 | } 10 | 11 | set ip_runs [get_runs -filter {SRCSET != sources_1 && IS_SYNTHESIS && STATUS != "synth_design Complete!"}] 12 | 13 | if { [llength $ip_runs] != 0} { 14 | launch_runs -quiet -jobs 2 {*}$ip_runs 15 | 16 | foreach r $ip_runs { 17 | wait_on_run $r 18 | } 19 | } 20 | 21 | } 22 | 23 | exit 24 | -------------------------------------------------------------------------------- /scripts/run_implementation.tcl: -------------------------------------------------------------------------------- 1 | update_compile_order -fileset sources_1 2 | 3 | reset_run impl_1 4 | reset_run synth_1 5 | launch_runs -jobs 6 impl_1 6 | wait_on_run impl_1 7 | 8 | exit 9 | -------------------------------------------------------------------------------- /scripts/run_simulation.tcl: -------------------------------------------------------------------------------- 1 | update_compile_order -fileset sources_1 2 | 3 | set simulations [get_fileset $env(SIMULATION)] 4 | 5 | if { [llength simulations] != 0} { 6 | foreach sim $simulations { 7 | update_compile_order -fileset $sim 8 | launch_simulation -simset $sim 9 | # make simulation complete 10 | run all 11 | } 12 | } 13 | 14 | exit -------------------------------------------------------------------------------- /sources/superscalar-inorder.tcl: -------------------------------------------------------------------------------- 1 | cd [file dirname [info script]] 2 | 3 | # Add cache 4 | source ../cache/sources.tcl 5 | cd [file dirname [info script]] 6 | 7 | # Add superscalar-inorder 8 | source ../superscalar_inorder_dual/sources.tcl 9 | cd [file dirname [info script]] 10 | 11 | add_files ../cache/src/top/mycpu_top.sv -------------------------------------------------------------------------------- /superscalar_inorder_bpb/ALU.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module ALU ( 4 | input word_t a, 5 | input word_t b, 6 | input alufunc_t alufunc, 7 | output word_t c, 8 | output logic exception_of 9 | ); 10 | shamt_t shamt; 11 | assign shamt = a[4: 0]; 12 | logic [32:0] temp; 13 | 14 | always_comb begin 15 | exception_of = 0; 16 | temp = '0; 17 | 18 | case (alufunc) 19 | ALU_AND: begin 20 | c = a & b; 21 | end 22 | ALU_ADD: begin 23 | c = a + b; 24 | temp = {a[31], a} + {b[31], b}; 25 | exception_of = (temp[32] != temp[31]); 26 | end 27 | ALU_OR: begin 28 | c = a | b; 29 | end 30 | ALU_SLL: begin 31 | c = b << shamt; 32 | end 33 | ALU_SRL: begin 34 | c = b >> shamt; 35 | end 36 | ALU_SRA: begin 37 | c = signed'(b) >>> shamt; 38 | end 39 | ALU_SUB: begin 40 | c = a - b; 41 | temp = {a[31], a} - {b[31], b}; 42 | exception_of = (temp[32] != temp[31]); 43 | end 44 | ALU_SLT: begin 45 | c = (signed'(a) < signed'(b)) ? 32'b1 : 32'b0; 46 | end 47 | ALU_NOR: begin 48 | c = ~(a | b); 49 | end 50 | ALU_XOR: begin 51 | c = a ^ b; 52 | end 53 | ALU_ADDU: begin 54 | c = a + b; 55 | end 56 | ALU_SUBU: begin 57 | c = a - b; 58 | end 59 | ALU_SLTU: begin 60 | c = (a < b) ? 32'b01 : 32'b00; 61 | end 62 | ALU_PASSA: begin 63 | c = a; 64 | end 65 | ALU_LUI : begin 66 | c = {b[15:0], 16'b0}; 67 | end 68 | ALU_PASSB: begin 69 | c = b; 70 | end 71 | default: begin 72 | c = '0; 73 | end 74 | endcase 75 | end 76 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/DIVU.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module DIVU ( 4 | input word_t a, b, 5 | input decoded_op_t op, 6 | input logic en, 7 | output word_t hi, lo, 8 | output logic finish 9 | ); 10 | dword_t ans; 11 | always_comb 12 | if (en) 13 | begin 14 | case (op) 15 | DIVU: begin 16 | ans = '0; 17 | lo = {1'b0, a} / {1'b0, b}; 18 | hi = {1'b0, a} % {1'b0, b}; 19 | end 20 | DIV: begin 21 | ans = '0; 22 | lo = signed'(a) / signed'(b); 23 | hi = signed'(a) % signed'(b); 24 | end 25 | default: begin 26 | hi = '0; 27 | lo = '0; 28 | ans = '0; 29 | end 30 | endcase 31 | end 32 | else 33 | begin 34 | hi = '0; 35 | lo = '0; 36 | end 37 | assign finish = 1'b1; 38 | 39 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/FU.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module FU( 4 | input logic clk, reset, first_cycpeE, 5 | input issue_data_t in, 6 | output exec_data_t out, 7 | output logic finish, 8 | input logic mul_timeok, div_timeok 9 | ); 10 | 11 | decoded_op_t op; 12 | assign op = in.instr.op; 13 | alufunc_t func; 14 | assign func = in.instr.ctl.alufunc; 15 | logic multype, divtype; 16 | assign multype = (op == MULT) || (op == MULTU); 17 | assign divtype = (op == DIV) || (op == DIVU); 18 | 19 | word_t alusrcaE, alusrcbE; 20 | assign alusrcaE = (in.instr.ctl.shamt_valid) ? ({27'b0, in.instr.shamt}) : (in.srca); 21 | assign alusrcbE = (in.instr.ctl.alusrc == REGB) ? (in.srcb) : (in.instr.extended_imm); 22 | 23 | word_t hi, lo, result; 24 | logic exception_of, taken, multok, multfinish; 25 | /* 26 | DIVU DIVU (alusrcaE, alusrcbE, op, divtype, hi_div, lo_div, div_finish); 27 | MULU MULU (alusrcaE, alusrcbE, op, multype, hi_mul, lo_mul, mul_finish); 28 | */ 29 | mult mult(clk, reset, alusrcaE, alusrcbE, op, hi, lo, multok); 30 | ALU ALU (alusrcaE, alusrcbE, func, result, exception_of); 31 | JUDGE JUDGE(alusrcaE, alusrcbE, in.instr.ctl.branch_type, taken); 32 | assign multfinish = (multok & ~first_cycpeE); 33 | assign finish = ((~divtype) && (~multype)) || multfinish; 34 | //assign finish = 1'b1; 35 | 36 | assign out.taken = taken; 37 | assign out.instr = in.instr; 38 | assign out.pcplus4 = in.pcplus4; 39 | assign out.exception_instr = in.exception_instr; 40 | assign out.exception_ri = in.exception_ri; 41 | assign out.srca = in.srca; 42 | assign out.srcb = in.srcb; 43 | assign out.destreg = in.destreg; 44 | assign out.in_delay_slot = in.in_delay_slot; 45 | assign out.cp0_addr = in.cp0_addr; 46 | assign out.cp0_cause = in.cp0_cause; 47 | assign out.cp0_status = in.cp0_status; 48 | assign out.cp0_epc = in.cp0_epc; 49 | assign out.pred = in.pred; 50 | 51 | word_t pcplus8; 52 | adder adderpcplus8(in.pcplus4, 32'b0100, pcplus8); 53 | 54 | assign out.hiresult = (multype | divtype) ? (hi) : (result);//mul/div or HTHI 55 | assign out.loresult = (multype | divtype) ? (lo) : (result);//mul/div or HTLO 56 | assign out.result = (in.instr.ctl.is_link) ? (pcplus8) : ( 57 | (in.instr.ctl.mul_div_r) ? (lo) : (result)); 58 | assign out.exception_of = (multype | divtype) ? ('0) : (exception_of); 59 | 60 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/JUDGE.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module JUDGE( 4 | input word_t srca, srcb, 5 | input branch_t branch_type, 6 | output logic taken 7 | ); 8 | 9 | always_comb begin 10 | case (branch_type) 11 | T_BEQ: taken = (srca == srcb); 12 | T_BNE: taken = (srca != srcb); 13 | T_BGEZ: taken = (~srca[31]); 14 | T_BLTZ: taken = (srca[31]); 15 | T_BGTZ: taken = (~srca[31] && srca != '0); 16 | T_BLEZ: taken = (srca[31] || srca == '0); 17 | default: taken = 1'b0; 18 | endcase 19 | end 20 | /* 21 | always_comb 22 | begin 23 | case (op) 24 | BEQ: taken = (srca == srcb); 25 | BNE: taken = (srca != srcb); 26 | BGEZ: taken = (~srca[31]); 27 | BLEZ: taken = (srca[31]); 28 | BGTZ: taken = (~srca[31] && srca != '0); 29 | BLTZ: taken = (srca[31] || srca == '0); 30 | BGEZAL: taken = (~srca[31]); 31 | BLTZAL: taken = (srca[31] || srca == '0); 32 | J: taken = 1'b1; 33 | JAL: taken = 1'b1; 34 | JR: taken = 1'b1; 35 | JALR: taken = 1'b1; 36 | default: taken = 1'b0; 37 | endcase 38 | end 39 | */ 40 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/MULU.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module MULU ( 4 | input word_t a, b, 5 | input decoded_op_t op, 6 | input logic en, 7 | output word_t hi, lo, 8 | output logic finish 9 | ); 10 | dword_t ans; 11 | always_comb 12 | if (en) 13 | begin 14 | case (op) 15 | MULTU: begin 16 | ans = {32'b0, a} * {32'b0, b}; 17 | hi = ans[63:32]; 18 | lo = ans[31:0]; 19 | end 20 | MULT: begin 21 | ans = signed'({{32{a[31]}}, a}) * signed'({{32{b[31]}}, b}); 22 | hi = ans[63:32]; 23 | lo = ans[31:0]; 24 | end 25 | endcase 26 | end 27 | else 28 | begin 29 | hi = '0; 30 | lo = '0; 31 | end 32 | assign finish = 1'b1; 33 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/adder.sv: -------------------------------------------------------------------------------- 1 | module adder #(parameter W = 32) ( 2 | input logic [W - 1: 0] a, b, 3 | output logic [W - 1: 0] c 4 | ); 5 | assign c = a + b; 6 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/bpb/bpb0.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bpb0( 4 | input logic clk, reset, stall, 5 | input word_t [1: 0] pc_predict, 6 | output logic [1: 0] hit, 7 | output bpb_result_t [1: 0] destpc_predict, 8 | input word_t pc_commit, 9 | input logic wen, 10 | input bpb_result_t destpc_commit 11 | ); 12 | 13 | logic [`BPB_ENTRY_WIDTH - 1: 0] i; 14 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_id [`BPB_ENTRIES - 1: 0]; 15 | 16 | word_t pc0, pc1, pc2; 17 | assign pc0 = pc_predict[0]; 18 | assign pc1 = pc_predict[1]; 19 | assign pc2 = pc_commit; 20 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_commit, entry_predict0, entry_predict1; 21 | assign entry_commit = {pc2[`BPB_ENTRY_WIDTH0 + 1: 2]}; 22 | assign entry_predict0 = {pc0[`BPB_ENTRY_WIDTH0 + 1: 2]}; 23 | assign entry_predict1 = {pc1[`BPB_ENTRY_WIDTH0 + 1: 2]}; 24 | 25 | logic [1: 0] hit_set [`BPB_ENTRIES - 1: 0]; 26 | bpb_result_t [1: 0] destpc_predict_set [`BPB_ENTRIES - 1: 0]; 27 | 28 | genvar j; 29 | generate 30 | for (j = 0; j < `BPB_ENTRIES; j = j + 1) begin: bpb_set 31 | bpb_line0 bpb_line(clk, reset, stall, 32 | pc_predict, 33 | hit_set[j], destpc_predict_set[j], 34 | pc_commit, 35 | wen && (entry_commit == j), 36 | destpc_commit); 37 | end 38 | endgenerate 39 | 40 | bpb_result_t [1: 0] destpc_predict_, destpc_predict__; 41 | assign destpc_predict_ = destpc_predict_set[entry_predict1]; 42 | assign destpc_predict__ = destpc_predict_set[entry_predict0]; 43 | assign destpc_predict[1] = destpc_predict_[1]; 44 | assign destpc_predict[0] = destpc_predict__[0]; 45 | 46 | logic [1: 0] hit_, hit__; 47 | assign hit_ = hit_set[entry_predict1]; 48 | assign hit__ = hit_set[entry_predict0]; 49 | assign hit[1] = hit_[1]; 50 | assign hit[0] = hit__[0]; 51 | 52 | endmodule 53 | -------------------------------------------------------------------------------- /superscalar_inorder_bpb/bpb/bpb1.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bpb1( 4 | input logic clk, reset, stall, 5 | input word_t [1: 0] pc_predict, 6 | output logic [1: 0] hit, 7 | output bpb_result_t [1: 0] destpc_predict, 8 | input word_t pc_commit, 9 | input logic wen, 10 | input bpb_result_t destpc_commit 11 | ); 12 | 13 | logic [`BPB_ENTRY_WIDTH - 1: 0] i; 14 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_id [`BPB_ENTRIES - 1: 0]; 15 | logic [`BPB_GLOBAL_WIDTH1 - 1: 0] history; 16 | always_ff @(posedge clk, posedge reset) 17 | begin 18 | if (reset) 19 | history <= '0; 20 | else 21 | if (wen) 22 | history <= {destpc_commit.taken}; 23 | end 24 | 25 | word_t pc0, pc1, pc2; 26 | assign pc0 = pc_predict[0]; 27 | assign pc1 = pc_predict[1]; 28 | assign pc2 = pc_commit; 29 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_commit, entry_predict0, entry_predict1; 30 | assign entry_commit = {pc2[`BPB_ENTRY_WIDTH1 - 1: 0]}; 31 | assign entry_predict0 = {pc0[`BPB_ENTRY_WIDTH1 - 1: 0]}; 32 | assign entry_predict1 = {pc1[`BPB_ENTRY_WIDTH1 - 1: 0]}; 33 | 34 | genvar j; 35 | logic [1: 0] hit_set [`BPB_ENTRIES - 1: 0]; 36 | bpb_result_t [`BPB_ENTRIES - 1: 0] destpc_predict_set; 37 | generate 38 | for (j = 0; j < `BPB_ENTRIES; j = j + 1) begin: bpb_set 39 | bpb_line1 bpb_line(clk, reset, stall, 40 | pc_predict, 41 | hit_set[j], destpc_predict_set[j], 42 | pc_commit, 43 | wen && (entry_commit == j), 44 | destpc_commit); 45 | end 46 | endgenerate 47 | 48 | assign destpc_predict[1] = destpc_predict_set[entry_predict1]; 49 | assign destpc_predict[0] = destpc_predict_set[entry_predict0]; 50 | logic [1: 0] hit_, hit__; 51 | assign hit_ = hit_set[entry_predict1]; 52 | assign hit__ = hit_set[entry_predict0]; 53 | assign hit[1] = hit_[1]; 54 | assign hit[0] = hit__[0]; 55 | 56 | endmodule 57 | -------------------------------------------------------------------------------- /superscalar_inorder_bpb/bpb/bpb2.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bpb2( 4 | input logic clk, reset, stall, 5 | input word_t [1: 0] pc_predict, 6 | output logic [1: 0] hit, 7 | output bpb_result_t [1: 0] destpc_predict, 8 | input word_t pc_commit, 9 | input logic wen, 10 | input bpb_result_t destpc_commit 11 | ); 12 | 13 | logic [`BPB_ENTRY_WIDTH - 1: 0] i; 14 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_id [`BPB_ENTRIES - 1: 0]; 15 | logic [`BPB_GLOBAL_WIDTH2 - 1: 0] history; 16 | always_ff @(posedge clk, posedge reset) 17 | begin 18 | if (reset) 19 | history <= '0; 20 | else 21 | if (wen) 22 | history <= {history[`BPB_GLOBAL_WIDTH2 - 2: 0], destpc_commit.taken}; 23 | end 24 | 25 | word_t pc0, pc1, pc2; 26 | assign pc0 = pc_predict[0]; 27 | assign pc1 = pc_predict[1]; 28 | assign pc2 = pc_commit; 29 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_commit, entry_predict0, entry_predict1; 30 | assign entry_commit = {pc2[`BPB_ENTRY_WIDTH2 - 1: 0], history}; 31 | assign entry_predict0 = {pc0[`BPB_ENTRY_WIDTH2 - 1: 0], history}; 32 | assign entry_predict1 = {pc1[`BPB_ENTRY_WIDTH2 - 1: 0], history}; 33 | 34 | genvar j; 35 | logic [1: 0] hit_set [`BPB_ENTRIES - 1: 0]; 36 | bpb_result_t [`BPB_ENTRIES - 1: 0] destpc_predict_set; 37 | generate 38 | for (j = 0; j < `BPB_ENTRIES; j = j + 1) begin: bpb_set 39 | bpb_line2 bpb_line(clk, reset, stall, 40 | pc_predict, 41 | hit_set[j], destpc_predict_set[j], 42 | pc_commit, 43 | wen && (entry_commit == j), 44 | destpc_commit); 45 | end 46 | endgenerate 47 | 48 | assign destpc_predict[1] = destpc_predict_set[entry_predict1]; 49 | assign destpc_predict[0] = destpc_predict_set[entry_predict0]; 50 | logic [1: 0] hit_, hit__; 51 | assign hit_ = hit_set[entry_predict1]; 52 | assign hit__ = hit_set[entry_predict0]; 53 | assign hit[1] = hit_[1]; 54 | assign hit[0] = hit__[0]; 55 | 56 | endmodule 57 | -------------------------------------------------------------------------------- /superscalar_inorder_bpb/bpb/bpb_decode.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bpb_decode( 4 | input word_t instr, 5 | output logic jump, branch, 6 | output word_t pcjump 7 | ); 8 | 9 | func_t func; 10 | assign func = instr[5:0]; 11 | always_comb 12 | begin 13 | jump = 1'b0; 14 | branch = 1'b0; 15 | case (func) 16 | `OP_J: jump = 1'b1; 17 | `OP_JAL: jump = 1'b1; 18 | `OP_BEQ: branch = 1'b1; 19 | `OP_BNE: branch = 1'b1; 20 | `OP_BGEZ: branch = 1'b1; 21 | `OP_BLEZ: branch = 1'b1; 22 | endcase 23 | end 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /superscalar_inorder_bpb/bpb/bpb_line0.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | /* 4 | state: 5 | 00 -> 01 taken 6 | 01 -> 11 taken 01 -> 00 not 7 | 11 -> 10 not 8 | 10 -> 11 taken 10 -> 00 not 9 | */ 10 | 11 | module bpb_line0( 12 | input logic clk, reset, stall, 13 | input word_t [1: 0] pc_predict, 14 | output logic [1: 0] hit_predict, 15 | output bpb_result_t [1: 0] destpc_predict, 16 | input word_t pc_commit, 17 | input logic wen, 18 | input bpb_result_t destpc_commit 19 | ); 20 | 21 | logic valid; 22 | word_t destpc; 23 | logic [1: 0] state; 24 | logic [`BPB_TAG_WIDTH0 - 1: 0] tag, tag_commit; 25 | assign tag_commit = pc_commit[31: 2 + `BPB_ENTRY_WIDTH0]; 26 | 27 | 28 | always_ff @(posedge clk, posedge reset) 29 | begin 30 | if (reset) 31 | begin 32 | valid <= 1'b0; 33 | end 34 | else 35 | if (wen && ~stall) 36 | begin 37 | if (tag != tag_commit || ~valid) 38 | begin 39 | valid = 1'b1; 40 | state = 2'b00; 41 | tag = tag_commit; 42 | destpc = destpc_commit.destpc; 43 | end 44 | case (state) 45 | 2'b00: state = (destpc_commit.taken) ? (2'b01) : (2'b00); 46 | 2'b01: state = (destpc_commit.taken) ? (2'b11) : (2'b00); 47 | 2'b10: state = (destpc_commit.taken) ? (2'b11) : (2'b00); 48 | 2'b11: state = (destpc_commit.taken) ? (2'b11) : (2'b10); 49 | endcase 50 | end 51 | end 52 | 53 | word_t pc_predict1, pc_predict0; 54 | assign pc_predict1 = pc_predict[1]; 55 | assign pc_predict0 = pc_predict[0]; 56 | assign destpc_predict[1].taken = ((tag == pc_predict1[31: 2 + `BPB_ENTRY_WIDTH0]) ? (state[1]) : (1'b0)) & valid; 57 | assign destpc_predict[1].destpc = destpc; 58 | assign destpc_predict[0].taken = ((tag == pc_predict0[31: 2 + `BPB_ENTRY_WIDTH0]) ? (state[1]) : (1'b0)) & valid; 59 | assign destpc_predict[0].destpc = destpc; 60 | assign hit_predict[1] = (tag == pc_predict1[31: 2 + `BPB_ENTRY_WIDTH0]) & valid; 61 | assign hit_predict[0] = (tag == pc_predict0[31: 2 + `BPB_ENTRY_WIDTH0]) & valid; 62 | 63 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/bpb/branchpredict.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module branchpredict( 4 | input logic clk, reset, stall, 5 | input word_t [1: 0] pc_predict, 6 | output bpb_result_t [1: 0] destpc_predict, 7 | input word_t pc_commit, 8 | input logic wen, 9 | input bpb_result_t destpc_commit 10 | ); 11 | 12 | logic [1: 0] hit0, hit1, hit2; 13 | bpb_result_t [1: 0] destpc_predict0, destpc_predict1, destpc_predict2; 14 | 15 | word_t [1: 0] pcjump; 16 | logic [1: 0] jump, branch; 17 | 18 | bpb0 bpb0(clk, reset, stall, 19 | pc_predict, 20 | hit0, destpc_predict0, 21 | pc_commit, 22 | wen, 23 | destpc_commit); 24 | /* 25 | bpb1 bpb1(clk, reset, stall, 26 | pc_predict, 27 | hit1, destpc_predict1, 28 | pc_commit, 29 | wen, 30 | destpc_commit); 31 | 32 | bpb2 bpb2(clk, reset, stall, 33 | pc_predict, 34 | hit2, destpc_predict2, 35 | pc_commit, 36 | wen, 37 | destpc_commit); 38 | 39 | assign pc_predict[0] = (hit2[0]) ? (destpc_predict2[0]) : ( 40 | (hit1[0]) ? (destpc_predict1[0]) : (destpc_predict0[0])); 41 | 42 | assign pc_predict[1] = (hit2[1]) ? (destpc_predict2[1]) : ( 43 | (hit1[1]) ? (destpc_predict1[1]) : (destpc_predict0[1])); 44 | */ 45 | 46 | assign destpc_predict[0] = (destpc_predict0[0]); 47 | assign destpc_predict[1] = (destpc_predict0[1]); 48 | 49 | //assign destpc_predict[0] = '0; 50 | //assign destpc_predict[1] = '0; 51 | 52 | endmodule 53 | -------------------------------------------------------------------------------- /superscalar_inorder_bpb/bypass.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bypass( 4 | input creg_addr_t [3: 0] reg_addrI, 5 | output word_t [3: 0] reg_dataI, 6 | input logic [1: 0] hiloreadI, 7 | output word_t [1: 0] hilodataI, 8 | input creg_addr_t [1: 0] cp0_addrI, 9 | output word_t [1: 0] cp0_dataI, 10 | output logic data_hazardI, 11 | //issue 12 | input bypass_upd_t execute, 13 | input bypass_upd_t commit, 14 | input bypass_upd_t retire, 15 | //forward 16 | output creg_addr_t [3: 0] reg_addrR, 17 | input word_t [3: 0] reg_dataR, 18 | output logic [1: 0] hiloreadR, 19 | input word_t hiR, loR, 20 | output creg_addr_t [1: 0] cp0_addrR, 21 | input word_t [1: 0] cp0_dataR 22 | //registers 23 | ); 24 | 25 | assign reg_addrR = reg_addrI; 26 | assign hiloreadR = hiloreadI; 27 | assign cp0_addrR = cp0_addrI; 28 | 29 | word_t [1: 0] _cp0_dataI; 30 | cp0_regs_t cp0_mask_and, cp0_mask_or; 31 | assign cp0_mask_and = `CP0_MASK_AND; 32 | assign cp0_mask_or = `CP0_MASK_OR; 33 | 34 | logic [3: 0] hazard; 35 | regbypass bypss_reg3 (reg_addrI[3], execute, commit, retire, reg_dataR[3], hazard[3], reg_dataI[3]); 36 | regbypass bypss_reg2 (reg_addrI[2], execute, commit, retire, reg_dataR[2], hazard[2], reg_dataI[2]); 37 | regbypass bypss_reg1 (reg_addrI[1], execute, commit, retire, reg_dataR[1], hazard[1], reg_dataI[1]); 38 | regbypass bypss_reg0 (reg_addrI[0], execute, commit, retire, reg_dataR[0], hazard[0], reg_dataI[0]); 39 | hlbypass bypass_hilo (execute, commit, retire, hiR, loR, hilodataI[1], hilodataI[0]); 40 | cp0bypass bypass_cp01 (cp0_addrI[1], execute, commit, retire, cp0_dataR[1], _cp0_dataI[1]); 41 | cp0bypass bypass_cp00 (cp0_addrI[0], execute, commit, retire, cp0_dataR[0], _cp0_dataI[0]); 42 | 43 | assign data_hazardI = hazard[3] | hazard[2] | hazard[1] | hazard[0]; 44 | 45 | word_t [1: 0] _cp0_mask_and, _cp0_mask_or; 46 | assign _cp0_mask_and = {cp0_mask_and[cp0_addrI[1]], cp0_mask_and[cp0_addrI[0]]}; 47 | assign _cp0_mask_or = {cp0_mask_or[cp0_addrI[1]], cp0_mask_or[cp0_addrI[0]]}; 48 | 49 | //assign cp0_dataI[1] = (_cp0_dataI[1] & _cp0_mask_and[1]) | _cp0_mask_or[1]; 50 | //assign cp0_dataI[0] = (_cp0_dataI[0] & _cp0_mask_and[0]) | _cp0_mask_or[0]; 51 | assign cp0_dataI = _cp0_dataI; 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /superscalar_inorder_bpb/control.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module control( 4 | input logic finishF, finishE, finishC, data_hazardI, queue_ofI, pcF, 5 | input logic is_eret, exception_valid, 6 | output logic stallF, stallD, flushD, stallI, flushI, 7 | output logic stallE, flushE, stallC, flushC, stallR, flushR, pc_new_commit, flush_ex 8 | ); 9 | 10 | assign flush_ex = is_eret | exception_valid; 11 | 12 | logic hazardC, hazardE, hazardI, hazardpc; 13 | assign hazardC = ~finishC; 14 | assign hazardE = ~finishE & finishC; 15 | assign hazardI = data_hazardI & finishE & finishC; 16 | 17 | assign flushI = pcF | flush_ex; 18 | assign flushE = hazardI | pcF | flush_ex; 19 | assign flushC = hazardE | (pcF & finishC) | flush_ex; 20 | assign flushR = hazardC; 21 | 22 | assign stallI = hazardC | hazardE | hazardI; 23 | assign stallE = hazardC | hazardE; 24 | assign stallC = hazardC; 25 | assign stallR = 'b0; 26 | 27 | assign flushD = (~finishF & ~queue_ofI) | pcF | flush_ex; 28 | assign stallD = queue_ofI; 29 | assign stallF = ~finishF | queue_ofI; 30 | 31 | assign pc_new_commit = pcF | flush_ex; 32 | 33 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/cp0bypass.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module cp0bypass( 4 | input creg_addr_t cp0_addr, 5 | input bypass_upd_t execute, 6 | input bypass_upd_t commit, 7 | input bypass_upd_t retire, 8 | input word_t cp0_data_complete, 9 | output word_t cp0_data 10 | ); 11 | logic regire_hit, commit_hit, execute_hit; 12 | assign execute_hit = (execute.cp0_addr[1] == cp0_addr && execute.cp0_wen[1]) | 13 | (execute.cp0_addr[0] == cp0_addr && execute.cp0_wen[0]); 14 | assign commit_hit = ((commit.cp0_addr[1] == cp0_addr && commit.cp0_wen[1]) | 15 | (commit.cp0_addr[0] == cp0_addr && commit.cp0_wen[0])) & (~execute_hit); 16 | assign retire_hit = ((retire.cp0_addr[1] == cp0_addr && execute.cp0_wen[1]) | 17 | (retire.cp0_addr[0] == cp0_addr && execute.cp0_wen[0])) & (~execute_hit) & (~commit_hit); 18 | 19 | logic [2: 0] hits; 20 | assign hits = {execute_hit, commit_hit, retire_hit}; 21 | assign hit = execute_hit | commit_hit | retire_hit; 22 | always_comb begin 23 | case (hits) 24 | 3'b100: cp0_data <= (execute.cp0_addr[0] == cp0_addr && execute.cp0_wen[0]) ? (execute.result[0]) : (execute.result[1]); 25 | 3'b010: cp0_data <= (commit.cp0_addr[0] == cp0_addr && commit.cp0_wen[0]) ? (commit.result[0]) : (commit.result[1]); 26 | 3'b001: cp0_data <= (retire.cp0_addr[0] == cp0_addr && retire.cp0_wen[0]) ? (retire.result[0]) : (retire.result[1]); 27 | default: cp0_data <= cp0_data_complete; 28 | endcase 29 | end 30 | 31 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/decode.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module decode( 4 | input fetch_data_t [1: 0] in, 5 | input logic [1: 0] hitF, 6 | output decode_data_t [1: 0] out, 7 | output logic [1: 0] hitD 8 | //input cp0_status_t cp0_status, 9 | //input cp0_status_t cp0_cause 10 | ); 11 | signaldecode signaldecode1 (in[1], out[1]); 12 | signaldecode signaldecode0 (in[0], out[0]); 13 | 14 | (*mark_debug = "true"*) logic debug1, debug0; 15 | assign debug1 = out[1].pred.taken & ( 16 | (out[1].pred.destpc != out[1].instr.pcbranch & out[1].instr.ctl.branch) | 17 | (out[1].pred.destpc != out[1].instr.pcjump & out[1].instr.ctl.jump) | 18 | (~out[1].instr.ctl.branch & ~out[1].instr.ctl.jump) ); 19 | assign debug0 = out[0].pred.taken & ( 20 | (out[0].pred.destpc != out[0].instr.pcbranch & out[0].instr.ctl.branch) | 21 | (out[0].pred.destpc != out[0].instr.pcjump & out[0].instr.ctl.jump) | 22 | (~out[0].instr.ctl.branch & ~out[0].instr.ctl.jump) ); 23 | 24 | assign hitD = hitF; 25 | endmodule 26 | -------------------------------------------------------------------------------- /superscalar_inorder_bpb/decode_to_issue_t.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module decode_to_issue_t( 4 | input decode_data_t in, 5 | input word_t hi, lo, 6 | input word_t reg_dataa, reg_datab, 7 | input word_t cp0_data, 8 | input cp0_status_t cp0_statusI, 9 | input cp0_cause_t cp0_causeI, 10 | input word_t cp0_epcI, 11 | output issue_data_t out, 12 | input logic BJp, 13 | input logic is_link 14 | ); 15 | 16 | assign out.instr = in.instr; 17 | assign out.pcplus4 = in.pcplus4; 18 | assign out.pred = in.pred; 19 | assign out.exception_instr = in.exception_instr; 20 | assign out.exception_ri = in.exception_ri; 21 | assign out.cp0_addr = in.cp0_addr; 22 | // assign out.exception_of = 'b0; 23 | assign out.srca = (in.instr.ctl.hitoreg) ? (hi) : ( 24 | (in.instr.ctl.cp0toreg) ? (cp0_data) : ( 25 | (is_link && in.srcrega == 5'd31) ? (in.pcplus4) : reg_dataa)); 26 | 27 | assign out.srcb = (in.instr.ctl.lotoreg) ? (lo) : ( 28 | (is_link && in.srcregb == 5'd31) ? (in.pcplus4) : (reg_datab)); 29 | 30 | assign out.destreg = in.destreg; 31 | assign out.in_delay_slot = BJp; 32 | assign out.cp0_status = cp0_statusI; 33 | assign out.cp0_cause = cp0_causeI; 34 | assign out.cp0_epc = cp0_epcI; 35 | 36 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/exception_checker.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module exception_checker( 4 | input logic flush, reset, 5 | input exec_data_t in, 6 | input logic [5: 0] ext_int, 7 | input logic timer_interrupt, 8 | output logic exception_valid, 9 | output word_t pcexception, 10 | output exception_t exception_data, 11 | output exec_data_t _out 12 | ); 13 | 14 | exec_data_t data; 15 | assign data = (reset | flush) ? ('0) : (in); 16 | assign _out = (exception_valid) ? ('0) : (data); 17 | 18 | decoded_op_t op; 19 | assign op = data.instr.op; 20 | word_t aluoutM; 21 | assign aluoutM = data.result; 22 | 23 | logic exception_load, exception_save, exception_sys, exception_bp; 24 | assign exception_load = ((op == LW) && (aluoutM[1:0] != '0)) || 25 | ((op == LH || op == LHU) && (aluoutM[0] != '0)); 26 | assign exception_save = ((op == SW) && (aluoutM[1:0] != '0)) || 27 | ((op == SH) && (aluoutM[0] != '0)); 28 | assign exception_sys = (data.instr.op == SYSCALL); 29 | assign exception_bp = (data.instr.op == BREAK); 30 | 31 | exception_pipeline_t pipe; 32 | assign pipe.exception_instr = data.exception_instr; 33 | assign pipe.exception_ri = data.exception_ri; 34 | assign pipe.exception_of = data.exception_of; 35 | assign pipe.exception_load = exception_load; 36 | assign pipe.exception_save = exception_save; 37 | assign pipe.exception_sys = exception_sys; 38 | assign pipe.exception_bp = exception_bp; 39 | assign pipe.in_delay_slot = data.in_delay_slot; 40 | assign pipe.pc = data.pcplus4 - 32'd4; 41 | assign pipe.vaddr = (data.exception_instr) ? pipe.pc : data.result; 42 | assign pipe.interrupt_info = ({ext_int, 2'b00} | data.cp0_cause.IP | {timer_interrupt, 7'b0}) & data.cp0_status.IM; 43 | 44 | exception exception (reset, ext_int, 45 | pipe, 46 | exception_valid, pcexception, 47 | exception_data, 48 | data.cp0_status); 49 | 50 | endmodule 51 | -------------------------------------------------------------------------------- /superscalar_inorder_bpb/exec_to_commit_t.sv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSCSCC-2020-Fudan/FDU1.1-NSCSCC/6c751483f2b8467548fb216fb23b995cd6ce8897/superscalar_inorder_bpb/exec_to_commit_t.sv -------------------------------------------------------------------------------- /superscalar_inorder_bpb/exec_to_exec_t.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module exec_to_exec_t( 4 | input exec_data_t a, 5 | output exec_data_t b 6 | ); 7 | assign b.instr = a.instr; 8 | assign b.pcplus4 = a.pcplus4; 9 | assign b.exception_instr = a.exception_instr; 10 | assign b.exception_ri = a.exception_ri; 11 | assign b.exception_of = a.exception_of; 12 | assign b.taken = a.taken; 13 | assign b.srca = a.srca; 14 | assign b.srcb = a.srcb; 15 | assign b.destreg = a.destreg; 16 | assign b.result = a.result; 17 | assign b.hiresult = a.hiresult; 18 | assign b.loresult = a.loresult; 19 | assign b.in_delay_slot = a.in_delay_slot; 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /superscalar_inorder_bpb/execute.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module execute( 4 | input logic clk, reset, first_cycpeE, 5 | input issue_data_t [1: 0] in, 6 | output exec_data_t [1: 0] out, 7 | //pipeline 8 | output logic finishE, 9 | input logic flushE, stallE, 10 | //control 11 | output bypass_upd_t bypass, 12 | //bypass 13 | input logic mul_timeok, div_timeok 14 | ); 15 | 16 | logic [1: 0] FU_finish; 17 | exec_data_t [1: 0] FU_result; 18 | FU FU1 (clk, reset, first_cycpeE, in[1], FU_result[1], FU_finish[1], mul_timeok, div_timeok); 19 | FU FU0 (clk, reset, first_cycpeE, in[0], FU_result[0], FU_finish[0], mul_timeok, div_timeok); 20 | 21 | logic finish; 22 | assign finish = FU_finish[1] && FU_finish[0]; 23 | assign finishE = finish; 24 | 25 | assign out[1] = FU_result[1]; 26 | assign out[0] = FU_result[0]; 27 | 28 | assign bypass.destreg = {out[1].destreg, out[0].destreg}; 29 | assign bypass.result = {out[1].result, out[0].result}; 30 | assign bypass.hiwrite = {out[1].instr.ctl.hiwrite, out[0].instr.ctl.hiwrite}; 31 | assign bypass.lowrite = {out[1].instr.ctl.lowrite, out[0].instr.ctl.lowrite}; 32 | assign bypass.hidata = {out[1].hiresult, out[0].hiresult}; 33 | assign bypass.lodata = {out[1].loresult, out[0].loresult}; 34 | assign bypass.memtoreg = {out[1].instr.ctl.memtoreg, out[0].instr.ctl.memtoreg}; 35 | assign bypass.cp0_addr = {out[1].cp0_addr, out[0].cp0_addr}; 36 | assign bypass.wen = {out[1].instr.ctl.regwrite, out[0].instr.ctl.regwrite}; 37 | assign bypass.cp0_wen = {out[1].instr.ctl.cp0write, out[0].instr.ctl.cp0write}; 38 | 39 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/extend.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module extend ( 4 | input halfword_t in, 5 | input logic s, 6 | output word_t out 7 | ); 8 | assign out = s ? {16'b0, in} : {{16{in[15]}}, in}; 9 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/handshake.sv: -------------------------------------------------------------------------------- 1 | 2 | `include "mips.svh" 3 | 4 | module handshake ( 5 | input logic clk, reset, 6 | input logic cpu_req, 7 | input logic addr_ok, data_ok, 8 | output logic cpu_data_ok, req 9 | ); 10 | 11 | typedef enum logic[1:0] { INIT, WAIT_ADDR, WAIT_DATA } handshake_state_t; 12 | handshake_state_t state, state_new; 13 | assign cpu_data_ok = state_new == INIT; 14 | always_ff @(posedge clk) begin 15 | if (reset) begin 16 | state <= INIT; 17 | end else begin 18 | state <= state_new; 19 | end 20 | end 21 | always_comb begin 22 | state_new = state; 23 | case (state) 24 | INIT: begin 25 | if (cpu_req) begin 26 | state_new = WAIT_ADDR; 27 | end 28 | end 29 | WAIT_ADDR: begin 30 | if (addr_ok) begin 31 | state_new = WAIT_DATA; 32 | if (data_ok) begin 33 | state_new = INIT; 34 | end 35 | end 36 | end 37 | WAIT_DATA: begin 38 | if (data_ok) begin 39 | state_new = INIT; 40 | end 41 | end 42 | default: begin 43 | state_new = INIT; 44 | end 45 | endcase 46 | end 47 | assign req = state == WAIT_ADDR; 48 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/hilo.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module hilo ( 4 | input logic clk, reset, 5 | output word_t hiW, loW, 6 | input hilo_w_t hlw 7 | ); 8 | 9 | word_t hi, lo; 10 | always_ff @(posedge clk, posedge reset) begin 11 | if (reset) begin 12 | hi <= '0; 13 | lo <= '0; 14 | end else begin 15 | if (hlw.wen_h) 16 | hi <= hlw.wd_h; 17 | else 18 | hi <= hi; 19 | 20 | if (hlw.wen_l) 21 | lo <= hlw.wd_l; 22 | else 23 | lo <= lo; 24 | end 25 | end 26 | 27 | assign hiW = hi; 28 | assign loW = lo; 29 | 30 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/hlbypass.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module hlbypass( 4 | input bypass_upd_t execute, 5 | input bypass_upd_t commit, 6 | input bypass_upd_t retire, 7 | input word_t hi_complete, lo_complete, 8 | output word_t hidata, lodata 9 | ); 10 | 11 | logic retire_hazard, commit_hazard, execute_hazard; 12 | logic [1: 0] retire_hit, commit_hit, execute_hit; 13 | assign execute_hit = {execute.hiwrite[1] | execute.hiwrite[0], execute.lowrite[1] | execute.lowrite[0]}; 14 | assign commit_hit = {commit.hiwrite[1] | commit.hiwrite[0], commit.lowrite[1] | commit.lowrite[0]} & (~execute_hit); 15 | assign retire_hit = {retire.hiwrite[1] | retire.hiwrite[0], retire.lowrite[1] | retire.lowrite[0]} & (~execute_hit) & (~commit_hit); 16 | 17 | logic [2: 0] hihits; 18 | assign hihits = {execute_hit[1], commit_hit[1], retire_hit[1]}; 19 | assign hihit = execute_hit[1] | commit_hit[1] | retire_hit[1]; 20 | always_comb begin 21 | case (hihits) 22 | 3'b100: hidata <= (execute.hiwrite[0]) ? (execute.hidata[0]) : (execute.hidata[1]); 23 | 3'b010: hidata <= (commit.hiwrite[0]) ? (commit.hidata[0]) : (commit.hidata[1]); 24 | 3'b001: hidata <= (retire.hiwrite[0]) ? (retire.hidata[0]) : (retire.hidata[1]); 25 | default: hidata <= hi_complete; 26 | endcase 27 | end 28 | 29 | logic [2: 0] lohits; 30 | assign lohits = {execute_hit[0], commit_hit[0], retire_hit[0]}; 31 | assign lohit = execute_hit[0] | commit_hit[0] | retire_hit[0]; 32 | always_comb begin 33 | case (lohits) 34 | 3'b100: lodata <= (execute.lowrite[0]) ? (execute.lodata[0]) : (execute.lodata[1]); 35 | 3'b010: lodata <= (commit.lowrite[0]) ? (commit.lodata[0]) : (commit.lodata[1]); 36 | 3'b001: lodata <= (retire.lowrite[0]) ? (retire.lodata[0]) : (retire.lodata[1]); 37 | default: lodata <= lo_complete; 38 | endcase 39 | end 40 | 41 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/mem_to_reg.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module mem_to_reg( 4 | input exec_data_t in, 5 | input m_q_t mem, 6 | output exec_data_t out 7 | ); 8 | 9 | assign out.instr = in.instr; 10 | assign out.pcplus4 = in.pcplus4; 11 | assign out.exception_instr = in.exception_instr; 12 | assign out.exception_ri = in.exception_ri; 13 | assign out.exception_of = in.exception_of; 14 | assign out.taken = in.taken; 15 | assign out.srca = in.srca; 16 | assign out.srcb = in.srcb; 17 | assign out.destreg = in.destreg; 18 | assign out.result = (in.instr.ctl.memtoreg) ? (mem.rd) : (in.result); 19 | assign out.hiresult = in.hiresult; 20 | assign out.loresult = in.loresult; 21 | assign out.in_delay_slot = in.in_delay_slot; 22 | assign out.cp0_status = in.cp0_status; 23 | assign out.cp0_cause = in.cp0_cause; 24 | assign out.cp0_addr = in.cp0_addr; 25 | assign out.cp0_epc = in.cp0_epc; 26 | assign out.pred = in.pred; 27 | 28 | endmodule 29 | -------------------------------------------------------------------------------- /superscalar_inorder_bpb/mult/.gitignore: -------------------------------------------------------------------------------- 1 | */* 2 | !*.xci -------------------------------------------------------------------------------- /superscalar_inorder_bpb/mult/divider.svh: -------------------------------------------------------------------------------- 1 | `ifndef __DIVIDER_SVH 2 | `define __DIVIDER_SVH 3 | `include "mips.svh" 4 | typedef enum logic[2:0] { TWO_P, ONE_P, ZERO_P, ONE_N, TWO_N, WRONG_N } quotient_bit_t; 5 | 6 | typedef struct packed{ 7 | logic ok; 8 | logic [64:0] PA; 9 | word_t B; 10 | logic [4:0] shiftnum; 11 | logic [31:0] Q; 12 | } divide_data_t; 13 | `endif 14 | -------------------------------------------------------------------------------- /superscalar_inorder_bpb/mult/multplier.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | module multiplier ( 3 | input logic clk, 4 | input word_t a, b, 5 | output dword_t hilo, 6 | input logic is_signed 7 | ); 8 | word_t A, B; 9 | dword_t P; 10 | mult_gen_0 mult_gen_0(.CLK(clk), .A, .B, .P); 11 | 12 | assign A = (is_signed & a[31]) ? -a:a; 13 | assign B = (is_signed & b[31]) ? -b:b; 14 | assign hilo = (is_signed & (a[31] ^ b[31])) ? -P:P; 15 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/pcselect.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module pcselect ( 4 | input logic exception_valid, is_eret, branch, jump, jr, 5 | input word_t pcexception, epc, pcbranch, pcjump, pcjr, pcplus, 6 | output word_t pc_new, 7 | output logic pc_upd 8 | ); 9 | assign pc_upd = exception_valid | is_eret | branch | jr | jump; 10 | assign pc_new = exception_valid ? pcexception : ( 11 | is_eret ? epc : ( 12 | branch ? pcbranch : ( 13 | jr ? pcjr : ( 14 | jump ? pcjump : 15 | pcplus)))); 16 | 17 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/pipelinereg.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module dreg( 4 | input logic clk, reset, 5 | input logic stallD, flushD, 6 | input fetch_data_t [1: 0] in, 7 | output fetch_data_t [1: 0] out, 8 | input logic [1: 0] hitF, 9 | output logic [1: 0] hitD 10 | ); 11 | 12 | always_ff @(posedge clk, posedge reset) 13 | begin 14 | if (reset) 15 | begin 16 | out <= '0; 17 | hitD <= '0; 18 | end 19 | else 20 | if (flushD) 21 | begin 22 | out <= '0; 23 | hitD <= '0; 24 | end 25 | else 26 | if (~stallD) 27 | begin 28 | out <= in; 29 | hitD <= hitF; 30 | end 31 | end 32 | endmodule 33 | 34 | module creg( 35 | input logic clk, reset, 36 | input logic stallC, flushC, 37 | input exec_data_t [1: 0] in, 38 | output exec_data_t [1: 0] out, 39 | output logic first_cycleC 40 | ); 41 | 42 | always_ff @(posedge clk, posedge reset) 43 | begin 44 | if (reset) 45 | begin 46 | out <= '0; 47 | first_cycleC <= '1; 48 | end 49 | else 50 | if (flushC) 51 | begin 52 | out <= '0; 53 | first_cycleC <= '1; 54 | end 55 | else 56 | if (~stallC) 57 | begin 58 | out <= in; 59 | first_cycleC <= '1; 60 | end 61 | else 62 | first_cycleC <= '0; 63 | end 64 | endmodule 65 | 66 | module rreg( 67 | input logic clk, reset, 68 | input logic stallR, flushR, 69 | input exec_data_t [1: 0] in, 70 | output exec_data_t [1: 0] out 71 | ); 72 | 73 | always_ff @(posedge clk, posedge reset) 74 | begin 75 | if (reset) 76 | out <= '0; 77 | else 78 | if (flushR) 79 | out <= '0; 80 | else 81 | if (~stallR) 82 | out <= in; 83 | else 84 | out <= out; 85 | end 86 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/regbypass.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module regbypass( 4 | input creg_addr_t reg_addr, 5 | input bypass_upd_t execute, 6 | input bypass_upd_t commit, 7 | input bypass_upd_t retire, 8 | input word_t reg_data_complete, 9 | output logic hazard, 10 | output word_t reg_data 11 | ); 12 | logic retire_hit, commit_hit, execute_hit; 13 | assign execute_hit = (execute.destreg[1] == reg_addr && execute.wen[1]) | 14 | (execute.destreg[0] == reg_addr && execute.wen[0]); 15 | assign commit_hit = ((commit.destreg[1] == reg_addr && commit.wen[1]) | 16 | (commit.destreg[0] == reg_addr && commit.wen[0])) & (~execute_hit); 17 | assign retire_hit = ((retire.destreg[1] == reg_addr && retire.wen[1]) | 18 | (retire.destreg[0] == reg_addr && retire.wen[0])) & (~execute_hit) & (~commit_hit); 19 | 20 | logic mem_hazard1, mem_hazard0, mem_hazard; 21 | assign mem_hazard1 = (execute.destreg[0] != reg_addr) & (execute.destreg[1] == reg_addr) & (execute.memtoreg[1]); 22 | assign mem_hazard0 = (execute.destreg[0] == reg_addr) & (execute.memtoreg[0]); 23 | assign mem_hazard = mem_hazard0 | mem_hazard1; 24 | assign hazard = mem_hazard; 25 | 26 | /* 27 | logic cp0_hazard1, cp0_hazard0, cp0_hazard; 28 | assign cp0_hazard1 = (execute.data[1].destreg == reg_addr) & (execute.data[1].instr.ctl.cp0toreg); 29 | assign cp0_hazard0 = ~(execute.data[1].destreg == reg_addr) & (execute.data[0].destreg == reg_addr) & (execute.data[0].instr.ctl.cp0toreg); 30 | assign cp0_hazard = cp0_hazard0 | cp0_hazard1; 31 | assign hazard = mem_hazard | cp0_hazard; 32 | */ 33 | 34 | logic [2: 0] hits; 35 | assign hits = {execute_hit, commit_hit, retire_hit}; 36 | assign hit = execute_hit | commit_hit | retire_hit; 37 | always_comb begin 38 | case (hits) 39 | 3'b100: reg_data <= (execute.destreg[0] == reg_addr && execute.wen[0]) ? (execute.result[0]) : (execute.result[1]); 40 | 3'b010: reg_data <= (commit.destreg[0] == reg_addr && commit.wen[0]) ? (commit.result[0]) : (commit.result[1]); 41 | 3'b001: reg_data <= (retire.destreg[0] == reg_addr && retire.wen[0]) ? (retire.result[0]) : (retire.result[1]); 42 | default: reg_data <= reg_data_complete; 43 | endcase 44 | end 45 | 46 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/regfile.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module regfile ( 4 | input logic clk, reset, 5 | input rf_w_t [1: 0] rfw, 6 | input creg_addr_t [3: 0] reg_addrW, 7 | output word_t [3: 0] reg_dataW 8 | ); 9 | word_t [31:0] R; 10 | always_ff @(posedge clk, posedge reset) begin 11 | if (reset) 12 | R <= '0; 13 | else 14 | begin 15 | if (rfw[1].wen && (rfw[1].addr != '0)) 16 | R[rfw[1].addr] = rfw[1].wd; 17 | else 18 | R[0] = '0; 19 | 20 | if (rfw[0].wen && (rfw[0].addr != '0)) 21 | R[rfw[0].addr] = rfw[0].wd; 22 | else 23 | R[0] = '0; 24 | end 25 | end 26 | 27 | assign reg_dataW[3] = (reg_addrW[3] != '0) ? R[reg_addrW[3]] : '0; 28 | assign reg_dataW[2] = (reg_addrW[2] != '0) ? R[reg_addrW[2]] : '0; 29 | assign reg_dataW[1] = (reg_addrW[1] != '0) ? R[reg_addrW[1]] : '0; 30 | assign reg_dataW[0] = (reg_addrW[0] != '0) ? R[reg_addrW[0]] : '0; 31 | 32 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/retire.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module retire( 4 | input exec_data_t [1: 0] in, 5 | output rf_w_t [1: 0] rfw, 6 | output word_t [1: 0] rt_pc, 7 | output hilo_w_t hlw, 8 | output rf_w_t [1: 0] cp0w, 9 | //register 10 | output bypass_upd_t bypass 11 | ); 12 | 13 | assign bypass.destreg = {in[1].destreg, in[0].destreg}; 14 | assign bypass.result = {in[1].result, in[0].result}; 15 | assign bypass.hiwrite = {in[1].instr.ctl.hiwrite, in[0].instr.ctl.hiwrite}; 16 | assign bypass.lowrite = {in[1].instr.ctl.lowrite, in[0].instr.ctl.lowrite}; 17 | assign bypass.hidata = {in[1].hiresult, in[0].hiresult}; 18 | assign bypass.lodata = {in[1].loresult, in[0].loresult}; 19 | assign bypass.memtoreg = {in[1].instr.ctl.memtoreg, in[0].instr.ctl.memtoreg}; 20 | assign bypass.cp0_addr = {in[1].cp0_addr, in[0].cp0_addr}; 21 | assign bypass.wen = {in[1].instr.ctl.regwrite, in[0].instr.ctl.regwrite}; 22 | assign bypass.cp0_wen = {in[1].instr.ctl.cp0write, in[0].instr.ctl.cp0write}; 23 | 24 | // signalretire signalretire [1: 0] (in[1], rfout, hiloout, cp0out); 25 | 26 | assign rfw[1].addr = in[1].destreg; 27 | assign rfw[1].wd = in[1].result; 28 | assign rfw[1].wen = in[1].instr.ctl.regwrite; 29 | assign rfw[0].addr = in[0].destreg; 30 | assign rfw[0].wd = in[0].result; 31 | assign rfw[0].wen = in[0].instr.ctl.regwrite; 32 | 33 | assign hlw.wen_h = in[1].instr.ctl.hiwrite | in[0].instr.ctl.hiwrite; 34 | assign hlw.wen_l = in[1].instr.ctl.lowrite | in[0].instr.ctl.lowrite; 35 | assign hlw.wd_h = (in[0].instr.ctl.hiwrite) ? (in[0].hiresult) : (in[1].hiresult); 36 | assign hlw.wd_l = (in[0].instr.ctl.lowrite) ? (in[0].loresult) : (in[1].loresult); 37 | 38 | assign cp0w[1].addr = in[1].cp0_addr; 39 | assign cp0w[1].wd = in[1].result; 40 | assign cp0w[1].wen = in[1].instr.ctl.cp0write; 41 | assign cp0w[0].addr = in[0].cp0_addr; 42 | assign cp0w[0].wd = in[0].result; 43 | assign cp0w[0].wen = in[0].instr.ctl.cp0write; 44 | 45 | assign rt_pc[1] = in[1].pcplus4 - 32'd4; 46 | assign rt_pc[0] = in[0].pcplus4 - 32'd4; 47 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/signalcommit.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module signalcommit ( 4 | input exec_data_t dataE, 5 | output exec_data_t dataM, 6 | output m_q_t mem 7 | // output bypass_t forward, 8 | // output exception_set_t exception, 9 | // output dmem_t dram_req, 10 | // input word_t readdata, 11 | // output cp0_commit_t cp0, 12 | // output logic is_eret 13 | ); 14 | 15 | logic wen, ren; 16 | word_t aluoutM, writedataM; 17 | decoded_op_t op; 18 | assign op = dataE.instr.op; 19 | assign aluoutM = dataE.result; 20 | assign ren = {4{dataE.instr.ctl.memtoreg}}; 21 | 22 | writedata_format writedata_format(.addr(aluoutM[1:0]), .op(op), ._wd(dataE.writedata), .en(wen), .wd(writedataM)); 23 | 24 | assign dataM = dataE; 25 | assign mem.ren = ren; 26 | assign mem.addr = aluoutM; 27 | assign mem.wen = wen; 28 | assign mem.addr = aluoutM; 29 | assign mem.wd = writedataM; 30 | assign mem.wt = dataE.instr.clt.memwrite; 31 | 32 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/signaldecode.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module signaldecode ( 4 | input fetch_data_t dataF, 5 | output decode_data_t dataD 6 | //input cp0_status_t cp0_status, 7 | //input cp0_status_t cp0_cause 8 | ); 9 | op_t op; 10 | func_t func; 11 | halfword_t imm; 12 | logic ext; 13 | word_t pcbranch, pcjump; 14 | word_t hi, lo; 15 | word_t aluoutM, resultW; 16 | logic is_reserved; 17 | creg_addr_t rs, rt, rd; 18 | assign op = dataF.instr_[31:26]; 19 | assign func = dataF.instr_[5:0]; 20 | assign imm = dataF.instr_[15:0]; 21 | assign rs = dataF.instr_[25:21]; 22 | assign rt = dataF.instr_[20:16]; 23 | assign rd = dataF.instr_[15:11]; 24 | // assign dataD.instr.rs = dataF.instr_[25:21]; 25 | // assign dataD.instr.rt = dataF.instr_[20:16]; 26 | // assign dataD.instr.rd = dataF.instr_[15:11]; 27 | 28 | maindecode maindecode(dataF.instr_, 29 | rs, rt, rd, 30 | dataD.instr.op, dataD.exception_ri, 31 | dataD.instr.ctl, 32 | dataD.srcrega, dataD.srcregb, dataD.destreg); 33 | assign dataD.cp0_addr = rd; 34 | 35 | assign dataD.instr.shamt = dataF.instr_[10:6]; 36 | assign is_reserved = (dataD.instr.op == RESERVED); 37 | 38 | word_t ext_imm; 39 | extend ext1(imm, dataD.instr.ctl.zeroext, ext_imm); 40 | assign pcbranch = dataF.pcplus4 + {dataD.instr.extended_imm[29:0], 2'b00}; 41 | assign pcjump = {dataF.pcplus4[31:28], dataF.instr_[25:0], 2'b00}; 42 | assign dataD.instr.pcbranch = pcbranch; 43 | assign dataD.instr.extended_imm = ext_imm; 44 | assign dataD.instr.pcjump = pcjump; 45 | assign dataD.pred = dataF.pred; 46 | assign dataD.pcplus4 = dataF.pcplus4; 47 | assign dataD.exception_instr = dataF.exception_instr; 48 | /* 49 | srcadmux srcadmux(.regfile(regfile.src1),.m(hazard.aluoutM),.w(hazard.resultW),.alusrcaE(hazard.alusrcaE), 50 | .forward(hazard.forwardAD), .ctl(dataD.instr.ctl), 51 | .hiD(hilo.hi), .loD(hilo.lo), .cp0D(cp0.rd), 52 | .srca(dataD.srca)); 53 | srcbdmux srcbdmux(.regfile(regfile.src2),.m(hazard.aluoutM),.w(hazard.resultW),.alusrcaE(hazard.alusrcaE), 54 | .forward(hazard.forwardBD), .srcb(dataD.srcb)); 55 | */ 56 | 57 | assign dataD.in_delay_slot = 1'b0; //dataF.in_delay_slot; 58 | // assign dataD.en = dataF.en; 59 | // ports 60 | 61 | //assign dataD.cp0_cause = cp0_cause; 62 | //assign dataD.cp0_status = cp0_status; 63 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/top/readdata_format.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module readdata_format ( 4 | input word_t _rd, 5 | output word_t rd, 6 | input logic[1:0] addr, 7 | input decoded_op_t op 8 | ); 9 | always_comb begin 10 | case (op) 11 | LB: begin 12 | case (addr) 13 | 2'b00: rd = {{24{_rd[7]}}, _rd[7:0]}; 14 | 2'b01: rd = {{24{_rd[15]}}, _rd[15:8]}; 15 | 2'b10: rd = {{24{_rd[23]}}, _rd[23:16]}; 16 | 2'b11: rd = {{24{_rd[31]}}, _rd[31:24]}; 17 | default: rd = _rd; 18 | endcase 19 | end 20 | LBU: begin 21 | case (addr) 22 | 2'b00: rd = {24'b0, _rd[7:0]}; 23 | 2'b01: rd = {24'b0, _rd[15:8]}; 24 | 2'b10: rd = {24'b0, _rd[23:16]}; 25 | 2'b11: rd = {24'b0, _rd[31:24]}; 26 | default: rd = _rd; 27 | endcase 28 | end 29 | LH: begin 30 | case (addr[1]) 31 | 1'b0: rd = {{16{_rd[15]}}, _rd[15:0]}; 32 | 1'b1: rd = {{16{_rd[31]}}, _rd[31:16]}; 33 | default: begin 34 | rd = _rd; 35 | end 36 | endcase 37 | end 38 | LHU: begin 39 | case (addr[1]) 40 | 1'b0: rd = {16'b0, _rd[15:0]}; 41 | 1'b1: rd = {16'b0, _rd[31:16]}; 42 | default: begin 43 | rd = _rd; 44 | end 45 | endcase 46 | end 47 | default: begin 48 | rd = _rd; 49 | end 50 | endcase 51 | end 52 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_bpb/writedata_format.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module writedata_format ( 4 | input exec_data_t in, 5 | output m_q_t out 6 | ); 7 | 8 | op_t op; 9 | assign op = in.instr.op; 10 | logic [1: 0] dmem_size_w, dmem_size_r; 11 | assign dmem_size_w = (op == SW) ? 2'b10 : (op == SH ? 2'b01:2'b00); 12 | assign dmem_size_r = (op == LW) ? 2'b10 : (op == LH ? 2'b01:2'b00); 13 | 14 | logic ren, wen; 15 | assign ren = in.instr.ctl.memtoreg; 16 | assign out.size = (wen) ? (dmem_size_w) : (dmem_size_r); 17 | assign out.en = wen | ren; 18 | assign out.addr = in.result; 19 | 20 | logic [1: 0] addr; 21 | assign addr = out.addr[1: 0]; 22 | word_t _wd, wd; 23 | assign _wd = in.srcb; 24 | assign out.wd = wd; 25 | assign out.wt = in.instr.ctl.memwrite; 26 | 27 | always_comb begin 28 | case (op) 29 | SW : begin 30 | wen = 1'b1; 31 | wd = _wd; 32 | end 33 | SH: begin 34 | case (addr[1]) 35 | 1'b0: begin 36 | wen = 1'b1; 37 | wd = _wd; 38 | end 39 | 1'b1: begin 40 | wen = 1'b1; 41 | wd = {_wd[15:0], 16'b0}; 42 | end 43 | default: begin 44 | wen = 'b0; 45 | wd = '0; 46 | end 47 | endcase 48 | end 49 | SB: begin 50 | case (addr) 51 | 2'b00: begin 52 | wen = 1'b1; 53 | wd = _wd; 54 | end 55 | 2'b01: begin 56 | wen = 1'b1; 57 | wd = {_wd[23:0], 8'b0}; 58 | end 59 | 2'b10: begin 60 | wen = 1'b1; 61 | wd = {_wd[15:0], 16'b0}; 62 | end 63 | 2'b11: begin 64 | wen = 1'b1; 65 | wd = {_wd[7:0], 24'b0}; 66 | end 67 | default: begin 68 | wen = 'b0; 69 | wd = '0; 70 | end 71 | endcase 72 | end 73 | default: begin 74 | wen = '0; 75 | wd = '0; 76 | end 77 | endcase 78 | end 79 | endmodule 80 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/ALU.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module ALU ( 4 | input word_t a, 5 | input word_t b, 6 | input alufunc_t alufunc, 7 | output word_t c, 8 | output logic exception_of 9 | ); 10 | shamt_t shamt; 11 | assign shamt = a[4: 0]; 12 | logic [32:0] temp; 13 | 14 | always_comb begin 15 | exception_of = 0; 16 | temp = '0; 17 | 18 | case (alufunc) 19 | ALU_AND: begin 20 | c = a & b; 21 | end 22 | ALU_ADD: begin 23 | c = a + b; 24 | temp = {a[31], a} + {b[31], b}; 25 | exception_of = (temp[32] != temp[31]); 26 | end 27 | ALU_OR: begin 28 | c = a | b; 29 | end 30 | ALU_SLL: begin 31 | c = b << shamt; 32 | end 33 | ALU_SRL: begin 34 | c = b >> shamt; 35 | end 36 | ALU_SRA: begin 37 | c = signed'(b) >>> shamt; 38 | end 39 | ALU_SUB: begin 40 | c = a - b; 41 | temp = {a[31], a} - {b[31], b}; 42 | exception_of = (temp[32] != temp[31]); 43 | end 44 | ALU_SLT: begin 45 | c = (signed'(a) < signed'(b)) ? 32'b1 : 32'b0; 46 | end 47 | ALU_NOR: begin 48 | c = ~(a | b); 49 | end 50 | ALU_XOR: begin 51 | c = a ^ b; 52 | end 53 | ALU_ADDU: begin 54 | c = a + b; 55 | end 56 | ALU_SUBU: begin 57 | c = a - b; 58 | end 59 | ALU_SLTU: begin 60 | c = (a < b) ? 32'b01 : 32'b00; 61 | end 62 | ALU_PASSA: begin 63 | c = a; 64 | end 65 | ALU_LUI : begin 66 | c = {b[15:0], 16'b0}; 67 | end 68 | ALU_PASSB: begin 69 | c = b; 70 | end 71 | default: begin 72 | c = '0; 73 | end 74 | endcase 75 | end 76 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/DIVU.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module DIVU ( 4 | input word_t a, b, 5 | input decoded_op_t op, 6 | input logic en, 7 | output word_t hi, lo, 8 | output logic finish 9 | ); 10 | dword_t ans; 11 | always_comb 12 | if (en) 13 | begin 14 | case (op) 15 | DIVU: begin 16 | ans = '0; 17 | lo = {1'b0, a} / {1'b0, b}; 18 | hi = {1'b0, a} % {1'b0, b}; 19 | end 20 | DIV: begin 21 | ans = '0; 22 | lo = signed'(a) / signed'(b); 23 | hi = signed'(a) % signed'(b); 24 | end 25 | default: begin 26 | hi = '0; 27 | lo = '0; 28 | ans = '0; 29 | end 30 | endcase 31 | end 32 | else 33 | begin 34 | hi = '0; 35 | lo = '0; 36 | end 37 | assign finish = 1'b1; 38 | 39 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/JUDGE.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module JUDGE( 4 | input word_t srca, srcb, 5 | input branch_t branch_type, 6 | output logic taken 7 | ); 8 | 9 | always_comb begin 10 | case (branch_type) 11 | T_BEQ: taken = (srca == srcb); 12 | T_BNE: taken = (srca != srcb); 13 | T_BGEZ: taken = (~srca[31]); 14 | T_BLTZ: taken = (srca[31]); 15 | T_BGTZ: taken = (~srca[31] && srca != '0); 16 | T_BLEZ: taken = (srca[31] || srca == '0); 17 | default: taken = 1'b0; 18 | endcase 19 | end 20 | /* 21 | always_comb 22 | begin 23 | case (op) 24 | BEQ: taken = (srca == srcb); 25 | BNE: taken = (srca != srcb); 26 | BGEZ: taken = (~srca[31]); 27 | BLEZ: taken = (srca[31]); 28 | BGTZ: taken = (~srca[31] && srca != '0); 29 | BLTZ: taken = (srca[31] || srca == '0); 30 | BGEZAL: taken = (~srca[31]); 31 | BLTZAL: taken = (srca[31] || srca == '0); 32 | J: taken = 1'b1; 33 | JAL: taken = 1'b1; 34 | JR: taken = 1'b1; 35 | JALR: taken = 1'b1; 36 | default: taken = 1'b0; 37 | endcase 38 | end 39 | */ 40 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/MULU.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module MULU ( 4 | input word_t a, b, 5 | input decoded_op_t op, 6 | input logic en, 7 | output word_t hi, lo, 8 | output logic finish 9 | ); 10 | dword_t ans; 11 | always_comb 12 | if (en) 13 | begin 14 | case (op) 15 | MULTU: begin 16 | ans = {32'b0, a} * {32'b0, b}; 17 | hi = ans[63:32]; 18 | lo = ans[31:0]; 19 | end 20 | MULT: begin 21 | ans = signed'({{32{a[31]}}, a}) * signed'({{32{b[31]}}, b}); 22 | hi = ans[63:32]; 23 | lo = ans[31:0]; 24 | end 25 | endcase 26 | end 27 | else 28 | begin 29 | hi = '0; 30 | lo = '0; 31 | end 32 | assign finish = 1'b1; 33 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/adder.sv: -------------------------------------------------------------------------------- 1 | module adder #(parameter W = 32) ( 2 | input logic [W - 1: 0] a, b, 3 | output logic [W - 1: 0] c 4 | ); 5 | assign c = a + b; 6 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/assets/commit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSCSCC-2020-Fudan/FDU1.1-NSCSCC/6c751483f2b8467548fb216fb23b995cd6ce8897/superscalar_inorder_dual/assets/commit.png -------------------------------------------------------------------------------- /superscalar_inorder_dual/assets/fetch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSCSCC-2020-Fudan/FDU1.1-NSCSCC/6c751483f2b8467548fb216fb23b995cd6ce8897/superscalar_inorder_dual/assets/fetch.png -------------------------------------------------------------------------------- /superscalar_inorder_dual/assets/issue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSCSCC-2020-Fudan/FDU1.1-NSCSCC/6c751483f2b8467548fb216fb23b995cd6ce8897/superscalar_inorder_dual/assets/issue.png -------------------------------------------------------------------------------- /superscalar_inorder_dual/assets/pipeline.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSCSCC-2020-Fudan/FDU1.1-NSCSCC/6c751483f2b8467548fb216fb23b995cd6ce8897/superscalar_inorder_dual/assets/pipeline.JPG -------------------------------------------------------------------------------- /superscalar_inorder_dual/assets/simplified_pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSCSCC-2020-Fudan/FDU1.1-NSCSCC/6c751483f2b8467548fb216fb23b995cd6ce8897/superscalar_inorder_dual/assets/simplified_pipeline.png -------------------------------------------------------------------------------- /superscalar_inorder_dual/bpb/bpb0.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bpb0( 4 | input logic clk, reset, stall, 5 | input word_t [1: 0] pc_predict, 6 | output logic [1: 0] hit, 7 | output bpb_result_t [1: 0] destpc_predict, 8 | input word_t pc_commit, 9 | input logic wen, 10 | input bpb_result_t destpc_commit 11 | ); 12 | 13 | logic [`BPB_ENTRY_WIDTH - 1: 0] i; 14 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_id [`BPB_ENTRIES - 1: 0]; 15 | 16 | word_t pc0, pc1, pc2; 17 | assign pc0 = pc_predict[0]; 18 | assign pc1 = pc_predict[1]; 19 | assign pc2 = pc_commit; 20 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_commit, entry_predict0, entry_predict1; 21 | assign entry_commit = {pc2[`BPB_ENTRY_WIDTH0 + 1: 2]}; 22 | assign entry_predict0 = {pc0[`BPB_ENTRY_WIDTH0 + 1: 2]}; 23 | assign entry_predict1 = {pc1[`BPB_ENTRY_WIDTH0 + 1: 2]}; 24 | 25 | logic [1: 0] hit_set [`BPB_ENTRIES - 1: 0]; 26 | bpb_result_t [1: 0] destpc_predict_set [`BPB_ENTRIES - 1: 0]; 27 | 28 | genvar j; 29 | generate 30 | for (j = 0; j < `BPB_ENTRIES; j = j + 1) begin: bpb_set 31 | bpb_line0 bpb_line(clk, reset, stall, 32 | //pc_predict, 33 | hit_set[j], destpc_predict_set[j], 34 | pc_commit, 35 | wen && (entry_commit == j), 36 | destpc_commit.taken); 37 | //destpc_commit); 38 | end 39 | endgenerate 40 | 41 | bpb_result_t [1: 0] destpc_predict_, destpc_predict__; 42 | assign destpc_predict_ = destpc_predict_set[entry_predict1]; 43 | assign destpc_predict__ = destpc_predict_set[entry_predict0]; 44 | assign destpc_predict[1] = destpc_predict_[1]; 45 | assign destpc_predict[0] = destpc_predict__[0]; 46 | 47 | logic [1: 0] hit_, hit__; 48 | assign hit_ = hit_set[entry_predict1]; 49 | assign hit__ = hit_set[entry_predict0]; 50 | assign hit[1] = hit_[1]; 51 | assign hit[0] = hit__[0]; 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/bpb/bpb1.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bpb1( 4 | input logic clk, reset, stall, 5 | input word_t [1: 0] pc_predict, 6 | output logic [1: 0] hit, 7 | output bpb_result_t [1: 0] destpc_predict, 8 | input word_t pc_commit, 9 | input logic wen, 10 | input bpb_result_t destpc_commit 11 | ); 12 | 13 | logic [`BPB_ENTRY_WIDTH - 1: 0] i; 14 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_id [`BPB_ENTRIES - 1: 0]; 15 | logic [`BPB_GLOBAL_WIDTH1 - 1: 0] history; 16 | always_ff @(posedge clk) 17 | begin 18 | if (~reset) 19 | history <= '0; 20 | else 21 | if (wen) 22 | history <= {destpc_commit.taken}; 23 | end 24 | 25 | word_t pc0, pc1, pc2; 26 | assign pc0 = pc_predict[0]; 27 | assign pc1 = pc_predict[1]; 28 | assign pc2 = pc_commit; 29 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_commit, entry_predict0, entry_predict1; 30 | assign entry_commit = {pc2[`BPB_ENTRY_WIDTH1 - 1: 0]}; 31 | assign entry_predict0 = {pc0[`BPB_ENTRY_WIDTH1 - 1: 0]}; 32 | assign entry_predict1 = {pc1[`BPB_ENTRY_WIDTH1 - 1: 0]}; 33 | 34 | genvar j; 35 | logic [1: 0] hit_set [`BPB_ENTRIES - 1: 0]; 36 | bpb_result_t [`BPB_ENTRIES - 1: 0] destpc_predict_set; 37 | generate 38 | for (j = 0; j < `BPB_ENTRIES; j = j + 1) begin: bpb_set 39 | bpb_line1 bpb_line(clk, reset, stall, 40 | pc_predict, 41 | hit_set[j], destpc_predict_set[j], 42 | pc_commit, 43 | wen && (entry_commit == j), 44 | destpc_commit); 45 | end 46 | endgenerate 47 | 48 | assign destpc_predict[1] = destpc_predict_set[entry_predict1]; 49 | assign destpc_predict[0] = destpc_predict_set[entry_predict0]; 50 | logic [1: 0] hit_, hit__; 51 | assign hit_ = hit_set[entry_predict1]; 52 | assign hit__ = hit_set[entry_predict0]; 53 | assign hit[1] = hit_[1]; 54 | assign hit[0] = hit__[0]; 55 | 56 | endmodule 57 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/bpb/bpb2.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bpb2( 4 | input logic clk, reset, stall, 5 | input word_t [1: 0] pc_predict, 6 | output logic [1: 0] hit, 7 | output bpb_result_t [1: 0] destpc_predict, 8 | input word_t pc_commit, 9 | input logic wen, 10 | input bpb_result_t destpc_commit 11 | ); 12 | 13 | logic [`BPB_ENTRY_WIDTH - 1: 0] i; 14 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_id [`BPB_ENTRIES - 1: 0]; 15 | logic [`BPB_GLOBAL_WIDTH2 - 1: 0] history; 16 | always_ff @(posedge clk) 17 | begin 18 | if (~reset) 19 | history <= '0; 20 | else 21 | if (wen) 22 | history <= {history[`BPB_GLOBAL_WIDTH2 - 2: 0], destpc_commit.taken}; 23 | end 24 | 25 | word_t pc0, pc1, pc2; 26 | assign pc0 = pc_predict[0]; 27 | assign pc1 = pc_predict[1]; 28 | assign pc2 = pc_commit; 29 | logic [`BPB_ENTRY_WIDTH - 1: 0] entry_commit, entry_predict0, entry_predict1; 30 | assign entry_commit = {pc2[`BPB_ENTRY_WIDTH2 - 1: 0], history}; 31 | assign entry_predict0 = {pc0[`BPB_ENTRY_WIDTH2 - 1: 0], history}; 32 | assign entry_predict1 = {pc1[`BPB_ENTRY_WIDTH2 - 1: 0], history}; 33 | 34 | genvar j; 35 | logic [1: 0] hit_set [`BPB_ENTRIES - 1: 0]; 36 | bpb_result_t [`BPB_ENTRIES - 1: 0] destpc_predict_set; 37 | generate 38 | for (j = 0; j < `BPB_ENTRIES; j = j + 1) begin: bpb_set 39 | bpb_line2 bpb_line(clk, reset, stall, 40 | pc_predict, 41 | hit_set[j], destpc_predict_set[j], 42 | pc_commit, 43 | wen && (entry_commit == j), 44 | destpc_commit); 45 | end 46 | endgenerate 47 | 48 | assign destpc_predict[1] = destpc_predict_set[entry_predict1]; 49 | assign destpc_predict[0] = destpc_predict_set[entry_predict0]; 50 | logic [1: 0] hit_, hit__; 51 | assign hit_ = hit_set[entry_predict1]; 52 | assign hit__ = hit_set[entry_predict0]; 53 | assign hit[1] = hit_[1]; 54 | assign hit[0] = hit__[0]; 55 | 56 | endmodule 57 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/bpb/bpb_decode.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bpb_decode( 4 | input word_t instr, 5 | output logic jump, branch, 6 | output word_t pcjump 7 | ); 8 | 9 | func_t func; 10 | assign func = instr[5:0]; 11 | always_comb 12 | begin 13 | jump = 1'b0; 14 | branch = 1'b0; 15 | case (func) 16 | `OP_J: jump = 1'b1; 17 | `OP_JAL: jump = 1'b1; 18 | `OP_BEQ: branch = 1'b1; 19 | `OP_BNE: branch = 1'b1; 20 | `OP_BGEZ: branch = 1'b1; 21 | `OP_BLEZ: branch = 1'b1; 22 | endcase 23 | end 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/bpb/bpbdecode.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bpbdecode( 4 | input word_t pc, pcplus4, instr, 5 | input bpb_result_t in, 6 | output bpb_result_t out, 7 | output logic jr_push, jr_pop, 8 | input word_t jr_destpc, 9 | input logic [`JR_ENTRY_WIDTH - 1: 0] jr_topF_in, 10 | output logic [`JR_ENTRY_WIDTH - 1: 0] jr_topF_out 11 | ); 12 | 13 | op_t op; 14 | assign op = instr[31:26]; 15 | func_t func; 16 | assign func = instr[5:0]; 17 | logic j_pc, b_pc, jr_pc; 18 | always_comb 19 | begin 20 | j_pc = 1'b0; 21 | b_pc = 1'b0; 22 | jr_pc = 1'b0; 23 | jr_push = 1'b0; 24 | jr_pop = 1'b0; 25 | case (op) 26 | `OP_J: j_pc = 1'b1; 27 | `OP_JAL: begin j_pc = 1'b1; jr_push = 1'b1; end 28 | `OP_BEQ: b_pc = 1'b1; 29 | `OP_BNE: b_pc = 1'b1; 30 | `OP_BGEZ: 31 | begin 32 | b_pc = 1'b1; 33 | jr_push = (instr[20: 16] == `B_BGEZAL || instr[20: 16] == `B_BLTZAL); 34 | end 35 | `OP_BGTZ: b_pc = 1'b1; 36 | `OP_BLEZ: b_pc = 1'b1; 37 | `OP_RT: 38 | begin 39 | jr_pc = (instr[5: 0] == `F_JR || instr[5: 0] == `F_JALR); 40 | jr_pop = (instr[5: 0] == `F_JR || instr[5: 0] == `F_JALR) && (instr[25: 21] == 5'b11111); 41 | jr_push = (instr[5: 0] == `F_JALR); 42 | end 43 | default: b_pc = 1'b0; 44 | endcase 45 | end 46 | 47 | assign out.taken = (in.taken & b_pc) | j_pc | jr_pc; 48 | 49 | word_t ext_imm, pcbranch, pcjump, destpc; 50 | extend ext_pb(instr[15: 0], 1'b0, ext_imm); 51 | assign pcjump = {pcplus4[31: 28], instr[25:0], 2'b00}; 52 | assign pcbranch = pcplus4 + {ext_imm[29:0], 2'b00}; 53 | assign destpc = (j_pc) ? (pcjump) : ( 54 | (b_pc) ? (pcbranch) : ( 55 | (jr_pc) ? (jr_destpc) : ('0))); 56 | 57 | assign out.destpc = destpc; 58 | 59 | logic [`JR_ENTRY_WIDTH - 1: 0] jr_top_plus, jr_top_minus; 60 | assign jr_top_plus = jr_topF_in + 2'b01; 61 | assign jr_top_minus = jr_topF_in - 2'b01; 62 | assign jr_topF_out = (~(jr_push ^ jr_pop)) ? (jr_topF_in) : ( 63 | (jr_push) ? (jr_top_plus) : ( 64 | (jr_pop) ? (jr_top_minus) : ('0))); 65 | 66 | endmodule 67 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/bpb/branchpredict.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module branchpredict( 4 | input logic clk, reset, stall, 5 | input word_t [1: 0] pc_predict, 6 | output bpb_result_t [1: 0] destpc_predict, 7 | input word_t pc_commit, 8 | input logic wen, 9 | input bpb_result_t destpc_commit 10 | ); 11 | 12 | logic [1: 0] hit0, hit1, hit2; 13 | bpb_result_t [1: 0] destpc_predict0, destpc_predict1, destpc_predict2; 14 | 15 | word_t [1: 0] pcjump; 16 | logic [1: 0] jump, branch; 17 | 18 | bpb0 bpb0(clk, reset, stall, 19 | pc_predict, 20 | hit0, destpc_predict0, 21 | pc_commit, 22 | wen, 23 | destpc_commit); 24 | /* 25 | bpb1 bpb1(clk, reset, stall, 26 | pc_predict, 27 | hit1, destpc_predict1, 28 | pc_commit, 29 | wen, 30 | destpc_commit); 31 | 32 | bpb2 bpb2(clk, reset, stall, 33 | pc_predict, 34 | hit2, destpc_predict2, 35 | pc_commit, 36 | wen, 37 | destpc_commit); 38 | 39 | assign pc_predict[0] = (hit2[0]) ? (destpc_predict2[0]) : ( 40 | (hit1[0]) ? (destpc_predict1[0]) : (destpc_predict0[0])); 41 | 42 | assign pc_predict[1] = (hit2[1]) ? (destpc_predict2[1]) : ( 43 | (hit1[1]) ? (destpc_predict1[1]) : (destpc_predict0[1])); 44 | */ 45 | 46 | assign destpc_predict[0] = (destpc_predict0[0]); 47 | assign destpc_predict[1] = (destpc_predict0[1]); 48 | 49 | //assign destpc_predict[0] = '0; 50 | //assign destpc_predict[1] = '0; 51 | 52 | endmodule 53 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/bpb/jrpredict.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module jrpredict( 4 | input logic clk, reset, en, 5 | input logic [1: 0] push, 6 | input word_t [1: 0] pc,//jal 7 | input logic [1: 0] pop,//jr 8 | //fetch 9 | input logic top_reset, 10 | input logic[`JR_ENTRY_WIDTH - 1: 0] top_commit, 11 | //commit 12 | output logic[`JR_ENTRY_WIDTH - 1: 0] jr_point, 13 | output word_t pc_jr 14 | ); 15 | 16 | word_t pcplus8; 17 | assign pcplus8 = (push[1] | pop[1]) ? (pc[1] + 5'b01000) : (pc[0] + 5'b01000); 18 | jrstack jrstak(clk, reset, 19 | (push[1] | push[0]) & en, 20 | pcplus8, 21 | (pop[1] | pop[0]) & en, 22 | top_reset, top_commit, 23 | jr_point, pc_jr); 24 | 25 | endmodule 26 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/bpb/jrstack.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module jrstack( 4 | input logic clk, reset, 5 | input logic push, 6 | input word_t pc,//jal 7 | input logic pop,//jr 8 | //fetch 9 | input logic top_reset, 10 | input logic[`JR_ENTRY_WIDTH - 1: 0] top_commit, 11 | //commit 12 | output logic[`JR_ENTRY_WIDTH - 1: 0] jr_point, 13 | output word_t pc_jr 14 | ); 15 | 16 | logic [`JR_ENTRIES - 1: 0] valid, valid_; 17 | word_t [`JR_ENTRIES - 1: 0] jr_stack, jr_stack_; 18 | logic [`JR_ENTRY_WIDTH - 1: 0] top, topplus1, topminus1, top_; 19 | 20 | assign topplus1 = top + 2'b01; 21 | assign topminus1 = top - 2'b01; 22 | always_comb 23 | begin 24 | top_ = top; 25 | jr_stack_ = jr_stack; 26 | valid_ = valid; 27 | if (push) 28 | begin 29 | top_ = topplus1; 30 | valid_[topplus1] = 1'b1; 31 | jr_stack_[topplus1] = pc; 32 | end 33 | if (pop) 34 | begin 35 | top_ = topminus1; 36 | valid_[topplus1] = 1'b0; 37 | jr_stack_[top] = '0; 38 | end 39 | if (pop & push) 40 | begin 41 | top_ = top; 42 | jr_stack_[top] = pc; 43 | end 44 | if (top_reset) 45 | top_ = top_commit; 46 | end 47 | 48 | always_ff @(posedge clk) 49 | begin 50 | if (~reset) 51 | begin 52 | top <= '0; 53 | valid <= '0; 54 | end 55 | else 56 | begin 57 | jr_stack <= jr_stack_; 58 | top <= top_; 59 | valid <= valid_; 60 | end 61 | end 62 | 63 | assign pc_jr = (valid[top]) ? (jr_stack[top]) : (pc); 64 | assign jr_point = top; 65 | endmodule 66 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/bypass.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bypass( 4 | input creg_addr_t [3: 0] reg_addrI, 5 | output word_t [3: 0] reg_dataI, 6 | input logic [1: 0] hiloreadI, 7 | output word_t [1: 0] hilodataI, 8 | input creg_addr_t [1: 0] cp0_addrI, 9 | output word_t [1: 0] cp0_dataI, 10 | input logic [3: 0] dhazard_maskI, 11 | output logic data_hazardI, 12 | //issue 13 | input bypass_upd_t execute, 14 | input bypass_upd_t commitex, 15 | input bypass_upd_t commitdt, 16 | input bypass_upd_t retire, 17 | //forward 18 | output creg_addr_t [3: 0] reg_addrR, 19 | input word_t [3: 0] reg_dataR, 20 | output logic [1: 0] hiloreadR, 21 | input word_t hiR, loR, 22 | output creg_addr_t [1: 0] cp0_addrR, 23 | input word_t [1: 0] cp0_dataR 24 | //registers 25 | ); 26 | 27 | assign reg_addrR = reg_addrI; 28 | assign hiloreadR = hiloreadI; 29 | assign cp0_addrR = cp0_addrI; 30 | 31 | word_t [1: 0] _cp0_dataI; 32 | cp0_regs_t cp0_mask_and, cp0_mask_or; 33 | assign cp0_mask_and = `CP0_MASK_AND; 34 | assign cp0_mask_or = `CP0_MASK_OR; 35 | 36 | logic [3: 0] hazard; 37 | regbypass bypss_reg3 (reg_addrI[3], execute, commitex, commitdt, retire, reg_dataR[3], hazard[3], reg_dataI[3]); 38 | regbypass bypss_reg2 (reg_addrI[2], execute, commitex, commitdt, retire, reg_dataR[2], hazard[2], reg_dataI[2]); 39 | regbypass bypss_reg1 (reg_addrI[1], execute, commitex, commitdt, retire, reg_dataR[1], hazard[1], reg_dataI[1]); 40 | regbypass bypss_reg0 (reg_addrI[0], execute, commitex, commitdt, retire, reg_dataR[0], hazard[0], reg_dataI[0]); 41 | hlbypass bypass_hilo (execute, commitex, commitdt, retire, hiR, loR, hilodataI[1], hilodataI[0]); 42 | cp0bypass bypass_cp01 (cp0_addrI[1], execute, commitex, commitdt, retire, cp0_dataR[1], _cp0_dataI[1]); 43 | cp0bypass bypass_cp00 (cp0_addrI[0], execute, commitex, commitdt, retire, cp0_dataR[0], _cp0_dataI[0]); 44 | 45 | assign data_hazardI = (hazard[3] & dhazard_maskI[3]) | 46 | (hazard[2] & dhazard_maskI[2]) | 47 | (hazard[1] & dhazard_maskI[1]) | 48 | (hazard[0] & dhazard_maskI[0]); 49 | 50 | word_t [1: 0] _cp0_mask_and, _cp0_mask_or; 51 | assign _cp0_mask_and = {cp0_mask_and[cp0_addrI[1]], cp0_mask_and[cp0_addrI[0]]}; 52 | assign _cp0_mask_or = {cp0_mask_or[cp0_addrI[1]], cp0_mask_or[cp0_addrI[0]]}; 53 | 54 | //assign cp0_dataI[1] = (_cp0_dataI[1] & _cp0_mask_and[1]) | _cp0_mask_or[1]; 55 | //assign cp0_dataI[0] = (_cp0_dataI[0] & _cp0_mask_and[0]) | _cp0_mask_or[0]; 56 | assign cp0_dataI = _cp0_dataI; 57 | 58 | endmodule 59 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/control.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module control( 4 | input logic clk, reset, 5 | input logic finishF, finishE, finishC, data_hazardI, queue_ofI, pcF, 6 | input logic is_eret, exception_valid, 7 | output logic stallF, stallD, flushD, stallI, flushI, 8 | output logic stallE, flushE, stallC, flushC, stallR, flushR, pc_new_commit, flush_ex 9 | ); 10 | 11 | assign flush_ex = (is_eret | exception_valid) & finishC; 12 | 13 | logic hazardC, hazardE, hazardI, hazardpc; 14 | assign hazardC = ~finishC; 15 | assign hazardE = ~finishE & finishC; 16 | assign hazardI = data_hazardI & finishE & finishC; 17 | 18 | assign flushI = pcF | flush_ex; 19 | assign flushE = hazardI | pcF | flush_ex; 20 | assign flushC = hazardE | (pcF & finishC) | flush_ex; 21 | assign flushR = hazardC; 22 | 23 | assign stallI = hazardC | hazardE | hazardI; 24 | assign stallE = hazardC | hazardE; 25 | assign stallC = hazardC; 26 | assign stallR = 'b0; 27 | 28 | assign flushD = (~finishF & ~queue_ofI) | pcF | flush_ex; 29 | assign stallD = queue_ofI; 30 | //assign stallF = ~finishF | queue_ofI; 31 | assign stallF = queue_ofI; 32 | 33 | assign pc_new_commit = pcF | flush_ex; 34 | 35 | int hazardC_count, hazardE_count, hazardI_count, hazardpc_count; 36 | always_ff @(posedge clk) 37 | begin 38 | if (~reset) 39 | begin 40 | hazardC_count <= 0; 41 | hazardE_count <= 0; 42 | hazardI_count <= 0; 43 | hazardpc_count <= 0; 44 | end 45 | else 46 | begin 47 | hazardC_count <= (hazardC) ? (hazardI_count + 1) : (hazardC_count); 48 | hazardE_count <= (hazardE) ? (hazardE_count + 1) : (hazardE_count); 49 | hazardI_count <= (hazardI) ? (hazardC_count + 1) : (hazardI_count); 50 | hazardpc_count <= (pc_new_commit) ? (hazardpc_count + 1) : (hazardpc_count); 51 | end 52 | end 53 | 54 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/cp0bypass.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module cp0bypass( 4 | input creg_addr_t cp0_addr, 5 | input bypass_upd_t execute, 6 | input bypass_upd_t commitex, commitdt, 7 | input bypass_upd_t retire, 8 | input word_t cp0_data_complete, 9 | output word_t cp0_data 10 | ); 11 | logic regire_hit, commit_hit, execute_hit; 12 | assign execute_hit = (execute.cp0_addr[1] == cp0_addr && execute.cp0_wen[1]) | 13 | (execute.cp0_addr[0] == cp0_addr && execute.cp0_wen[0]); 14 | assign commitex_hit = ((commitex.cp0_addr[1] == cp0_addr && commitex.cp0_wen[1]) | 15 | (commitex.cp0_addr[0] == cp0_addr && commitex.cp0_wen[0])) & (~execute_hit); 16 | assign commitdt_hit = ((commitdt.cp0_addr[1] == cp0_addr && commitdt.cp0_wen[1]) | 17 | (commitdt.cp0_addr[0] == cp0_addr && commitdt.cp0_wen[0])) & (~execute_hit) & (~commitex_hit); 18 | assign retire_hit = ((retire.cp0_addr[1] == cp0_addr && execute.cp0_wen[1]) | 19 | (retire.cp0_addr[0] == cp0_addr && execute.cp0_wen[0])) & (~execute_hit) & (~commitex_hit) & (~commitdt_hit); 20 | 21 | logic [3: 0] hits; 22 | assign hits = {execute_hit, commitex_hit, commitdt_hit, retire_hit}; 23 | //assign hit = execute_hit | commitex_hit | commitdt_hit | retire_hit; 24 | always_comb begin 25 | case (hits) 26 | 4'b1000: cp0_data <= (execute.cp0_addr[0] == cp0_addr && execute.cp0_wen[0]) ? (execute.result[0]) : (execute.result[1]); 27 | 4'b0100: cp0_data <= (commitex.cp0_addr[0] == cp0_addr && commitex.cp0_wen[0]) ? (commitex.result[0]) : (commitex.result[1]); 28 | 4'b0010: cp0_data <= (commitdt.cp0_addr[0] == cp0_addr && commitdt.cp0_wen[0]) ? (commitdt.result[0]) : (commitdt.result[1]); 29 | 4'b0001: cp0_data <= (retire.cp0_addr[0] == cp0_addr && retire.cp0_wen[0]) ? (retire.result[0]) : (retire.result[1]); 30 | default: cp0_data <= cp0_data_complete; 31 | endcase 32 | end 33 | 34 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/decode.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module decode( 4 | input fetch_data_t [1: 0] in, 5 | input logic [1: 0] hitF, 6 | output decode_data_t [1: 0] out, 7 | output logic [1: 0] hitD 8 | //input cp0_status_t cp0_status, 9 | //input cp0_status_t cp0_cause 10 | ); 11 | signaldecode signaldecode1 (in[1], out[1]); 12 | signaldecode signaldecode0 (in[0], out[0]); 13 | 14 | (*mark_debug = "true"*) logic debug1, debug0; 15 | assign debug1 = out[1].pred.taken & ( 16 | (out[1].pred.destpc != out[1].instr.pcbranch & out[1].instr.ctl.branch) | 17 | (out[1].pred.destpc != out[1].instr.pcjump & out[1].instr.ctl.jump) | 18 | (~out[1].instr.ctl.branch & ~out[1].instr.ctl.jump) ); 19 | assign debug0 = out[0].pred.taken & ( 20 | (out[0].pred.destpc != out[0].instr.pcbranch & out[0].instr.ctl.branch) | 21 | (out[0].pred.destpc != out[0].instr.pcjump & out[0].instr.ctl.jump) | 22 | (~out[0].instr.ctl.branch & ~out[0].instr.ctl.jump) ); 23 | 24 | assign hitD = hitF; 25 | endmodule 26 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/decode_to_issue_t.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module decode_to_issue_t( 4 | input decode_data_t in, 5 | input word_t hi, lo, 6 | input word_t reg_dataa, reg_datab, 7 | input word_t cp0_data, 8 | input cp0_status_t cp0_statusI, 9 | input cp0_cause_t cp0_causeI, 10 | input word_t cp0_epcI, 11 | output issue_data_t out, 12 | input logic BJp, 13 | input logic is_link 14 | ); 15 | 16 | assign out.instr = in.instr; 17 | assign out.pcplus4 = in.pcplus4; 18 | assign out.pred = in.pred; 19 | assign out.exception_instr = in.exception_instr; 20 | assign out.exception_ri = in.exception_ri; 21 | assign out.cp0_addr = in.cp0_addr; 22 | // assign out.exception_of = 'b0; 23 | assign out.srca = (in.instr.ctl.hitoreg) ? (hi) : ( 24 | (in.instr.ctl.cp0toreg) ? (cp0_data) : ( 25 | (is_link && in.srcrega == 5'd31) ? (in.pcplus4) : reg_dataa)); 26 | 27 | assign out.srcb = (in.instr.ctl.lotoreg) ? (lo) : ( 28 | (is_link && in.srcregb == 5'd31) ? (in.pcplus4) : (reg_datab)); 29 | 30 | assign out.destreg = in.destreg; 31 | assign out.in_delay_slot = BJp; 32 | assign out.cp0_status = cp0_statusI; 33 | assign out.cp0_cause = cp0_causeI; 34 | assign out.cp0_epc = cp0_epcI; 35 | assign out.jrtop = in.jrtop; 36 | 37 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/exception_checker.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module exception_checker( 4 | input logic reset, flush, 5 | input exec_data_t in, 6 | input logic [5: 0] ext_int, 7 | input logic timer_interrupt, 8 | output logic exception_valid, 9 | output word_t pcexception, 10 | output exception_t exception_data, 11 | output exec_data_t _out 12 | ); 13 | 14 | logic exception_valid_; 15 | word_t pcexception_; 16 | exception_t exception_data_; 17 | exec_data_t _out_; 18 | 19 | exec_data_t data; 20 | assign data = (~reset) ? ('0) : (in); 21 | assign _out_ = (exception_valid_) ? ('0) : (data); 22 | 23 | decoded_op_t op; 24 | assign op = data.instr.op; 25 | word_t aluoutM; 26 | assign aluoutM = data.result; 27 | 28 | logic exception_load, exception_save, exception_sys, exception_bp; 29 | assign exception_load = ((op == LW) && (aluoutM[1:0] != '0)) || 30 | ((op == LH || op == LHU) && (aluoutM[0] != '0)); 31 | assign exception_save = ((op == SW) && (aluoutM[1:0] != '0)) || 32 | ((op == SH) && (aluoutM[0] != '0)); 33 | assign exception_sys = (data.instr.op == SYSCALL); 34 | assign exception_bp = (data.instr.op == BREAK); 35 | 36 | exception_pipeline_t pipe; 37 | assign pipe.exception_instr = data.exception_instr; 38 | assign pipe.exception_ri = data.exception_ri; 39 | assign pipe.exception_of = data.exception_of; 40 | assign pipe.exception_load = exception_load; 41 | assign pipe.exception_save = exception_save; 42 | assign pipe.exception_sys = exception_sys; 43 | assign pipe.exception_bp = exception_bp; 44 | assign pipe.in_delay_slot = data.in_delay_slot; 45 | assign pipe.pc = data.pcplus4 - 32'd4; 46 | assign pipe.vaddr = (data.exception_instr) ? pipe.pc : data.result; 47 | assign pipe.interrupt_info = ({ext_int, 2'b00} | data.cp0_cause.IP | {/*1'b0*/timer_interrupt, 7'b0}) & data.cp0_status.IM; 48 | 49 | exception exception (reset, ext_int, 50 | pipe, 51 | exception_valid_, pcexception_, 52 | exception_data_, 53 | data.cp0_status); 54 | 55 | assign exception_valid = (~flush) ? (exception_valid_) : (1'b0); 56 | assign pcexception = (~flush) ? (pcexception_) : ('0); 57 | assign exception_data = (~flush) ? (exception_data_) : ('0); 58 | assign _out = (~flush) ? (_out_) : ('0); 59 | 60 | endmodule 61 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/exec_to_commit_t.sv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSCSCC-2020-Fudan/FDU1.1-NSCSCC/6c751483f2b8467548fb216fb23b995cd6ce8897/superscalar_inorder_dual/exec_to_commit_t.sv -------------------------------------------------------------------------------- /superscalar_inorder_dual/exec_to_exec_t.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module exec_to_exec_t( 4 | input exec_data_t a, 5 | output exec_data_t b 6 | ); 7 | assign b.instr = a.instr; 8 | assign b.pcplus4 = a.pcplus4; 9 | assign b.exception_instr = a.exception_instr; 10 | assign b.exception_ri = a.exception_ri; 11 | assign b.exception_of = a.exception_of; 12 | assign b.taken = a.taken; 13 | assign b.srca = a.srca; 14 | assign b.srcb = a.srcb; 15 | assign b.destreg = a.destreg; 16 | assign b.result = a.result; 17 | assign b.hiresult = a.hiresult; 18 | assign b.loresult = a.loresult; 19 | assign b.in_delay_slot = a.in_delay_slot; 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/execute.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module execute( 4 | input logic clk, reset, first_cycpeE, 5 | input issue_data_t [1: 0] in, 6 | output exec_data_t [1: 0] out, 7 | //pipeline 8 | output logic finishE, 9 | input logic flushE, stallE, 10 | //control 11 | output bypass_upd_t bypass, 12 | //bypass 13 | input logic mul_timeok, div_timeok 14 | ); 15 | 16 | logic [1: 0] FU_finish; 17 | exec_data_t [1: 0] FU_result; 18 | 19 | logic multok, multen0, multen1; 20 | word_t multsrca1, multsrcb1, multsrca0, multsrcb0, hi, lo; 21 | decoded_op_t mult_op, mult_op1, mult_op0; 22 | FU FU1 (clk, reset, flushE, first_cycpeE, 23 | in[1], FU_result[1], FU_finish[1], 24 | mul_timeok, div_timeok, 25 | multsrca1, multsrcb1, mult_op1, multen1, 26 | hi, lo, multok); 27 | FU FU0 (clk, reset, flushE, first_cycpeE, 28 | in[0], FU_result[0], FU_finish[0], 29 | mul_timeok, div_timeok, 30 | multsrca0, multsrcb0, mult_op0, multen0, 31 | hi, lo, multok); 32 | word_t multsrca, multsrcb; 33 | assign multsrca = (multen1) ? (multsrca1) : (multsrca0); 34 | assign multsrcb = (multen1) ? (multsrcb1) : (multsrcb0); 35 | assign mult_op = (multen1) ? (mult_op1) : (mult_op0); 36 | mult mult(clk, reset, flushE, multsrca, multsrcb, mult_op, hi, lo, multok); 37 | 38 | logic finish; 39 | assign finish = FU_finish[1] && FU_finish[0]; 40 | assign finishE = finish; 41 | 42 | assign out[1] = FU_result[1]; 43 | assign out[0] = FU_result[0]; 44 | 45 | assign bypass.destreg = {out[1].destreg, out[0].destreg}; 46 | assign bypass.result = {out[1].result, out[0].result}; 47 | assign bypass.hiwrite = {out[1].instr.ctl.hiwrite, out[0].instr.ctl.hiwrite}; 48 | assign bypass.lowrite = {out[1].instr.ctl.lowrite, out[0].instr.ctl.lowrite}; 49 | assign bypass.hidata = {out[1].hiresult, out[0].hiresult}; 50 | assign bypass.lodata = {out[1].loresult, out[0].loresult}; 51 | assign bypass.memtoreg = {out[1].instr.ctl.memtoreg, out[0].instr.ctl.memtoreg}; 52 | assign bypass.cp0_addr = {out[1].cp0_addr, out[0].cp0_addr}; 53 | assign bypass.wen = {out[1].instr.ctl.regwrite, out[0].instr.ctl.regwrite}; 54 | assign bypass.cp0_wen = {out[1].instr.ctl.cp0write, out[0].instr.ctl.cp0write}; 55 | 56 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/extend.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module extend ( 4 | input halfword_t in, 5 | input logic s, 6 | output word_t out 7 | ); 8 | assign out = s ? {16'b0, in} : {{16{in[15]}}, in}; 9 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/fetch/pc_cmtselect.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module pc_cmtselect( 4 | input logic clk, reset, 5 | input logic exception_valid, is_eret, branch, jump, jr, 6 | input word_t pcexception, epc, pcbranch, pcjump, pcjr, 7 | output word_t pc_new, 8 | output logic pc_upd 9 | ); 10 | assign pc_upd = exception_valid | is_eret | branch | jr | jump; 11 | assign pc_new = exception_valid ? pcexception : ( 12 | is_eret ? epc : ( 13 | branch ? pcbranch : ( 14 | jr ? pcjr : ( 15 | jump ? pcjump : 16 | 32'hbfc00000)))); 17 | 18 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/fetch/pcfetch.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module pcfetch( 4 | input logic clk, reset, stall, flush, 5 | input word_t pc_new, 6 | output word_t addr, 7 | output word_t pc, pcplus4, pcplus8, 8 | input logic inst_ibus_addr_ok, 9 | output logic inst_ibus_req, finish_pc, 10 | //to fetch control 11 | output word_t [1: 0] pc_predictF, 12 | input bpb_result_t [1: 0] destpc_predictF_in, 13 | output bpb_result_t [1: 0] destpc_predictF_out 14 | ); 15 | 16 | logic finish_his; 17 | always_ff @(posedge clk) 18 | begin 19 | if (~reset) 20 | begin 21 | pc <= 32'Hbfc00000; 22 | finish_his <= 1'b0; 23 | inst_ibus_req <= 1'b1; 24 | end 25 | else 26 | begin 27 | if (inst_ibus_addr_ok) 28 | begin 29 | inst_ibus_req = 1'b0; 30 | finish_his = 1'b1; 31 | end 32 | 33 | if (~stall || flush) 34 | begin 35 | pc <= pc_new; 36 | finish_his = 1'b0; 37 | inst_ibus_req = 1'b1; 38 | end 39 | else 40 | if (~finish_pc) 41 | inst_ibus_req = 1'b1; 42 | end 43 | end 44 | assign finish_pc = finish_his | inst_ibus_addr_ok; 45 | //assign inst_ibus_req = ~finish_pc; 46 | 47 | assign addr = pc; 48 | assign pcplus4 = pc + 5'b00100; 49 | assign pcplus8 = pc + 5'b01000; 50 | 51 | assign pc_predictF = {pc, pcplus4}; 52 | assign destpc_predictF_out = destpc_predictF_in; 53 | 54 | endmodule 55 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/handshake.sv: -------------------------------------------------------------------------------- 1 | 2 | `include "mips.svh" 3 | 4 | module handshake ( 5 | input logic clk, reset, 6 | input logic cpu_req, 7 | input logic addr_ok, data_ok, 8 | output logic cpu_data_ok, req 9 | ); 10 | 11 | typedef enum logic[1:0] { INIT, WAIT_ADDR, WAIT_DATA } handshake_state_t; 12 | handshake_state_t state, state_new; 13 | assign cpu_data_ok = state_new == INIT; 14 | always_ff @(posedge clk) begin 15 | if (~reset) begin 16 | state <= INIT; 17 | end else begin 18 | state <= state_new; 19 | end 20 | end 21 | always_comb begin 22 | state_new = state; 23 | case (state) 24 | INIT: begin 25 | if (cpu_req) begin 26 | state_new = WAIT_ADDR; 27 | end 28 | end 29 | WAIT_ADDR: begin 30 | if (addr_ok) begin 31 | state_new = WAIT_DATA; 32 | end 33 | if (data_ok) begin 34 | state_new = INIT; 35 | end 36 | end 37 | WAIT_DATA: begin 38 | if (data_ok) begin 39 | state_new = INIT; 40 | end 41 | end 42 | default: begin 43 | state_new = INIT; 44 | end 45 | endcase 46 | end 47 | assign req = state == WAIT_ADDR; 48 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/hilo.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module hilo ( 4 | input logic clk, reset, 5 | output word_t hiW, loW, 6 | input hilo_w_t hlw 7 | ); 8 | 9 | word_t hi, lo; 10 | always_ff @(posedge clk) begin 11 | if (~reset) begin 12 | hi <= '0; 13 | lo <= '0; 14 | end else begin 15 | if (hlw.wen_h) 16 | hi <= hlw.wd_h; 17 | else 18 | hi <= hi; 19 | 20 | if (hlw.wen_l) 21 | lo <= hlw.wd_l; 22 | else 23 | lo <= lo; 24 | end 25 | end 26 | 27 | assign hiW = hi; 28 | assign loW = lo; 29 | 30 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/hlbypass.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module hlbypass( 4 | input bypass_upd_t execute, 5 | input bypass_upd_t commitex, commitdt, 6 | input bypass_upd_t retire, 7 | input word_t hi_complete, lo_complete, 8 | output word_t hidata, lodata 9 | ); 10 | 11 | logic retire_hazard, commitex_hazard, commitdt_hazard, execute_hazard; 12 | logic [1: 0] retire_hit, commitex_hit, commitdt_hit, execute_hit; 13 | assign execute_hit = {execute.hiwrite[1] | execute.hiwrite[0], execute.lowrite[1] | execute.lowrite[0]}; 14 | assign commitex_hit = {commitex.hiwrite[1] | commitex.hiwrite[0], commitex.lowrite[1] | commitex.lowrite[0]} & (~execute_hit); 15 | assign commitdt_hit = {commitdt.hiwrite[1] | commitdt.hiwrite[0], commitdt.lowrite[1] | commitdt.lowrite[0]} & (~execute_hit) & (~commitex_hit); 16 | assign retire_hit = {retire.hiwrite[1] | retire.hiwrite[0], retire.lowrite[1] | retire.lowrite[0]} & (~execute_hit) & (~commitex_hit) & (~commitdt_hit); 17 | 18 | logic [3: 0] hihits; 19 | assign hihits = {execute_hit[1], commitex_hit[1], commitdt_hit[1], retire_hit[1]}; 20 | //assign hihit = execute_hit[1] | commit_hit[1] | retire_hit[1]; 21 | always_comb begin 22 | case (hihits) 23 | 4'b1000: hidata <= (execute.hiwrite[0]) ? (execute.hidata[0]) : (execute.hidata[1]); 24 | 4'b0100: hidata <= (commitex.hiwrite[0]) ? (commitex.hidata[0]) : (commitex.hidata[1]); 25 | 4'b0010: hidata <= (commitdt.hiwrite[0]) ? (commitdt.hidata[0]) : (commitdt.hidata[1]); 26 | 4'b0001: hidata <= (retire.hiwrite[0]) ? (retire.hidata[0]) : (retire.hidata[1]); 27 | default: hidata <= hi_complete; 28 | endcase 29 | end 30 | 31 | logic [3: 0] lohits; 32 | assign lohits = {execute_hit[0], commitex_hit[0], commitdt_hit[0], retire_hit[0]}; 33 | //assign lohit = execute_hit[0] | commit_hit[0] | retire_hit[0]; 34 | always_comb begin 35 | case (lohits) 36 | 4'b1000: lodata <= (execute.lowrite[0]) ? (execute.lodata[0]) : (execute.lodata[1]); 37 | 4'b0100: lodata <= (commitex.lowrite[0]) ? (commitex.lodata[0]) : (commitex.lodata[1]); 38 | 4'b0010: lodata <= (commitdt.lowrite[0]) ? (commitdt.lodata[0]) : (commitdt.lodata[1]); 39 | 4'b0001: lodata <= (retire.lowrite[0]) ? (retire.lodata[0]) : (retire.lodata[1]); 40 | default: lodata <= lo_complete; 41 | endcase 42 | end 43 | 44 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/mem_to_reg.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module mem_to_reg( 4 | input exec_data_t in, 5 | input m_q_t mem, 6 | output exec_data_t out 7 | ); 8 | 9 | assign out.instr = in.instr; 10 | assign out.pcplus4 = in.pcplus4; 11 | assign out.exception_instr = in.exception_instr; 12 | assign out.exception_ri = in.exception_ri; 13 | assign out.exception_of = in.exception_of; 14 | assign out.taken = in.taken; 15 | assign out.srca = in.srca; 16 | assign out.srcb = in.srcb; 17 | assign out.destreg = in.destreg; 18 | assign out.result = (in.instr.ctl.memtoreg) ? (mem.rd) : (in.result); 19 | assign out.hiresult = in.hiresult; 20 | assign out.loresult = in.loresult; 21 | assign out.in_delay_slot = in.in_delay_slot; 22 | assign out.cp0_status = in.cp0_status; 23 | assign out.cp0_cause = in.cp0_cause; 24 | assign out.cp0_addr = in.cp0_addr; 25 | assign out.cp0_epc = in.cp0_epc; 26 | assign out.pred = in.pred; 27 | assign out.jrtop = in.jrtop; 28 | 29 | endmodule 30 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/mult/.gitignore: -------------------------------------------------------------------------------- 1 | */* 2 | !*.xci -------------------------------------------------------------------------------- /superscalar_inorder_dual/mult/divider.svh: -------------------------------------------------------------------------------- 1 | `ifndef __DIVIDER_SVH 2 | `define __DIVIDER_SVH 3 | `include "mips.svh" 4 | typedef enum logic[2:0] { TWO_P, ONE_P, ZERO_P, ONE_N, TWO_N, WRONG_N } quotient_bit_t; 5 | 6 | typedef struct packed{ 7 | logic [64:0] PA; 8 | word_t B; 9 | logic [4:0] shiftnum; 10 | logic [31:0] Q; 11 | } divide_data_t; 12 | `endif 13 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/mult/multplier.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | module multiplier ( 3 | input logic clk, 4 | input word_t a, b, 5 | output dword_t hilo, 6 | input logic is_signed 7 | ); 8 | word_t A, B; 9 | dword_t P; 10 | mult_gen_0 mult_gen_0(.CLK(clk), .A, .B, .P); 11 | 12 | assign A = (is_signed & a[31]) ? -a:a; 13 | assign B = (is_signed & b[31]) ? -b:b; 14 | assign hilo = (is_signed & (a[31] ^ b[31])) ? -P:P; 15 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/pcselect.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module pcselect ( 4 | input logic exception_valid, is_eret, branch, jump, jr, 5 | input word_t pcexception, epc, pcbranch, pcjump, pcjr, pcplus, 6 | output word_t pc_new, 7 | output logic pc_upd 8 | ); 9 | assign pc_upd = exception_valid | is_eret | branch | jr | jump; 10 | assign pc_new = exception_valid ? pcexception : ( 11 | is_eret ? epc : ( 12 | branch ? pcbranch : ( 13 | jr ? pcjr : ( 14 | jump ? pcjump : 15 | pcplus)))); 16 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/regfile.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module regfile ( 4 | input logic clk, reset, 5 | input rf_w_t [1: 0] rfw, 6 | input creg_addr_t [3: 0] reg_addrW, 7 | output word_t [3: 0] reg_dataW 8 | ); 9 | word_t [31:0] R; 10 | always_ff @(posedge clk) begin 11 | if (~reset) 12 | R <= '0; 13 | else 14 | begin 15 | if (rfw[1].wen && (rfw[1].addr != '0)) 16 | R[rfw[1].addr] = rfw[1].wd; 17 | else 18 | R[0] = '0; 19 | 20 | if (rfw[0].wen && (rfw[0].addr != '0)) 21 | R[rfw[0].addr] = rfw[0].wd; 22 | else 23 | R[0] = '0; 24 | end 25 | end 26 | 27 | assign reg_dataW[3] = (reg_addrW[3] != '0) ? R[reg_addrW[3]] : '0; 28 | assign reg_dataW[2] = (reg_addrW[2] != '0) ? R[reg_addrW[2]] : '0; 29 | assign reg_dataW[1] = (reg_addrW[1] != '0) ? R[reg_addrW[1]] : '0; 30 | assign reg_dataW[0] = (reg_addrW[0] != '0) ? R[reg_addrW[0]] : '0; 31 | 32 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/retire.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module retire( 4 | input exec_data_t [1: 0] in, 5 | output rf_w_t [1: 0] rfw, 6 | output word_t [1: 0] rt_pc, 7 | output hilo_w_t hlw, 8 | output rf_w_t [1: 0] cp0w, 9 | //register 10 | output bypass_upd_t bypass 11 | ); 12 | 13 | assign bypass.destreg = {in[1].destreg, in[0].destreg}; 14 | assign bypass.result = {in[1].result, in[0].result}; 15 | assign bypass.hiwrite = {in[1].instr.ctl.hiwrite, in[0].instr.ctl.hiwrite}; 16 | assign bypass.lowrite = {in[1].instr.ctl.lowrite, in[0].instr.ctl.lowrite}; 17 | assign bypass.hidata = {in[1].hiresult, in[0].hiresult}; 18 | assign bypass.lodata = {in[1].loresult, in[0].loresult}; 19 | assign bypass.memtoreg = {in[1].instr.ctl.memtoreg, in[0].instr.ctl.memtoreg}; 20 | assign bypass.cp0_addr = {in[1].cp0_addr, in[0].cp0_addr}; 21 | assign bypass.wen = {in[1].instr.ctl.regwrite, in[0].instr.ctl.regwrite}; 22 | assign bypass.cp0_wen = {in[1].instr.ctl.cp0write, in[0].instr.ctl.cp0write}; 23 | 24 | // signalretire signalretire [1: 0] (in[1], rfout, hiloout, cp0out); 25 | 26 | assign rfw[1].addr = in[1].destreg; 27 | assign rfw[1].wd = in[1].result; 28 | assign rfw[1].wen = in[1].instr.ctl.regwrite; 29 | assign rfw[0].addr = in[0].destreg; 30 | assign rfw[0].wd = in[0].result; 31 | assign rfw[0].wen = in[0].instr.ctl.regwrite; 32 | 33 | assign hlw.wen_h = in[1].instr.ctl.hiwrite | in[0].instr.ctl.hiwrite; 34 | assign hlw.wen_l = in[1].instr.ctl.lowrite | in[0].instr.ctl.lowrite; 35 | assign hlw.wd_h = (in[0].instr.ctl.hiwrite) ? (in[0].hiresult) : (in[1].hiresult); 36 | assign hlw.wd_l = (in[0].instr.ctl.lowrite) ? (in[0].loresult) : (in[1].loresult); 37 | 38 | assign cp0w[1].addr = in[1].cp0_addr; 39 | assign cp0w[1].wd = in[1].result; 40 | assign cp0w[1].wen = in[1].instr.ctl.cp0write; 41 | assign cp0w[0].addr = in[0].cp0_addr; 42 | assign cp0w[0].wd = in[0].result; 43 | assign cp0w[0].wen = in[0].instr.ctl.cp0write; 44 | 45 | assign rt_pc[1] = in[1].pcplus4 - 32'd4; 46 | assign rt_pc[0] = in[0].pcplus4 - 32'd4; 47 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/sbuffer/sbuffer.sv: -------------------------------------------------------------------------------- 1 | `include "sbuffer.svh" 2 | 3 | module sbuffer( 4 | input logic clk, reset, 5 | input m_q_t in, 6 | output m_q_t out, 7 | output logic sbuffer_of, 8 | output logic finishS, 9 | input decoded_op_t __op, 10 | //to commit 11 | output logic dmem_wt, 12 | output word_t dmem_addr, dmem_wd, 13 | input word_t dmem_rd, 14 | output logic dmem_en, 15 | output logic [1: 0] dmem_size, 16 | input logic dataOK 17 | //to memory 18 | ); 19 | 20 | logic [`SBUFFER_SIZE - 1: 0] valid; 21 | m_q_t [`SBUFFER_SIZE - 1: 0] buffer; 22 | logic [`SBUFFER_WIDTH - 1: 0] head, tail, headplus1, tailplus1; 23 | assign headplus1 = head + 3'b001; 24 | assign tailplus1 = tail + 3'b001; 25 | 26 | assign sbuffer_of = (valid[tail] && in.en && in.wt); 27 | assign finishS = (~in.en) || (~valid[head] && ~in.wt && dataOK) || (in.wt && ~sbuffer_of); 28 | 29 | always_ff @(posedge clk) 30 | begin 31 | if (~reset) 32 | begin 33 | head <= '0; 34 | tail <= '0; 35 | valid <= '0; 36 | end 37 | else 38 | begin 39 | if (dataOK && valid[head]) 40 | begin 41 | valid[head] = 1'b0; 42 | head = headplus1; 43 | end 44 | if (in.en && in.wt && ~sbuffer_of) 45 | begin 46 | valid[tail] = 1'b1; 47 | buffer[tail] = in; 48 | tail = tailplus1; 49 | end 50 | end 51 | end 52 | 53 | m_q_t top; 54 | assign top = (valid[head]) ? (buffer[head]) : ( 55 | (in.en && ~in.wt) ? (in) : ('0)); 56 | 57 | assign dmem_wt = top.wt; 58 | assign dmem_addr = top.addr; 59 | assign dmem_wd = top.wd; 60 | assign dmem_en = top.en; 61 | assign dmem_size = top.size; 62 | 63 | readdata_format readdata_format (dmem_rd, out.rd, top.addr[1: 0], __op); 64 | assign dmem_wt = out.wt; 65 | assign dmem_addr = out.addr; 66 | assign dmem_wd = out.wd; 67 | assign dmem_en = out.en; 68 | assign dmem_size = out.size; 69 | 70 | endmodule 71 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/sbuffer/sbuffer.svh: -------------------------------------------------------------------------------- 1 | `ifndef __SBUFFER_SVH 2 | `define __SBUFFER_SVH 3 | 4 | `include "mips.svh" 5 | 6 | `define SBUFFER_SIZE 'd8 7 | `define SBUFFER_WIDTH 'd3 8 | 9 | `endif 10 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/signalcommit.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module signalcommit ( 4 | input exec_data_t dataE, 5 | output exec_data_t dataM, 6 | output m_q_t mem 7 | // output bypass_t forward, 8 | // output exception_set_t exception, 9 | // output dmem_t dram_req, 10 | // input word_t readdata, 11 | // output cp0_commit_t cp0, 12 | // output logic is_eret 13 | ); 14 | 15 | logic wen, ren; 16 | word_t aluoutM, writedataM; 17 | decoded_op_t op; 18 | assign op = dataE.instr.op; 19 | assign aluoutM = dataE.result; 20 | assign ren = {4{dataE.instr.ctl.memtoreg}}; 21 | 22 | writedata_format writedata_format(.addr(aluoutM[1:0]), .op(op), ._wd(dataE.writedata), .en(wen), .wd(writedataM)); 23 | 24 | assign dataM = dataE; 25 | assign mem.ren = ren; 26 | assign mem.addr = aluoutM; 27 | assign mem.wen = wen; 28 | assign mem.addr = aluoutM; 29 | assign mem.wd = writedataM; 30 | assign mem.wt = dataE.instr.clt.memwrite; 31 | 32 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/signaldecode.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module signaldecode ( 4 | input fetch_data_t dataF, 5 | output decode_data_t dataD 6 | //input cp0_status_t cp0_status, 7 | //input cp0_status_t cp0_cause 8 | ); 9 | op_t op; 10 | func_t func; 11 | halfword_t imm; 12 | logic ext; 13 | word_t pcbranch, pcjump; 14 | word_t hi, lo; 15 | word_t aluoutM, resultW; 16 | logic is_reserved; 17 | creg_addr_t rs, rt, rd; 18 | assign op = dataF.instr_[31:26]; 19 | assign func = dataF.instr_[5:0]; 20 | assign imm = dataF.instr_[15:0]; 21 | assign rs = dataF.instr_[25:21]; 22 | assign rt = dataF.instr_[20:16]; 23 | assign rd = dataF.instr_[15:11]; 24 | // assign dataD.instr.rs = dataF.instr_[25:21]; 25 | // assign dataD.instr.rt = dataF.instr_[20:16]; 26 | // assign dataD.instr.rd = dataF.instr_[15:11]; 27 | 28 | maindecode maindecode(dataF.instr_, 29 | rs, rt, rd, 30 | dataD.instr.op, dataD.exception_ri, 31 | dataD.instr.ctl, 32 | dataD.srcrega, dataD.srcregb, dataD.destreg); 33 | assign dataD.cp0_addr = rd; 34 | 35 | assign dataD.instr.shamt = dataF.instr_[10:6]; 36 | assign is_reserved = (dataD.instr.op == RESERVED); 37 | 38 | word_t ext_imm; 39 | extend ext1(imm, dataD.instr.ctl.zeroext, ext_imm); 40 | assign pcbranch = dataF.pcplus4 + {dataD.instr.extended_imm[29:0], 2'b00}; 41 | assign pcjump = {dataF.pcplus4[31:28], dataF.instr_[25:0], 2'b00}; 42 | assign dataD.instr.pcbranch = pcbranch; 43 | assign dataD.instr.extended_imm = ext_imm; 44 | assign dataD.instr.pcjump = pcjump; 45 | assign dataD.pred = dataF.pred; 46 | assign dataD.pcplus4 = dataF.pcplus4; 47 | assign dataD.exception_instr = dataF.exception_instr; 48 | /* 49 | srcadmux srcadmux(.regfile(regfile.src1),.m(hazard.aluoutM),.w(hazard.resultW),.alusrcaE(hazard.alusrcaE), 50 | .forward(hazard.forwardAD), .ctl(dataD.instr.ctl), 51 | .hiD(hilo.hi), .loD(hilo.lo), .cp0D(cp0.rd), 52 | .srca(dataD.srca)); 53 | srcbdmux srcbdmux(.regfile(regfile.src2),.m(hazard.aluoutM),.w(hazard.resultW),.alusrcaE(hazard.alusrcaE), 54 | .forward(hazard.forwardBD), .srcb(dataD.srcb)); 55 | */ 56 | 57 | assign dataD.in_delay_slot = 1'b0; //dataF.in_delay_slot; 58 | assign dataD.jrtop = dataF.jrtop; 59 | // assign dataD.en = dataF.en; 60 | // ports 61 | 62 | //assign dataD.cp0_cause = cp0_cause; 63 | //assign dataD.cp0_status = cp0_status; 64 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/sources.tcl: -------------------------------------------------------------------------------- 1 | cd [file dirname [info script]] 2 | add_files [glob *.sv] 3 | add_files [glob *.v] 4 | add_files [glob *.svh] 5 | add_files [glob bpb/*.sv] 6 | add_files [glob mult/*.sv] 7 | add_files [glob mult/*.svh] 8 | add_files [glob fetch/*.sv*] 9 | add_files [glob commit/*.sv*] 10 | add_files [glob sbuffer/*.sv] 11 | add_files [glob sbuffer/*.svh] 12 | add_files [glob mult/*/*.xci] 13 | add_files [glob top/*.sv] 14 | -------------------------------------------------------------------------------- /superscalar_inorder_dual/top/readdata_format.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module readdata_format ( 4 | input word_t _rd, 5 | output word_t rd, 6 | input logic[1:0] addr, 7 | input decoded_op_t op 8 | ); 9 | always_comb begin 10 | case (op) 11 | LB: begin 12 | case (addr) 13 | 2'b00: rd = {{24{_rd[7]}}, _rd[7:0]}; 14 | 2'b01: rd = {{24{_rd[15]}}, _rd[15:8]}; 15 | 2'b10: rd = {{24{_rd[23]}}, _rd[23:16]}; 16 | 2'b11: rd = {{24{_rd[31]}}, _rd[31:24]}; 17 | default: rd = _rd; 18 | endcase 19 | end 20 | LBU: begin 21 | case (addr) 22 | 2'b00: rd = {24'b0, _rd[7:0]}; 23 | 2'b01: rd = {24'b0, _rd[15:8]}; 24 | 2'b10: rd = {24'b0, _rd[23:16]}; 25 | 2'b11: rd = {24'b0, _rd[31:24]}; 26 | default: rd = _rd; 27 | endcase 28 | end 29 | LH: begin 30 | case (addr[1]) 31 | 1'b0: rd = {{16{_rd[15]}}, _rd[15:0]}; 32 | 1'b1: rd = {{16{_rd[31]}}, _rd[31:16]}; 33 | default: begin 34 | rd = _rd; 35 | end 36 | endcase 37 | end 38 | LHU: begin 39 | case (addr[1]) 40 | 1'b0: rd = {16'b0, _rd[15:0]}; 41 | 1'b1: rd = {16'b0, _rd[31:16]}; 42 | default: begin 43 | rd = _rd; 44 | end 45 | endcase 46 | end 47 | default: begin 48 | rd = _rd; 49 | end 50 | endcase 51 | end 52 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_dual/writedata_format.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module writedata_format ( 4 | input exec_data_t in, 5 | output m_q_t out 6 | ); 7 | 8 | op_t op; 9 | assign op = in.instr.op; 10 | logic [1: 0] dmem_size_w, dmem_size_r; 11 | assign dmem_size_w = (op == SW) ? 2'b10 : (op == SH ? 2'b01:2'b00); 12 | assign dmem_size_r = (op == LW) ? 2'b10 : (op == LH ? 2'b01:2'b00); 13 | 14 | logic ren, wen; 15 | assign ren = in.instr.ctl.memtoreg; 16 | assign out.size = (wen) ? (dmem_size_w) : (dmem_size_r); 17 | assign out.en = wen | ren; 18 | assign out.addr = in.result; 19 | 20 | logic [1: 0] addr; 21 | assign addr = out.addr[1: 0]; 22 | word_t _wd, wd; 23 | assign _wd = in.srcb; 24 | assign out.wd = wd; 25 | assign out.wt = in.instr.ctl.memwrite; 26 | 27 | always_comb begin 28 | case (op) 29 | SW : begin 30 | wen = 1'b1; 31 | wd = _wd; 32 | end 33 | SH: begin 34 | case (addr[1]) 35 | 1'b0: begin 36 | wen = 1'b1; 37 | wd = _wd; 38 | end 39 | 1'b1: begin 40 | wen = 1'b1; 41 | wd = {_wd[15:0], 16'b0}; 42 | end 43 | default: begin 44 | wen = 'b0; 45 | wd = '0; 46 | end 47 | endcase 48 | end 49 | SB: begin 50 | case (addr) 51 | 2'b00: begin 52 | wen = 1'b1; 53 | wd = _wd; 54 | end 55 | 2'b01: begin 56 | wen = 1'b1; 57 | wd = {_wd[23:0], 8'b0}; 58 | end 59 | 2'b10: begin 60 | wen = 1'b1; 61 | wd = {_wd[15:0], 16'b0}; 62 | end 63 | 2'b11: begin 64 | wen = 1'b1; 65 | wd = {_wd[7:0], 24'b0}; 66 | end 67 | default: begin 68 | wen = 'b0; 69 | wd = '0; 70 | end 71 | endcase 72 | end 73 | default: begin 74 | wen = '0; 75 | wd = '0; 76 | end 77 | endcase 78 | end 79 | endmodule 80 | -------------------------------------------------------------------------------- /superscalar_inorder_signal/ALU.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module ALU ( 4 | input word_t a, 5 | input word_t b, 6 | input alufunc_t alufunc, 7 | output word_t c, 8 | output logic exception_of 9 | ); 10 | shamt_t shamt; 11 | assign shamt = a[4: 0]; 12 | logic [32:0] temp; 13 | 14 | always_comb begin 15 | exception_of = 0; 16 | temp = '0; 17 | 18 | case (alufunc) 19 | ALU_AND: begin 20 | c = a & b; 21 | end 22 | ALU_ADD: begin 23 | c = a + b; 24 | temp = {a[31], a} + {b[31], b}; 25 | exception_of = (temp[32] != temp[31]); 26 | end 27 | ALU_OR: begin 28 | c = a | b; 29 | end 30 | ALU_SLL: begin 31 | c = b << shamt; 32 | end 33 | ALU_SRL: begin 34 | c = b >> shamt; 35 | end 36 | ALU_SRA: begin 37 | c = signed'(b) >>> shamt; 38 | end 39 | ALU_SUB: begin 40 | c = a - b; 41 | temp = {a[31], a} - {b[31], b}; 42 | exception_of = (temp[32] != temp[31]); 43 | end 44 | ALU_SLT: begin 45 | c = (signed'(a) < signed'(b)) ? 32'b1 : 32'b0; 46 | end 47 | ALU_NOR: begin 48 | c = ~(a | b); 49 | end 50 | ALU_XOR: begin 51 | c = a ^ b; 52 | end 53 | ALU_ADDU: begin 54 | c = a + b; 55 | end 56 | ALU_SUBU: begin 57 | c = a - b; 58 | end 59 | ALU_SLTU: begin 60 | c = (a < b) ? 32'b01 : 32'b00; 61 | end 62 | ALU_PASSA: begin 63 | c = a; 64 | end 65 | ALU_LUI : begin 66 | c = {b[15:0], 16'b0}; 67 | end 68 | ALU_PASSB: begin 69 | c = b; 70 | end 71 | default: begin 72 | c = '0; 73 | end 74 | endcase 75 | end 76 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/DIVU.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module DIVU ( 4 | input word_t a, b, 5 | input decoded_op_t op, 6 | input logic en, 7 | output word_t hi, lo, 8 | output logic finish 9 | ); 10 | dword_t ans; 11 | always_comb 12 | if (en) 13 | begin 14 | case (op) 15 | DIVU: begin 16 | ans = '0; 17 | lo = {1'b0, a} / {1'b0, b}; 18 | hi = {1'b0, a} % {1'b0, b}; 19 | end 20 | DIV: begin 21 | ans = '0; 22 | lo = signed'(a) / signed'(b); 23 | hi = signed'(a) % signed'(b); 24 | end 25 | default: begin 26 | hi = '0; 27 | lo = '0; 28 | ans = '0; 29 | end 30 | endcase 31 | end 32 | else 33 | begin 34 | hi = '0; 35 | lo = '0; 36 | end 37 | assign finish = 1'b1; 38 | 39 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/FU.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module FU( 4 | input issue_data_t in, 5 | output exec_data_t out, 6 | output logic finish, 7 | input logic mul_timeok, div_timeok 8 | ); 9 | 10 | decoded_op_t op; 11 | assign op = in.instr.op; 12 | alufunc_t func; 13 | assign func = in.instr.ctl.alufunc; 14 | logic multype, divtype; 15 | assign multype = (op == MULT) || (op == MULTU); 16 | assign divtype = (op == DIV) || (op == DIVU); 17 | 18 | word_t alusrcaE, alusrcbE; 19 | assign alusrcaE = (in.instr.ctl.shamt_valid) ? ({27'b0, in.instr.shamt}) : (in.srca); 20 | assign alusrcbE = (in.instr.ctl.alusrc == REGB) ? (in.srcb) : (in.instr.extended_imm); 21 | 22 | word_t hi_div, lo_div, hi_mul, lo_mul, result; 23 | logic exception_of, taken; 24 | DIVU DIVU (alusrcaE, alusrcbE, op, divtype, hi_div, lo_div, div_finish); 25 | MULU MULU (alusrcaE, alusrcbE, op, multype, hi_mul, lo_mul, mul_finish); 26 | ALU ALU (alusrcaE, alusrcbE, func, result, exception_of); 27 | JUDGE JUDGE(alusrcaE, alusrcbE, in.instr.ctl.branch_type, taken); 28 | assign finish = (~divtype || div_timeok) && (~multype || mul_timeok); 29 | //assign finish = 1'b1; 30 | 31 | word_t hi, lo; 32 | assign hi = (multype) ? (hi_mul) : (hi_div); 33 | assign lo = (multype) ? (lo_mul) : (lo_div); 34 | 35 | assign out.taken = taken; 36 | assign out.instr = in.instr; 37 | assign out.pcplus4 = in.pcplus4; 38 | assign out.exception_instr = in.exception_instr; 39 | assign out.exception_ri = in.exception_ri; 40 | assign out.srca = in.srca; 41 | assign out.srcb = in.srcb; 42 | assign out.destreg = in.destreg; 43 | assign out.in_delay_slot = in.in_delay_slot; 44 | assign out.cp0_addr = in.cp0_addr; 45 | assign out.cp0_cause = in.cp0_cause; 46 | assign out.cp0_status = in.cp0_status; 47 | assign out.cp0_epc = in.cp0_epc; 48 | 49 | word_t pcplus8; 50 | adder adderpcplus8(in.pcplus4, 32'b0100, pcplus8); 51 | 52 | assign out.hiresult = (multype | divtype) ? (hi) : (result);//mul/div or HTHI 53 | assign out.loresult = (multype | divtype) ? (lo) : (result);//mul/div or HTLO 54 | assign out.result = (in.instr.ctl.is_link) ? (pcplus8) : ( 55 | (in.instr.ctl.mul_div_r) ? (lo) : (result)); 56 | assign out.exception_of = (multype | divtype) ? ('0) : (exception_of); 57 | 58 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/JUDGE.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module JUDGE( 4 | input word_t srca, srcb, 5 | input branch_t branch_type, 6 | output logic taken 7 | ); 8 | 9 | always_comb begin 10 | case (branch_type) 11 | T_BEQ: taken = (srca == srcb); 12 | T_BNE: taken = (srca != srcb); 13 | T_BGEZ: taken = (~srca[31]); 14 | T_BLTZ: taken = (srca[31]); 15 | T_BGTZ: taken = (~srca[31] && srca != '0); 16 | T_BLEZ: taken = (srca[31] || srca == '0); 17 | default: taken = 1'b0; 18 | endcase 19 | end 20 | /* 21 | always_comb 22 | begin 23 | case (op) 24 | BEQ: taken = (srca == srcb); 25 | BNE: taken = (srca != srcb); 26 | BGEZ: taken = (~srca[31]); 27 | BLEZ: taken = (srca[31]); 28 | BGTZ: taken = (~srca[31] && srca != '0); 29 | BLTZ: taken = (srca[31] || srca == '0); 30 | BGEZAL: taken = (~srca[31]); 31 | BLTZAL: taken = (srca[31] || srca == '0); 32 | J: taken = 1'b1; 33 | JAL: taken = 1'b1; 34 | JR: taken = 1'b1; 35 | JALR: taken = 1'b1; 36 | default: taken = 1'b0; 37 | endcase 38 | end 39 | */ 40 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/MULU.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module MULU ( 4 | input word_t a, b, 5 | input decoded_op_t op, 6 | input logic en, 7 | output word_t hi, lo, 8 | output logic finish 9 | ); 10 | dword_t ans; 11 | always_comb 12 | if (en) 13 | begin 14 | case (op) 15 | MULTU: begin 16 | ans = {32'b0, a} * {32'b0, b}; 17 | hi = ans[63:32]; 18 | lo = ans[31:0]; 19 | end 20 | MULT: begin 21 | ans = signed'({{32{a[31]}}, a}) * signed'({{32{b[31]}}, b}); 22 | hi = ans[63:32]; 23 | lo = ans[31:0]; 24 | end 25 | endcase 26 | end 27 | else 28 | begin 29 | hi = '0; 30 | lo = '0; 31 | end 32 | assign finish = 1'b1; 33 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/adder.sv: -------------------------------------------------------------------------------- 1 | module adder #(parameter W = 32) ( 2 | input logic [W - 1: 0] a, b, 3 | output logic [W - 1: 0] c 4 | ); 5 | assign c = a + b; 6 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/bypass.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module bypass( 4 | input creg_addr_t [3: 0] reg_addrI, 5 | output word_t [3: 0] reg_dataI, 6 | input logic [1: 0] hiloreadI, 7 | output word_t [1: 0] hilodataI, 8 | input creg_addr_t [1: 0] cp0_addrI, 9 | output word_t [1: 0] cp0_dataI, 10 | output logic data_hazardI, 11 | //issue 12 | input bypass_upd_t execute, 13 | input bypass_upd_t commit, 14 | input bypass_upd_t retire, 15 | //forward 16 | output creg_addr_t [3: 0] reg_addrR, 17 | input word_t [3: 0] reg_dataR, 18 | output logic [1: 0] hiloreadR, 19 | input word_t hiR, loR, 20 | output creg_addr_t [1: 0] cp0_addrR, 21 | input word_t [1: 0] cp0_dataR 22 | //registers 23 | ); 24 | 25 | assign reg_addrR = reg_addrI; 26 | assign hiloreadR = hiloreadI; 27 | assign cp0_addrR = cp0_addrI; 28 | 29 | word_t [1: 0] _cp0_dataI; 30 | cp0_regs_t cp0_mask_and, cp0_mask_or; 31 | assign cp0_mask_and = `CP0_MASK_AND; 32 | assign cp0_mask_or = `CP0_MASK_OR; 33 | 34 | logic [3: 0] hazard; 35 | regbypass bypss_reg3 (reg_addrI[3], execute, commit, retire, reg_dataR[3], hazard[3], reg_dataI[3]); 36 | regbypass bypss_reg2 (reg_addrI[2], execute, commit, retire, reg_dataR[2], hazard[2], reg_dataI[2]); 37 | regbypass bypss_reg1 (reg_addrI[1], execute, commit, retire, reg_dataR[1], hazard[1], reg_dataI[1]); 38 | regbypass bypss_reg0 (reg_addrI[0], execute, commit, retire, reg_dataR[0], hazard[0], reg_dataI[0]); 39 | hlbypass bypass_hilo (execute, commit, retire, hiR, loR, hilodataI[1], hilodataI[0]); 40 | cp0bypass bypass_cp01 (cp0_addrI[1], execute, commit, retire, cp0_dataR[1], _cp0_dataI[1]); 41 | cp0bypass bypass_cp00 (cp0_addrI[0], execute, commit, retire, cp0_dataR[0], _cp0_dataI[0]); 42 | 43 | assign data_hazardI = hazard[3] | hazard[2] | hazard[1] | hazard[0]; 44 | 45 | word_t [1: 0] _cp0_mask_and, _cp0_mask_or; 46 | assign _cp0_mask_and = {cp0_mask_and[cp0_addrI[1]], cp0_mask_and[cp0_addrI[0]]}; 47 | assign _cp0_mask_or = {cp0_mask_or[cp0_addrI[1]], cp0_mask_or[cp0_addrI[0]]}; 48 | 49 | //assign cp0_dataI[1] = (_cp0_dataI[1] & _cp0_mask_and[1]) | _cp0_mask_or[1]; 50 | //assign cp0_dataI[0] = (_cp0_dataI[0] & _cp0_mask_and[0]) | _cp0_mask_or[0]; 51 | assign cp0_dataI = _cp0_dataI; 52 | 53 | endmodule 54 | -------------------------------------------------------------------------------- /superscalar_inorder_signal/control.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module control( 4 | input logic finishF, finishE, finishC, data_hazardI, queue_ofI, pcF, 5 | input logic is_eret, exception_valid, 6 | output logic stallF, stallD, flushD, stallI, flushI, 7 | output logic stallE, flushE, stallC, flushC, stallR, flushR, pc_new_commit, flush_ex 8 | ); 9 | 10 | assign flush_ex = is_eret | exception_valid; 11 | 12 | logic hazardC, hazardE, hazardI, hazardpc; 13 | assign hazardC = ~finishC; 14 | assign hazardE = ~finishE & finishC; 15 | assign hazardI = data_hazardI & finishE & finishC; 16 | 17 | assign flushI = pcF | flush_ex; 18 | assign flushE = hazardI | pcF | flush_ex; 19 | assign flushC = hazardE | (pcF & finishC) | flush_ex; 20 | assign flushR = hazardC; 21 | 22 | assign stallI = hazardC | hazardE | hazardI; 23 | assign stallE = hazardC | hazardE; 24 | assign stallC = hazardC; 25 | assign stallR = 'b0; 26 | 27 | assign flushD = (~finishF & ~queue_ofI) | pcF | flush_ex; 28 | assign stallD = queue_ofI; 29 | assign stallF = ~finishF | queue_ofI; 30 | 31 | assign pc_new_commit = pcF | flush_ex; 32 | 33 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/cp0bypass.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module cp0bypass( 4 | input creg_addr_t cp0_addr, 5 | input bypass_upd_t execute, 6 | input bypass_upd_t commit, 7 | input bypass_upd_t retire, 8 | input word_t cp0_data_complete, 9 | output word_t cp0_data 10 | ); 11 | logic regire_hit, commit_hit, execute_hit; 12 | assign execute_hit = (execute.cp0_addr[1] == cp0_addr && execute.cp0_wen[1]) | 13 | (execute.cp0_addr[0] == cp0_addr && execute.cp0_wen[0]); 14 | assign commit_hit = ((commit.cp0_addr[1] == cp0_addr && commit.cp0_wen[1]) | 15 | (commit.cp0_addr[0] == cp0_addr && commit.cp0_wen[0])) & (~execute_hit); 16 | assign retire_hit = ((retire.cp0_addr[1] == cp0_addr && execute.cp0_wen[1]) | 17 | (retire.cp0_addr[0] == cp0_addr && execute.cp0_wen[0])) & (~execute_hit) & (~commit_hit); 18 | 19 | logic [2: 0] hits; 20 | assign hits = {execute_hit, commit_hit, retire_hit}; 21 | assign hit = execute_hit | commit_hit | retire_hit; 22 | always_comb begin 23 | case (hits) 24 | 3'b100: cp0_data <= (execute.cp0_addr[0] == cp0_addr && execute.cp0_wen[0]) ? (execute.result[0]) : (execute.result[1]); 25 | 3'b010: cp0_data <= (commit.cp0_addr[0] == cp0_addr && commit.cp0_wen[0]) ? (commit.result[0]) : (commit.result[1]); 26 | 3'b001: cp0_data <= (retire.cp0_addr[0] == cp0_addr && retire.cp0_wen[0]) ? (retire.result[0]) : (retire.result[1]); 27 | default: cp0_data <= cp0_data_complete; 28 | endcase 29 | end 30 | 31 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/decode.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module decode( 4 | (*mark_debug = "true"*) input fetch_data_t [1: 0] in, 5 | input logic [1: 0] hitF, 6 | (*mark_debug = "true"*) output decode_data_t [1: 0] out, 7 | output logic [1: 0] hitD 8 | //input cp0_status_t cp0_status, 9 | //input cp0_status_t cp0_cause 10 | ); 11 | signaldecode signaldecode1 (in[1], out[1]); 12 | signaldecode signaldecode0 (in[0], out[0]); 13 | assign hitD = hitF; 14 | endmodule 15 | -------------------------------------------------------------------------------- /superscalar_inorder_signal/decode_to_issue_t.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module decode_to_issue_t( 4 | input decode_data_t in, 5 | input word_t hi, lo, 6 | input word_t reg_dataa, reg_datab, 7 | input word_t cp0_data, 8 | input cp0_status_t cp0_statusI, 9 | input cp0_cause_t cp0_causeI, 10 | input word_t cp0_epcI, 11 | output issue_data_t out, 12 | input logic BJp, 13 | input logic is_link 14 | ); 15 | 16 | assign out.instr = in.instr; 17 | assign out.pcplus4 = in.pcplus4; 18 | assign out.exception_instr = in.exception_instr; 19 | assign out.exception_ri = in.exception_ri; 20 | assign out.cp0_addr = in.cp0_addr; 21 | // assign out.exception_of = 'b0; 22 | assign out.srca = (in.instr.ctl.hitoreg) ? (hi) : ( 23 | (in.instr.ctl.cp0toreg) ? (cp0_data) : ( 24 | (is_link && in.srcrega == 5'd31) ? (in.pcplus4) : reg_dataa)); 25 | 26 | assign out.srcb = (in.instr.ctl.lotoreg) ? (lo) : ( 27 | (is_link && in.srcregb == 5'd31) ? (in.pcplus4) : (reg_datab)); 28 | 29 | assign out.destreg = in.destreg; 30 | assign out.in_delay_slot = BJp; 31 | assign out.cp0_status = cp0_statusI; 32 | assign out.cp0_cause = cp0_causeI; 33 | assign out.cp0_epc = cp0_epcI; 34 | 35 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/exception_checker.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module exception_checker( 4 | input logic flush, reset, 5 | input exec_data_t in, 6 | input logic [5: 0] ext_int, 7 | input logic timer_interrupt, 8 | output logic exception_valid, 9 | output word_t pcexception, 10 | output exception_t exception_data, 11 | output exec_data_t _out 12 | ); 13 | 14 | exec_data_t data; 15 | assign data = (reset | flush) ? ('0) : (in); 16 | assign _out = (exception_valid) ? ('0) : (data); 17 | 18 | decoded_op_t op; 19 | assign op = data.instr.op; 20 | word_t aluoutM; 21 | assign aluoutM = data.result; 22 | 23 | logic exception_load, exception_save, exception_sys, exception_bp; 24 | assign exception_load = ((op == LW) && (aluoutM[1:0] != '0)) || 25 | ((op == LH || op == LHU) && (aluoutM[0] != '0)); 26 | assign exception_save = ((op == SW) && (aluoutM[1:0] != '0)) || 27 | ((op == SH) && (aluoutM[0] != '0)); 28 | assign exception_sys = (data.instr.op == SYSCALL); 29 | assign exception_bp = (data.instr.op == BREAK); 30 | 31 | exception_pipeline_t pipe; 32 | assign pipe.exception_instr = data.exception_instr; 33 | assign pipe.exception_ri = data.exception_ri; 34 | assign pipe.exception_of = data.exception_of; 35 | assign pipe.exception_load = exception_load; 36 | assign pipe.exception_save = exception_save; 37 | assign pipe.exception_sys = exception_sys; 38 | assign pipe.exception_bp = exception_bp; 39 | assign pipe.in_delay_slot = data.in_delay_slot; 40 | assign pipe.pc = data.pcplus4 - 32'd4; 41 | assign pipe.vaddr = (data.exception_instr) ? pipe.pc : data.result; 42 | assign pipe.interrupt_info = ({ext_int, 2'b00} | data.cp0_cause.IP | {timer_interrupt, 7'b0}) & data.cp0_status.IM; 43 | 44 | exception exception (reset, ext_int, 45 | pipe, 46 | exception_valid, pcexception, 47 | exception_data, 48 | data.cp0_status); 49 | 50 | endmodule 51 | -------------------------------------------------------------------------------- /superscalar_inorder_signal/exec_to_commit_t.sv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NSCSCC-2020-Fudan/FDU1.1-NSCSCC/6c751483f2b8467548fb216fb23b995cd6ce8897/superscalar_inorder_signal/exec_to_commit_t.sv -------------------------------------------------------------------------------- /superscalar_inorder_signal/exec_to_exec_t.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module exec_to_exec_t( 4 | input exec_data_t a, 5 | output exec_data_t b 6 | ); 7 | assign b.instr = a.instr; 8 | assign b.pcplus4 = a.pcplus4; 9 | assign b.exception_instr = a.exception_instr; 10 | assign b.exception_ri = a.exception_ri; 11 | assign b.exception_of = a.exception_of; 12 | assign b.taken = a.taken; 13 | assign b.srca = a.srca; 14 | assign b.srcb = a.srcb; 15 | assign b.destreg = a.destreg; 16 | assign b.result = a.result; 17 | assign b.hiresult = a.hiresult; 18 | assign b.loresult = a.loresult; 19 | assign b.in_delay_slot = a.in_delay_slot; 20 | 21 | endmodule 22 | -------------------------------------------------------------------------------- /superscalar_inorder_signal/execute.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module execute( 4 | input logic clk, reset, 5 | input issue_data_t [1: 0] in, 6 | output exec_data_t [1: 0] out, 7 | //pipeline 8 | output logic finishE, 9 | input logic flushE, stallE, 10 | //control 11 | output bypass_upd_t bypass, 12 | //bypass 13 | input logic mul_timeok, div_timeok 14 | ); 15 | 16 | logic [1: 0] FU_finish; 17 | exec_data_t [1: 0] FU_result; 18 | FU FU1 (in[1], FU_result[1], FU_finish[1], mul_timeok, div_timeok); 19 | FU FU0 (in[0], FU_result[0], FU_finish[0], mul_timeok, div_timeok); 20 | 21 | logic finish; 22 | assign finish = FU_finish[1] && FU_finish[0]; 23 | assign finishE = finish; 24 | 25 | assign out[1] = FU_result[1]; 26 | assign out[0] = FU_result[0]; 27 | 28 | assign bypass.destreg = {out[1].destreg, out[0].destreg}; 29 | assign bypass.result = {out[1].result, out[0].result}; 30 | assign bypass.hiwrite = {out[1].instr.ctl.hiwrite, out[0].instr.ctl.hiwrite}; 31 | assign bypass.lowrite = {out[1].instr.ctl.lowrite, out[0].instr.ctl.lowrite}; 32 | assign bypass.hidata = {out[1].hiresult, out[0].hiresult}; 33 | assign bypass.lodata = {out[1].loresult, out[0].loresult}; 34 | assign bypass.memtoreg = {out[1].instr.ctl.memtoreg, out[0].instr.ctl.memtoreg}; 35 | assign bypass.cp0_addr = {out[1].cp0_addr, out[0].cp0_addr}; 36 | assign bypass.wen = {out[1].instr.ctl.regwrite, out[0].instr.ctl.regwrite}; 37 | assign bypass.cp0_wen = {out[1].instr.ctl.cp0write, out[0].instr.ctl.cp0write}; 38 | 39 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/extend.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module extend ( 4 | input halfword_t in, 5 | input logic s, 6 | output word_t out 7 | ); 8 | assign out = s ? {16'b0, in} : {{16{in[15]}}, in}; 9 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/handshake.sv: -------------------------------------------------------------------------------- 1 | 2 | `include "mips.svh" 3 | 4 | module handshake ( 5 | input logic clk, reset, 6 | input logic cpu_req, 7 | input logic addr_ok, data_ok, 8 | output logic cpu_data_ok, req 9 | ); 10 | 11 | typedef enum logic[1:0] { INIT, WAIT_ADDR, WAIT_DATA } handshake_state_t; 12 | handshake_state_t state, state_new; 13 | assign cpu_data_ok = state_new == INIT; 14 | always_ff @(posedge clk) begin 15 | if (reset) begin 16 | state <= INIT; 17 | end else begin 18 | state <= state_new; 19 | end 20 | end 21 | always_comb begin 22 | state_new = state; 23 | case (state) 24 | INIT: begin 25 | if (cpu_req) begin 26 | state_new = WAIT_ADDR; 27 | end 28 | end 29 | WAIT_ADDR: begin 30 | if (addr_ok) begin 31 | state_new = WAIT_DATA; 32 | if (data_ok) begin 33 | state_new = INIT; 34 | end 35 | end 36 | end 37 | WAIT_DATA: begin 38 | if (data_ok) begin 39 | state_new = INIT; 40 | end 41 | end 42 | default: begin 43 | state_new = INIT; 44 | end 45 | endcase 46 | end 47 | assign req = state == WAIT_ADDR; 48 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/hilo.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module hilo ( 4 | input logic clk, reset, 5 | input logic hiloread, 6 | output word_t hiW, loW, 7 | input hilo_w_t hlw 8 | ); 9 | 10 | word_t hi, lo; 11 | always_ff @(posedge clk, posedge reset) begin 12 | if (reset) begin 13 | hi <= '0; 14 | lo <= '0; 15 | end else begin 16 | if (hlw.wen_h) 17 | hi <= hlw.wd_h; 18 | else 19 | hi <= hi; 20 | 21 | if (hlw.wen_l) 22 | lo <= hlw.wd_l; 23 | else 24 | lo <= lo; 25 | end 26 | end 27 | 28 | assign hiW = hi; 29 | assign loW = lo; 30 | 31 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/hlbypass.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module hlbypass( 4 | input bypass_upd_t execute, 5 | input bypass_upd_t commit, 6 | input bypass_upd_t retire, 7 | input word_t hi_complete, lo_complete, 8 | output word_t hidata, lodata 9 | ); 10 | 11 | logic retire_hazard, commit_hazard, execute_hazard; 12 | logic [1: 0] retire_hit, commit_hit, execute_hit; 13 | assign execute_hit = {execute.hiwrite[1] | execute.hiwrite[0], execute.lowrite[1] | execute.lowrite[0]}; 14 | assign commit_hit = {commit.hiwrite[1] | commit.hiwrite[0], commit.lowrite[1] | commit.lowrite[0]} & (~execute_hit); 15 | assign retire_hit = {retire.hiwrite[1] | retire.hiwrite[0], retire.lowrite[1] | retire.lowrite[0]} & (~execute_hit) & (~commit_hit); 16 | 17 | logic [2: 0] hihits; 18 | assign hihits = {execute_hit[1], commit_hit[1], retire_hit[1]}; 19 | assign hihit = execute_hit[1] | commit_hit[1] | retire_hit[1]; 20 | always_comb begin 21 | case (hihits) 22 | 3'b100: hidata <= (execute.hiwrite[0]) ? (execute.hidata[0]) : (execute.hidata[1]); 23 | 3'b010: hidata <= (commit.hiwrite[0]) ? (commit.hidata[0]) : (commit.hidata[1]); 24 | 3'b001: hidata <= (retire.hiwrite[0]) ? (retire.hidata[0]) : (retire.hidata[1]); 25 | default: hidata <= hi_complete; 26 | endcase 27 | end 28 | 29 | logic [2: 0] lohits; 30 | assign lohits = {execute_hit[0], commit_hit[0], retire_hit[0]}; 31 | assign lohit = execute_hit[0] | commit_hit[0] | retire_hit[0]; 32 | always_comb begin 33 | case (lohits) 34 | 3'b100: lodata <= (execute.lowrite[0]) ? (execute.lodata[0]) : (execute.lodata[1]); 35 | 3'b010: lodata <= (commit.lowrite[0]) ? (commit.lodata[0]) : (commit.lodata[1]); 36 | 3'b001: lodata <= (retire.lowrite[0]) ? (retire.lodata[0]) : (retire.lodata[1]); 37 | default: lodata <= lo_complete; 38 | endcase 39 | end 40 | 41 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/mem_to_reg.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module mem_to_reg( 4 | input exec_data_t in, 5 | input m_q_t mem, 6 | output exec_data_t out 7 | ); 8 | 9 | assign out.instr = in.instr; 10 | assign out.pcplus4 = in.pcplus4; 11 | assign out.exception_instr = in.exception_instr; 12 | assign out.exception_ri = in.exception_ri; 13 | assign out.exception_of = in.exception_of; 14 | assign out.taken = in.taken; 15 | assign out.srca = in.srca; 16 | assign out.srcb = in.srcb; 17 | assign out.destreg = in.destreg; 18 | assign out.result = (in.instr.ctl.memtoreg) ? (mem.rd) : (in.result); 19 | assign out.hiresult = in.hiresult; 20 | assign out.loresult = in.loresult; 21 | assign out.in_delay_slot = in.in_delay_slot; 22 | assign out.cp0_status = in.cp0_status; 23 | assign out.cp0_cause = in.cp0_cause; 24 | assign out.cp0_addr = in.cp0_addr; 25 | assign out.cp0_epc = in.cp0_epc; 26 | endmodule 27 | -------------------------------------------------------------------------------- /superscalar_inorder_signal/pcselect.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module pcselect ( 4 | input logic exception_valid, is_eret, branch, jump, jr, 5 | input word_t pcexception, epc, pcbranch, pcjump, pcjr, pcplus, 6 | output word_t pc_new, 7 | output logic pc_upd 8 | ); 9 | assign pc_upd = exception_valid | is_eret | branch | jr | jump; 10 | assign pc_new = exception_valid ? pcexception : ( 11 | is_eret ? epc : ( 12 | branch ? pcbranch : ( 13 | jr ? pcjr : ( 14 | jump ? pcjump : 15 | pcplus)))); 16 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/pipelinereg.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module dreg( 4 | input logic clk, reset, 5 | input logic stallD, flushD, 6 | input fetch_data_t [1: 0] in, 7 | output fetch_data_t [1: 0] out, 8 | input logic [1: 0] hitF, 9 | output logic [1: 0] hitD 10 | ); 11 | 12 | always_ff @(posedge clk, posedge reset) 13 | begin 14 | if (reset) 15 | begin 16 | out <= '0; 17 | hitD <= '0; 18 | end 19 | else 20 | if (flushD) 21 | begin 22 | out <= '0; 23 | hitD <= '0; 24 | end 25 | else 26 | if (~stallD) 27 | begin 28 | out <= in; 29 | hitD <= hitF; 30 | end 31 | end 32 | endmodule 33 | 34 | module creg( 35 | input logic clk, reset, 36 | input logic stallC, flushC, 37 | input exec_data_t [1: 0] in, 38 | output exec_data_t [1: 0] out, 39 | output logic first_cycleC 40 | ); 41 | 42 | always_ff @(posedge clk, posedge reset) 43 | begin 44 | if (reset) 45 | begin 46 | out <= '0; 47 | first_cycleC <= '1; 48 | end 49 | else 50 | if (flushC) 51 | begin 52 | out <= '0; 53 | first_cycleC <= '1; 54 | end 55 | else 56 | if (~stallC) 57 | begin 58 | out <= in; 59 | first_cycleC <= '1; 60 | end 61 | else 62 | first_cycleC <= '0; 63 | end 64 | endmodule 65 | 66 | module rreg( 67 | input logic clk, reset, 68 | input logic stallR, flushR, 69 | input exec_data_t [1: 0] in, 70 | output exec_data_t [1: 0] out 71 | ); 72 | 73 | always_ff @(posedge clk, posedge reset) 74 | begin 75 | if (reset) 76 | out <= '0; 77 | else 78 | if (flushR) 79 | out <= '0; 80 | else 81 | if (~stallR) 82 | out <= in; 83 | else 84 | out <= out; 85 | end 86 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/regbypass.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module regbypass( 4 | input creg_addr_t reg_addr, 5 | input bypass_upd_t execute, 6 | input bypass_upd_t commit, 7 | input bypass_upd_t retire, 8 | input word_t reg_data_complete, 9 | output logic hazard, 10 | output word_t reg_data 11 | ); 12 | logic retire_hit, commit_hit, execute_hit; 13 | assign execute_hit = (execute.destreg[1] == reg_addr && execute.wen[1]) | 14 | (execute.destreg[0] == reg_addr && execute.wen[0]); 15 | assign commit_hit = ((commit.destreg[1] == reg_addr && commit.wen[1]) | 16 | (commit.destreg[0] == reg_addr && commit.wen[0])) & (~execute_hit); 17 | assign retire_hit = ((retire.destreg[1] == reg_addr && retire.wen[1]) | 18 | (retire.destreg[0] == reg_addr && retire.wen[0])) & (~execute_hit) & (~commit_hit); 19 | 20 | logic mem_hazard1, mem_hazard0, mem_hazard; 21 | assign mem_hazard1 = (execute.destreg[0] != reg_addr) & (execute.destreg[1] == reg_addr) & (execute.memtoreg[1]); 22 | assign mem_hazard0 = (execute.destreg[0] == reg_addr) & (execute.memtoreg[0]); 23 | assign mem_hazard = mem_hazard0 | mem_hazard1; 24 | assign hazard = mem_hazard; 25 | 26 | /* 27 | logic cp0_hazard1, cp0_hazard0, cp0_hazard; 28 | assign cp0_hazard1 = (execute.data[1].destreg == reg_addr) & (execute.data[1].instr.ctl.cp0toreg); 29 | assign cp0_hazard0 = ~(execute.data[1].destreg == reg_addr) & (execute.data[0].destreg == reg_addr) & (execute.data[0].instr.ctl.cp0toreg); 30 | assign cp0_hazard = cp0_hazard0 | cp0_hazard1; 31 | assign hazard = mem_hazard | cp0_hazard; 32 | */ 33 | 34 | logic [2: 0] hits; 35 | assign hits = {execute_hit, commit_hit, retire_hit}; 36 | assign hit = execute_hit | commit_hit | retire_hit; 37 | always_comb begin 38 | case (hits) 39 | 3'b100: reg_data <= (execute.destreg[0] == reg_addr && execute.wen[0]) ? (execute.result[0]) : (execute.result[1]); 40 | 3'b010: reg_data <= (commit.destreg[0] == reg_addr && commit.wen[0]) ? (commit.result[0]) : (commit.result[1]); 41 | 3'b001: reg_data <= (retire.destreg[0] == reg_addr && retire.wen[0]) ? (retire.result[0]) : (retire.result[1]); 42 | default: reg_data <= reg_data_complete; 43 | endcase 44 | end 45 | 46 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/regfile.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module regfile ( 4 | input logic clk, reset, 5 | input rf_w_t [1: 0] rfw, 6 | input creg_addr_t [3: 0] reg_addrW, 7 | output word_t [3: 0] reg_dataW 8 | ); 9 | word_t [31:0] R; 10 | always_ff @(posedge clk, posedge reset) begin 11 | if (reset) 12 | R <= '0; 13 | else 14 | begin 15 | if (rfw[1].wen && (rfw[1].addr != '0)) 16 | R[rfw[1].addr] = rfw[1].wd; 17 | else 18 | R[0] = '0; 19 | 20 | if (rfw[0].wen && (rfw[0].addr != '0)) 21 | R[rfw[0].addr] = rfw[0].wd; 22 | else 23 | R[0] = '0; 24 | end 25 | end 26 | 27 | assign reg_dataW[3] = (reg_addrW[3] != '0) ? R[reg_addrW[3]] : '0; 28 | assign reg_dataW[2] = (reg_addrW[2] != '0) ? R[reg_addrW[2]] : '0; 29 | assign reg_dataW[1] = (reg_addrW[1] != '0) ? R[reg_addrW[1]] : '0; 30 | assign reg_dataW[0] = (reg_addrW[0] != '0) ? R[reg_addrW[0]] : '0; 31 | 32 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/retire.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module retire( 4 | input exec_data_t [1: 0] in, 5 | output rf_w_t [1: 0] rfw, 6 | output word_t [1: 0] rt_pc, 7 | output hilo_w_t hlw, 8 | output rf_w_t [1: 0] cp0w, 9 | //register 10 | output bypass_upd_t bypass 11 | ); 12 | 13 | assign bypass.destreg = {in[1].destreg, in[0].destreg}; 14 | assign bypass.result = {in[1].result, in[0].result}; 15 | assign bypass.hiwrite = {in[1].instr.ctl.hiwrite, in[0].instr.ctl.hiwrite}; 16 | assign bypass.lowrite = {in[1].instr.ctl.lowrite, in[0].instr.ctl.lowrite}; 17 | assign bypass.hidata = {in[1].hiresult, in[0].hiresult}; 18 | assign bypass.lodata = {in[1].loresult, in[0].loresult}; 19 | assign bypass.memtoreg = {in[1].instr.ctl.memtoreg, in[0].instr.ctl.memtoreg}; 20 | assign bypass.cp0_addr = {in[1].cp0_addr, in[0].cp0_addr}; 21 | assign bypass.wen = {in[1].instr.ctl.regwrite, in[0].instr.ctl.regwrite}; 22 | assign bypass.cp0_wen = {in[1].instr.ctl.cp0write, in[0].instr.ctl.cp0write}; 23 | 24 | // signalretire signalretire [1: 0] (in[1], rfout, hiloout, cp0out); 25 | 26 | assign rfw[1].addr = in[1].destreg; 27 | assign rfw[1].wd = in[1].result; 28 | assign rfw[1].wen = in[1].instr.ctl.regwrite; 29 | assign rfw[0].addr = in[0].destreg; 30 | assign rfw[0].wd = in[0].result; 31 | assign rfw[0].wen = in[0].instr.ctl.regwrite; 32 | 33 | assign hlw.wen_h = in[1].instr.ctl.hiwrite | in[0].instr.ctl.hiwrite; 34 | assign hlw.wen_l = in[1].instr.ctl.lowrite | in[0].instr.ctl.lowrite; 35 | assign hlw.wd_h = (in[0].instr.ctl.hiwrite) ? (in[0].hiresult) : (in[1].hiresult); 36 | assign hlw.wd_l = (in[0].instr.ctl.lowrite) ? (in[0].loresult) : (in[1].loresult); 37 | 38 | assign cp0w[1].addr = in[1].cp0_addr; 39 | assign cp0w[1].wd = in[1].result; 40 | assign cp0w[1].wen = in[1].instr.ctl.cp0write; 41 | assign cp0w[0].addr = in[0].cp0_addr; 42 | assign cp0w[0].wd = in[0].result; 43 | assign cp0w[0].wen = in[0].instr.ctl.cp0write; 44 | 45 | assign rt_pc[1] = in[1].pcplus4 - 32'd4; 46 | assign rt_pc[0] = in[0].pcplus4 - 32'd4; 47 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/signalcommit.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module signalcommit ( 4 | input exec_data_t dataE, 5 | output exec_data_t dataM, 6 | output m_q_t mem 7 | // output bypass_t forward, 8 | // output exception_set_t exception, 9 | // output dmem_t dram_req, 10 | // input word_t readdata, 11 | // output cp0_commit_t cp0, 12 | // output logic is_eret 13 | ); 14 | 15 | logic wen, ren; 16 | word_t aluoutM, writedataM; 17 | decoded_op_t op; 18 | assign op = dataE.instr.op; 19 | assign aluoutM = dataE.result; 20 | assign ren = {4{dataE.instr.ctl.memtoreg}}; 21 | 22 | writedata_format writedata_format(.addr(aluoutM[1:0]), .op(op), ._wd(dataE.writedata), .en(wen), .wd(writedataM)); 23 | 24 | assign dataM = dataE; 25 | assign mem.ren = ren; 26 | assign mem.addr = aluoutM; 27 | assign mem.wen = wen; 28 | assign mem.addr = aluoutM; 29 | assign mem.wd = writedataM; 30 | assign mem.wt = dataE.instr.clt.memwrite; 31 | 32 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/signaldecode.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module signaldecode ( 4 | input fetch_data_t dataF, 5 | output decode_data_t dataD 6 | //input cp0_status_t cp0_status, 7 | //input cp0_status_t cp0_cause 8 | ); 9 | op_t op; 10 | func_t func; 11 | halfword_t imm; 12 | logic ext; 13 | word_t pcbranch, pcjump; 14 | word_t hi, lo; 15 | word_t aluoutM, resultW; 16 | logic is_reserved; 17 | creg_addr_t rs, rt, rd; 18 | assign op = dataF.instr_[31:26]; 19 | assign func = dataF.instr_[5:0]; 20 | assign imm = dataF.instr_[15:0]; 21 | assign rs = dataF.instr_[25:21]; 22 | assign rt = dataF.instr_[20:16]; 23 | assign rd = dataF.instr_[15:11]; 24 | // assign dataD.instr.rs = dataF.instr_[25:21]; 25 | // assign dataD.instr.rt = dataF.instr_[20:16]; 26 | // assign dataD.instr.rd = dataF.instr_[15:11]; 27 | 28 | maindecode maindecode(dataF.instr_, 29 | rs, rt, rd, 30 | dataD.instr.op, dataD.exception_ri, 31 | dataD.instr.ctl, 32 | dataD.srcrega, dataD.srcregb, dataD.destreg); 33 | assign dataD.cp0_addr = rd; 34 | 35 | assign dataD.instr.shamt = dataF.instr_[10:6]; 36 | assign is_reserved = (dataD.instr.op == RESERVED); 37 | 38 | word_t ext_imm; 39 | extend ext1(imm, dataD.instr.ctl.zeroext, ext_imm); 40 | assign pcbranch = dataF.pcplus4 + {dataD.instr.extended_imm[29:0], 2'b00}; 41 | assign pcjump = {dataF.pcplus4[31:28], dataF.instr_[25:0], 2'b00}; 42 | assign dataD.instr.pcbranch = pcbranch; 43 | assign dataD.instr.extended_imm = ext_imm; 44 | assign dataD.instr.pcjump = pcjump; 45 | 46 | assign dataD.pcplus4 = dataF.pcplus4; 47 | assign dataD.exception_instr = dataF.exception_instr; 48 | /* 49 | srcadmux srcadmux(.regfile(regfile.src1),.m(hazard.aluoutM),.w(hazard.resultW),.alusrcaE(hazard.alusrcaE), 50 | .forward(hazard.forwardAD), .ctl(dataD.instr.ctl), 51 | .hiD(hilo.hi), .loD(hilo.lo), .cp0D(cp0.rd), 52 | .srca(dataD.srca)); 53 | srcbdmux srcbdmux(.regfile(regfile.src2),.m(hazard.aluoutM),.w(hazard.resultW),.alusrcaE(hazard.alusrcaE), 54 | .forward(hazard.forwardBD), .srcb(dataD.srcb)); 55 | */ 56 | 57 | assign dataD.in_delay_slot = 1'b0; //dataF.in_delay_slot; 58 | // assign dataD.en = dataF.en; 59 | // ports 60 | 61 | //assign dataD.cp0_cause = cp0_cause; 62 | //assign dataD.cp0_status = cp0_status; 63 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/top/readdata_format.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module readdata_format ( 4 | input word_t _rd, 5 | output word_t rd, 6 | input logic[1:0] addr, 7 | input decoded_op_t op 8 | ); 9 | always_comb begin 10 | case (op) 11 | LB: begin 12 | case (addr) 13 | 2'b00: rd = {{24{_rd[7]}}, _rd[7:0]}; 14 | 2'b01: rd = {{24{_rd[15]}}, _rd[15:8]}; 15 | 2'b10: rd = {{24{_rd[23]}}, _rd[23:16]}; 16 | 2'b11: rd = {{24{_rd[31]}}, _rd[31:24]}; 17 | default: rd = _rd; 18 | endcase 19 | end 20 | LBU: begin 21 | case (addr) 22 | 2'b00: rd = {24'b0, _rd[7:0]}; 23 | 2'b01: rd = {24'b0, _rd[15:8]}; 24 | 2'b10: rd = {24'b0, _rd[23:16]}; 25 | 2'b11: rd = {24'b0, _rd[31:24]}; 26 | default: rd = _rd; 27 | endcase 28 | end 29 | LH: begin 30 | case (addr[1]) 31 | 1'b0: rd = {{16{_rd[15]}}, _rd[15:0]}; 32 | 1'b1: rd = {{16{_rd[31]}}, _rd[31:16]}; 33 | default: begin 34 | rd = _rd; 35 | end 36 | endcase 37 | end 38 | LHU: begin 39 | case (addr[1]) 40 | 1'b0: rd = {16'b0, _rd[15:0]}; 41 | 1'b1: rd = {16'b0, _rd[31:16]}; 42 | default: begin 43 | rd = _rd; 44 | end 45 | endcase 46 | end 47 | default: begin 48 | rd = _rd; 49 | end 50 | endcase 51 | end 52 | endmodule -------------------------------------------------------------------------------- /superscalar_inorder_signal/writedata_format.sv: -------------------------------------------------------------------------------- 1 | `include "mips.svh" 2 | 3 | module writedata_format ( 4 | input exec_data_t in, 5 | output m_q_t out 6 | ); 7 | 8 | op_t op; 9 | assign op = in.instr.op; 10 | logic [1: 0] dmem_size_w, dmem_size_r; 11 | assign dmem_size_w = (op == SW) ? 2'b10 : (op == SH ? 2'b01:2'b00); 12 | assign dmem_size_r = (op == LW) ? 2'b10 : (op == LH ? 2'b01:2'b00); 13 | 14 | logic ren, wen; 15 | assign ren = in.instr.ctl.memtoreg; 16 | assign out.size = (wen) ? (dmem_size_w) : (dmem_size_r); 17 | assign out.en = wen | ren; 18 | assign out.addr = in.result; 19 | 20 | logic [1: 0] addr; 21 | assign addr = out.addr[1: 0]; 22 | word_t _wd, wd; 23 | assign _wd = in.srcb; 24 | assign out.wd = wd; 25 | assign out.wt = in.instr.ctl.memwrite; 26 | 27 | always_comb begin 28 | case (op) 29 | SW : begin 30 | wen = 1'b1; 31 | wd = _wd; 32 | end 33 | SH: begin 34 | case (addr[1]) 35 | 1'b0: begin 36 | wen = 1'b1; 37 | wd = _wd; 38 | end 39 | 1'b1: begin 40 | wen = 1'b1; 41 | wd = {_wd[15:0], 16'b0}; 42 | end 43 | default: begin 44 | wen = 'b0; 45 | wd = '0; 46 | end 47 | endcase 48 | end 49 | SB: begin 50 | case (addr) 51 | 2'b00: begin 52 | wen = 1'b1; 53 | wd = _wd; 54 | end 55 | 2'b01: begin 56 | wen = 1'b1; 57 | wd = {_wd[23:0], 8'b0}; 58 | end 59 | 2'b10: begin 60 | wen = 1'b1; 61 | wd = {_wd[15:0], 16'b0}; 62 | end 63 | 2'b11: begin 64 | wen = 1'b1; 65 | wd = {_wd[7:0], 24'b0}; 66 | end 67 | default: begin 68 | wen = 'b0; 69 | wd = '0; 70 | end 71 | endcase 72 | end 73 | default: begin 74 | wen = '0; 75 | wd = '0; 76 | end 77 | endcase 78 | end 79 | endmodule 80 | --------------------------------------------------------------------------------