Skip to content

Commit

Permalink
!!!TEMP!!! Improve Stage D testbench and fix bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
JZJisawesome committed Mar 28, 2024
1 parent 42ebc22 commit 65da0bd
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 50 deletions.
43 changes: 21 additions & 22 deletions rtl/letc/core/letc_core_stage_d.sv
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ always_comb begin
ctrl.rd_src = RD_SRC_ALU;
ctrl.rd_we = 1'b1;
ctrl.alu_op1_src = ALU_OP1_SRC_PC;
ctrl.alu_op2_src = ALU_OP2_SRC_IMM;
ctrl.alu_op2_src = ALU_OP2_SRC_FOUR;
ctrl.alu_op = ALU_OP_ADD;
ctrl.branch = BRANCH_JAL;
end
Expand Down Expand Up @@ -357,11 +357,10 @@ always_comb begin
rs2_rdata = i_bypass_rs2 ? i_bypass_rs2_rdata : i_rs2_rdata;
end

//FIXME should we be doing i_f2_to_d.valid & !i_stage_stall & !i_stage_flush?
word_t csr_rdata;
always_comb begin
//Assumes no read side effects since we don't handle flushing...
o_csr_explicit_ren = i_f2_to_d.valid & ~i_stage_stall & (ctrl.csr_op == CSR_OP_ACCESS);
o_csr_explicit_ren = i_f2_to_d.valid & !i_stage_stall & !i_stage_flush & (ctrl.csr_op == CSR_OP_ACCESS);
o_csr_explicit_ridx = csr_idx;
csr_rdata = i_csr_explicit_rdata;
//i_csr_explicit_rill//TODO actually cause exception on illegal CSR read (very low priority)
Expand Down Expand Up @@ -389,26 +388,26 @@ always_comb begin
end

always_comb begin
//FIXME should we be doing i_f2_to_d.valid & !i_stage_stall & !i_stage_flush?
//TODO catch misaligned branches
unique0 case (ctrl.branch)
BRANCH_COND: begin
o_branch_taken = i_f2_to_d.valid & branch_cmp_result;
o_branch_target = i_f2_to_d.pc_word + imm_b[31:2];
end
BRANCH_JALR: begin
o_branch_taken = i_f2_to_d.valid;
o_branch_target = jalr_branch_target[31:2];
end
BRANCH_JAL: begin
o_branch_taken = i_f2_to_d.valid;
o_branch_target = i_f2_to_d.pc_word + imm_j[31:2];
end
default: begin
o_branch_taken = 1'b0;
o_branch_target = 30'hDEADBEE;
end
endcase
o_branch_taken = 1'b0;
o_branch_target = 30'hDEADBEE;

if (i_f2_to_d.valid & !i_stage_stall & !i_stage_flush) begin//TODO is this the correct criteria for this if?
unique0 case (ctrl.branch)
BRANCH_COND: begin
o_branch_taken = i_f2_to_d.valid & branch_cmp_result;
o_branch_target = i_f2_to_d.pc_word + imm_b[31:2];
end
BRANCH_JALR: begin
o_branch_taken = i_f2_to_d.valid;
o_branch_target = jalr_branch_target[31:2];
end
BRANCH_JAL: begin
o_branch_taken = i_f2_to_d.valid;
o_branch_target = i_f2_to_d.pc_word + imm_j[31:2];
end
endcase
end
end

/* ------------------------------------------------------------------------------------------------
Expand Down
163 changes: 135 additions & 28 deletions verif/nonuvm/letc/core/stage_d/letc_core_stage_d_tb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,6 @@ endclocking
* --------------------------------------------------------------------------------------------- */

initial begin
`ifndef VERILATOR
//Something is causing problems in Verilator, but works fine in xsim
//(signals barely change and the dumped FST is corrupt due to enums; VCDs are fineish)

//Setup
cb.i_stage_flush <= 1'b0;
cb.i_stage_stall <= 1'b0;
Expand All @@ -161,75 +157,186 @@ initial begin
cb.i_rst_n <= 1'b1;
##2;

/////////////////////////////////////////
//Testing valid timing
/////////////////////////////////////////

cb.i_f2_to_d.valid <= 1'b1;
##1;//One cycle for clocking block
assert(!cb.o_d_to_e1.valid);//Too soon
##1;//One cycle for the decode stage
assert(cb.o_d_to_e1.valid);

cb.i_f2_to_d.valid <= 1'b0;
##1;//One cycle for clocking block
assert(cb.o_d_to_e1.valid);//Too soon
##1;//One cycle for the decode stage
assert(!cb.o_d_to_e1.valid);

cb.i_f2_to_d.valid <= 1'b1;//Remaining tests can assume this
##1;

`ifndef VERILATOR
//Something is causing problems in Verilator, but works fine in xsim
//(signals barely change and the dumped FST is corrupt due to enums; VCDs are fineish)


/////////////////////////////////////////
//Testing other timing
/////////////////////////////////////////

//TODO test the timing of other combinational vs sequential logic

/////////////////////////////////////////
//Testing immediate generation
/////////////////////////////////////////

//I type instructions
cb.i_f2_to_d.valid <= 1'b1;
cb.i_f2_to_d.instr <= 30'(32'h1684a783 >> 2);//lw a5, 360(s1)
##2;//Once cycle for clocking block, one for the decode stage
##2;//One cycle for clocking block, one for the decode stage
assert(cb.o_d_to_e1.immediate == 32'd360);
cb.i_f2_to_d.valid <= 1'b1;
cb.i_f2_to_d.instr <= 30'(32'hf854a783 >> 2);//addi t0, gp, -123
##2;//Once cycle for clocking block, one for the decode stage
##2;
assert(cb.o_d_to_e1.immediate == 32'hffffff85);

//S type instructions
cb.i_f2_to_d.valid <= 1'b1;
cb.i_f2_to_d.instr <= 30'(32'h00112623 >> 2);//sw ra, 12(sp)
##2;//Once cycle for clocking block, one for the decode stage
##2;
assert(cb.o_d_to_e1.immediate == 32'd12);
cb.i_f2_to_d.valid <= 1'b1;
cb.i_f2_to_d.instr <= 30'(32'he248ac23 >> 2);//sw tp, -456(a7)
##2;//Once cycle for clocking block, one for the decode stage
##2;
assert(cb.o_d_to_e1.immediate == 32'hfffffe38);

//B type instructions
cb.i_f2_to_d.valid <= 1'b1;
cb.i_f2_to_d.instr <= 30'(32'h00078a63 >> 2);//beqz a5, offset 0x14
//Branches are handled in decode, so it's no longer guaranteed the output immediate will be correct
//##2;//Once cycle for clocking block, one for the decode stage
//##2;//One cycle for clocking block, one for the decode stage
//assert(cb.o_d_to_e1.immediate == 32'h00000014);
##1;//Once cycle for clocking block
##1;//One cycle for clocking block
assert(dut.imm_b == 32'h00000014);
cb.i_f2_to_d.valid <= 1'b1;
cb.i_f2_to_d.instr <= 30'(32'hfc20e6e3 >> 2);//bltu x1, x2, offset -0x34
##1;//Once cycle for clocking block
##1;//One cycle for clocking block
assert(dut.imm_b == 32'hffffffcc);

//U type instructions
cb.i_f2_to_d.valid <= 1'b1;
cb.i_f2_to_d.instr <= 30'(32'h000067b7 >> 2);//lui a5, 0x6
##2;//Once cycle for clocking block, one for the decode stage
##2;
assert(cb.o_d_to_e1.immediate == 32'h00006000);
cb.i_f2_to_d.valid <= 1'b1;
cb.i_f2_to_d.instr <= 30'(32'habcd1117 >> 2);//auipc sp, 0xabcd1
##2;//Once cycle for clocking block, one for the decode stage
##2;
assert(cb.o_d_to_e1.immediate == 32'habcd1000);

//J type instructions
cb.i_f2_to_d.valid <= 1'b1;
cb.i_f2_to_d.instr <= 30'(32'hfd9fc0ef >> 2);//jal offset -0x3028
//Branches are handled in decode, so it's no longer guaranteed the output immediate will be correct
//##2;//Once cycle for clocking block, one for the decode stage
//##2;//One cycle for clocking block, one for the decode stage
//assert(cb.o_d_to_e1.immediate == 32'hffffcfd8);
##1;//Once cycle for clocking block
##1;
assert(dut.imm_j == 32'hffffcfd8);
cb.i_f2_to_d.valid <= 1'b1;
cb.i_f2_to_d.instr <= 30'(32'h0040006f >> 2);//jal offset +4
##1;//Once cycle for clocking block
##1;
assert(dut.imm_j == 32'h4);

//CSR micro immediates and index
cb.i_f2_to_d.valid <= 1'b1;
cb.i_f2_to_d.instr <= 30'(32'h34417073 >> 2);//csrci mip, 2
##2;//Once cycle for clocking block, one for the decode stage
##2;
assert(cb.o_d_to_e1.immediate == 32'h00000002);
assert(cb.o_d_to_e1.csr_idx == 32'h00000344);//mip

//TODO other decode tests

/////////////////////////////////////////
//Testing alu/alu op mux ctrl signals
/////////////////////////////////////////

//ALU_OP_ADD, pc, imm
cb.i_f2_to_d.instr <= 30'(32'h0007b197 >> 2);//auipc x3, 123
##2;
assert(cb.o_d_to_e1.alu_op == ALU_OP_ADD);
assert(cb.o_d_to_e1.alu_op1_src == ALU_OP1_SRC_PC);
assert(cb.o_d_to_e1.alu_op2_src == ALU_OP2_SRC_IMM);

//ALU_OP_ADD, 0, imm
cb.i_f2_to_d.instr <= 30'(32'h0cafe2b7 >> 2);//lui t0, 0xcafe
##2;
assert(cb.o_d_to_e1.alu_op == ALU_OP_ADD);
assert(cb.o_d_to_e1.alu_op1_src == ALU_OP1_SRC_ZERO);
assert(cb.o_d_to_e1.alu_op2_src == ALU_OP2_SRC_IMM);

//ALU_OP_ADD, pc, 4
cb.i_f2_to_d.instr <= 30'(32'hfd9fc0ef >> 2);//jal offset -0x3028
##2;
assert(cb.o_d_to_e1.alu_op == ALU_OP_ADD);
assert(cb.o_d_to_e1.alu_op1_src == ALU_OP1_SRC_PC);
assert(cb.o_d_to_e1.alu_op2_src == ALU_OP2_SRC_FOUR);

//ALU_OP_ADD, 0, rs1
cb.i_f2_to_d.instr <= 30'(32'h30401073 >> 2);//csrw mie, zero
##2;
assert(cb.o_d_to_e1.alu_op == ALU_OP_ADD);
assert(cb.o_d_to_e1.alu_op1_src == ALU_OP1_SRC_ZERO);
assert(cb.o_d_to_e1.alu_op2_src == ALU_OP2_SRC_RS1);

//ALU_OP_SUB, rs1, rs2
cb.i_f2_to_d.instr <= 30'(32'h40208033 >> 2);//sub x0, x1, x2
##2;
assert(cb.o_d_to_e1.alu_op == ALU_OP_SUB);
assert(cb.o_d_to_e1.alu_op1_src == ALU_OP1_SRC_RS1);
assert(cb.o_d_to_e1.alu_op2_src == ALU_OP2_SRC_RS2);

//TODO more

//ALU_OP_OR, csr, imm
cb.i_f2_to_d.instr <= 30'(32'h300ae6f3 >> 2);//csrrsi x13, mstatus, 0b10101
##2;
assert(cb.o_d_to_e1.alu_op == ALU_OP_OR);
assert(cb.o_d_to_e1.alu_op1_src == ALU_OP1_SRC_CSR);
assert(cb.o_d_to_e1.alu_op1_src == ALU_OP2_SRC_IMM);

//ALU_OP_AND, rs1, imm
cb.i_f2_to_d.instr <= 30'(32'hedc0f093 >> 2);//andi x1, x1, ~0x123
##2;
assert(cb.o_d_to_e1.alu_op == ALU_OP_AND);
assert(cb.o_d_to_e1.alu_op1_src == ALU_OP1_SRC_RS1);
assert(cb.o_d_to_e1.alu_op2_src == ALU_OP2_SRC_IMM);

//ALU_OP_MCLR, csr, rs1
cb.i_f2_to_d.instr <= 30'(32'h301fba73 >> 2);//csrrc x20, misa, x31
##2;
assert(cb.o_d_to_e1.alu_op == ALU_OP_MCLR);
assert(cb.o_d_to_e1.alu_op1_src == ALU_OP1_SRC_CSR);
assert(cb.o_d_to_e1.alu_op2_src == ALU_OP2_SRC_RS1);

/////////////////////////////////////////
//Testing rf access and bypassing
/////////////////////////////////////////

//TODO

/////////////////////////////////////////
//Testing CSR reads and ctrl signals
/////////////////////////////////////////

//TODO

/////////////////////////////////////////
//Testing branching
/////////////////////////////////////////

//TODO

/////////////////////////////////////////
//Testing cache management signals
/////////////////////////////////////////

//TODO

/////////////////////////////////////////
//Testing exceptions
/////////////////////////////////////////

//TODO

`endif //VERILATOR

##10;
Expand Down

0 comments on commit 65da0bd

Please sign in to comment.