mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 21:07:34 -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
|
||||
interrupts
|
||||
debug
|
||||
tracer
|
||||
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:`exceptions-interrupts` deals with the infrastructure for handling exceptions and interrupts,
|
||||
: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`.
|
||||
|
||||
|
||||
|
|
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:
|
||||
- rtl/ibex_tracer_defines.sv
|
||||
- rtl/ibex_tracer.sv
|
||||
- rtl/ibex_core_tracer.sv
|
||||
file_type: systemVerilogSource
|
||||
|
||||
parameters:
|
||||
RVFI:
|
||||
datatype: bool
|
||||
paramtype: vlogdefine
|
||||
description: Enable RVFI signals for tracing
|
||||
|
||||
targets:
|
||||
default:
|
||||
filesets:
|
||||
- files_rtl
|
||||
parameters:
|
||||
- RVFI=true
|
||||
|
|
|
@ -747,56 +747,4 @@ module ibex_core #(
|
|||
assign rvfi_changed_pc = rvfi_pc_id_q != pc_id;
|
||||
`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
|
||||
|
|
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
|
||||
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_b;
|
||||
|
||||
|
@ -286,13 +282,6 @@ module ibex_id_stage #(
|
|||
// ALU MUX for Operand 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 //
|
||||
///////////////////////
|
||||
|
|
|
@ -42,41 +42,16 @@ module ibex_tracer #(
|
|||
input logic [3:0] core_id_i,
|
||||
input logic [5:0] cluster_id_i,
|
||||
|
||||
input logic valid_i,
|
||||
input logic [31:0] pc_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] rs2_value_i,
|
||||
input logic [31:0] lsu_value_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 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_wdata_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
|
||||
input logic [31:0] ex_data_rdata_i
|
||||
);
|
||||
|
||||
integer f;
|
||||
|
@ -135,20 +110,26 @@ module ibex_tracer #(
|
|||
|
||||
foreach(regs_write[i]) 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
|
||||
|
||||
foreach(regs_read[i]) 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
|
||||
|
||||
if (mem_access.size() > 0) begin
|
||||
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
|
||||
|
||||
$fwrite(f, "\n");
|
||||
|
@ -174,7 +155,7 @@ module ibex_tracer #(
|
|||
begin
|
||||
regs_read.push_back('{rs1, rs1_value_i});
|
||||
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
|
||||
endfunction // printIInstr
|
||||
|
||||
|
@ -182,21 +163,21 @@ module ibex_tracer #(
|
|||
begin
|
||||
regs_read.push_back('{rs1, rs1_value_i});
|
||||
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
|
||||
endfunction // printIuInstr
|
||||
|
||||
function void printUInstr(input string mnemonic);
|
||||
begin
|
||||
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
|
||||
endfunction // printUInstr
|
||||
|
||||
function void printUJInstr(input string mnemonic);
|
||||
begin
|
||||
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
|
||||
endfunction // printUJInstr
|
||||
|
||||
|
@ -204,7 +185,7 @@ module ibex_tracer #(
|
|||
begin
|
||||
regs_read.push_back('{rs1, rs1_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
|
||||
endfunction // printSBInstr
|
||||
|
||||
|
@ -219,14 +200,15 @@ module ibex_tracer #(
|
|||
regs_read.push_back('{rs1, rs1_value_i});
|
||||
str = $sformatf("%-16s x%0d, x%0d, 0x%h", mnemonic, rd, rs1, csr);
|
||||
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
|
||||
endfunction // printCSRInstr
|
||||
|
||||
function void printLoadInstr();
|
||||
string mnemonic;
|
||||
string mnemonic;
|
||||
logic [2:0] size;
|
||||
mem_acc_t mem_acc;
|
||||
begin
|
||||
// detect reg-reg load and find size
|
||||
size = instr_i[14:12];
|
||||
|
@ -257,15 +239,20 @@ module ibex_tracer #(
|
|||
if (instr_i[14:12] != 3'b111) begin
|
||||
// regular load
|
||||
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
|
||||
printMnemonic("INVALID");
|
||||
end
|
||||
|
||||
mem_acc.addr = ex_data_addr_i;
|
||||
mem_acc.rdata = ex_data_rdata_i;
|
||||
mem_access.push_back(mem_acc);
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void printStoreInstr();
|
||||
string mnemonic;
|
||||
string mnemonic;
|
||||
mem_acc_t mem_acc;
|
||||
begin
|
||||
|
||||
unique case (instr_i[13:12])
|
||||
|
@ -286,10 +273,15 @@ module ibex_tracer #(
|
|||
// regular store
|
||||
regs_read.push_back('{rs2, rs2_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
|
||||
printMnemonic("INVALID");
|
||||
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
|
||||
endfunction // printSInstr
|
||||
|
||||
|
@ -327,12 +319,11 @@ module ibex_tracer #(
|
|||
assign rs3 = instr_i[`REG_S3];
|
||||
|
||||
// log execution
|
||||
always @(negedge clk_i) begin
|
||||
always @(posedge clk_i) begin
|
||||
instr_trace_t trace;
|
||||
mem_acc_t mem_acc;
|
||||
// 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 ||
|
||||
dret_insn_i || csr_status_i || ex_data_req_i) && is_decoding_i) begin
|
||||
if (valid_i) begin
|
||||
trace = new ();
|
||||
|
||||
trace.simtime = $time;
|
||||
|
@ -410,38 +401,11 @@ module ibex_tracer #(
|
|||
|
||||
// replace register written back
|
||||
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;
|
||||
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();
|
||||
end
|
||||
end // always @ (posedge clk_i)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue