diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | src/rv2insn.sv | 12 | ||||
-rw-r--r-- | src/ttarv32.sv | 102 | ||||
-rw-r--r-- | tb/Makefile | 10 | ||||
-rw-r--r-- | tb/ttarv32_tb.sv | 45 |
5 files changed, 164 insertions, 8 deletions
@@ -1,4 +1,5 @@ tb/rv2insn -tb/rv2insn.hex +tb/ttarv32 tb/*.vcd +tb/*.hex tb/*objdir diff --git a/src/rv2insn.sv b/src/rv2insn.sv index 1d9996c..8717d0f 100644 --- a/src/rv2insn.sv +++ b/src/rv2insn.sv @@ -33,8 +33,8 @@ endfunction function automatic decode_out_t op_imm(xlen_t pc, itype_t rv, alu_counter_t alu_counter); alu_counter_t fu = next_alu(alu_counter); unique case (rv.funct3) - 3'b000: return {{NOP, NOP}, - {`rn(rv.rs1), `alu(fu)}, + 3'b000: return {{`rn(rv.rs1), `alu(fu)}, + {NOP, NOP}, {`alu(fu), `rn(rv.rd)}, ALU_ADDI, imm_t'(signed'(rv.imm)), fu}; @@ -50,13 +50,13 @@ function automatic decode_out_t op(xlen_t pc, rtype_t rv, alu_counter_t alu_coun 3'b000: begin unique case (rv.funct7) 7'b0000000: - return {{`rn(rv.rs1), `alu(fu)}, - {`rn(rv.rs2), `alu(fu)}, + return {{`rn(rv.rs2), `alu(fu)}, + {`rn(rv.rs1), `alu(fu)}, {`alu(fu), `rn(rv.rd)}, ALU_ADD, imm_t'(0), fu}; 7'b0100000: - return {{`rn(rv.rs1), `alu(fu)}, - {`rn(rv.rs2), `alu(fu)}, + return {{`rn(rv.rs2), `alu(fu)}, + {`rn(rv.rs1), `alu(fu)}, {`alu(fu), `rn(rv.rd)}, ALU_SUB, imm_t'(0), fu}; diff --git a/src/ttarv32.sv b/src/ttarv32.sv new file mode 100644 index 0000000..0edf1cb --- /dev/null +++ b/src/ttarv32.sv @@ -0,0 +1,102 @@ +`include "common.svh" + +module ttarv32 #( + parameter SLOT_COUNT, + parameter SLOT_DEPTH, + parameter ALU_COUNT +)( + input clk_i, + input rst_ni, + input rv_t[SLOT_COUNT-1:0] rv_i, + output xlen_t pc_o +); + +typedef struct packed { + mov_t[1:0] in; + mov_t[SLOT_DEPTH-1:0] out; + op_t op; + imm_t imm; +} slot_t; + +insn_t[SLOT_COUNT-1:0] rv_que; + +insn_t[SLOT_COUNT-1:0] prev_que_r; +insn_t[SLOT_COUNT-1:0] next_que; + +slot_t[SLOT_COUNT-1:0] prev_slots_r; +slot_t[SLOT_COUNT-1:0] next_slots; + +xlen_t pc_r; + +rv2insn #( + .QUE_DEPTH(SLOT_COUNT), + .ALU_COUNT(ALU_COUNT) +) rv2insn ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .pc_i(pc_r), + .rv_i(rv_i), + .que_o(rv_que) +); + +typedef struct packed { + insn_t[SLOT_COUNT-1:0] que; + xlen_t pc; +} merge_t; + +/* repetition from sched.sv, hmm */ +function automatic insn_t[SLOT_COUNT-1:0] next_insn(insn_t[SLOT_COUNT-1:0] que); + return que >> $bits(insn_t); +endfunction + +function automatic logic is_noop(mov_t m); + return m.src == NOP && m.dst == NOP; +endfunction + +/* not the best thing in the world but good enough for now */ +function automatic logic is_free(insn_t i); + return is_noop(i.in[0]) & is_noop(i.in[1]) & is_noop(i.out); +endfunction + +function automatic merge_t merge(int i, + insn_t[SLOT_COUNT-1:0] prev_que, insn_t[SLOT_COUNT-1:0] next_que, xlen_t pc); + if (i < SLOT_COUNT) begin + logic ok = is_free(prev_que[i]); + prev_que[i] = ok ? next_que[0] : prev_que[i]; + return merge(i + 1, + prev_que, + ok ? next_insn(next_que) : next_que, + ok ? pc + 1 : pc); + end else begin + return {prev_que, pc}; + end +endfunction + +merge_t merged; +assign merged = merge(0, prev_que_r, rv_que, pc_r); + +sched #( + .QUE_DEPTH(SLOT_COUNT), + .SLOT_COUNT(SLOT_COUNT), + .SLOT_DEPTH(SLOT_DEPTH), + .slot_t(slot_t) +) sched ( + .que_i(merged.que), + .que_o(next_que), + .slots_i(prev_slots_r), + .slots_o(next_slots) +); + +always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + prev_slots_r <= 0; + prev_que_r <= 0; + pc_r <= 0; + end else begin + prev_slots_r <= next_slots; + prev_que_r <= next_que; + pc_r <= merged.pc; + end +end + +endmodule diff --git a/tb/Makefile b/tb/Makefile index a76747f..f34cb5e 100644 --- a/tb/Makefile +++ b/tb/Makefile @@ -1,4 +1,4 @@ -all: rv2insn sched +all: rv2insn sched ttarv32 .PHONY: sched sched: sched_tb.sv ../src/sched.sv ../src/common.svh @@ -12,3 +12,11 @@ rv2insn: rv2insn_tb.sv ../src/rv2insn.sv ../src/common.svh riscv32-unknown-elf-objcopy -O verilog rv2insn rv2insn.hex verilator --Mdir rv2insn_objdir --assert --trace --binary -I../src rv2insn_tb.sv ./rv2insn_objdir/Vrv2insn_tb + +.PHONY: ttarv32 +ttarv32: ttarv32_tb.sv ../src/ttarv32.sv ../src/rv2insn.sv ../src/sched.sv ../src/common.svh + riscv32-unknown-elf-gcc -ffreestanding -nostdlib -march=rv32i -mabi=ilp32 \ + -Wl,-Ttext=0 data/rv2insn.S -o ttarv32 + riscv32-unknown-elf-objcopy -O verilog rv2insn ttarv32.hex + verilator --Mdir ttarv32_objdir --assert --trace --binary -I../src ttarv32_tb.sv + ./ttarv32_objdir/Vttarv32_tb diff --git a/tb/ttarv32_tb.sv b/tb/ttarv32_tb.sv new file mode 100644 index 0000000..6277f02 --- /dev/null +++ b/tb/ttarv32_tb.sv @@ -0,0 +1,45 @@ +`include "common.svh" + +module ttarv32_tb; + +function automatic rv_t[3:0] unp2p(logic[7:0] in[4*4]); + logic [15:0][7:0] conversion; + for (int i = 0; i < 4 * 4; ++i) begin + conversion[i] = in[i]; + end + return conversion; +endfunction + +xlen_t pc; +logic[7:0] rv[4*4]; + +logic clk; +logic rst_n; + +ttarv32 #( + .SLOT_COUNT(4), + .SLOT_DEPTH(3), + .ALU_COUNT(2) +) ttarv32 ( + .clk_i(clk), + .rst_ni(rst_n), + .rv_i(unp2p(rv)), + .pc_o(pc) +); + +initial begin + $dumpfile("ttarv32_tb.vcd"); + $dumpvars(); + $readmemh("ttarv32.hex", rv); + + clk = 0; + rst_n = 0; + + #10 rst_n = 1; + clk = 1; + + #10 + $finish; +end + +endmodule |