From 1290418aa35a0db2f804ca8e68f33c1c4c23f262 Mon Sep 17 00:00:00 2001 From: Brendan Haines Date: Fri, 6 Nov 2020 23:18:37 -0700 Subject: [PATCH] properly flushes pipeline after jump --- hdl/core.v | 136 ++++++++++++++++++++++++++++------------------- hdl/tb/core_tb.v | 6 ++- sim/core_tb.wcfg | 72 +++++++++++-------------- test/test.S | 9 +++- 4 files changed, 126 insertions(+), 97 deletions(-) diff --git a/hdl/core.v b/hdl/core.v index 510bab4..7ffaf0d 100644 --- a/hdl/core.v +++ b/hdl/core.v @@ -64,6 +64,10 @@ module core( output dummy_out ); +parameter PIPELINED = 1; + +localparam INST_NOP = 32'h00000013; // nop + // Register File reg [31:0] regfile [0:31]; initial begin : init_regfile @@ -75,10 +79,8 @@ end // Registers reg [31:0] r_if_pc = 0, r_id_pc, r_ex_pc, r_mem_pc, r_wb_pc; -reg r_id_stall, r_ex_stall, r_mem_stall, r_wb_stall; reg [31:0] r_id_inst, r_ex_inst, r_mem_inst, r_wb_inst; reg [4:0] r_ex_rd, r_mem_rd, r_wb_rd; -reg r_ex_alu_seed; reg [3:0] r_ex_aluop; reg [31:0] r_ex_s1, r_ex_s2, r_mem_s1, r_mem_s2; reg [31:0] r_mem_alu_out, r_wb_alu_out; @@ -86,22 +88,23 @@ reg r_mem_alu_zero; reg r_ex_jump; reg r_ex_store, r_mem_store; reg r_ex_load, r_mem_load; +reg [31:0] r_mem_wdata, r_wb_wdata; +reg r_id_valid=0, r_ex_valid=0, r_mem_valid=0, r_wb_valid=0; // IF -reg s_if_halt; +reg s_if_stall = 0; reg [31:0] s_if_next_pc; reg [31:0] s_if_inst; -reg s_if_stall; always @(*) begin - s_if_halt = 0; + s_if_stall = s_id_stall || 0; - if (r_ex_jump) begin + if (r_ex_jump && r_ex_valid) begin s_if_next_pc = s_ex_alu_out; - s_if_stall = 1'b1; + // s_if_stall = 1'b1; end else begin s_if_next_pc = r_if_pc + 4; - s_if_stall = 1'b0; + // s_if_stall = 1'b0; end mem_inst_addr = r_if_pc; @@ -109,7 +112,7 @@ always @(*) begin end // ID -reg s_id_halt; +reg s_id_stall; reg [6:0] s_id_opcode; reg [2:0] s_id_funct3; reg [6:0] s_id_funct7; @@ -117,7 +120,6 @@ reg [4:0] s_id_rd, s_id_rs1, s_id_rs2; reg [31:0] s_id_immed_itype, s_id_immed_stype, s_id_immed_utype, s_id_immed_btype, s_id_immed_jtype; reg [31:0] s_id_s1, s_id_s2; reg [3:0] s_id_aluop; -reg s_id_alu_seed; reg s_id_invalid; reg s_id_jump, s_id_branch; reg s_id_store, s_id_load; @@ -154,7 +156,7 @@ localparam ALUOP_ADD = 4'b0000, always @(*) begin - s_id_halt = 0; + s_id_stall = s_ex_stall || 0; s_id_invalid = 0; s_id_store = 0; s_id_load = 0; @@ -272,21 +274,20 @@ always @(*) begin if (s_id_invalid) begin $display("%0t:\tInvalid instruction at PC=0x%h", $time, r_id_pc); - s_id_halt = 1'b1; s_id_aluop = 3'hx; - s_id_alu_seed = 1'bx; end end // EX -reg s_ex_halt; +reg s_ex_stall; reg [31:0] s_ex_data1, s_ex_data2; reg [31:0] s_ex_alu_out; reg s_ex_alu_zero; reg [31:0] s_ex_ra; +reg [31:0] s_ex_wdata; always @(*) begin - s_ex_halt = 0; + s_ex_stall = s_mem_stall || 0; // NOTE: s_ex_data* exist for adding data paths bypassing regfile in the future s_ex_data1 = r_ex_s1; @@ -324,21 +325,25 @@ always @(*) begin s_ex_alu_out = s_ex_data1 < s_ex_data2; end default: begin - s_ex_halt = 1; s_ex_alu_out = 32'hxxxxxxxx; end endcase s_ex_alu_zero = (s_ex_alu_out == 0); s_ex_ra = r_ex_pc + 4; + if (r_ex_jump) begin + s_ex_wdata = s_ex_ra; + end else begin + s_ex_wdata = s_ex_alu_out; + end end // MEM -reg s_mem_halt; +reg s_mem_stall; reg s_mem_bp; always @(*) begin - s_mem_halt = 0; + s_mem_stall = s_wb_stall || 0; s_mem_bp = 0; // if (r_mem_store) begin @@ -357,74 +362,93 @@ always @(*) begin end // WB -reg s_wb_halt; +reg s_wb_stall; reg [31:0] s_wb_data; reg s_wb_write; always @(*) begin - s_wb_halt = 0; + s_wb_stall = 1'b0; // load instructions do not use output of alu in wb - s_wb_data = r_wb_alu_out; + s_wb_data = r_wb_wdata; // FIXME: always writes!!! - s_wb_write = !r_wb_stall; + s_wb_write = 1; //!s_wb_stall; end // SYS -reg s_sys_halt; - -always @(*) begin - s_sys_halt = s_if_halt || s_id_halt || s_ex_halt || s_mem_halt || s_wb_halt; -end // Register update -always @(posedge clk) begin +always @(posedge clk) begin: pipeline_update + integer i; if (reset) begin r_if_pc <= 32'h00000000; - // rather than resetting all flip-flops just stall the pipeline so values are ignored. - r_id_stall <= 1; - r_ex_stall <= 1; - r_mem_stall <= 1; - r_wb_stall <= 1; + + r_id_pc <= 0; + r_id_inst <= INST_NOP; + + r_ex_pc <= 0; + r_ex_inst <= INST_NOP; + r_ex_rd <= 0; + r_ex_s1 <= 0; + r_ex_s2 <= 0; + r_ex_aluop <= 0; + r_ex_jump <= 0; + r_ex_store <= 0; + r_ex_load <= 0; + + r_mem_pc <= 0; + r_mem_inst <= INST_NOP; + r_mem_rd <= 0; + r_mem_s1 <= 0; + r_mem_s2 <= 0; + r_mem_alu_out <= 0; + r_mem_alu_zero <= 0; + r_mem_store <= 0; + r_mem_load <= 0; + r_mem_wdata <= 0; + + r_wb_pc <= 0; + r_wb_inst <= INST_NOP; + r_wb_rd <= 0; + r_wb_alu_out <= 0; + r_wb_wdata <= 0; + + for (i=1; i<32; i=i+1) begin + regfile[i] <= 0; + end end else begin - // NOTE: halt disabled because startup causes hault - // if (s_sys_halt && 0) begin - // // stay halted forever - // end else begin // IF - // if (!s_mem_bp) begin + if (!s_if_stall) begin r_if_pc <= s_if_next_pc; - // end + end // ID - // if (!s_mem_bp) begin - r_id_stall <= s_if_stall; + if (!s_id_stall) begin r_id_pc <= r_if_pc; r_id_inst <= s_if_inst; - // end + r_id_valid <= ~(r_ex_jump && r_ex_valid); + end // EX - // if (!s_mem_bp) begin + if (!s_ex_stall) begin // TODO: also stall EX if taking branch - r_ex_stall <= r_id_stall; r_ex_pc <= r_id_pc; r_ex_inst <= r_id_inst; r_ex_rd <= s_id_rd; r_ex_s1 <= s_id_s1; r_ex_s2 <= s_id_s2; r_ex_aluop <= s_id_aluop; - r_ex_alu_seed <= s_id_alu_seed; r_ex_jump <= s_id_jump; r_ex_store <= s_id_store; r_ex_load <= s_id_load; - // end + r_ex_valid <= r_id_valid && ~(r_ex_jump && r_ex_valid); + end // MEM - // if (!s_mem_bp) begin - r_mem_stall <= r_ex_stall; + if (!s_mem_stall) begin r_mem_pc <= r_ex_pc; r_mem_inst <= r_ex_inst; r_mem_rd <= r_ex_rd; @@ -434,21 +458,25 @@ always @(posedge clk) begin r_mem_alu_zero <= s_ex_alu_zero; r_mem_store <= r_ex_store; r_mem_load <= r_ex_load; - // end + r_mem_wdata <= s_ex_wdata; + r_mem_valid <= r_ex_valid; + end // WB - // if (!s_mem_bp) begin - r_wb_stall <= r_mem_stall; + if (!s_wb_stall) begin r_wb_pc <= r_mem_pc; + r_wb_inst <= r_mem_inst; r_wb_rd <= r_mem_rd; r_wb_alu_out <= r_mem_alu_out; - // end + r_wb_wdata <= r_mem_wdata; + r_wb_valid <= r_mem_valid; + end // Register File - if (r_wb_rd != 0 && s_wb_write) begin + // TODO: should I write if s_wb_stall=1? + if (r_wb_rd != 0 && s_wb_write && r_wb_valid) begin regfile[r_wb_rd] <= s_wb_data; end - // end end end diff --git a/hdl/tb/core_tb.v b/hdl/tb/core_tb.v index 650f0da..d72645e 100644 --- a/hdl/tb/core_tb.v +++ b/hdl/tb/core_tb.v @@ -15,6 +15,8 @@ wire [31:0] mem_inst_addr; wire [31:0] mem_inst_idx = mem_inst_addr >> 2; wire [31:0] mem_inst_data = mem_inst_idx < MEM_INST_LENGTH ? mem_inst[mem_inst_idx] : INST_NOP; +wire dummy_out; + initial begin: mem_inst_init integer i; for (i=0; i IF label + + s_if_stall + s_if_stall + r_if_pc[31:0] r_if_pc[31:0] @@ -202,17 +206,17 @@ s_if_inst[31:0] HEXRADIX - - s_if_halt - s_if_halt - ID label - - r_id_stall - r_id_stall + + r_id_valid + r_id_valid + + + s_id_stall + s_id_stall r_id_pc[31:0] @@ -265,10 +269,6 @@ s_id_aluop[3:0] s_id_aluop[3:0] - - s_id_alu_seed - s_id_alu_seed - s_id_jump s_id_jump @@ -277,17 +277,17 @@ s_id_invalid s_id_invalid - - s_id_halt - s_id_halt - EX label - - r_ex_stall - r_ex_stall + + r_ex_valid + r_ex_valid + + + s_ex_stall + s_ex_stall r_ex_pc[31:0] @@ -318,10 +318,6 @@ r_ex_aluop[3:0] r_ex_aluop[3:0] - - r_ex_alu_seed - r_ex_alu_seed - s_ex_data1[31:0] s_ex_data1[31:0] @@ -345,17 +341,17 @@ r_ex_jump r_ex_jump - - s_ex_halt - s_ex_halt - MEM label - - r_mem_stall - r_mem_stall + + r_mem_valid + r_mem_valid + + + s_mem_stall + s_mem_stall r_mem_pc[31:0] @@ -381,17 +377,17 @@ r_mem_alu_zero r_mem_alu_zero - - s_mem_halt - s_mem_halt - WB label - - r_wb_stall - r_wb_stall + + r_wb_valid + r_wb_valid + + + s_wb_stall + s_wb_stall r_wb_pc[31:0] @@ -418,9 +414,5 @@ s_wb_data[31:0] HEXRADIX - - s_wb_halt - s_wb_halt - diff --git a/test/test.S b/test/test.S index 7a18eb2..cc4075d 100644 --- a/test/test.S +++ b/test/test.S @@ -201,7 +201,7 @@ _start: auipc x3, 0 # x3 = pc + 0 auipc x4, 3 # x4 = pc + 0x3000 auipc x5, 0xfffff # x5 = pc + 0xfffff000 - # TODO: verify auipc adds and does not concatenate + # TODO: verify auipc adds and does not concatenate (must have PC>0xfff for this) nop nop nop @@ -221,7 +221,12 @@ loop: nop nop nop - j loop # loop forever + jal x1, loop # loop forever + addi x2, x0, 0 # NOTE: this should never be executed + addi x3, x0, 0 # NOTE: this should never be executed + addi x4, x0, 0 # NOTE: this should never be executed + addi x5, x0, 0 # NOTE: this should never be executed + addi x6, x0, 0 # NOTE: this should never be executed nop nop nop