mirror of
https://github.com/olofk/serv.git
synced 2025-04-20 03:47:09 -04:00
Fix misaligned jumps
This commit is contained in:
parent
f12f8ecf61
commit
34fc93ba09
3 changed files with 72 additions and 36 deletions
|
@ -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;
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue