mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 12:57:13 -04:00
The RVFI implementation make use of signals from the decoder and controller to detect the state of the processor. Especially the signal for a new and retired instruction.
This commit is contained in:
parent
b8e1f552b4
commit
d059979af6
4 changed files with 92 additions and 85 deletions
|
@ -101,8 +101,6 @@ module ibex_controller (
|
|||
input logic stall_jump_i,
|
||||
input logic stall_branch_i,
|
||||
|
||||
output logic id_out_valid_o, // ID stage has valid output
|
||||
|
||||
// performance monitors
|
||||
output logic perf_jump_o, // we are executing a jump
|
||||
// instruction (j, jr, jal, jalr)
|
||||
|
@ -533,9 +531,6 @@ module ibex_controller (
|
|||
// multicycle instr causes an exception for example
|
||||
assign instr_valid_clear_o = ~stall | halt_id;
|
||||
|
||||
// signal that ID stage has valid output
|
||||
assign id_out_valid_o = ~stall & instr_valid_i & ~special_req;
|
||||
|
||||
// update registers
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : update_regs
|
||||
if (!rst_ni) begin
|
||||
|
|
157
rtl/ibex_core.sv
157
rtl/ibex_core.sv
|
@ -180,8 +180,6 @@ module ibex_core #(
|
|||
logic id_in_ready;
|
||||
logic ex_valid;
|
||||
|
||||
logic if_id_pipe_reg_we;
|
||||
|
||||
logic lsu_data_valid;
|
||||
|
||||
// Signals between instruction core interface and pipe (if and id stages)
|
||||
|
@ -216,13 +214,11 @@ module ibex_core #(
|
|||
logic perf_store;
|
||||
|
||||
// for RVFI
|
||||
logic id_out_valid, unused_id_out_valid; // ID stage has valid output data
|
||||
logic illegal_insn_id, unused_illegal_insn_id; // ID stage sees an illegal instruction
|
||||
|
||||
// RISC-V Formal Interface signals
|
||||
`ifdef RVFI
|
||||
logic [31:0] rvfi_insn_opcode;
|
||||
logic rvfi_valid_int;
|
||||
logic [31:0] rvfi_insn_id;
|
||||
logic [4:0] rvfi_rs1_addr_id;
|
||||
logic [4:0] rvfi_rs2_addr_id;
|
||||
logic [31:0] rvfi_rs1_data_d;
|
||||
|
@ -240,11 +236,6 @@ module ibex_core #(
|
|||
logic rvfi_rd_we_id;
|
||||
logic rvfi_insn_new_d;
|
||||
logic rvfi_insn_new_q;
|
||||
logic rvfi_insn_clear_d;
|
||||
logic rvfi_insn_clear_q;
|
||||
logic rvfi_changed_insn;
|
||||
logic rvfi_changed_pc;
|
||||
logic [31:0] rvfi_pc_id_q;
|
||||
logic [3:0] rvfi_mem_mask_int;
|
||||
logic [31:0] rvfi_mem_rdata_d;
|
||||
logic [31:0] rvfi_mem_rdata_q;
|
||||
|
@ -336,7 +327,6 @@ module ibex_core #(
|
|||
|
||||
// pipeline stalls
|
||||
.id_in_ready_i ( id_in_ready ),
|
||||
.if_id_pipe_reg_we_o ( if_id_pipe_reg_we ),
|
||||
|
||||
.if_busy_o ( if_busy ),
|
||||
.perf_imiss_o ( perf_imiss )
|
||||
|
@ -389,8 +379,6 @@ module ibex_core #(
|
|||
.ex_valid_i ( ex_valid ),
|
||||
.lsu_valid_i ( lsu_data_valid ),
|
||||
|
||||
.id_out_valid_o ( id_out_valid ),
|
||||
|
||||
.alu_operator_ex_o ( alu_operator_ex ),
|
||||
.alu_operand_a_ex_o ( alu_operand_a_ex ),
|
||||
.alu_operand_b_ex_o ( alu_operand_b_ex ),
|
||||
|
@ -465,7 +453,6 @@ module ibex_core #(
|
|||
);
|
||||
|
||||
// for RVFI only
|
||||
assign unused_id_out_valid = id_out_valid;
|
||||
assign unused_illegal_insn_id = illegal_insn_id;
|
||||
|
||||
ibex_ex_block #(
|
||||
|
@ -611,33 +598,55 @@ module ibex_core #(
|
|||
);
|
||||
|
||||
`ifdef RVFI
|
||||
always_ff @(posedge clk) begin
|
||||
rvfi_halt <= '0;
|
||||
rvfi_trap <= '0;
|
||||
rvfi_intr <= irq_ack_o;
|
||||
rvfi_order <= rst_ni ? rvfi_order + rvfi_valid : '0;
|
||||
rvfi_insn <= rvfi_insn_opcode;
|
||||
rvfi_mode <= PRIV_LVL_M;
|
||||
rvfi_rs1_addr <= rvfi_rs1_addr_id;
|
||||
rvfi_rs2_addr <= rvfi_rs2_addr_id;
|
||||
rvfi_pc_rdata <= pc_id;
|
||||
rvfi_mem_rmask <= rvfi_mem_mask_int;
|
||||
rvfi_mem_wmask <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
|
||||
rvfi_valid <= rvfi_valid_int;
|
||||
rvfi_rs1_rdata <= rvfi_rs1_data_d;
|
||||
rvfi_rs2_rdata <= rvfi_rs2_data_d;
|
||||
always_ff @(posedge clk or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
rvfi_halt <= '0;
|
||||
rvfi_trap <= '0;
|
||||
rvfi_intr <= '0;
|
||||
rvfi_order <= '0;
|
||||
rvfi_insn <= '0;
|
||||
rvfi_mode <= '0;
|
||||
rvfi_rs1_addr <= '0;
|
||||
rvfi_rs2_addr <= '0;
|
||||
rvfi_pc_rdata <= '0;
|
||||
rvfi_pc_wdata <= '0;
|
||||
rvfi_mem_rmask <= '0;
|
||||
rvfi_mem_wmask <= '0;
|
||||
rvfi_valid <= '0;
|
||||
rvfi_rs1_rdata <= '0;
|
||||
rvfi_rs2_rdata <= '0;
|
||||
rvfi_rd_wdata <= '0;
|
||||
rvfi_rd_addr <= '0;
|
||||
rvfi_mem_rdata <= '0;
|
||||
rvfi_mem_wdata <= '0;
|
||||
rvfi_mem_addr <= '0;
|
||||
end else begin
|
||||
rvfi_halt <= '0;
|
||||
rvfi_trap <= illegal_insn_id;
|
||||
rvfi_intr <= irq_ack_o;
|
||||
rvfi_order <= rvfi_order + rvfi_valid;
|
||||
rvfi_insn <= rvfi_insn_id;
|
||||
rvfi_mode <= PRIV_LVL_M; // TODO: Update for user mode support
|
||||
rvfi_rs1_addr <= rvfi_rs1_addr_id;
|
||||
rvfi_rs2_addr <= rvfi_rs2_addr_id;
|
||||
rvfi_pc_rdata <= pc_id;
|
||||
rvfi_pc_wdata <= pc_if;
|
||||
rvfi_mem_rmask <= rvfi_mem_mask_int;
|
||||
rvfi_mem_wmask <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
|
||||
rvfi_valid <= instr_ret;
|
||||
rvfi_rs1_rdata <= rvfi_rs1_data_d;
|
||||
rvfi_rs2_rdata <= rvfi_rs2_data_d;
|
||||
rvfi_rd_wdata <= rvfi_rd_wdata_d;
|
||||
rvfi_rd_addr <= rvfi_rd_addr_d;
|
||||
rvfi_mem_rdata <= rvfi_mem_rdata_d;
|
||||
rvfi_mem_wdata <= rvfi_mem_wdata_d;
|
||||
rvfi_mem_addr <= rvfi_mem_addr_d;
|
||||
end
|
||||
end
|
||||
|
||||
assign rvfi_pc_wdata = pc_id;
|
||||
assign rvfi_rd_wdata = rvfi_rd_wdata_q;
|
||||
assign rvfi_rd_addr = rvfi_rd_addr_q;
|
||||
assign rvfi_mem_rdata = rvfi_mem_rdata_q;
|
||||
assign rvfi_mem_wdata = rvfi_mem_wdata_q;
|
||||
assign rvfi_mem_addr = rvfi_mem_addr_q;
|
||||
|
||||
// Keep the mem data stable for each instruction cycle
|
||||
always_comb begin
|
||||
if (rvfi_insn_new_d) begin
|
||||
if (rvfi_insn_new_d && lsu_data_valid) begin
|
||||
rvfi_mem_addr_d = alu_adder_result_ex;
|
||||
rvfi_mem_rdata_d = regfile_wdata_lsu;
|
||||
rvfi_mem_wdata_d = data_wdata_ex;
|
||||
|
@ -647,10 +656,16 @@ module ibex_core #(
|
|||
rvfi_mem_wdata_d = rvfi_mem_wdata_q;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
rvfi_mem_addr_q <= rvfi_mem_addr_d;
|
||||
rvfi_mem_rdata_q <= rvfi_mem_rdata_d;
|
||||
rvfi_mem_wdata_q <= rvfi_mem_wdata_d;
|
||||
always_ff @(posedge clk or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
rvfi_mem_addr_q <= '0;
|
||||
rvfi_mem_rdata_q <= '0;
|
||||
rvfi_mem_wdata_q <= '0;
|
||||
end else begin
|
||||
rvfi_mem_addr_q <= rvfi_mem_addr_d;
|
||||
rvfi_mem_rdata_q <= rvfi_mem_rdata_d;
|
||||
rvfi_mem_wdata_q <= rvfi_mem_wdata_d;
|
||||
end
|
||||
end
|
||||
// Byte enable based on data type
|
||||
always_comb begin
|
||||
|
@ -662,19 +677,17 @@ module ibex_core #(
|
|||
endcase
|
||||
end
|
||||
|
||||
assign rvfi_valid_int = id_out_valid && if_id_pipe_reg_we && !illegal_c_insn_id;
|
||||
|
||||
always_comb begin
|
||||
if (instr_is_compressed_id) begin
|
||||
rvfi_insn_opcode = {16'b0, instr_rdata_c_id};
|
||||
rvfi_insn_id = {16'b0, instr_rdata_c_id};
|
||||
end else begin
|
||||
rvfi_insn_opcode = instr_rdata_id;
|
||||
rvfi_insn_id = instr_rdata_id;
|
||||
end
|
||||
end
|
||||
|
||||
// Source register data are kept stable for each instruction cycle
|
||||
always_comb begin
|
||||
if (rvfi_insn_new_d) begin
|
||||
if (instr_new_id) begin
|
||||
rvfi_rs1_data_d = rvfi_rs1_data_id;
|
||||
rvfi_rs2_data_d = rvfi_rs2_data_id;
|
||||
end else begin
|
||||
|
@ -682,9 +695,14 @@ module ibex_core #(
|
|||
rvfi_rs2_data_d = rvfi_rs2_data_q;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
rvfi_rs1_data_q <= rvfi_rs1_data_d;
|
||||
rvfi_rs2_data_q <= rvfi_rs2_data_d;
|
||||
always_ff @(posedge clk or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
rvfi_rs1_data_q <= '0;
|
||||
rvfi_rs2_data_q <= '0;
|
||||
end else begin
|
||||
rvfi_rs1_data_q <= rvfi_rs1_data_d;
|
||||
rvfi_rs2_data_q <= rvfi_rs2_data_d;
|
||||
end
|
||||
end
|
||||
|
||||
// RD write register is refreshed only once per cycle and
|
||||
|
@ -694,7 +712,6 @@ module ibex_core #(
|
|||
if (!rvfi_rd_we_id) begin
|
||||
rvfi_rd_addr_d = '0;
|
||||
rvfi_rd_wdata_d = '0;
|
||||
rvfi_insn_clear_d = 1'b0;
|
||||
end else begin
|
||||
rvfi_rd_addr_d = rvfi_rd_addr_id;
|
||||
if (!rvfi_rd_addr_id) begin
|
||||
|
@ -702,43 +719,41 @@ module ibex_core #(
|
|||
end else begin
|
||||
rvfi_rd_wdata_d = rvfi_rd_wdata_id;
|
||||
end
|
||||
rvfi_insn_clear_d = 1'b1;
|
||||
end
|
||||
end else begin
|
||||
rvfi_rd_addr_d = rvfi_rd_addr_q;
|
||||
rvfi_rd_wdata_d = rvfi_rd_wdata_q;
|
||||
rvfi_insn_clear_d = 1'b0;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
rvfi_insn_clear_q <= rvfi_insn_clear_d;
|
||||
rvfi_rd_addr_q <= rvfi_rd_addr_d;
|
||||
rvfi_rd_wdata_q <= rvfi_rd_wdata_d;
|
||||
always_ff @(posedge clk or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
rvfi_rd_addr_q <= '0;
|
||||
rvfi_rd_wdata_q <= '0;
|
||||
end else begin
|
||||
rvfi_rd_addr_q <= rvfi_rd_addr_d;
|
||||
rvfi_rd_wdata_q <= rvfi_rd_wdata_d;
|
||||
end
|
||||
end
|
||||
|
||||
// New instruction signalling based on changes of
|
||||
// instruction data, program counter and valid signal
|
||||
always_comb begin
|
||||
if (rvfi_changed_insn || rvfi_changed_pc || rvfi_valid ) begin
|
||||
if (instr_new_id) begin
|
||||
rvfi_insn_new_d = 1'b1;
|
||||
end else if (rvfi_insn_clear_q) begin
|
||||
rvfi_insn_new_d = 1'b0;
|
||||
end else begin
|
||||
rvfi_insn_new_d = rvfi_insn_new_q;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk) begin
|
||||
rvfi_insn_new_q <= rvfi_insn_new_d;
|
||||
always_ff @(posedge clk or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
rvfi_insn_new_q <= 1'b0;
|
||||
end else begin
|
||||
if (instr_ret) begin
|
||||
rvfi_insn_new_q <= 1'b0;
|
||||
end else begin
|
||||
rvfi_insn_new_q <= rvfi_insn_new_d;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Change in instruction code
|
||||
assign rvfi_changed_insn = rvfi_insn != rvfi_insn_opcode;
|
||||
|
||||
// Change in program counter
|
||||
always_ff @(posedge clk) begin
|
||||
rvfi_pc_id_q <= pc_id;
|
||||
end
|
||||
assign rvfi_changed_pc = rvfi_pc_id_q != pc_id;
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -70,8 +70,6 @@ module ibex_id_stage #(
|
|||
// Stalls
|
||||
input logic ex_valid_i, // EX stage has valid output
|
||||
input logic lsu_valid_i, // LSU has valid output, or is done
|
||||
output logic id_out_valid_o, // ID stage is done
|
||||
|
||||
// ALU
|
||||
output ibex_defines::alu_op_e alu_operator_ex_o,
|
||||
output logic [31:0] alu_operand_a_ex_o,
|
||||
|
@ -480,8 +478,6 @@ module ibex_id_stage #(
|
|||
.stall_jump_i ( stall_jump ),
|
||||
.stall_branch_i ( stall_branch ),
|
||||
|
||||
.id_out_valid_o ( id_out_valid_o ),
|
||||
|
||||
// Performance Counters
|
||||
.perf_jump_o ( perf_jump_o ),
|
||||
.perf_tbranch_o ( perf_tbranch_o )
|
||||
|
|
|
@ -77,7 +77,6 @@ module ibex_if_stage #(
|
|||
|
||||
// pipeline stall
|
||||
input logic id_in_ready_i, // ID stage is ready for new instr
|
||||
output logic if_id_pipe_reg_we_o, // IF-ID pipeline reg write enable
|
||||
|
||||
// misc signals
|
||||
output logic if_busy_o, // IF stage is busy fetching instr
|
||||
|
@ -104,6 +103,8 @@ module ibex_if_stage #(
|
|||
logic [5:0] irq_id;
|
||||
logic unused_irq_bit;
|
||||
|
||||
logic if_id_pipe_reg_we; // IF-ID pipeline reg write enable
|
||||
|
||||
logic [7:0] unused_boot_addr;
|
||||
|
||||
assign unused_boot_addr = boot_addr_i[7:0];
|
||||
|
@ -193,7 +194,7 @@ module ibex_if_stage #(
|
|||
if (fetch_valid) begin
|
||||
have_instr = 1'b1;
|
||||
|
||||
if (req_i && if_id_pipe_reg_we_o) begin
|
||||
if (req_i && if_id_pipe_reg_we) begin
|
||||
fetch_ready = 1'b1;
|
||||
offset_in_init_d = 1'b0;
|
||||
end
|
||||
|
@ -231,7 +232,7 @@ module ibex_if_stage #(
|
|||
);
|
||||
|
||||
// IF-ID pipeline registers, frozen when the ID stage is stalled
|
||||
assign if_id_pipe_reg_we_o = have_instr & id_in_ready_i;
|
||||
assign if_id_pipe_reg_we = have_instr & id_in_ready_i;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : if_id_pipeline_regs
|
||||
if (!rst_ni) begin
|
||||
|
@ -243,8 +244,8 @@ module ibex_if_stage #(
|
|||
illegal_c_insn_id_o <= 1'b0;
|
||||
pc_id_o <= '0;
|
||||
end else begin
|
||||
instr_new_id_o <= if_id_pipe_reg_we_o;
|
||||
if (if_id_pipe_reg_we_o) begin
|
||||
instr_new_id_o <= if_id_pipe_reg_we;
|
||||
if (if_id_pipe_reg_we) begin
|
||||
instr_valid_id_o <= 1'b1;
|
||||
instr_rdata_id_o <= instr_decompressed;
|
||||
instr_rdata_c_id_o <= fetch_rdata[15:0];
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue