Fix misaligned jumps

This commit is contained in:
Olof Kindgren 2018-11-15 12:50:40 +01:00
parent f12f8ecf61
commit 34fc93ba09
3 changed files with 72 additions and 36 deletions

View file

@ -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;

View file

@ -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};

View file

@ -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;