From 34fc93ba09edbd9e676d39600c177d2f55d38a2a Mon Sep 17 00:00:00 2001 From: Olof Kindgren Date: Thu, 15 Nov 2018 12:50:40 +0100 Subject: [PATCH] Fix misaligned jumps --- rtl/serv_ctrl.v | 29 ++++++++++++++------- rtl/serv_decode.v | 64 +++++++++++++++++++++++++++++------------------ rtl/serv_top.v | 15 ++++++++--- 3 files changed, 72 insertions(+), 36 deletions(-) diff --git a/rtl/serv_ctrl.v b/rtl/serv_ctrl.v index c086a3f..38a8b84 100644 --- a/rtl/serv_ctrl.v +++ b/rtl/serv_ctrl.v @@ -3,6 +3,8 @@ module serv_ctrl ( input clk, input i_en, + input i_pc_en, + input i_cnt_done, input i_jump, input i_offset, input i_rs1, @@ -12,6 +14,7 @@ module serv_ctrl input i_csr_pc, output o_rd, output o_bad_pc, + output reg o_misalign = 1'b0, output [31:0] o_ibus_adr, output reg o_ibus_cyc = 1'b0, input i_ibus_ack); @@ -29,17 +32,17 @@ module serv_ctrl wire offset_a; - assign plus_4 = en_2r & !en_3r; + assign plus_4 = en_pc_2r & !en_pc_3r; assign o_ibus_adr[0] = pc; - assign o_bad_pc = pc_plus_offset; + assign o_bad_pc = pc_plus_offset_aligned; ser_add ser_add_pc_plus_4 ( .clk (clk), .a (pc), .b (plus_4), - .clr (!i_en), + .clr (i_cnt_done), .q (pc_plus_4), .o_v ()); @@ -50,13 +53,13 @@ module serv_ctrl pc_reg ( .clk (clk), - .i_en (i_en), + .i_en (i_pc_en), .i_d (new_pc), .o_q (pc), .o_par (o_ibus_adr[31:1]) ); - assign new_pc = i_trap ? i_csr_pc : i_jump ? pc_plus_offset_aligned : pc_plus_4; + assign new_pc = i_trap ? (i_csr_pc & en_pc_r) : i_jump ? pc_plus_offset_aligned : pc_plus_4; assign o_rd = i_auipc ? pc_plus_offset_aligned : pc_plus_4; assign offset_a = i_jalr ? i_rs1 : pc; @@ -66,23 +69,31 @@ module serv_ctrl .clk (clk), .a (offset_a), .b (i_offset), - .clr (!i_en), + .clr (i_cnt_done), .q (pc_plus_offset), .o_v ()); - wire pc_plus_offset_aligned = pc_plus_offset & en_r; + wire pc_plus_offset_aligned = pc_plus_offset & en_pc_r; - reg en_r = 1'b1; + reg en_r = 1'b0; reg en_2r = 1'b0; reg en_3r = 1'b0; + reg en_pc_r = 1'b1; + reg en_pc_2r = 1'b0; + reg en_pc_3r = 1'b0; always @(posedge clk) begin en_r <= i_en; en_2r <= en_r; en_3r <= en_2r; + en_pc_r <= i_pc_en; + en_pc_2r <= en_pc_r; + en_pc_3r <= en_pc_2r; - if (en_r & !i_en) + if (en_r & !en_2r) + o_misalign <= pc_plus_offset; + if (en_pc_r & !i_pc_en) o_ibus_cyc <= 1'b1; else if (o_ibus_cyc & i_ibus_ack) o_ibus_cyc <= 1'b0; diff --git a/rtl/serv_decode.v b/rtl/serv_decode.v index d0f1b42..928dd16 100644 --- a/rtl/serv_decode.v +++ b/rtl/serv_decode.v @@ -1,15 +1,19 @@ +`default_nettype none module serv_decode ( input clk, input [31:0] i_wb_rdt, input i_wb_en, + output o_cnt_done, output o_ibus_active, output o_ctrl_en, + output o_ctrl_pc_en, output o_ctrl_jump, output o_ctrl_jalr, output o_ctrl_auipc, - output reg o_ctrl_trap = 1'b0, + output o_ctrl_trap, output o_ctrl_mret, + input i_ctrl_misalign, output o_rf_rd_en, output reg [4:0] o_rf_rd_addr, output o_rf_rs_en, @@ -46,7 +50,8 @@ module serv_decode localparam [1:0] IDLE = 2'd0, INIT = 2'd1, - RUN = 2'd2; + RUN = 2'd2, + TRAP = 2'd3; localparam [4:0] OP_LOAD = 5'b00000, @@ -68,21 +73,30 @@ module serv_decode wire mem_op; wire shift_op; wire csr_op; + wire slt_op; + wire branch_op; wire jump_misaligned; reg signbit; + assign o_cnt_done = cnt_done; + assign o_ibus_active = (state == IDLE); assign mem_op = (opcode == OP_LOAD) | (opcode == OP_STORE); assign shift_op = ((opcode == OP_OPIMM) & (o_funct3[1:0] == 2'b01)) | ((opcode == OP_OP ) & (o_funct3[1:0] == 2'b01)); - assign o_ctrl_en = running; + assign slt_op = (((opcode == OP_OPIMM) | (opcode == OP_OP)) & + (o_funct3[2:1] == 2'b01)); + + assign branch_op = (opcode == OP_BRANCH); + + assign o_ctrl_pc_en = running | o_ctrl_trap; assign o_ctrl_jump = (opcode == OP_JAL) | (opcode == OP_JALR) | - ((opcode == OP_BRANCH) & i_alu_cmp); + (branch_op & i_alu_cmp); assign o_ctrl_jalr = (opcode == OP_JALR); @@ -92,25 +106,27 @@ module serv_decode assign o_rf_rd_en = running & !o_ctrl_trap & (opcode != OP_STORE) & - (opcode != OP_BRANCH); + !branch_op; assign o_rf_rs_en = cnt_en; assign o_alu_en = cnt_en; + assign o_ctrl_en = cnt_en; + assign o_alu_init = (state == INIT); assign o_alu_sub = (opcode == OP_OP) ? signbit /* ? 1'b1*/ : - ((opcode == OP_BRANCH) & (o_funct3 == 3'b100)) ? 1'b1 : - ((opcode == OP_BRANCH) & (o_funct3 == 3'b101)) ? 1'b1 : - ((opcode == OP_BRANCH) & (o_funct3 == 3'b110)) ? 1'b1 : + (branch_op & (o_funct3 == 3'b100)) ? 1'b1 : + (branch_op & (o_funct3 == 3'b101)) ? 1'b1 : + (branch_op & (o_funct3 == 3'b110)) ? 1'b1 : ((opcode == OP_OPIMM) & (o_funct3 == 3'b000)) ? 1'b0 : 1'bx; - assign o_alu_cmp_neg = (opcode == OP_BRANCH) & o_funct3[0]; + assign o_alu_cmp_neg = branch_op & o_funct3[0]; - assign o_csr_en = ((opcode == OP_SYSTEM) & (|o_funct3) | o_ctrl_mret | o_ctrl_trap) & running; + assign o_csr_en = ((opcode == OP_SYSTEM) & (|o_funct3) | o_ctrl_mret | o_ctrl_trap) & (running | o_ctrl_trap); always @(o_funct3) begin casez (o_funct3) @@ -177,7 +193,7 @@ module serv_decode assign o_mem_init = mem_op & (state == INIT); - assign jal_misalign = imm[21] & (opcode == OP_JAL); + wire jal_misalign = imm[21] & (opcode == OP_JAL); reg [4:0] opcode; reg [31:0] imm; @@ -261,41 +277,41 @@ module serv_decode always @(posedge clk) go <= i_wb_en; - wire cnt_en = - (state == RUN) | - (state == INIT); + wire cnt_en = (state != IDLE); wire cnt_done = cnt == 31; assign running = (state == RUN); + assign o_ctrl_trap = (state == TRAP); + always @(posedge clk) begin - if (cnt_done) - o_ctrl_trap <= i_mem_misalign; - if (go) - o_ctrl_trap <= jal_misalign; state <= state; case (state) IDLE : begin if (go) begin state <= RUN; - if ((opcode == OP_BRANCH) | - (((opcode == OP_OPIMM) | (opcode == OP_OP)) & - (o_funct3[2:1] == 2'b01)) | + if (branch_op | + slt_op | (opcode == OP_JAL) | (opcode == OP_JALR) | mem_op | shift_op) state <= INIT; end - if (i_mem_dbus_ack | i_mem_misalign) + if (i_mem_dbus_ack) state <= RUN; end INIT : begin if (cnt_done) - state <= mem_op ? IDLE : RUN; + state <= (i_mem_misalign | (o_ctrl_jump & i_ctrl_misalign) /*| jal_misalign*/) ? TRAP : + mem_op ? IDLE : RUN; end RUN : begin if (cnt_done) state <= IDLE; end - default : state <= 3'bxxx; + TRAP : begin + if (cnt_done) + state <= IDLE; + end + default : state <= 2'bxx; endcase cnt <= cnt + {4'd0,cnt_en}; diff --git a/rtl/serv_top.v b/rtl/serv_top.v index d942b3a..ccb0a29 100644 --- a/rtl/serv_top.v +++ b/rtl/serv_top.v @@ -61,6 +61,8 @@ module serv_top wire rd; wire ctrl_en; + wire ctrl_pc_en; + wire ctrl_misalign; wire jump; wire jalr; wire auipc; @@ -70,6 +72,7 @@ module serv_top wire imm; wire trap; + wire cnt_done; wire [2:0] funct3; wire alu_en; @@ -113,13 +116,16 @@ module serv_top .clk (clk), .i_wb_rdt (i_ibus_rdt), .i_wb_en (o_ibus_cyc & i_ibus_ack), + .o_cnt_done (cnt_done), .o_ibus_active (), .o_ctrl_en (ctrl_en), + .o_ctrl_pc_en (ctrl_pc_en), .o_ctrl_jump (jump), .o_ctrl_jalr (jalr), .o_ctrl_auipc (auipc), .o_ctrl_trap (trap), .o_ctrl_mret (mret), + .i_ctrl_misalign(ctrl_misalign), .o_funct3 (funct3), .o_alu_en (alu_en), .o_alu_init (alu_init), @@ -157,6 +163,8 @@ module serv_top ( .clk (clk), .i_en (ctrl_en), + .i_pc_en (ctrl_pc_en), + .i_cnt_done (cnt_done), .i_jump (jump), .i_offset (offset), .i_rs1 (rs1), @@ -166,6 +174,7 @@ module serv_top .i_csr_pc (csr_rd), .o_rd (ctrl_rd), .o_bad_pc (bad_pc), + .o_misalign (ctrl_misalign), .o_ibus_adr (o_ibus_adr), .o_ibus_cyc (o_ibus_cyc), .i_ibus_ack (i_ibus_ack)); @@ -255,10 +264,10 @@ module serv_top `ifdef RISCV_FORMAL reg [31:0] rs1_fv, rs2_fv, rd_fv; reg [31:0] pc = RESET_PC; - reg ctrl_en_r = 1'b0; + reg ctrl_pc_en_r = 1'b0; always @(posedge clk) begin - ctrl_en_r <= ctrl_en; + ctrl_pc_en_r <= ctrl_pc_en; if (rs_en) begin rs1_fv <= {rs1,rs1_fv[31:1]}; rs2_fv <= {rs2,rs2_fv[31:1]}; @@ -267,7 +276,7 @@ module serv_top rd_fv <= {rd,rd_fv[31:1]}; end rvfi_valid <= 1'b0; - if (ctrl_en_r & !ctrl_en) begin + if (ctrl_pc_en_r & !ctrl_pc_en) begin pc <= o_ibus_adr; rvfi_valid <= 1'b1; rvfi_order <= rvfi_order + 1;