[test] Connect FPU subsystem

This commit is contained in:
Hailin 2022-06-20 12:06:59 +02:00 committed by Pirmin Vogel
parent 83588ae089
commit 13bbaf72d9
16 changed files with 830 additions and 198 deletions

View file

@ -58,8 +58,8 @@ ISS := spike
# ISS runtime options
ISS_OPTS :=
# ISA
ISA := rv32imcb
ISA_ISS := rv32imc_Zba_Zbb_Zbc_Zbs_Xbitmanip
ISA := rv32imfcb
ISA_ISS := rv32imfc_Zba_Zbb_Zbc_Zbs_Xbitmanip
# Test name (default: full regression)
TEST := all
TESTLIST := riscv_dv_extension/testlist.yaml

View file

@ -13,6 +13,54 @@
+define+TRACE_EXECUTION
+define+RVFI
// common cells
+incdir+${PRJ_DIR}/vendor/pulp_common_cells/include
${PRJ_DIR}/vendor/pulp_common_cells/src/cf_math_pkg.sv
${PRJ_DIR}/vendor/pulp_common_cells/src/fifo_v3.sv
${PRJ_DIR}/vendor/pulp_common_cells/src/stream_fifo.sv
${PRJ_DIR}/vendor/pulp_common_cells/src/lzc.sv
${PRJ_DIR}/vendor/pulp_common_cells/src/rr_arb_tree.sv
// fpu_div_sqrt_mvp
+incdir+${PRJ_DIR}/vendor/pulp_fpu_div_sqrt_mvp/
${PRJ_DIR}/vendor/pulp_fpu_div_sqrt_mvp/hdl/defs_div_sqrt_mvp.sv
${PRJ_DIR}/vendor/pulp_fpu_div_sqrt_mvp/hdl/control_mvp.sv
${PRJ_DIR}/vendor/pulp_fpu_div_sqrt_mvp/hdl/div_sqrt_mvp_wrapper.sv
${PRJ_DIR}/vendor/pulp_fpu_div_sqrt_mvp/hdl/div_sqrt_top_mvp.sv
${PRJ_DIR}/vendor/pulp_fpu_div_sqrt_mvp/hdl/iteration_div_sqrt_mvp.sv
${PRJ_DIR}/vendor/pulp_fpu_div_sqrt_mvp/hdl/norm_div_sqrt_mvp.sv
${PRJ_DIR}/vendor/pulp_fpu_div_sqrt_mvp/hdl/nrbd_nrsc_mvp.sv
${PRJ_DIR}/vendor/pulp_fpu_div_sqrt_mvp/hdl/preprocess_mvp.sv
// fpnew
+incdir+${PRJ_DIR}/vendor/openhwgroup_cvfpu/
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_pkg.sv
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_cast_multi.sv
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_classifier.sv
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_divsqrt_multi.sv
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_fma.sv
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_fma_multi.sv
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_noncomp.sv
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_opgroup_block.sv
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_opgroup_fmt_slice.sv
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_opgroup_multifmt_slice.sv
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_rounding.sv
${PRJ_DIR}/vendor/openhwgroup_cvfpu/src/fpnew_top.sv
// FPU Subsystem files
+incdir+${PRJ_DIR}/vendor/pulp_fpu_ss/src
${PRJ_DIR}/vendor/pulp_fpu_ss/src/fpu_ss_pkg.sv
${PRJ_DIR}/vendor/pulp_fpu_ss/src/fpu_ss_instr_pkg.sv
${PRJ_DIR}/vendor/pulp_fpu_ss/src/fpu_ss_prd_f_pkg.sv
${PRJ_DIR}/vendor/pulp_fpu_ss/src/fpu_ss_prd_zfinx_pkg.sv
${PRJ_DIR}/vendor/pulp_fpu_ss/src/fpu_ss.sv
${PRJ_DIR}/vendor/pulp_fpu_ss/src/fpu_ss_compressed_predecoder.sv
${PRJ_DIR}/vendor/pulp_fpu_ss/src/fpu_ss_predecoder.sv
${PRJ_DIR}/vendor/pulp_fpu_ss/src/fpu_ss_decoder.sv
${PRJ_DIR}/vendor/pulp_fpu_ss/src/fpu_ss_regfile.sv
${PRJ_DIR}/vendor/pulp_fpu_ss/src/fpu_ss_csr.sv
${PRJ_DIR}/vendor/pulp_fpu_ss/src/fpu_ss_controller.sv
// Shared lowRISC code
+incdir+${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl
${PRJ_DIR}/vendor/lowrisc_ip/ip/prim/rtl/prim_assert.sv

View file

@ -32,7 +32,8 @@ finally:
INSTR_RE = \
re.compile(r"^\s*(?P<time>\d+)\s+(?P<cycle>\d+)\s+(?P<pc>[0-9a-f]+)\s+"
r"(?P<bin>[0-9a-f]+)\s+(?P<instr>\S+\s+\S+)\s*")
RD_RE = re.compile(r"(x(?P<rd>[1-9]\d*)=0x(?P<rd_val>[0-9a-f]+))")
# RD_RE = re.compile(r"(x(?P<rd>[1-9]\d*)=0x(?P<rd_val>[0-9a-f]+))")
RD_RE = re.compile(r"((?P<reg>[xf]?)(?P<rd>[0-9]\d*)=0x(?P<rd_val>[0-9a-f]+))")
ADDR_RE = re.compile(r"(?P<rd>[a-z0-9]+?),"
r"(?P<imm>[\-0-9]+?)"
r"\((?P<rs1>[a-z0-9]+)\)")
@ -76,10 +77,14 @@ def _process_ibex_sim_log_fd(log_fd, csv_fd, full_trace=True):
expand_trace_entry(trace_entry, m.group("instr").split()[1])
c = RD_RE.search(line)
# if c:
# abi_name = gpr_to_abi("x{}".format(c.group("rd")))
if c:
abi_name = gpr_to_abi("x{}".format(c.group("rd")))
gpr_entry = "{}:{}".format(abi_name, c.group("rd_val"))
trace_entry.gpr.append(gpr_entry)
not_x0 = (c.group("reg") + c.group("rd")) != 'x0'
if not_x0:
abi_name = gpr_to_abi("{}{}".format(c.group("reg"), c.group("rd")))
gpr_entry = "{}:{}".format(abi_name, c.group("rd_val"))
trace_entry.gpr.append(gpr_entry)
trace_csv.write_trace_entry(trace_entry)

View file

@ -21,7 +21,7 @@
parameter int XLEN = 32;
// GPR setting
parameter int NUM_FLOAT_GPR = 0;
parameter int NUM_FLOAT_GPR = 32;
parameter int NUM_GPR = 32;
parameter int NUM_VEC_GPR = 0;
@ -53,7 +53,7 @@ bit support_unaligned_load_store = 1'b1;
// ISA supported by the processor
riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV32C,
RV32ZBA, RV32ZBB, RV32ZBC, RV32ZBS, RV32B};
RV32ZBA, RV32ZBB, RV32ZBC, RV32ZBS, RV32B, RV32F, RV32FC};
// Interrupt mode support
mtvec_mode_t supported_interrupt_mode[$] = {VECTORED};

View file

@ -768,3 +768,30 @@
rtl_test: core_ibex_base_test
rtl_params:
RV32B: ["ibex_pkg::RV32BFull", "ibex_pkg::RV32BOTEarlGrey", "ibex_pkg::RV32BBalanced"]
# Floating Point Tests
- test: riscv_arithmetic_fp_test
description: >
Arithmetic instruction test, no load/store/branch instructions
gen_opts: >
+instr_cnt=10000
+num_of_sub_program=0
+no_fence=1
+no_data_page=1
+no_branch_jump=1
+boot_mode=m
+enable_floating_point=1
iterations: 10
gen_test: riscv_instr_base_test
rtl_test: core_ibex_base_test
- test: riscv_rand_instr_fp_test
description: >
Random instruction stress test
iterations: 10
gen_test: riscv_instr_base_test
gen_opts: >
+instr_cnt=10000
+num_of_sub_program=5
+enable_floating_point=1
rtl_test: core_ibex_base_test

View file

@ -68,6 +68,31 @@ module core_ibex_tb_top;
parameter bit XInterface = 1'b1;
parameter bit MemInterface = 1'b1;
logic x_compressed_valid;
logic x_compressed_ready;
ibex_pkg::x_compressed_req_t x_compressed_req;
ibex_pkg::x_compressed_resp_t x_compressed_resp;
logic x_issue_valid;
logic x_issue_ready;
ibex_pkg::x_issue_req_t x_issue_req;
ibex_pkg::x_issue_resp_t x_issue_resp;
logic x_commit_valid;
ibex_pkg::x_commit_t x_commit;
logic x_mem_valid;
logic x_mem_ready;
ibex_pkg::x_mem_req_t x_mem_req;
ibex_pkg::x_mem_resp_t x_mem_resp;
logic x_mem_result_valid;
ibex_pkg::x_mem_result_t x_mem_result;
logic x_result_valid;
logic x_result_ready;
ibex_pkg::x_result_t x_result;
ibex_top_tracing #(
.DmHaltAddr (32'h`BOOT_ADDR + 'h0 ),
.DmExceptionAddr (32'h`BOOT_ADDR + 'h4 ),
@ -139,27 +164,83 @@ module core_ibex_tb_top;
.alert_major_bus_o (dut_if.alert_major_bus ),
.core_sleep_o (dut_if.core_sleep ),
.x_compressed_valid_o ( ),
.x_compressed_ready_i (1'b0 ),
.x_compressed_req_o ( ),
.x_compressed_resp_i ('0 ),
.x_issue_valid_o ( ),
.x_issue_ready_i (1'b0 ),
.x_issue_req_o ( ),
.x_issue_resp_i ('0 ),
.x_commit_valid_o ( ),
.x_commit_o ( ),
.x_mem_valid_i (1'b0 ),
.x_mem_ready_o ( ),
.x_mem_req_i ('0 ),
.x_mem_resp_o ( ),
.x_mem_result_valid_o ( ),
.x_mem_result_o ( ),
.x_result_valid_i (1'b0 ),
.x_result_ready_o ( ),
.x_result_i ('0 )
.x_compressed_valid_o (x_compressed_valid ),
.x_compressed_ready_i (x_compressed_ready ),
.x_compressed_req_o (x_compressed_req ),
.x_compressed_resp_i (x_compressed_resp ),
.x_issue_valid_o (x_issue_valid ),
.x_issue_ready_i (x_issue_ready ),
.x_issue_req_o (x_issue_req ),
.x_issue_resp_i (x_issue_resp ),
.x_commit_valid_o (x_commit_valid ),
.x_commit_o (x_commit ),
.x_mem_valid_i (x_mem_valid ),
.x_mem_ready_o (x_mem_ready ),
.x_mem_req_i (x_mem_req ),
.x_mem_resp_o (x_mem_resp ),
.x_mem_result_valid_o (x_mem_result_valid ),
.x_mem_result_o (x_mem_result ),
.x_result_valid_i (x_result_valid ),
.x_result_ready_o (x_result_ready ),
.x_result_i (x_result )
);
fpu_ss #(
.PULP_ZFINX ( 0 ),
.INPUT_BUFFER_DEPTH ( 2 ),
.OUT_OF_ORDER ( 1 ),
.FORWARDING ( 1 ),
.FPU_FEATURES ( ),
.FPU_IMPLEMENTATION ( )
) fpu_ss_i (
// clock and reset
.clk_i (clk),
.rst_ni (rst_n),
// Compressed Interface
.x_compressed_valid_i (x_compressed_valid),
.x_compressed_ready_o (x_compressed_ready),
.x_compressed_req_i (x_compressed_req),
.x_compressed_resp_o (x_compressed_resp),
// Issue Interface
.x_issue_valid_i (x_issue_valid),
.x_issue_ready_o (x_issue_ready),
.x_issue_req_i (x_issue_req),
.x_issue_resp_o (x_issue_resp),
// Commit Interface
.x_commit_valid_i (x_commit_valid),
.x_commit_i (x_commit),
// Memory Request/Response Interface
.x_mem_valid_o (x_mem_valid),
.x_mem_ready_i (x_mem_ready),
.x_mem_req_o (x_mem_req),
.x_mem_resp_i (x_mem_resp),
// Memory Result Interface
.x_mem_result_valid_i (x_mem_result_valid),
.x_mem_result_i (x_mem_result),
// Result Interface
.x_result_valid_o (x_result_valid),
.x_result_ready_i (x_result_ready),
.x_result_o (x_result)
);
// always_comb begin
// if (fpu_ss_i.fpr_we) begin
// force dut.u_ibex_top.u_ibex_core.rvfi_rd_wdata_d = fpu_ss_i.fpr_wb_data;
// end else begin
// release dut.u_ibex_top.u_ibex_core.rvfi_rd_wdata_d;
// end
// end
always_comb begin
force dut.u_ibex_top.u_ibex_core.rvfi_rd_wdata_fp = fpu_ss_i.fpr_wb_data;
end
// We should never see any alerts triggered in normal testing
`ASSERT(NoAlertsTriggered,
!dut_if.alert_minor && !dut_if.alert_major_internal && !dut_if.alert_major_bus, clk, !rst_n)

View file

@ -149,6 +149,7 @@ targets:
# RAM primitives wider than 64bit (required for ECC) fail to build in
# Verilator without increasing the unroll count (see Verilator#1266)
- "--unroll-count 72"
- "-Wno-BLKANDNBLK"
sim:
<<: *default_target
@ -171,7 +172,17 @@ targets:
- '-CFLAGS "-std=c++11 -Wall -DVM_TRACE_FMT_FST -DTOPLEVEL_NAME=ibex_simple_system -g"'
- '-LDFLAGS "-pthread -lutil -lelf"'
- "-Wall"
- "-Wwarn-IMPERFECTSCH"
# - "-Wwarn-IMPERFECTSCH"
# RAM primitives wider than 64bit (required for ECC) fail to build in
# Verilator without increasing the unroll count (see Verilator#1266)
- "--unroll-count 72"
- "-Wno-BLKANDNBLK"
- "-Wno-UNUSED"
- "-Wno-WIDTH"
- "-Wno-LITENDIAN"
- "-Wno-UNOPTFLAT"
- "-Wno-UNSIGNED"
- "-Wno-WIDTHCONCAT"
- "-Wno-VARHIDDEN"
- "-Wno-IMPORTSTAR"
- "-Wno-DECLFILENAME"

View file

@ -9,6 +9,7 @@ filesets:
depend:
- lowrisc:ibex:ibex_top_tracing
- lowrisc:ibex:sim_shared
- lowrisc:ibex:fpu_ss
files:
- rtl/ibex_simple_system.sv
file_type: systemVerilogSource

View file

@ -185,6 +185,31 @@ module ibex_simple_system (
assign instr_rdata_intg = '0;
end
logic x_compressed_valid;
logic x_compressed_ready;
ibex_pkg::x_compressed_req_t x_compressed_req;
ibex_pkg::x_compressed_resp_t x_compressed_resp;
logic x_issue_valid;
logic x_issue_ready;
ibex_pkg::x_issue_req_t x_issue_req;
ibex_pkg::x_issue_resp_t x_issue_resp;
logic x_commit_valid;
ibex_pkg::x_commit_t x_commit;
logic x_mem_valid;
logic x_mem_ready;
ibex_pkg::x_mem_req_t x_mem_req;
ibex_pkg::x_mem_resp_t x_mem_resp;
logic x_mem_result_valid;
ibex_pkg::x_mem_result_t x_mem_result;
logic x_result_valid;
logic x_result_ready;
ibex_pkg::x_result_t x_result;
ibex_top_tracing #(
.SecureIbex ( SecureIbex ),
.ICacheScramble ( ICacheScramble ),
@ -258,27 +283,71 @@ module ibex_simple_system (
.alert_major_bus_o (),
.core_sleep_o (),
.x_compressed_valid_o (),
.x_compressed_ready_i (1'b0),
.x_compressed_req_o (),
.x_compressed_resp_i ('0),
.x_issue_valid_o (),
.x_issue_ready_i (1'b0),
.x_issue_req_o (),
.x_issue_resp_i ('0),
.x_commit_valid_o (),
.x_commit_o (),
.x_mem_valid_i (1'b0),
.x_mem_ready_o (),
.x_mem_req_i ('0),
.x_mem_resp_o (),
.x_mem_result_valid_o (),
.x_mem_result_o (),
.x_result_valid_i (1'b0),
.x_result_ready_o (),
.x_result_i ('0)
.x_compressed_valid_o (x_compressed_valid),
.x_compressed_ready_i (x_compressed_ready),
.x_compressed_req_o (x_compressed_req),
.x_compressed_resp_i (x_compressed_resp),
.x_issue_valid_o (x_issue_valid),
.x_issue_ready_i (x_issue_ready),
.x_issue_req_o (x_issue_req),
.x_issue_resp_i (x_issue_resp),
.x_commit_valid_o (x_commit_valid),
.x_commit_o (x_commit),
.x_mem_valid_i (x_mem_valid),
.x_mem_ready_o (x_mem_ready),
.x_mem_req_i (x_mem_req),
.x_mem_resp_o (x_mem_resp),
.x_mem_result_valid_o (x_mem_result_valid),
.x_mem_result_o (x_mem_result),
.x_result_valid_i (x_result_valid),
.x_result_ready_o (x_result_ready),
.x_result_i (x_result)
);
fpu_ss #(
.PULP_ZFINX ( 0 ),
.INPUT_BUFFER_DEPTH ( 2 ),
.OUT_OF_ORDER ( 1 ),
.FORWARDING ( 1 ),
.FPU_FEATURES ( ),
.FPU_IMPLEMENTATION ( )
) fpu_ss_i (
// clock and reset
.clk_i (clk_sys),
.rst_ni (rst_sys_n),
// Compressed Interface
.x_compressed_valid_i (x_compressed_valid),
.x_compressed_ready_o (x_compressed_ready),
.x_compressed_req_i (x_compressed_req),
.x_compressed_resp_o (x_compressed_resp),
// Issue Interface
.x_issue_valid_i (x_issue_valid),
.x_issue_ready_o (x_issue_ready),
.x_issue_req_i (x_issue_req),
.x_issue_resp_o (x_issue_resp),
// Commit Interface
.x_commit_valid_i (x_commit_valid),
.x_commit_i (x_commit),
// Memory Request/Response Interface
.x_mem_valid_o (x_mem_valid),
.x_mem_ready_i (x_mem_ready),
.x_mem_req_o (x_mem_req),
.x_mem_resp_i (x_mem_resp),
// Memory Result Interface
.x_mem_result_valid_i (x_mem_result_valid),
.x_mem_result_i (x_mem_result),
// Result Interface
.x_result_valid_o (x_result_valid),
.x_result_ready_i (x_result_ready),
.x_result_o (x_result)
);
// SRAM block for instruction and data storage
ram_2p #(
.Depth(1024*1024/4),

View file

@ -8,7 +8,7 @@ COMMON_SRCS = $(wildcard $(COMMON_DIR)/*.c)
INCS := -I$(COMMON_DIR)
# ARCH = rv32im # to disable compressed instructions
ARCH ?= rv32imc
ARCH ?= rv32imfc
ifdef PROGRAM
PROGRAM_C := $(PROGRAM).c

View file

@ -0,0 +1,14 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# Generate a baremetal application
# Name of the program $(PROGRAM).c will be added as a source file
PROGRAM = hello_test_float
PROGRAM_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
# Any extra source files to include in the build. Use the upper case .S
# extension for assembly files
EXTRA_SRCS :=
include ${PROGRAM_DIR}/../common/common.mk

View file

@ -0,0 +1,53 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include "simple_system_common.h"
// #include "stdio.h"
volatile float a, b, c;
void add(float a, float b, float *res) {
*res = a + a * b;
}
int main(int argc, char **argv) {
pcount_enable(0);
pcount_reset();
pcount_enable(1);
a = 123.243;
b = 475.874;
add(a, b, &c);
// printf("The result is: %f", c);
puts("Hello simple system\n");
puthex(0xDEADBEEF);
putchar('\n');
puthex(0xBAADF00D);
putchar('\n');
pcount_enable(0);
// Enable periodic timer interrupt
// (the actual timebase is a bit meaningless in simulation)
timer_enable(2000);
uint64_t last_elapsed_time = get_elapsed_time();
while (last_elapsed_time <= 4) {
uint64_t cur_time = get_elapsed_time();
if (cur_time != last_elapsed_time) {
last_elapsed_time = cur_time;
if (last_elapsed_time & 1) {
puts("Tick!\n");
} else {
puts("Tock!\n");
}
}
asm volatile("wfi");
}
return 0;
}

View file

@ -1238,6 +1238,51 @@ module ibex_core import ibex_pkg::*; #(
end
`ifdef RVFI
typedef struct packed {
logic [63:0] rvfi_order;
logic [31:0] rvfi_insn;
logic rvfi_trap;
logic rvfi_halt;
logic rvfi_intr;
logic [ 1:0] rvfi_mode;
logic [ 1:0] rvfi_ixl;
logic [ 4:0] rvfi_rs1_addr;
logic [ 4:0] rvfi_rs2_addr;
logic [ 4:0] rvfi_rs3_addr;
logic [31:0] rvfi_rs1_rdata;
logic [31:0] rvfi_rs2_rdata;
logic [31:0] rvfi_rs3_rdata;
logic [ 4:0] rvfi_rd_addr;
logic [31:0] rvfi_rd_wdata;
logic [31:0] rvfi_pc_rdata;
logic [31:0] rvfi_pc_wdata;
logic [31:0] rvfi_mem_addr;
logic [ 3:0] rvfi_mem_rmask;
logic [ 3:0] rvfi_mem_wmask;
logic [31:0] rvfi_mem_rdata;
logic [31:0] rvfi_mem_wdata;
logic [31:0] rvfi_ext_mip;
logic rvfi_ext_nmi;
logic rvfi_ext_debug_req;
logic [63:0] rvfi_ext_mcycle;
} rvfi_t;
rvfi_t rvfi_ibex_push, rvfi_ibex_pop;
rvfi_t [ICB_DEPTH-1:0] rvfi_xif_q;
rvfi_t rvfi_out;
logic rvfi_out_valid;
logic [ICB_ID_W-1:0] rvfi_xif_id_q;
logic rvfi_xif_id_valid_q;
logic rvfi_ibex_push_valid;
logic rvfi_ibex_pop_valid, rvfi_ibex_pop_ready;
logic rvfi_xif_push_valid;
logic rvfi_xif_pop_valid, rvfi_xif_pop_ready;
rvfi_t [31:0] rvfi_xif_buffer;
logic [31:0] rvfi_xif_valid_q, rvfi_xif_valid_d;
logic [5:0] rvfi_xif_addr_push, rvfi_xif_addr_pop;
logic [5:0] rvfi_xif_addr_fin;
// When writeback stage is present RVFI information is emitted when instruction is finished in
// third stage but some information must be captured whilst the instruction is in the second
// stage. Without writeback stage RVFI information is all emitted when instruction retires in
@ -1292,6 +1337,8 @@ module ibex_core import ibex_pkg::*; #(
logic [31:0] rvfi_rd_wdata_wb;
logic [31:0] rvfi_rd_wdata_d;
logic [31:0] rvfi_rd_wdata_q;
logic [31:0] rvfi_rd_wdata_fp;
logic [31:0] rvfi_rd_wdata_int;
logic rvfi_rd_we_wb;
logic [3:0] rvfi_mem_mask_int;
logic [31:0] rvfi_mem_rdata_d;
@ -1303,10 +1350,9 @@ module ibex_core import ibex_pkg::*; #(
logic rvfi_trap_id;
logic rvfi_trap_wb;
logic [63:0] rvfi_stage_order_d;
logic [63:0] rvfi_stage_order_last;
logic [63:0] rvfi_stage_order_q;
logic rvfi_id_done;
logic rvfi_wb_done;
logic rvfi_xif_last_q;
logic new_debug_req;
logic new_nmi;
@ -1327,47 +1373,65 @@ module ibex_core import ibex_pkg::*; #(
logic rvfi_stage_valid_d [RVFI_STAGES];
logic [ICB_DEPTH-1:0][63:0] rvfi_offl_order;
logic [ICB_DEPTH-1:0][31:0] rvfi_offl_rs1_rdata;
logic [ICB_DEPTH-1:0][31:0] rvfi_offl_rs2_rdata;
logic [ICB_DEPTH-1:0][31:0] rvfi_offl_rs3_rdata;
logic [ICB_DEPTH-1:0][4:0] rvfi_offl_rs1_addr;
logic [ICB_DEPTH-1:0][4:0] rvfi_offl_rs2_addr;
logic [ICB_DEPTH-1:0][4:0] rvfi_offl_rs3_addr;
logic [ICB_DEPTH-1:0][4:0] rvfi_offl_rd_addr;
logic [ICB_DEPTH-1:0][31:0] rvfi_offl_insn;
logic [ICB_DEPTH-1:0][31:0] rvfi_offl_pc_rdata;
logic [ICB_DEPTH-1:0][31:0] rvfi_offl_pc_wdata;
logic [ICB_DEPTH-1:0][1:0] rvfi_offl_mode;
logic instr_id_xif_mem;
logic instr_id_xif_mem_result;
logic [ICB_ID_W-1:0] rvfi_xif_issue_id;
logic [ICB_ID_W-1:0] rvfi_xif_issue_id_q;
logic [ICB_ID_W-1:0] rvfi_xif_commit_id;
logic [ICB_ID_W-1:0] rvfi_xif_mem_id;
logic [ICB_ID_W-1:0] rvfi_xif_mem_result_id;
logic [ICB_ID_W-1:0] rvfi_xif_result_id;
assign rvfi_valid = rvfi_stage_valid [RVFI_STAGES-1];
assign rvfi_order = rvfi_stage_order [RVFI_STAGES-1];
assign rvfi_insn = rvfi_stage_insn [RVFI_STAGES-1];
assign rvfi_trap = rvfi_stage_trap [RVFI_STAGES-1];
assign rvfi_halt = rvfi_stage_halt [RVFI_STAGES-1];
assign rvfi_intr = rvfi_stage_intr [RVFI_STAGES-1];
assign rvfi_mode = rvfi_stage_mode [RVFI_STAGES-1];
assign rvfi_ixl = rvfi_stage_ixl [RVFI_STAGES-1];
assign rvfi_rs1_addr = rvfi_stage_rs1_addr [RVFI_STAGES-1];
assign rvfi_rs2_addr = rvfi_stage_rs2_addr [RVFI_STAGES-1];
assign rvfi_rs3_addr = rvfi_stage_rs3_addr [RVFI_STAGES-1];
assign rvfi_rs1_rdata = rvfi_stage_rs1_rdata[RVFI_STAGES-1];
assign rvfi_rs2_rdata = rvfi_stage_rs2_rdata[RVFI_STAGES-1];
assign rvfi_rs3_rdata = rvfi_stage_rs3_rdata[RVFI_STAGES-1];
assign rvfi_rd_addr = rvfi_stage_rd_addr [RVFI_STAGES-1];
assign rvfi_rd_wdata = rvfi_stage_rd_wdata [RVFI_STAGES-1];
assign rvfi_pc_rdata = rvfi_stage_pc_rdata [RVFI_STAGES-1];
assign rvfi_pc_wdata = rvfi_stage_pc_wdata [RVFI_STAGES-1];
assign rvfi_mem_addr = rvfi_stage_mem_addr [RVFI_STAGES-1];
assign rvfi_mem_rmask = rvfi_stage_mem_rmask[RVFI_STAGES-1];
assign rvfi_mem_wmask = rvfi_stage_mem_wmask[RVFI_STAGES-1];
assign rvfi_mem_rdata = rvfi_stage_mem_rdata[RVFI_STAGES-1];
assign rvfi_mem_wdata = rvfi_stage_mem_wdata[RVFI_STAGES-1];
assign rvfi_valid = rvfi_out_valid;
assign rvfi_order = rvfi_out.rvfi_order;
assign rvfi_insn = rvfi_out.rvfi_insn;
assign rvfi_trap = rvfi_out.rvfi_trap;
assign rvfi_halt = rvfi_out.rvfi_halt;
assign rvfi_intr = rvfi_out.rvfi_intr;
assign rvfi_mode = rvfi_out.rvfi_mode;
assign rvfi_ixl = rvfi_out.rvfi_ixl;
assign rvfi_rs1_addr = rvfi_out.rvfi_rs1_addr;
assign rvfi_rs2_addr = rvfi_out.rvfi_rs2_addr;
assign rvfi_rs3_addr = rvfi_out.rvfi_rs3_addr;
assign rvfi_rs1_rdata = rvfi_out.rvfi_rs1_rdata;
assign rvfi_rs2_rdata = rvfi_out.rvfi_rs2_rdata;
assign rvfi_rs3_rdata = rvfi_out.rvfi_rs3_rdata;
assign rvfi_rd_addr = rvfi_out.rvfi_rd_addr;
assign rvfi_rd_wdata = rvfi_out.rvfi_rd_wdata;
assign rvfi_pc_rdata = rvfi_out.rvfi_pc_rdata;
assign rvfi_pc_wdata = rvfi_out.rvfi_pc_wdata;
assign rvfi_mem_addr = rvfi_out.rvfi_mem_addr;
assign rvfi_mem_rmask = rvfi_out.rvfi_mem_rmask;
assign rvfi_mem_wmask = rvfi_out.rvfi_mem_wmask;
assign rvfi_mem_rdata = rvfi_out.rvfi_mem_rdata;
assign rvfi_mem_wdata = rvfi_out.rvfi_mem_wdata;
assign rvfi_ext_mip = rvfi_out.rvfi_ext_mip;
assign rvfi_ext_nmi = rvfi_out.rvfi_ext_nmi;
assign rvfi_ext_debug_req = rvfi_out.rvfi_ext_debug_req;
assign rvfi_ext_mcycle = rvfi_out.rvfi_ext_mcycle;
assign rvfi_ibex_push_valid = rvfi_stage_valid [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_order = rvfi_stage_order [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_insn = rvfi_stage_insn [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_trap = rvfi_stage_trap [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_halt = rvfi_stage_halt [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_intr = rvfi_stage_intr [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_mode = rvfi_stage_mode [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_ixl = rvfi_stage_ixl [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_rs1_addr = rvfi_stage_rs1_addr [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_rs2_addr = rvfi_stage_rs2_addr [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_rs3_addr = rvfi_stage_rs3_addr [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_rs1_rdata = rvfi_stage_rs1_rdata[RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_rs2_rdata = rvfi_stage_rs2_rdata[RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_rs3_rdata = rvfi_stage_rs3_rdata[RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_rd_addr = rvfi_stage_rd_addr [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_rd_wdata = rvfi_stage_rd_wdata [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_pc_rdata = rvfi_stage_pc_rdata [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_pc_wdata = rvfi_stage_pc_wdata [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_mem_addr = rvfi_stage_mem_addr [RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_mem_rmask = rvfi_stage_mem_rmask[RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_mem_wmask = rvfi_stage_mem_wmask[RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_mem_rdata = rvfi_stage_mem_rdata[RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_mem_wdata = rvfi_stage_mem_wdata[RVFI_STAGES-1];
assign rvfi_rd_addr_wb = rf_waddr_wb;
assign rvfi_rd_wdata_wb = rf_we_wb ? rf_wdata_wb : rf_wdata_lsu;
@ -1376,16 +1440,16 @@ module ibex_core import ibex_pkg::*; #(
always_comb begin
// Use always_comb instead of continuous assign so first assign can set 0 as default everywhere
// that is overridden by more specific settings.
rvfi_ext_mip = '0;
rvfi_ext_mip[CSR_MSIX_BIT] = rvfi_ext_stage_mip[RVFI_STAGES].irq_software;
rvfi_ext_mip[CSR_MTIX_BIT] = rvfi_ext_stage_mip[RVFI_STAGES].irq_timer;
rvfi_ext_mip[CSR_MEIX_BIT] = rvfi_ext_stage_mip[RVFI_STAGES].irq_external;
rvfi_ext_mip[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = rvfi_ext_stage_mip[RVFI_STAGES].irq_fast;
rvfi_ibex_push.rvfi_ext_mip = '0;
rvfi_ibex_push.rvfi_ext_mip[CSR_MSIX_BIT] = rvfi_ext_stage_mip[RVFI_STAGES].irq_software;
rvfi_ibex_push.rvfi_ext_mip[CSR_MTIX_BIT] = rvfi_ext_stage_mip[RVFI_STAGES].irq_timer;
rvfi_ibex_push.rvfi_ext_mip[CSR_MEIX_BIT] = rvfi_ext_stage_mip[RVFI_STAGES].irq_external;
rvfi_ibex_push.rvfi_ext_mip[CSR_MFIX_BIT_HIGH:CSR_MFIX_BIT_LOW] = rvfi_ext_stage_mip[RVFI_STAGES].irq_fast;
end
assign rvfi_ext_nmi = rvfi_ext_stage_nmi[RVFI_STAGES];
assign rvfi_ext_debug_req = rvfi_ext_stage_debug_req[RVFI_STAGES];
assign rvfi_ext_mcycle = rvfi_ext_stage_mcycle[RVFI_STAGES-1];
assign rvfi_ibex_push.rvfi_ext_nmi = rvfi_ext_stage_nmi[RVFI_STAGES];
assign rvfi_ibex_push.rvfi_ext_debug_req = rvfi_ext_stage_debug_req[RVFI_STAGES];
assign rvfi_ibex_push.rvfi_ext_mcycle = rvfi_ext_stage_mcycle[RVFI_STAGES-1];
// When an instruction takes a trap the `rvfi_trap` signal will be set. Instructions that take
// traps flush the pipeline so ordinarily wouldn't be seen to be retire. The RVFI tracking
@ -1406,11 +1470,11 @@ module ibex_core import ibex_pkg::*; #(
// awaiting instruction retirement and RF Write data/Mem read data whilst instruction is in WB
// So first stage becomes valid when instruction leaves ID/EX stage and remains valid until
// instruction leaves WB
assign rvfi_stage_valid_d[0] = (rvfi_id_done & ~dummy_instr_id) | instr_id_xif_done |
assign rvfi_stage_valid_d[0] = (rvfi_id_done & ~dummy_instr_id) |
(rvfi_stage_valid[0] & ~rvfi_wb_done);
// Second stage is output stage so simple valid cycle after instruction leaves WB (and so has
// retired)
assign rvfi_stage_valid_d[1] = rvfi_wb_done;
assign rvfi_stage_valid_d[1] = rvfi_wb_done & rvfi_stage_valid[0];
// Signal new instruction in WB cycle after instruction leaves ID/EX (to enter WB)
logic rvfi_instr_new_wb_q;
@ -1434,7 +1498,7 @@ module ibex_core import ibex_pkg::*; #(
end else begin : gen_rvfi_no_wb_stage
// Without writeback stage first RVFI stage is output stage so simply valid the cycle after
// instruction leaves ID/EX (and so has retired)
assign rvfi_stage_valid_d[0] = (rvfi_id_done & ~dummy_instr_id) | instr_id_xif_done;
assign rvfi_stage_valid_d[0] = (rvfi_id_done & ~dummy_instr_id);
// Without writeback stage signal new instr_new_wb when instruction enters ID/EX to correctly
// setup register write signals
assign rvfi_instr_new_wb = instr_new_id;
@ -1443,10 +1507,7 @@ module ibex_core import ibex_pkg::*; #(
assign rvfi_wb_done = instr_done_wb;
end
assign rvfi_stage_order_last = rvfi_xif_last_q ?
rvfi_offl_order[rvfi_xif_issue_id_q] : rvfi_stage_order[0];
assign rvfi_stage_order_d = dummy_instr_id ?
rvfi_stage_order_last : rvfi_stage_order_last + 64'd1;
assign rvfi_stage_order_d = dummy_instr_id ? rvfi_stage_order_q : rvfi_stage_order_q + 64'd1;
// For interrupts and debug Ibex will take the relevant trap as soon as whatever instruction in ID
// finishes or immediately if the ID stage is empty. The rvfi_ext interface provides the DV
@ -1517,51 +1578,190 @@ module ibex_core import ibex_pkg::*; #(
end
end
assign rvfi_xif_issue_id = x_issue_req_o.id[ICB_ID_W-1:0];
assign rvfi_xif_commit_id = x_commit_o.id[ICB_ID_W-1:0];
assign rvfi_xif_result_id = x_result_i.id[ICB_ID_W-1:0];
prim_fifo_sync #(
.Width (5),
.Pass (1'b1),
.Depth (32),
.OutputZeroIfEmpty(1'b1)
) rvfi_xif_fifo_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (1'b0),
// Record the metadata of offloaded instructions, that writeback to the
// integer register file. those will appear in the core trace log.
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_offl_order <= '0;
rvfi_offl_rs1_rdata <= '0;
rvfi_offl_rs2_rdata <= '0;
rvfi_offl_rs3_rdata <= '0;
rvfi_offl_rs1_addr <= '0;
rvfi_offl_rs2_addr <= '0;
rvfi_offl_rs3_addr <= '0;
rvfi_offl_rd_addr <= '0;
rvfi_offl_insn <= '0;
rvfi_offl_pc_rdata <= '0;
rvfi_offl_pc_wdata <= '0;
rvfi_offl_mode <= '0;
rvfi_xif_issue_id_q <= '0;
end else if (instr_id_xif_offl) begin
rvfi_offl_order[rvfi_xif_issue_id] <= rvfi_stage_order_d;
rvfi_offl_rs1_rdata[rvfi_xif_issue_id] <= x_issue_req_o.rs[0];
rvfi_offl_rs2_rdata[rvfi_xif_issue_id] <= x_issue_req_o.rs[1];
rvfi_offl_rs3_rdata[rvfi_xif_issue_id] <= (X_NUM_RS == 2) ? '0 : x_issue_req_o.rs[2];
rvfi_offl_rs1_addr[rvfi_xif_issue_id] <= instr_rs1;
rvfi_offl_rs2_addr[rvfi_xif_issue_id] <= instr_rs2;
rvfi_offl_rs3_addr[rvfi_xif_issue_id] <= instr_rs3;
rvfi_offl_rd_addr[rvfi_xif_issue_id] <= instr_rd;
rvfi_offl_insn[rvfi_xif_issue_id] <= rvfi_insn_id;
rvfi_offl_pc_rdata[rvfi_xif_issue_id] <= pc_id;
rvfi_offl_pc_wdata[rvfi_xif_issue_id] <= pc_if;
rvfi_offl_mode[rvfi_xif_issue_id] <= {priv_mode_id};
rvfi_xif_issue_id_q <= rvfi_xif_issue_id;
.wvalid_i(rvfi_xif_push_valid),
.wready_o(),
.wdata_i (rvfi_xif_addr_push),
.rvalid_o(rvfi_xif_pop_valid),
.rready_i(rvfi_xif_pop_ready),
.rdata_o (rvfi_xif_addr_pop),
.full_o (),
.depth_o()
);
prim_fifo_sync #(
.Width ($bits(rvfi_ibex_push)),
.Pass (1'b1),
.Depth (32),
.OutputZeroIfEmpty(1'b1)
) rvfi_ibex_fifo_i (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (1'b0),
.wvalid_i(rvfi_ibex_push_valid),
.wready_o(),
.wdata_i (rvfi_ibex_push),
.rvalid_o(rvfi_ibex_pop_valid),
.rready_i(rvfi_ibex_pop_ready),
.rdata_o (rvfi_ibex_pop),
.full_o (),
.depth_o()
);
assign rvfi_xif_addr_fin = rvfi_xif_q[rvfi_xif_id_q].rvfi_order[4:0];
assign rvfi_xif_addr_push = rvfi_stage_order_d[4:0];
always_comb begin
rvfi_xif_valid_d = rvfi_xif_valid_q;
if (rvfi_xif_pop_ready) begin
rvfi_xif_valid_d[rvfi_xif_addr_pop] = 1'b0;
end
if (rvfi_xif_id_valid_q) begin
rvfi_xif_valid_d[rvfi_xif_addr_fin] = 1'b1;
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_xif_last_q <= 1'b0;
end else if (instr_id_xif_offl) begin
rvfi_xif_last_q <= 1'b1;
end else if (rvfi_id_done) begin
rvfi_xif_last_q <= 1'b0;
rvfi_xif_buffer <= '0;
end else if (rvfi_xif_id_valid_q) begin
rvfi_xif_buffer[rvfi_xif_addr_fin] <= rvfi_xif_q[rvfi_xif_id_q];
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_xif_id_valid_q <= 1'b0;
rvfi_xif_id_q <= '0;
end else begin
rvfi_xif_id_valid_q <= instr_id_xif_done;
rvfi_xif_id_q <= rvfi_xif_result_id;
end
end
always_comb begin
rvfi_out_valid = 1'b0;
rvfi_out = '0;
rvfi_xif_pop_ready = 1'b0;
rvfi_ibex_pop_ready = 1'b0;
if (rvfi_xif_pop_valid & rvfi_ibex_pop_valid) begin
if (rvfi_ibex_pop.rvfi_order < rvfi_xif_buffer[rvfi_xif_addr_pop].rvfi_order) begin
rvfi_ibex_pop_ready = 1'b1;
rvfi_out_valid = 1'b1;
rvfi_out = rvfi_ibex_pop;
end else begin
if (rvfi_xif_valid_q[rvfi_xif_addr_pop]) begin
rvfi_xif_pop_ready = 1'b1;
rvfi_out_valid = 1'b1;
rvfi_out = rvfi_xif_buffer[rvfi_xif_addr_pop];
end
end
end else if (rvfi_xif_pop_valid & ~rvfi_ibex_pop_valid) begin
if (rvfi_xif_valid_q[rvfi_xif_addr_pop]) begin
rvfi_xif_pop_ready = 1'b1;
rvfi_out_valid = 1'b1;
rvfi_out = rvfi_xif_buffer[rvfi_xif_addr_pop];
end
end else if (~rvfi_xif_pop_valid & rvfi_ibex_pop_valid) begin
rvfi_ibex_pop_ready = 1'b1;
rvfi_out_valid = 1'b1;
rvfi_out = rvfi_ibex_pop;
end
end
assign rvfi_xif_issue_id = x_issue_req_o.id[ICB_ID_W-1:0];
assign rvfi_xif_mem_id = x_mem_req_i.id[ICB_ID_W-1:0];
assign rvfi_xif_mem_result_id = x_mem_result_o.id[ICB_ID_W-1:0];
assign rvfi_xif_result_id = x_result_i.id[ICB_ID_W-1:0];
assign instr_id_xif_mem = x_mem_valid_i & x_mem_ready_o;
assign instr_id_xif_mem_result = x_mem_result_valid_o;
assign rvfi_xif_push_valid = instr_id_xif_offl;
assign rvfi_rd_wdata_fp = '0;
assign rvfi_rd_wdata_int = x_result_i.data;
// Record the metadata of offloaded instructions, that writeback to the
// integer register file. those will appear in the core trace log.
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_xif_q <= '0;
end else begin
if (instr_id_xif_offl) begin
rvfi_xif_q[rvfi_xif_issue_id].rvfi_order <= rvfi_stage_order_d;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_rs1_rdata <= x_issue_req_o.rs[0];
rvfi_xif_q[rvfi_xif_issue_id].rvfi_rs2_rdata <= x_issue_req_o.rs[1];
rvfi_xif_q[rvfi_xif_issue_id].rvfi_rs3_rdata <= (X_NUM_RS == 2) ? '0 : x_issue_req_o.rs[2];
rvfi_xif_q[rvfi_xif_issue_id].rvfi_rs1_addr <= instr_rs1;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_rs2_addr <= instr_rs2;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_rs3_addr <= instr_rs3;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_rd_addr <= instr_rd;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_insn <= rvfi_insn_id;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_pc_rdata <= pc_id;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_pc_wdata <= pc_if;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_mode <= {priv_mode_id};
rvfi_xif_q[rvfi_xif_issue_id].rvfi_mem_rmask <= '0;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_mem_wmask <= '0;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_mem_rdata <= '0;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_mem_wdata <= '0;
rvfi_xif_q[rvfi_xif_issue_id].rvfi_mem_addr <= '0;
end
if (instr_id_xif_mem) begin
rvfi_xif_q[rvfi_xif_mem_id].rvfi_mem_rmask <= rvfi_mem_mask_int;
rvfi_xif_q[rvfi_xif_mem_id].rvfi_mem_wmask <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
rvfi_xif_q[rvfi_xif_mem_id].rvfi_mem_rdata <= rvfi_mem_rdata_d;
rvfi_xif_q[rvfi_xif_mem_id].rvfi_mem_wdata <= rvfi_mem_wdata_d;
rvfi_xif_q[rvfi_xif_mem_id].rvfi_mem_addr <= rvfi_mem_addr_d;
end
if (instr_id_xif_mem_result) begin
rvfi_xif_q[rvfi_xif_mem_id].rvfi_mem_rdata <= rvfi_mem_rdata_d;
end
if (instr_id_xif_done) begin
rvfi_xif_q[rvfi_xif_result_id].rvfi_halt <= '0;
rvfi_xif_q[rvfi_xif_result_id].rvfi_trap <= rvfi_trap_id;
rvfi_xif_q[rvfi_xif_result_id].rvfi_intr <= rvfi_intr_d;
rvfi_xif_q[rvfi_xif_result_id].rvfi_ixl <= CSR_MISA_MXL;
rvfi_xif_q[rvfi_xif_result_id].rvfi_ext_mip <= '0;
rvfi_xif_q[rvfi_xif_result_id].rvfi_ext_nmi <= '0;
rvfi_xif_q[rvfi_xif_result_id].rvfi_ext_debug_req <= '0;
rvfi_xif_q[rvfi_xif_result_id].rvfi_ext_mcycle <= cs_registers_i.mcycle_counter_i.counter_val_o;
if (id_stage_i.x_result_wb_en) begin
rvfi_xif_q[rvfi_xif_result_id].rvfi_rd_wdata <= rvfi_rd_wdata_int;
end else begin
rvfi_xif_q[rvfi_xif_result_id].rvfi_rd_wdata <= rvfi_rd_wdata_fp;
end
end
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_stage_order_q <= '0;
end else if (instr_id_xif_offl | rvfi_id_done) begin
rvfi_stage_order_q <= rvfi_stage_order_d;
end
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_xif_valid_q <= '0;
end else begin
rvfi_xif_valid_q <= rvfi_xif_valid_d;
end
end
@ -1627,62 +1827,6 @@ module ibex_core import ibex_pkg::*; #(
rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i];
rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i];
rvfi_ext_stage_mcycle[i] <= cs_registers_i.mcycle_counter_i.counter_val_o;
end else if (instr_id_xif_done) begin
if (instr_id_xif_offl & rvfi_xif_issue_id == rvfi_xif_result_id) begin
rvfi_stage_halt[i] <= '0;
rvfi_stage_trap[i] <= rvfi_trap_id;
rvfi_stage_intr[i] <= rvfi_intr_d;
rvfi_stage_order[i] <= rvfi_stage_order_d;
rvfi_stage_insn[i] <= rvfi_insn_id;
rvfi_stage_mode[i] <= {priv_mode_id};
rvfi_stage_ixl[i] <= CSR_MISA_MXL;
rvfi_stage_rs1_addr[i] <= instr_rs1;
rvfi_stage_rs2_addr[i] <= instr_rs2;
rvfi_stage_rs3_addr[i] <= instr_rs3;
rvfi_stage_pc_rdata[i] <= pc_id;
rvfi_stage_pc_wdata[i] <= pc_if;
rvfi_stage_mem_rmask[i] <= rvfi_mem_mask_int;
rvfi_stage_mem_wmask[i] <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
rvfi_stage_rs1_rdata[i] <= x_issue_req_o.rs[0];
rvfi_stage_rs2_rdata[i] <= x_issue_req_o.rs[1];
rvfi_stage_rs3_rdata[i] <= (X_NUM_RS == 2) ? '0 : x_issue_req_o.rs[2];
rvfi_stage_rd_addr[i] <= instr_rd;
rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d;
rvfi_stage_mem_rdata[i] <= '0;
rvfi_stage_mem_wdata[i] <= '0;
rvfi_stage_mem_addr[i] <= '0;
rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i];
rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i];
rvfi_ext_stage_mcycle[i] <= cs_registers_i.mcycle_counter_i.counter_val_o;
end else begin
rvfi_stage_halt[i] <= '0;
rvfi_stage_trap[i] <= rvfi_trap_id;
rvfi_stage_intr[i] <= rvfi_intr_d;
rvfi_stage_order[i] <= rvfi_offl_order[rvfi_xif_commit_id];
rvfi_stage_insn[i] <= rvfi_offl_insn[rvfi_xif_result_id];
rvfi_stage_mode[i] <= rvfi_offl_mode[rvfi_xif_result_id];
rvfi_stage_ixl[i] <= CSR_MISA_MXL;
rvfi_stage_rs1_addr[i] <= rvfi_offl_rs1_addr[rvfi_xif_result_id];
rvfi_stage_rs2_addr[i] <= rvfi_offl_rs2_addr[rvfi_xif_result_id];
rvfi_stage_rs3_addr[i] <= rvfi_offl_rs3_addr[rvfi_xif_result_id];
rvfi_stage_pc_rdata[i] <= rvfi_offl_pc_rdata[rvfi_xif_result_id];
rvfi_stage_pc_wdata[i] <= rvfi_offl_pc_wdata[rvfi_xif_result_id];
rvfi_stage_mem_rmask[i] <= rvfi_mem_mask_int;
rvfi_stage_mem_wmask[i] <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
rvfi_stage_rs1_rdata[i] <= rvfi_offl_rs1_rdata[rvfi_xif_result_id];
rvfi_stage_rs2_rdata[i] <= rvfi_offl_rs2_rdata[rvfi_xif_result_id];
rvfi_stage_rs3_rdata[i] <= rvfi_offl_rs3_rdata[rvfi_xif_result_id];
rvfi_stage_rd_addr[i] <= rvfi_offl_rd_addr[rvfi_xif_result_id];
rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d;
rvfi_stage_mem_rdata[i] <= '0;
rvfi_stage_mem_wdata[i] <= '0;
rvfi_stage_mem_addr[i] <= '0;
rvfi_ext_stage_mip[i+1] <= rvfi_ext_stage_mip[i];
rvfi_ext_stage_nmi[i+1] <= rvfi_ext_stage_nmi[i];
rvfi_ext_stage_debug_req[i+1] <= rvfi_ext_stage_debug_req[i];
rvfi_ext_stage_mcycle[i] <= cs_registers_i.mcycle_counter_i.counter_val_o;
end
end
end else begin
if (rvfi_wb_done) begin

View file

@ -95,6 +95,7 @@ module ibex_tracer (
localparam logic [4:0] RD = (1 << 3);
localparam logic [4:0] MEM = (1 << 4);
logic [4:0] data_accessed;
logic [3:0] data_accessed_fp;
logic trace_log_enable;
initial begin
@ -135,15 +136,27 @@ module ibex_tracer (
if ((data_accessed & RS1) != 0) begin
$fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs1_addr), rvfi_rs1_rdata);
end
if ((data_accessed_fp & RS1) != 0) begin
$fwrite(file_handle, " %s:0x%08x", reg_addr_to_str_fp(rvfi_rs1_addr), rvfi_rs1_rdata);
end
if ((data_accessed & RS2) != 0) begin
$fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs2_addr), rvfi_rs2_rdata);
end
if ((data_accessed_fp & RS2) != 0) begin
$fwrite(file_handle, " %s:0x%08x", reg_addr_to_str_fp(rvfi_rs2_addr), rvfi_rs2_rdata);
end
if ((data_accessed & RS3) != 0) begin
$fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs3_addr), rvfi_rs3_rdata);
end
if ((data_accessed_fp & RS3) != 0) begin
$fwrite(file_handle, " %s:0x%08x", reg_addr_to_str_fp(rvfi_rs3_addr), rvfi_rs3_rdata);
end
if ((data_accessed & RD) != 0) begin
$fwrite(file_handle, " %s=0x%08x", reg_addr_to_str(rvfi_rd_addr), rvfi_rd_wdata);
end
if ((data_accessed_fp & RD) != 0) begin
$fwrite(file_handle, " %s=0x%08x", reg_addr_to_str_fp(rvfi_rd_addr), rvfi_rd_wdata);
end
if ((data_accessed & MEM) != 0) begin
$fwrite(file_handle, " PA:0x%08x", rvfi_mem_addr);
@ -168,6 +181,15 @@ module ibex_tracer (
end
endfunction
// Format register address with "f" prefix, left-aligned to a fixed width of 3 characters.
function automatic string reg_addr_to_str_fp(input logic [4:0] addr);
if (addr < 10) begin
return $sformatf(" f%0d", addr);
end else begin
return $sformatf("f%0d", addr);
end
endfunction
// Get a CSR name for a CSR address.
function automatic string get_csr_name(input logic [11:0] csr_addr);
unique case (csr_addr)
@ -735,6 +757,91 @@ module ibex_tracer (
decoded_str = $sformatf("fence\t%s,%s", predecessor, successor);
endfunction
// floating point support
function automatic void decode_fp_store_insn(input string mnemonic);
data_accessed = MEM;
data_accessed_fp = RS1 | RS2;
decoded_str = $sformatf("%s\tf%0d,%0d(x%0d)",
mnemonic,
rvfi_rs2_addr,
$signed({{20{rvfi_insn[31]}}, rvfi_insn[31:25], rvfi_insn[11:7]}),
rvfi_rs1_addr);
endfunction
function automatic void decode_fp_load_insn(input string mnemonic);
data_accessed = MEM;
data_accessed_fp = RD | RS1;
decoded_str = $sformatf("%s\tf%0d,%0d(x%0d)", mnemonic, rvfi_rd_addr,
$signed({{20 {rvfi_insn[31]}}, rvfi_insn[31:20]}), rvfi_rs1_addr);
endfunction
function automatic void decode_fp_s_insn(input string mnemonic);
data_accessed_fp = RD | RS1;
decoded_str = $sformatf("%s\tf%0d,f%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr);
endfunction
function automatic void decode_fp_s2_insn(input string mnemonic);
data_accessed_fp = RD | RS1 | RS2;
decoded_str = $sformatf("%s\tf%0d,f%0d,f%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr,
rvfi_rs2_addr);
endfunction
function automatic void decode_fp_s3_insn(input string mnemonic);
data_accessed_fp = RD | RS1 | RS2 | RS3;
decoded_str = $sformatf("%s\tf%0d,f%0d,f%0d,f%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr,
rvfi_rs2_addr, rvfi_rs3_addr);
endfunction
function automatic void decode_fp_w_s_insn(input string mnemonic);
data_accessed = RD;
data_accessed_fp = RS1;
decoded_str = $sformatf("%s\tx%0d,f%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr);
endfunction
function automatic void decode_fp_w_s2_insn(input string mnemonic);
data_accessed = RD;
data_accessed_fp = RS1 | RS2;
decoded_str = $sformatf("%s\tx%0d,f%0d,f%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr,
rvfi_rs2_addr);
endfunction
function automatic void decode_fp_s_w_insn(input string mnemonic);
data_accessed = RS1;
data_accessed_fp = RD;
decoded_str = $sformatf("%s\tf%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr);
endfunction
function automatic void decode_fp_compressed_load_insn(input string mnemonic);
logic [7:0] imm;
if (rvfi_insn[1:0] == OPCODE_C0) begin
// C.FLW
imm = {1'b0, rvfi_insn[5], rvfi_insn[12:10], rvfi_insn[6], 2'b00};
end else begin
// C.FLWSP
imm = {rvfi_insn[3:2], rvfi_insn[12], rvfi_insn[6:4], 2'b00};
end
data_accessed = MEM;
data_accessed_fp = RS1 | RD;
decoded_str = $sformatf("%s\tf%0d,%0d(x%0d)", mnemonic, rvfi_rd_addr, imm, rvfi_rs1_addr);
endfunction
function automatic void decode_fp_compressed_store_insn(input string mnemonic);
logic [7:0] imm;
if (rvfi_insn[1:0] == OPCODE_C0) begin
// C.FSW
imm = {1'b0, rvfi_insn[5], rvfi_insn[12:10], rvfi_insn[6], 2'b00};
end else begin
// C.FSWSP
imm = {rvfi_insn[8:7], rvfi_insn[12:9], 2'b00};
end
data_accessed = MEM;
data_accessed_fp = RS1 | RS2;
decoded_str = $sformatf("%s\tf%0d,%0d(x%0d)", mnemonic, rvfi_rs2_addr, imm, rvfi_rs1_addr);
endfunction
// cycle counter
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
@ -761,6 +868,7 @@ module ibex_tracer (
always_comb begin
decoded_str = "";
data_accessed = 5'h0;
data_accessed_fp = 4'h0;
insn_is_compressed = 0;
// Check for compressed instructions
@ -822,6 +930,11 @@ module ibex_tracer (
INSN_CSLLI: decode_ci_cslli_insn("c.slli");
INSN_CLWSP: decode_compressed_load_insn("c.lwsp");
INSN_SWSP: decode_compressed_store_insn("c.swsp");
// FP Instructions
INSN_C_FLW: decode_fp_compressed_load_insn("c.flw");
INSN_C_FSW: decode_fp_compressed_store_insn("c.fsw");
INSN_C_FLWSP: decode_fp_compressed_load_insn("c.flwsp");
INSN_C_FSWSP: decode_fp_compressed_store_insn("c.fswsp");
default: decode_mnemonic("INVALID");
endcase
end
@ -1062,6 +1175,34 @@ module ibex_tracer (
INSN_CRC32C_H: decode_r1_insn("crc32c.h");
INSN_CRC32C_W: decode_r1_insn("crc32c.w");
// RV32F
INSN_FLW: decode_fp_load_insn("flw");
INSN_FSW: decode_fp_store_insn("fsw");
INSN_FMADD_S: decode_fp_s3_insn("fmadd.s");
INSN_FMSUB_S: decode_fp_s3_insn("fmsub.s");
INSN_FNMADD_S: decode_fp_s3_insn("fnmadd.s");
INSN_FNMSUB_S: decode_fp_s3_insn("fnmsub.s");
INSN_FADD_S: decode_fp_s2_insn("fadd.s");
INSN_FSUB_S: decode_fp_s2_insn("fsub.s");
INSN_FMUL_S: decode_fp_s2_insn("fmul.s");
INSN_FDIV_S: decode_fp_s2_insn("fdiv.s");
INSN_FSQRT_S: decode_fp_s_insn("fsqrt.s");
INSN_FSGNJ_S: decode_fp_s2_insn("fsgnj.s");
INSN_FSGNJN_S: decode_fp_s2_insn("fsgnjn.s");
INSN_FSGNJX_S: decode_fp_s2_insn("fsgnjx.s");
INSN_FMIN_S: decode_fp_s2_insn("fmin.s");
INSN_FMAX_S: decode_fp_s2_insn("fmax.s");
INSN_FCVT_W_S: decode_fp_w_s_insn("fcvt.w.s");
INSN_FCVT_WU_S: decode_fp_w_s_insn("fcvt.wu.s");
INSN_FMV_X_W: decode_fp_w_s_insn("fmv.x.w");
INSN_FEQ_S: decode_fp_w_s2_insn("feq.s");
INSN_FLT_S: decode_fp_w_s2_insn("flt.s");
INSN_FLE_S: decode_fp_w_s2_insn("fle.s");
INSN_FCLASS_S: decode_fp_w_s_insn("fclass.s");
INSN_FCVT_S_W: decode_fp_s_w_insn("fcvt.s.w");
INSN_FCVT_S_WU: decode_fp_s_w_insn("fcvt.s.wu");
INSN_FMV_W_X: decode_fp_s_w_insn("fmv.w.x");
default: decode_mnemonic("INVALID");
endcase
end

View file

@ -332,4 +332,40 @@ package ibex_tracer_pkg;
parameter logic [15:0] INSN_CJR = { 3'b100, 1'b0, 5'h0, 5'h0, {OPCODE_C2} };
parameter logic [15:0] INSN_CJALR = { 3'b100, 1'b1, 5'h?, 5'h0, {OPCODE_C2} };
// F Extension
parameter logic [31:0] INSN_FLW = { 17'h?, 3'b010, 5'h?, 7'b0000111 };
parameter logic [31:0] INSN_FSW = { 17'h?, 3'b010, 5'h?, 7'b0100111 };
parameter logic [31:0] INSN_FMADD_S = { 5'h?, 2'b00, 18'h?, 7'b1000011 };
parameter logic [31:0] INSN_FMSUB_S = { 5'h?, 2'b00, 18'h?, 7'b1000111 };
parameter logic [31:0] INSN_FNMSUB_S = { 5'h?, 2'b00, 18'h?, 7'b1001011 };
parameter logic [31:0] INSN_FNMADD_S = { 5'h?, 2'b00, 18'h?, 7'b1001111 };
parameter logic [31:0] INSN_FADD_S = { 5'b00000, 2'b00, 18'h?, 7'b1010011 };
parameter logic [31:0] INSN_FSUB_S = { 5'b00001, 2'b00, 18'h?, 7'b1010011 };
parameter logic [31:0] INSN_FMUL_S = { 5'b00010, 2'b00, 18'h?, 7'b1010011 };
parameter logic [31:0] INSN_FDIV_S = { 5'b00011, 2'b00, 18'h?, 7'b1010011 };
parameter logic [31:0] INSN_FSQRT_S = { 5'b01011, 2'b00, 5'b00000, 13'h?, 7'b1010011 };
parameter logic [31:0] INSN_FSGNJ_S = { 5'b00100, 2'b00, 10'h?, 3'b000, 5'h?, 7'b1010011 };
parameter logic [31:0] INSN_FSGNJN_S = { 5'b00100, 2'b00, 10'h?, 3'b001, 5'h?, 7'b1010011 };
parameter logic [31:0] INSN_FSGNJX_S = { 5'b00100, 2'b00, 10'h?, 3'b010, 5'h?, 7'b1010011 };
parameter logic [31:0] INSN_FMIN_S = { 5'b00101, 2'b00, 10'h?, 3'b000, 5'h?, 7'b1010011 };
parameter logic [31:0] INSN_FMAX_S = { 5'b00101, 2'b00, 10'h?, 3'b001, 5'h?, 7'b1010011 };
parameter logic [31:0] INSN_FCVT_W_S = { 5'b11000, 2'b00, 5'b00000, 13'h?, 7'b1010011 };
parameter logic [31:0] INSN_FCVT_WU_S = { 5'b11000, 2'b00, 5'b00001, 13'h?, 7'b1010011 };
parameter logic [31:0] INSN_FMV_X_W = { 5'b11100, 2'b00, 5'b00000, 5'h?, 3'b000, 5'h?, 7'b1010011 };
parameter logic [31:0] INSN_FEQ_S = { 5'b10100, 2'b00, 10'h?, 3'b010, 5'h?, 7'b1010011 };
parameter logic [31:0] INSN_FLT_S = { 5'b10100, 2'b00, 10'h?, 3'b001, 5'h?, 7'b1010011 };
parameter logic [31:0] INSN_FLE_S = { 5'b10100, 2'b00, 10'h?, 3'b000, 5'h?, 7'b1010011 };
parameter logic [31:0] INSN_FCLASS_S = { 5'b11100, 2'b00, 5'b00000, 5'h?, 3'b001, 5'h?, 7'b1010011 };
parameter logic [31:0] INSN_FCVT_S_W = { 5'b11010, 2'b00, 5'b00000, 13'h?, 7'b1010011 };
parameter logic [31:0] INSN_FCVT_S_WU = { 5'b11010, 2'b00, 5'b00001, 13'h?, 7'b1010011 };
parameter logic [31:0] INSN_FMV_W_X = { 5'b11110, 2'b00, 5'b00000, 5'h?, 3'b000, 5'h?, 7'b1010011 };
// Compressed F Instruction
parameter logic [15:0] INSN_C_FLWSP = { 3'b011, 11'h?, {OPCODE_C2} };
parameter logic [15:0] INSN_C_FSWSP = { 3'b111, 11'h?, {OPCODE_C2} };
parameter logic [15:0] INSN_C_FLW = { 3'b011, 11'h?, {OPCODE_C0} };
parameter logic [15:0] INSN_C_FSW = { 3'b111, 11'h?, {OPCODE_C0} };
endpackage

View file

@ -27,8 +27,10 @@ sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
from riscv_trace_csv import *
from lib import *
# RD_RE = re.compile(r"(core\s+\d+:\s+)?(?P<pri>\d) 0x(?P<addr>[a-f0-9]+?) " \
# "\((?P<bin>.*?)\) (?P<reg>[xf]\s*\d*?) 0x(?P<val>[a-f0-9]+)")
RD_RE = re.compile(r"(core\s+\d+:\s+)?(?P<pri>\d) 0x(?P<addr>[a-f0-9]+?) " \
"\((?P<bin>.*?)\) (?P<reg>[xf]\s*\d*?) 0x(?P<val>[a-f0-9]+)")
"\((?P<bin>.*?)\) ((c([0-9]+?)_([a-z]+?) 0x([a-f0-9]+?) )*?)(?P<reg>[xf]\s*\d*?) 0x(?P<val>[a-f0-9]+)")
CORE_RE = re.compile(
r"core\s+\d+:\s+0x(?P<addr>[a-f0-9]+?) \(0x(?P<bin>.*?)\) (?P<instr>.*?)$")
ADDR_RE = re.compile(