mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-25 06:27:22 -04:00
Tracer rewrite
Instantiate tracer module in a separate core file and use only RVFI signals.
This commit is contained in:
parent
1e2d5b7eda
commit
014c753dde
8 changed files with 237 additions and 134 deletions
|
@ -16,6 +16,7 @@ Ibex User Manual
|
||||||
exception_interrupts
|
exception_interrupts
|
||||||
interrupts
|
interrupts
|
||||||
debug
|
debug
|
||||||
|
tracer
|
||||||
rvfi
|
rvfi
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ The control and status registers are explained in :ref:`cs-registers`.
|
||||||
:ref:`performance-counters` gives an overview of the performance monitors and event counters available in Ibex.
|
:ref:`performance-counters` gives an overview of the performance monitors and event counters available in Ibex.
|
||||||
:ref:`exceptions-interrupts` deals with the infrastructure for handling exceptions and interrupts,
|
:ref:`exceptions-interrupts` deals with the infrastructure for handling exceptions and interrupts,
|
||||||
:ref:`debug-support` gives a brief overview on the debug infrastructure.
|
:ref:`debug-support` gives a brief overview on the debug infrastructure.
|
||||||
|
:ref:`tracer` gives a brief overview of the tracer module.
|
||||||
For information regarding formal verification support, check out :ref:`rvfi`.
|
For information regarding formal verification support, check out :ref:`rvfi`.
|
||||||
|
|
||||||
|
|
||||||
|
|
11
doc/tracer.rst
Normal file
11
doc/tracer.rst
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
.. _tracer:
|
||||||
|
|
||||||
|
Tracer
|
||||||
|
======
|
||||||
|
|
||||||
|
The module ``ibex_tracer`` can be used to create a log of the executed instructions.
|
||||||
|
It is used by ``ibex_core_tracer`` which forwards the signals added by :ref:`rvfi` as an input for the tracer.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
``ibex_tracer`` is not compatible with Verilator.
|
|
@ -11,9 +11,18 @@ filesets:
|
||||||
files:
|
files:
|
||||||
- rtl/ibex_tracer_defines.sv
|
- rtl/ibex_tracer_defines.sv
|
||||||
- rtl/ibex_tracer.sv
|
- rtl/ibex_tracer.sv
|
||||||
|
- rtl/ibex_core_tracer.sv
|
||||||
file_type: systemVerilogSource
|
file_type: systemVerilogSource
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
RVFI:
|
||||||
|
datatype: bool
|
||||||
|
paramtype: vlogdefine
|
||||||
|
description: Enable RVFI signals for tracing
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
default:
|
default:
|
||||||
filesets:
|
filesets:
|
||||||
- files_rtl
|
- files_rtl
|
||||||
|
parameters:
|
||||||
|
- RVFI=true
|
||||||
|
|
|
@ -747,56 +747,4 @@ module ibex_core #(
|
||||||
assign rvfi_changed_pc = rvfi_pc_id_q != pc_id;
|
assign rvfi_changed_pc = rvfi_pc_id_q != pc_id;
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
|
|
||||||
`ifndef VERILATOR
|
|
||||||
`ifdef TRACE_EXECUTION
|
|
||||||
ibex_tracer ibex_tracer_i (
|
|
||||||
.clk_i ( clk_i ), // always-on clk for tracer
|
|
||||||
.rst_ni ( rst_ni ),
|
|
||||||
|
|
||||||
.fetch_enable_i ( fetch_enable_i ),
|
|
||||||
.core_id_i ( core_id_i ),
|
|
||||||
.cluster_id_i ( cluster_id_i ),
|
|
||||||
|
|
||||||
.pc_i ( id_stage_i.pc_id_i ),
|
|
||||||
.instr_i ( id_stage_i.instr_rdata_i ),
|
|
||||||
.compressed_i ( id_stage_i.instr_is_compressed_i ),
|
|
||||||
.id_valid_i ( id_stage_i.id_valid_o ),
|
|
||||||
.is_decoding_i ( id_stage_i.is_decoding_o ),
|
|
||||||
.is_branch_i ( id_stage_i.branch_in_id ),
|
|
||||||
.branch_taken_i ( id_stage_i.branch_set_q ),
|
|
||||||
.pipe_flush_i ( id_stage_i.controller_i.pipe_flush_i ),
|
|
||||||
.mret_insn_i ( id_stage_i.controller_i.mret_insn_i ),
|
|
||||||
.dret_insn_i ( id_stage_i.controller_i.dret_insn_i ),
|
|
||||||
.ecall_insn_i ( id_stage_i.controller_i.ecall_insn_i ),
|
|
||||||
.ebrk_insn_i ( id_stage_i.controller_i.ebrk_insn_i ),
|
|
||||||
.csr_status_i ( id_stage_i.controller_i.csr_status_i ),
|
|
||||||
.rs1_value_i ( id_stage_i.operand_a_fw_id ),
|
|
||||||
.rs2_value_i ( id_stage_i.operand_b_fw_id ),
|
|
||||||
|
|
||||||
.lsu_value_i ( data_wdata_ex ),
|
|
||||||
|
|
||||||
.ex_reg_addr_i ( id_stage_i.regfile_waddr ),
|
|
||||||
.ex_reg_we_i ( id_stage_i.regfile_we ),
|
|
||||||
.ex_reg_wdata_i ( id_stage_i.regfile_wdata ),
|
|
||||||
.lsu_data_valid_i ( lsu_data_valid ),
|
|
||||||
.ex_data_addr_i ( data_addr_o ),
|
|
||||||
.ex_data_req_i ( data_req_o ),
|
|
||||||
.ex_data_gnt_i ( data_gnt_i ),
|
|
||||||
.ex_data_we_i ( data_we_o ),
|
|
||||||
|
|
||||||
.ex_data_wdata_i ( data_wdata_o ),
|
|
||||||
|
|
||||||
.lsu_reg_wdata_i ( regfile_wdata_lsu ),
|
|
||||||
|
|
||||||
.imm_i_type_i ( id_stage_i.imm_i_type ),
|
|
||||||
.imm_s_type_i ( id_stage_i.imm_s_type ),
|
|
||||||
.imm_b_type_i ( id_stage_i.imm_b_type ),
|
|
||||||
.imm_u_type_i ( id_stage_i.imm_u_type ),
|
|
||||||
.imm_j_type_i ( id_stage_i.imm_j_type ),
|
|
||||||
.zimm_rs1_type_i ( id_stage_i.zimm_rs1_type )
|
|
||||||
);
|
|
||||||
`endif
|
|
||||||
`endif
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
180
rtl/ibex_core_tracer.sv
Normal file
180
rtl/ibex_core_tracer.sv
Normal file
|
@ -0,0 +1,180 @@
|
||||||
|
// Copyright lowRISC contributors.
|
||||||
|
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
|
||||||
|
// ibex_tracer relies on the signals from the RISC-V Formal Interface
|
||||||
|
`define RVFI
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Top level module of the ibex RISC-V core with tracing enabled
|
||||||
|
*/
|
||||||
|
module ibex_core_tracer #(
|
||||||
|
parameter int unsigned MHPMCounterNum = 8,
|
||||||
|
parameter int unsigned MHPMCounterWidth = 40,
|
||||||
|
parameter bit RV32E = 0,
|
||||||
|
parameter bit RV32M = 1,
|
||||||
|
parameter int unsigned DmHaltAddr = 32'h1A110800,
|
||||||
|
parameter int unsigned DmExceptionAddr = 32'h1A110808
|
||||||
|
) (
|
||||||
|
// Clock and Reset
|
||||||
|
input logic clk_i,
|
||||||
|
input logic rst_ni,
|
||||||
|
|
||||||
|
input logic test_en_i, // enable all clock gates for testing
|
||||||
|
|
||||||
|
// Core ID, Cluster ID and boot address are considered more or less static
|
||||||
|
input logic [ 3:0] core_id_i,
|
||||||
|
input logic [ 5:0] cluster_id_i,
|
||||||
|
input logic [31:0] boot_addr_i,
|
||||||
|
|
||||||
|
// Instruction memory interface
|
||||||
|
output logic instr_req_o,
|
||||||
|
input logic instr_gnt_i,
|
||||||
|
input logic instr_rvalid_i,
|
||||||
|
output logic [31:0] instr_addr_o,
|
||||||
|
input logic [31:0] instr_rdata_i,
|
||||||
|
|
||||||
|
// Data memory interface
|
||||||
|
output logic data_req_o,
|
||||||
|
input logic data_gnt_i,
|
||||||
|
input logic data_rvalid_i,
|
||||||
|
output logic data_we_o,
|
||||||
|
output logic [3:0] data_be_o,
|
||||||
|
output logic [31:0] data_addr_o,
|
||||||
|
output logic [31:0] data_wdata_o,
|
||||||
|
input logic [31:0] data_rdata_i,
|
||||||
|
input logic data_err_i,
|
||||||
|
|
||||||
|
// Interrupt inputs
|
||||||
|
input logic irq_i, // level sensitive IR lines
|
||||||
|
input logic [4:0] irq_id_i,
|
||||||
|
output logic irq_ack_o, // irq ack
|
||||||
|
output logic [4:0] irq_id_o,
|
||||||
|
|
||||||
|
// Debug Interface
|
||||||
|
input logic debug_req_i,
|
||||||
|
|
||||||
|
// RISC-V Formal Interface
|
||||||
|
// Does not comply with the coding standards of _i/_o suffixes, but follows
|
||||||
|
// the convention of RISC-V Formal Interface Specification.
|
||||||
|
`ifdef RVFI
|
||||||
|
output logic rvfi_valid,
|
||||||
|
output logic [63:0] rvfi_order,
|
||||||
|
output logic [31:0] rvfi_insn,
|
||||||
|
output logic rvfi_trap,
|
||||||
|
output logic rvfi_halt,
|
||||||
|
output logic rvfi_intr,
|
||||||
|
output logic [ 1:0] rvfi_mode,
|
||||||
|
output logic [ 4:0] rvfi_rs1_addr,
|
||||||
|
output logic [ 4:0] rvfi_rs2_addr,
|
||||||
|
output logic [31:0] rvfi_rs1_rdata,
|
||||||
|
output logic [31:0] rvfi_rs2_rdata,
|
||||||
|
output logic [ 4:0] rvfi_rd_addr,
|
||||||
|
output logic [31:0] rvfi_rd_wdata,
|
||||||
|
output logic [31:0] rvfi_pc_rdata,
|
||||||
|
output logic [31:0] rvfi_pc_wdata,
|
||||||
|
output logic [31:0] rvfi_mem_addr,
|
||||||
|
output logic [ 3:0] rvfi_mem_rmask,
|
||||||
|
output logic [ 3:0] rvfi_mem_wmask,
|
||||||
|
output logic [31:0] rvfi_mem_rdata,
|
||||||
|
output logic [31:0] rvfi_mem_wdata,
|
||||||
|
`endif
|
||||||
|
|
||||||
|
// CPU Control Signals
|
||||||
|
input logic fetch_enable_i
|
||||||
|
|
||||||
|
);
|
||||||
|
|
||||||
|
import ibex_defines::*;
|
||||||
|
|
||||||
|
ibex_core #(
|
||||||
|
.MHPMCounterNum(MHPMCounterNum),
|
||||||
|
.MHPMCounterWidth(MHPMCounterWidth),
|
||||||
|
.RV32E(RV32E),
|
||||||
|
.RV32M(RV32M),
|
||||||
|
.DmHaltAddr(DmHaltAddr),
|
||||||
|
.DmExceptionAddr(DmExceptionAddr)
|
||||||
|
) u_ibex_core (
|
||||||
|
.clk_i,
|
||||||
|
.rst_ni,
|
||||||
|
|
||||||
|
.test_en_i,
|
||||||
|
|
||||||
|
.core_id_i,
|
||||||
|
.cluster_id_i,
|
||||||
|
.boot_addr_i,
|
||||||
|
|
||||||
|
.instr_req_o,
|
||||||
|
.instr_gnt_i,
|
||||||
|
.instr_rvalid_i,
|
||||||
|
.instr_addr_o,
|
||||||
|
.instr_rdata_i,
|
||||||
|
|
||||||
|
.data_req_o,
|
||||||
|
.data_gnt_i,
|
||||||
|
.data_rvalid_i,
|
||||||
|
.data_we_o,
|
||||||
|
.data_be_o,
|
||||||
|
.data_addr_o,
|
||||||
|
.data_wdata_o,
|
||||||
|
.data_rdata_i,
|
||||||
|
.data_err_i,
|
||||||
|
|
||||||
|
.irq_i,
|
||||||
|
.irq_id_i,
|
||||||
|
.irq_ack_o,
|
||||||
|
.irq_id_o,
|
||||||
|
|
||||||
|
.debug_req_i,
|
||||||
|
|
||||||
|
`ifdef RVFI
|
||||||
|
.rvfi_valid,
|
||||||
|
.rvfi_order,
|
||||||
|
.rvfi_insn,
|
||||||
|
.rvfi_trap,
|
||||||
|
.rvfi_halt,
|
||||||
|
.rvfi_intr,
|
||||||
|
.rvfi_mode,
|
||||||
|
.rvfi_rs1_addr,
|
||||||
|
.rvfi_rs2_addr,
|
||||||
|
.rvfi_rs1_rdata,
|
||||||
|
.rvfi_rs2_rdata,
|
||||||
|
.rvfi_rd_addr,
|
||||||
|
.rvfi_rd_wdata,
|
||||||
|
.rvfi_pc_rdata,
|
||||||
|
.rvfi_pc_wdata,
|
||||||
|
.rvfi_mem_addr,
|
||||||
|
.rvfi_mem_rmask,
|
||||||
|
.rvfi_mem_wmask,
|
||||||
|
.rvfi_mem_rdata,
|
||||||
|
.rvfi_mem_wdata,
|
||||||
|
`endif
|
||||||
|
|
||||||
|
.fetch_enable_i
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
`ifndef VERILATOR
|
||||||
|
ibex_tracer ibex_tracer_i (
|
||||||
|
.clk_i ( clk_i ),
|
||||||
|
.rst_ni ( rst_ni ),
|
||||||
|
|
||||||
|
.fetch_enable_i ( fetch_enable_i ),
|
||||||
|
.core_id_i ( core_id_i ),
|
||||||
|
.cluster_id_i ( cluster_id_i ),
|
||||||
|
|
||||||
|
.valid_i ( rvfi_valid ),
|
||||||
|
.pc_i ( rvfi_pc_rdata ),
|
||||||
|
.instr_i ( rvfi_insn ),
|
||||||
|
.rs1_value_i ( rvfi_rs1_rdata ),
|
||||||
|
.rs2_value_i ( rvfi_rs2_rdata ),
|
||||||
|
.ex_reg_addr_i ( rvfi_rd_addr ),
|
||||||
|
.ex_reg_wdata_i ( rvfi_rd_wdata ),
|
||||||
|
.ex_data_addr_i ( rvfi_mem_addr ),
|
||||||
|
.ex_data_wdata_i ( rvfi_mem_wdata ),
|
||||||
|
.ex_data_rdata_i ( rvfi_mem_rdata )
|
||||||
|
);
|
||||||
|
`endif // VERILATOR
|
||||||
|
|
||||||
|
endmodule
|
|
@ -228,10 +228,6 @@ module ibex_id_stage #(
|
||||||
// CSR control
|
// CSR control
|
||||||
logic csr_status;
|
logic csr_status;
|
||||||
|
|
||||||
// For tracer
|
|
||||||
logic [31:0] operand_a_fw_id, unused_operand_a_fw_id;
|
|
||||||
logic [31:0] operand_b_fw_id, unused_operand_b_fw_id;
|
|
||||||
|
|
||||||
logic [31:0] alu_operand_a;
|
logic [31:0] alu_operand_a;
|
||||||
logic [31:0] alu_operand_b;
|
logic [31:0] alu_operand_b;
|
||||||
|
|
||||||
|
@ -286,13 +282,6 @@ module ibex_id_stage #(
|
||||||
// ALU MUX for Operand B
|
// ALU MUX for Operand B
|
||||||
assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : regfile_rdata_b;
|
assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : regfile_rdata_b;
|
||||||
|
|
||||||
// Signals used by tracer
|
|
||||||
assign operand_a_fw_id = lsu_addr_incr_req_i ? lsu_addr_last_i : regfile_rdata_a;
|
|
||||||
assign operand_b_fw_id = regfile_rdata_b;
|
|
||||||
|
|
||||||
assign unused_operand_a_fw_id = operand_a_fw_id;
|
|
||||||
assign unused_operand_b_fw_id = operand_b_fw_id;
|
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// Register File MUX //
|
// Register File MUX //
|
||||||
///////////////////////
|
///////////////////////
|
||||||
|
|
|
@ -42,41 +42,16 @@ module ibex_tracer #(
|
||||||
input logic [3:0] core_id_i,
|
input logic [3:0] core_id_i,
|
||||||
input logic [5:0] cluster_id_i,
|
input logic [5:0] cluster_id_i,
|
||||||
|
|
||||||
|
input logic valid_i,
|
||||||
input logic [31:0] pc_i,
|
input logic [31:0] pc_i,
|
||||||
input logic [31:0] instr_i,
|
input logic [31:0] instr_i,
|
||||||
input logic compressed_i,
|
|
||||||
input logic id_valid_i,
|
|
||||||
input logic is_decoding_i,
|
|
||||||
input logic is_branch_i,
|
|
||||||
input logic branch_taken_i,
|
|
||||||
input logic pipe_flush_i,
|
|
||||||
input logic mret_insn_i,
|
|
||||||
input logic dret_insn_i,
|
|
||||||
input logic ecall_insn_i,
|
|
||||||
input logic ebrk_insn_i,
|
|
||||||
input logic csr_status_i,
|
|
||||||
input logic [31:0] rs1_value_i,
|
input logic [31:0] rs1_value_i,
|
||||||
input logic [31:0] rs2_value_i,
|
input logic [31:0] rs2_value_i,
|
||||||
input logic [31:0] lsu_value_i,
|
|
||||||
|
|
||||||
input logic [(RegAddrWidth-1):0] ex_reg_addr_i,
|
input logic [(RegAddrWidth-1):0] ex_reg_addr_i,
|
||||||
input logic ex_reg_we_i,
|
|
||||||
input logic [31:0] ex_reg_wdata_i,
|
input logic [31:0] ex_reg_wdata_i,
|
||||||
input logic lsu_data_valid_i,
|
|
||||||
input logic ex_data_req_i,
|
|
||||||
input logic ex_data_gnt_i,
|
|
||||||
input logic ex_data_we_i,
|
|
||||||
input logic [31:0] ex_data_addr_i,
|
input logic [31:0] ex_data_addr_i,
|
||||||
input logic [31:0] ex_data_wdata_i,
|
input logic [31:0] ex_data_wdata_i,
|
||||||
|
input logic [31:0] ex_data_rdata_i
|
||||||
input logic [31:0] lsu_reg_wdata_i,
|
|
||||||
|
|
||||||
input logic [31:0] imm_i_type_i,
|
|
||||||
input logic [31:0] imm_s_type_i,
|
|
||||||
input logic [31:0] imm_b_type_i,
|
|
||||||
input logic [31:0] imm_u_type_i,
|
|
||||||
input logic [31:0] imm_j_type_i,
|
|
||||||
input logic [31:0] zimm_rs1_type_i
|
|
||||||
);
|
);
|
||||||
|
|
||||||
integer f;
|
integer f;
|
||||||
|
@ -135,20 +110,26 @@ module ibex_tracer #(
|
||||||
|
|
||||||
foreach(regs_write[i]) begin
|
foreach(regs_write[i]) begin
|
||||||
if (regs_write[i].addr != 0) begin
|
if (regs_write[i].addr != 0) begin
|
||||||
$fwrite(f, " %s=%08x", regAddrToStr(regs_write[i].addr), regs_write[i].value);
|
$fwrite(f, " %s=0x%08x", regAddrToStr(regs_write[i].addr), regs_write[i].value);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
foreach(regs_read[i]) begin
|
foreach(regs_read[i]) begin
|
||||||
if (regs_read[i].addr != 0) begin
|
if (regs_read[i].addr != 0) begin
|
||||||
$fwrite(f, " %s:%08x", regAddrToStr(regs_read[i].addr), regs_read[i].value);
|
$fwrite(f, " %s:0x%08x", regAddrToStr(regs_read[i].addr), regs_read[i].value);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (mem_access.size() > 0) begin
|
if (mem_access.size() > 0) begin
|
||||||
mem_acc = mem_access.pop_front();
|
mem_acc = mem_access.pop_front();
|
||||||
|
|
||||||
$fwrite(f, " PA:%08x", mem_acc.addr);
|
$fwrite(f, " PA:0x%08x", mem_acc.addr);
|
||||||
|
|
||||||
|
if (mem_acc.we == 1'b1) begin
|
||||||
|
$fwrite(f, " store:0x%08x", mem_acc.wdata);
|
||||||
|
end else begin
|
||||||
|
$fwrite(f, " load:0x%08x", mem_acc.rdata);
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
$fwrite(f, "\n");
|
$fwrite(f, "\n");
|
||||||
|
@ -174,7 +155,7 @@ module ibex_tracer #(
|
||||||
begin
|
begin
|
||||||
regs_read.push_back('{rs1, rs1_value_i});
|
regs_read.push_back('{rs1, rs1_value_i});
|
||||||
regs_write.push_back('{rd, 'x});
|
regs_write.push_back('{rd, 'x});
|
||||||
str = $sformatf("%-16s x%0d, x%0d, %0d", mnemonic, rd, rs1, $signed(imm_i_type_i));
|
str = $sformatf("%-16s x%0d, x%0d, %0d", mnemonic, rd, rs1, $signed({{20 {instr[31]}}, instr[31:20]}));
|
||||||
end
|
end
|
||||||
endfunction // printIInstr
|
endfunction // printIInstr
|
||||||
|
|
||||||
|
@ -182,21 +163,21 @@ module ibex_tracer #(
|
||||||
begin
|
begin
|
||||||
regs_read.push_back('{rs1, rs1_value_i});
|
regs_read.push_back('{rs1, rs1_value_i});
|
||||||
regs_write.push_back('{rd, 'x});
|
regs_write.push_back('{rd, 'x});
|
||||||
str = $sformatf("%-16s x%0d, x%0d, 0x%0x", mnemonic, rd, rs1, imm_i_type_i);
|
str = $sformatf("%-16s x%0d, x%0d, 0x%0x", mnemonic, rd, rs1, {{20 {instr[31]}}, instr[31:20]});
|
||||||
end
|
end
|
||||||
endfunction // printIuInstr
|
endfunction // printIuInstr
|
||||||
|
|
||||||
function void printUInstr(input string mnemonic);
|
function void printUInstr(input string mnemonic);
|
||||||
begin
|
begin
|
||||||
regs_write.push_back('{rd, 'x});
|
regs_write.push_back('{rd, 'x});
|
||||||
str = $sformatf("%-16s x%0d, 0x%0h", mnemonic, rd, {imm_u_type_i[31:12], 12'h000});
|
str = $sformatf("%-16s x%0d, 0x%0h", mnemonic, rd, {instr[31:12], 12'h000});
|
||||||
end
|
end
|
||||||
endfunction // printUInstr
|
endfunction // printUInstr
|
||||||
|
|
||||||
function void printUJInstr(input string mnemonic);
|
function void printUJInstr(input string mnemonic);
|
||||||
begin
|
begin
|
||||||
regs_write.push_back('{rd, 'x});
|
regs_write.push_back('{rd, 'x});
|
||||||
str = $sformatf("%-16s x%0d, %0d", mnemonic, rd, $signed(imm_j_type_i));
|
str = $sformatf("%-16s x%0d, %0d", mnemonic, rd, $signed({ {12 {instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 }));
|
||||||
end
|
end
|
||||||
endfunction // printUJInstr
|
endfunction // printUJInstr
|
||||||
|
|
||||||
|
@ -204,7 +185,7 @@ module ibex_tracer #(
|
||||||
begin
|
begin
|
||||||
regs_read.push_back('{rs1, rs1_value_i});
|
regs_read.push_back('{rs1, rs1_value_i});
|
||||||
regs_read.push_back('{rs2, rs2_value_i});
|
regs_read.push_back('{rs2, rs2_value_i});
|
||||||
str = $sformatf("%-16s x%0d, x%0d, %0d", mnemonic, rs1, rs2, $signed(imm_b_type_i));
|
str = $sformatf("%-16s x%0d, x%0d, %0d", mnemonic, rs1, rs2, $signed({ {19 {instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0 }));
|
||||||
end
|
end
|
||||||
endfunction // printSBInstr
|
endfunction // printSBInstr
|
||||||
|
|
||||||
|
@ -219,7 +200,7 @@ module ibex_tracer #(
|
||||||
regs_read.push_back('{rs1, rs1_value_i});
|
regs_read.push_back('{rs1, rs1_value_i});
|
||||||
str = $sformatf("%-16s x%0d, x%0d, 0x%h", mnemonic, rd, rs1, csr);
|
str = $sformatf("%-16s x%0d, x%0d, 0x%h", mnemonic, rd, rs1, csr);
|
||||||
end else begin
|
end else begin
|
||||||
str = $sformatf("%-16s x%0d, 0x%h, 0x%h", mnemonic, rd, zimm_rs1_type_i, csr);
|
str = $sformatf("%-16s x%0d, 0x%h, 0x%h", mnemonic, rd, { 27'b0, instr[`REG_S1] }, csr);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endfunction // printCSRInstr
|
endfunction // printCSRInstr
|
||||||
|
@ -227,6 +208,7 @@ module ibex_tracer #(
|
||||||
function void printLoadInstr();
|
function void printLoadInstr();
|
||||||
string mnemonic;
|
string mnemonic;
|
||||||
logic [2:0] size;
|
logic [2:0] size;
|
||||||
|
mem_acc_t mem_acc;
|
||||||
begin
|
begin
|
||||||
// detect reg-reg load and find size
|
// detect reg-reg load and find size
|
||||||
size = instr_i[14:12];
|
size = instr_i[14:12];
|
||||||
|
@ -257,15 +239,20 @@ module ibex_tracer #(
|
||||||
if (instr_i[14:12] != 3'b111) begin
|
if (instr_i[14:12] != 3'b111) begin
|
||||||
// regular load
|
// regular load
|
||||||
regs_read.push_back('{rs1, rs1_value_i});
|
regs_read.push_back('{rs1, rs1_value_i});
|
||||||
str = $sformatf("%-16s x%0d, %0d(x%0d)", mnemonic, rd, $signed(imm_i_type_i), rs1);
|
str = $sformatf("%-16s x%0d, %0d(x%0d)", mnemonic, rd, $signed({{20 {instr[31]}}, instr[31:20]}), rs1);
|
||||||
end else begin
|
end else begin
|
||||||
printMnemonic("INVALID");
|
printMnemonic("INVALID");
|
||||||
end
|
end
|
||||||
|
|
||||||
|
mem_acc.addr = ex_data_addr_i;
|
||||||
|
mem_acc.rdata = ex_data_rdata_i;
|
||||||
|
mem_access.push_back(mem_acc);
|
||||||
end
|
end
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function void printStoreInstr();
|
function void printStoreInstr();
|
||||||
string mnemonic;
|
string mnemonic;
|
||||||
|
mem_acc_t mem_acc;
|
||||||
begin
|
begin
|
||||||
|
|
||||||
unique case (instr_i[13:12])
|
unique case (instr_i[13:12])
|
||||||
|
@ -286,10 +273,15 @@ module ibex_tracer #(
|
||||||
// regular store
|
// regular store
|
||||||
regs_read.push_back('{rs2, rs2_value_i});
|
regs_read.push_back('{rs2, rs2_value_i});
|
||||||
regs_read.push_back('{rs1, rs1_value_i});
|
regs_read.push_back('{rs1, rs1_value_i});
|
||||||
str = $sformatf("%-16s x%0d, %0d(x%0d)", mnemonic, rs2, $signed(imm_s_type_i), rs1);
|
str = $sformatf("%-16s x%0d, %0d(x%0d)", mnemonic, rs2, $signed({ {20 {instr[31]}}, instr[31:25], instr[11:7] }), rs1);
|
||||||
end else begin
|
end else begin
|
||||||
printMnemonic("INVALID");
|
printMnemonic("INVALID");
|
||||||
end
|
end
|
||||||
|
|
||||||
|
mem_acc.addr = ex_data_addr_i;
|
||||||
|
mem_acc.we = 1'b1;
|
||||||
|
mem_acc.wdata = ex_data_wdata_i;
|
||||||
|
mem_access.push_back(mem_acc);
|
||||||
end
|
end
|
||||||
endfunction // printSInstr
|
endfunction // printSInstr
|
||||||
|
|
||||||
|
@ -327,12 +319,11 @@ module ibex_tracer #(
|
||||||
assign rs3 = instr_i[`REG_S3];
|
assign rs3 = instr_i[`REG_S3];
|
||||||
|
|
||||||
// log execution
|
// log execution
|
||||||
always @(negedge clk_i) begin
|
always @(posedge clk_i) begin
|
||||||
instr_trace_t trace;
|
instr_trace_t trace;
|
||||||
mem_acc_t mem_acc;
|
mem_acc_t mem_acc;
|
||||||
// special case for WFI because we don't wait for unstalling there
|
// special case for WFI because we don't wait for unstalling there
|
||||||
if ((id_valid_i || mret_insn_i || ecall_insn_i || pipe_flush_i || ebrk_insn_i ||
|
if (valid_i) begin
|
||||||
dret_insn_i || csr_status_i || ex_data_req_i) && is_decoding_i) begin
|
|
||||||
trace = new ();
|
trace = new ();
|
||||||
|
|
||||||
trace.simtime = $time;
|
trace.simtime = $time;
|
||||||
|
@ -410,38 +401,11 @@ module ibex_tracer #(
|
||||||
|
|
||||||
// replace register written back
|
// replace register written back
|
||||||
foreach(trace.regs_write[i]) begin
|
foreach(trace.regs_write[i]) begin
|
||||||
if ((trace.regs_write[i].addr == ex_reg_addr_i) && ex_reg_we_i) begin
|
if ((trace.regs_write[i].addr == ex_reg_addr_i)) begin
|
||||||
trace.regs_write[i].value = ex_reg_wdata_i;
|
trace.regs_write[i].value = ex_reg_wdata_i;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
// look for data accesses and log them
|
|
||||||
if (ex_data_req_i) begin
|
|
||||||
|
|
||||||
if (!ex_data_gnt_i) begin
|
|
||||||
//we wait until the the gnt comes
|
|
||||||
do @(negedge clk_i);
|
|
||||||
while (!ex_data_gnt_i);
|
|
||||||
end
|
|
||||||
|
|
||||||
mem_acc.addr = ex_data_addr_i;
|
|
||||||
mem_acc.we = ex_data_we_i;
|
|
||||||
|
|
||||||
if (mem_acc.we) begin
|
|
||||||
mem_acc.wdata = ex_data_wdata_i;
|
|
||||||
end else begin
|
|
||||||
mem_acc.wdata = 'x;
|
|
||||||
end
|
|
||||||
//we wait until the the data instruction ends
|
|
||||||
do @(negedge clk_i);
|
|
||||||
while (!lsu_data_valid_i);
|
|
||||||
|
|
||||||
if (!mem_acc.we) begin
|
|
||||||
//load operations
|
|
||||||
foreach(trace.regs_write[i])
|
|
||||||
trace.regs_write[i].value = lsu_reg_wdata_i;
|
|
||||||
end
|
|
||||||
trace.mem_access.push_back(mem_acc);
|
|
||||||
end
|
|
||||||
trace.printInstrTrace();
|
trace.printInstrTrace();
|
||||||
end
|
end
|
||||||
end // always @ (posedge clk_i)
|
end // always @ (posedge clk_i)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue