mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-20 03:47:15 -04:00
Updated
This commit is contained in:
parent
3d7b832ca6
commit
764871c051
22 changed files with 792 additions and 68 deletions
|
@ -1,5 +1,5 @@
|
|||
# **zero**riscy: RISC-V Core
|
||||
# **zero-riscy**: RISC-V Core
|
||||
|
||||
**zero**riscy is a small 3-stage RISC-V core derivated by littleRISCV.
|
||||
**zero-riscy** is a small 3-stage RISC-V core derivated by littleRISCV.
|
||||
|
||||
**zero**riscy fully implements the RV32IC instruction set and it is meant for control code.
|
||||
**zero-riscy** fully implements the RV32IC instruction set and it is meant for control code.
|
2
alu.sv
2
alu.sv
|
@ -24,7 +24,7 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
|
@ -128,8 +128,8 @@ module zeroriscy_controller
|
|||
begin
|
||||
// print warning in case of decoding errors
|
||||
if (is_decoding_o && illegal_insn_i) begin
|
||||
$display("%t: Illegal instruction (core %0d) at PC 0x%h:", $time, littleriscv_core.core_id_i,
|
||||
littleriscv_id_stage.pc_id_i);
|
||||
$display("%t: Illegal instruction (core %0d) at PC 0x%h:", $time, zeroriscy_core.core_id_i,
|
||||
zeroriscy_id_stage.pc_id_i);
|
||||
end
|
||||
end
|
||||
// synopsys translate_on
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
|
|
16
decoder.sv
16
decoder.sv
|
@ -26,7 +26,7 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
|
@ -118,12 +118,9 @@ module zeroriscy_decoder
|
|||
imm_a_mux_sel_o = IMMA_ZERO;
|
||||
imm_b_mux_sel_o = IMMB_I;
|
||||
|
||||
|
||||
regfile_mem_we = 1'b0;
|
||||
regfile_alu_we = 1'b0;
|
||||
|
||||
|
||||
|
||||
csr_access_o = 1'b0;
|
||||
csr_op = CSR_OP_NONE;
|
||||
|
||||
|
@ -419,16 +416,9 @@ module zeroriscy_decoder
|
|||
{6'b00_0000, 3'b001}: alu_operator_o = ALU_SLL; // Shift Left Logical
|
||||
{6'b00_0000, 3'b101}: alu_operator_o = ALU_SRL; // Shift Right Logical
|
||||
{6'b10_0000, 3'b101}: alu_operator_o = ALU_SRA; // Shift Right Arithmetic
|
||||
|
||||
|
||||
{6'b00_0010, 3'b010}: alu_operator_o = ALU_SLETS; // Set Lower Equal Than
|
||||
{6'b00_0010, 3'b011}: alu_operator_o = ALU_SLETU; // Set Lower Equal Than Unsigned
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
default: begin
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
|
@ -508,9 +498,6 @@ module zeroriscy_decoder
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
default: begin
|
||||
illegal_insn_o = 1'b1;
|
||||
end
|
||||
|
@ -536,7 +523,6 @@ module zeroriscy_decoder
|
|||
// the correct one
|
||||
regfile_alu_we = 1'b0;
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import riscv_defines::*;
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
module zeroriscy_if_stage #(
|
||||
parameter RDATA_WIDTH = 32
|
||||
|
@ -268,7 +268,7 @@ module zeroriscy_if_stage #(
|
|||
logic illegal_c_insn;
|
||||
logic instr_compressed_int;
|
||||
|
||||
littleriscv_compressed_decoder compressed_decoder_i
|
||||
zeroriscy_compressed_decoder compressed_decoder_i
|
||||
(
|
||||
.instr_i ( fetch_rdata ),
|
||||
.instr_o ( instr_decompressed ),
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
module zeroriscy_load_store_unit
|
||||
(
|
||||
|
|
4
mult.sv
4
mult.sv
|
@ -22,10 +22,10 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
import riscv_defines::*;
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
|
||||
module littleriscv_mult
|
||||
module zeroriscy_mult
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
module zeroriscy_prefetch_L0_buffer
|
||||
#(
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
// input port: send address one cycle before the data
|
||||
// clear_i clears the FIFO for the following cycle. in_addr_i can be sent in
|
||||
// this cycle already
|
||||
module littleriscv_fetch_fifo
|
||||
module zeroriscy_fetch_fifo
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
@ -232,7 +232,7 @@ module littleriscv_fetch_fifo
|
|||
endmodule
|
||||
|
||||
|
||||
module littleriscv_prefetch_buffer
|
||||
module zeroriscy_prefetch_buffer
|
||||
(
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
@ -283,7 +283,7 @@ module littleriscv_prefetch_buffer
|
|||
// consumes addresses and rdata
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
littleriscv_fetch_fifo fifo_i
|
||||
zeroriscy_fetch_fifo fifo_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
module zeroriscy_register_file
|
||||
#(
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
module zeroriscy_register_file
|
||||
#(
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import riscv_defines::*;
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
// do not import anything if the simchecker is not used
|
||||
// this gets rid of warnings during simulation
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
littleriscv:
|
||||
zeroriscy:
|
||||
incdirs: [
|
||||
include,
|
||||
]
|
||||
files: [
|
||||
include/riscv_defines.sv,
|
||||
include/riscv_tracer_defines.sv,
|
||||
include/zeroriscy_defines.sv,
|
||||
include/zeroriscy_tracer_defines.sv,
|
||||
alu.sv,
|
||||
alu_simplified.sv,
|
||||
alu_simplified_splitted.sv,
|
||||
alu_div.sv,
|
||||
compressed_decoder.sv,
|
||||
controller.sv,
|
||||
cs_registers.sv,
|
||||
|
@ -16,19 +13,15 @@ littleriscv:
|
|||
decoder.sv,
|
||||
exc_controller.sv,
|
||||
ex_stage.sv,
|
||||
hwloop_controller.sv,
|
||||
hwloop_regs.sv,
|
||||
id_stage.sv,
|
||||
if_stage.sv,
|
||||
load_store_unit.sv,
|
||||
mult.sv,
|
||||
prefetch_buffer.sv,
|
||||
prefetch_buffer_small.sv,
|
||||
prefetch_buffer_only_aligned.sv,
|
||||
prefetch_L0_buffer.sv,
|
||||
littleriscv_core.sv,
|
||||
zeroriscy_core.sv,
|
||||
]
|
||||
littleriscv_vip_rtl:
|
||||
zeroriscy_vip_rtl:
|
||||
targets: [
|
||||
rtl,
|
||||
]
|
||||
|
@ -36,12 +29,11 @@ littleriscv_vip_rtl:
|
|||
include,
|
||||
]
|
||||
files: [
|
||||
include/riscv_defines.sv,
|
||||
include/riscv_tracer_defines.sv,
|
||||
riscv_tracer.sv,
|
||||
riscv_simchecker.sv,
|
||||
include/zeroriscy_defines.sv,
|
||||
include/zeroriscy_tracer_defines.sv,
|
||||
zeroriscy_tracer.sv,
|
||||
]
|
||||
littleriscv_regfile_rtl:
|
||||
zeroriscy_regfile_rtl:
|
||||
targets: [
|
||||
rtl,
|
||||
]
|
||||
|
@ -51,7 +43,7 @@ littleriscv_regfile_rtl:
|
|||
files: [
|
||||
register_file.sv,
|
||||
]
|
||||
littleriscv_regfile_fpga:
|
||||
zeroriscy_regfile_fpga:
|
||||
targets: [
|
||||
xilinx,
|
||||
]
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "riscv_config.sv"
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
|
||||
|
@ -268,7 +268,7 @@ module zeroriscy_core
|
|||
// |___|_| |____/ |_/_/ \_\____|_____| //
|
||||
// //
|
||||
//////////////////////////////////////////////////
|
||||
littleriscv_if_stage
|
||||
zeroriscy_if_stage
|
||||
#(
|
||||
.RDATA_WIDTH ( INSTR_RDATA_WIDTH )
|
||||
)
|
||||
|
@ -333,7 +333,7 @@ module zeroriscy_core
|
|||
// |___|____/ |____/ |_/_/ \_\____|_____| //
|
||||
// //
|
||||
/////////////////////////////////////////////////
|
||||
littleriscv_id_stage
|
||||
zeroriscy_id_stage
|
||||
#(
|
||||
)
|
||||
id_stage_i
|
||||
|
@ -448,7 +448,7 @@ module zeroriscy_core
|
|||
);
|
||||
|
||||
|
||||
littleriscv_ex_block ex_block_i
|
||||
zeroriscy_ex_block ex_block_i
|
||||
(
|
||||
// Alu signals from ID stage
|
||||
//TODO: hot encoding
|
||||
|
@ -473,7 +473,7 @@ module zeroriscy_core
|
|||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
littleriscv_load_store_unit load_store_unit_i
|
||||
zeroriscy_load_store_unit load_store_unit_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_ni ),
|
||||
|
@ -528,7 +528,7 @@ module zeroriscy_core
|
|||
// Control and Status Registers //
|
||||
//////////////////////////////////////
|
||||
|
||||
littleriscv_cs_registers
|
||||
zeroriscy_cs_registers
|
||||
#(
|
||||
.N_EXT_CNT ( N_EXT_PERF_COUNTERS )
|
||||
)
|
||||
|
@ -603,7 +603,7 @@ module zeroriscy_core
|
|||
// //
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
littleriscv_debug_unit debug_unit_i
|
||||
zeroriscy_debug_unit debug_unit_i
|
||||
(
|
||||
.clk ( clk_i ), // always-running clock for debug
|
||||
.rst_n ( rst_ni ),
|
||||
|
@ -663,7 +663,7 @@ module zeroriscy_core
|
|||
|
||||
|
||||
`ifdef TRACE_EXECUTION
|
||||
littleriscv_tracer riscv_tracer_i
|
||||
zeroriscy_tracer zeroriscy_tracer_i
|
||||
(
|
||||
.clk ( clk_i ), // always-running clock for tracing
|
||||
.rst_n ( rst_ni ),
|
||||
|
@ -722,7 +722,7 @@ module zeroriscy_core
|
|||
logic is_interrupt;
|
||||
assign is_interrupt = (pc_mux_id == PC_EXCEPTION) && (exc_pc_mux_id == EXC_PC_IRQ);
|
||||
|
||||
littleriscv_simchecker riscv_simchecker_i
|
||||
zeroriscy_simchecker zeroriscy_simchecker_i
|
||||
(
|
||||
.clk ( clk_i ), // always-running clock for tracing
|
||||
.rst_n ( rst_ni ),
|
||||
|
|
746
zeroriscy_tracer.sv
Normal file
746
zeroriscy_tracer.sv
Normal file
|
@ -0,0 +1,746 @@
|
|||
// Copyright 2015 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the “License”); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Engineer: Andreas Traber - atraber@iis.ee.ethz.ch //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// Davide Schiavone - pschiavo@iis.ee.ethz.ch //
|
||||
// //
|
||||
// Design Name: RISC-V Tracer //
|
||||
// Project Name: zero-riscy //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Traces the executed instructions //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
`include "zeroriscy_config.sv"
|
||||
|
||||
import zeroriscy_defines::*;
|
||||
import zeroriscy_tracer_defines::*;
|
||||
|
||||
|
||||
// Source/Destination register instruction index
|
||||
`define REG_S1 19:15
|
||||
`define REG_S2 24:20
|
||||
`define REG_S3 29:25
|
||||
`define REG_D 11:07
|
||||
|
||||
|
||||
module zeroriscy_tracer
|
||||
#(
|
||||
parameter REG_ADDR_WIDTH = 5
|
||||
)
|
||||
(
|
||||
// Clock and Reset
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
input logic fetch_enable,
|
||||
input logic [3:0] core_id,
|
||||
input logic [5:0] cluster_id,
|
||||
|
||||
input logic [31:0] pc,
|
||||
input logic [31:0] instr,
|
||||
input logic compressed,
|
||||
input logic id_valid,
|
||||
input logic is_decoding,
|
||||
input logic pipe_flush,
|
||||
|
||||
input logic [31:0] rs1_value,
|
||||
input logic [31:0] rs2_value,
|
||||
input logic [31:0] rs3_value,
|
||||
input logic [31:0] rs2_value_vec,
|
||||
|
||||
input logic ex_valid,
|
||||
input logic [(REG_ADDR_WIDTH-1):0] ex_reg_addr,
|
||||
input logic ex_reg_we,
|
||||
input logic [31:0] ex_reg_wdata,
|
||||
input logic data_valid_lsu,
|
||||
input logic ex_data_req,
|
||||
input logic ex_data_gnt,
|
||||
input logic ex_data_we,
|
||||
input logic [31:0] ex_data_addr,
|
||||
input logic [31:0] ex_data_wdata,
|
||||
|
||||
input logic wb_bypass,
|
||||
|
||||
input logic wb_valid,
|
||||
input logic [(REG_ADDR_WIDTH-1):0] wb_reg_addr,
|
||||
input logic wb_reg_we,
|
||||
input logic [31:0] wb_reg_wdata,
|
||||
|
||||
input logic [31:0] imm_u_type,
|
||||
input logic [31:0] imm_uj_type,
|
||||
input logic [31:0] imm_i_type,
|
||||
input logic [11:0] imm_iz_type,
|
||||
input logic [31:0] imm_z_type,
|
||||
input logic [31:0] imm_s_type,
|
||||
input logic [31:0] imm_sb_type,
|
||||
input logic [31:0] imm_s2_type,
|
||||
input logic [31:0] imm_s3_type,
|
||||
input logic [31:0] imm_vs_type,
|
||||
input logic [31:0] imm_vu_type,
|
||||
input logic [ 4:0] imm_clip_type
|
||||
);
|
||||
|
||||
integer f;
|
||||
string fn;
|
||||
integer cycles;
|
||||
logic [ 4:0] rd, rs1, rs2, rs3;
|
||||
|
||||
typedef struct {
|
||||
logic [(REG_ADDR_WIDTH-1):0] addr;
|
||||
logic [31:0] value;
|
||||
} reg_t;
|
||||
|
||||
typedef struct {
|
||||
logic [31:0] addr;
|
||||
logic we;
|
||||
logic [ 3:0] be;
|
||||
logic [31:0] wdata;
|
||||
logic [31:0] rdata;
|
||||
} mem_acc_t;
|
||||
|
||||
class instr_trace_t;
|
||||
time simtime;
|
||||
integer cycles;
|
||||
logic [31:0] pc;
|
||||
logic [31:0] instr;
|
||||
string str;
|
||||
reg_t regs_read[$];
|
||||
reg_t regs_write[$];
|
||||
mem_acc_t mem_access[$];
|
||||
|
||||
function new ();
|
||||
str = "";
|
||||
regs_read = {};
|
||||
regs_write = {};
|
||||
mem_access = {};
|
||||
endfunction
|
||||
|
||||
function string regAddrToStr(input logic [(REG_ADDR_WIDTH-1):0] addr);
|
||||
begin
|
||||
if (addr < 10)
|
||||
return $sformatf(" x%0d", addr);
|
||||
else
|
||||
return $sformatf("x%0d", addr);
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void printInstrTrace();
|
||||
mem_acc_t mem_acc;
|
||||
begin
|
||||
$fwrite(f, "%t %15d %h %h %-36s", simtime,
|
||||
cycles,
|
||||
pc,
|
||||
instr,
|
||||
str);
|
||||
|
||||
foreach(regs_write[i]) begin
|
||||
if (regs_write[i].addr != 0)
|
||||
$fwrite(f, " %s=%08x", regAddrToStr(regs_write[i].addr), regs_write[i].value);
|
||||
end
|
||||
|
||||
foreach(regs_read[i]) begin
|
||||
if (regs_read[i].addr != 0)
|
||||
$fwrite(f, " %s:%08x", regAddrToStr(regs_read[i].addr), regs_read[i].value);
|
||||
end
|
||||
|
||||
if (mem_access.size() > 0) begin
|
||||
mem_acc = mem_access.pop_front();
|
||||
|
||||
$fwrite(f, " PA:%08x", mem_acc.addr);
|
||||
end
|
||||
|
||||
$fwrite(f, "\n");
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void printMnemonic(input string mnemonic);
|
||||
begin
|
||||
str = mnemonic;
|
||||
end
|
||||
endfunction // printMnemonic
|
||||
|
||||
function void printRInstr(input string mnemonic);
|
||||
begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
regs_write.push_back('{rd, 'x});
|
||||
str = $sformatf("%-16s x%0d, x%0d, x%0d", mnemonic, rd, rs1, rs2);
|
||||
end
|
||||
endfunction // printRInstr
|
||||
|
||||
function void printAddNInstr(input string mnemonic);
|
||||
begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
regs_write.push_back('{rd, 'x});
|
||||
str = $sformatf("%-16s x%0d, x%0d, x%0d, 0x%0d", mnemonic, rd, rs1, rs2, $unsigned(imm_s3_type[4:0]));
|
||||
end
|
||||
endfunction // printAddNInstr
|
||||
|
||||
function void printR1Instr(input string mnemonic);
|
||||
begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_write.push_back('{rd, 'x});
|
||||
str = $sformatf("%-16s x%0d, x%0d", mnemonic, rd, rs1);
|
||||
end
|
||||
endfunction // printR1Instr
|
||||
|
||||
function void printR3Instr(input string mnemonic);
|
||||
begin
|
||||
regs_read.push_back('{rd, rs3_value});
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
regs_write.push_back('{rd, 'x});
|
||||
str = $sformatf("%-16s x%0d, x%0d, x%0d", mnemonic, rd, rs1, rs2);
|
||||
end
|
||||
endfunction // printR3Instr
|
||||
|
||||
function void printClipInstr(input string mnemonic);
|
||||
begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_write.push_back('{rd, 'x});
|
||||
str = $sformatf("%-16s x%0d, x%0d, %0d", mnemonic, rd, rs1, $unsigned(imm_clip_type));
|
||||
end
|
||||
endfunction // printRInstr
|
||||
|
||||
function void printIInstr(input string mnemonic);
|
||||
begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_write.push_back('{rd, 'x});
|
||||
str = $sformatf("%-16s x%0d, x%0d, %0d", mnemonic, rd, rs1, $signed(imm_i_type));
|
||||
end
|
||||
endfunction // printIInstr
|
||||
|
||||
function void printIuInstr(input string mnemonic);
|
||||
begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_write.push_back('{rd, 'x});
|
||||
str = $sformatf("%-16s x%0d, x%0d, 0x%0x", mnemonic, rd, rs1, imm_i_type);
|
||||
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[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_uj_type));
|
||||
end
|
||||
endfunction // printUJInstr
|
||||
|
||||
function void printSBInstr(input string mnemonic);
|
||||
begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
str = $sformatf("%-16s x%0d, x%0d, %0d", mnemonic, rs1, rs2, $signed(imm_sb_type));
|
||||
end
|
||||
endfunction // printSBInstr
|
||||
|
||||
function void printSBallInstr(input string mnemonic);
|
||||
begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
str = $sformatf("%-16s x%0d, %0d", mnemonic, rs1, $signed(imm_sb_type));
|
||||
end
|
||||
endfunction // printSBInstr
|
||||
|
||||
function void printCSRInstr(input string mnemonic);
|
||||
logic [11:0] csr;
|
||||
begin
|
||||
csr = instr[31:20];
|
||||
|
||||
regs_write.push_back('{rd, 'x});
|
||||
|
||||
if (instr[14] == 1'b0) begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
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, imm_z_type, csr);
|
||||
end
|
||||
end
|
||||
endfunction // printCSRInstr
|
||||
|
||||
function void printBit1Instr(input string mnemonic);
|
||||
begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_write.push_back('{rd, 'x});
|
||||
str = $sformatf("%-16s x%0d, x%0d, %0d, %0d", mnemonic, rd, rs1, imm_s3_type, imm_s2_type);
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void printBit2Instr(input string mnemonic);
|
||||
begin
|
||||
regs_read.push_back('{rd, rs3_value});
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_write.push_back('{rd, 'x});
|
||||
str = $sformatf("%-16s x%0d, x%0d, %0d, %0d", mnemonic, rd, rs1, imm_s3_type, imm_s2_type);
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void printLoadInstr();
|
||||
string mnemonic;
|
||||
logic [2:0] size;
|
||||
begin
|
||||
// detect reg-reg load and find size
|
||||
size = instr[14:12];
|
||||
if (instr[14:12] == 3'b111)
|
||||
size = instr[30:28];
|
||||
|
||||
case (size)
|
||||
3'b000: mnemonic = "lb";
|
||||
3'b001: mnemonic = "lh";
|
||||
3'b010: mnemonic = "lw";
|
||||
3'b100: mnemonic = "lbu";
|
||||
3'b101: mnemonic = "lhu";
|
||||
3'b110: mnemonic = "p.elw";
|
||||
3'b011,
|
||||
3'b111: begin
|
||||
printMnemonic("INVALID");
|
||||
return;
|
||||
end
|
||||
endcase
|
||||
|
||||
regs_write.push_back('{rd, 'x});
|
||||
|
||||
if (instr[14:12] != 3'b111) begin
|
||||
// regular load
|
||||
if (instr[6:0] != OPCODE_LOAD_POST) begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
str = $sformatf("%-16s x%0d, %0d(x%0d)", mnemonic, rd, $signed(imm_i_type), rs1);
|
||||
end else begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_write.push_back('{rs1, 'x});
|
||||
str = $sformatf("p.%-14s x%0d, %0d(x%0d!)", mnemonic, rd, $signed(imm_i_type), rs1);
|
||||
end
|
||||
end else begin
|
||||
// reg-reg load
|
||||
if (instr[6:0] != OPCODE_LOAD_POST) begin
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
str = $sformatf("%-16s x%0d, x%0d(x%0d)", mnemonic, rd, rs2, rs1);
|
||||
end else begin
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_write.push_back('{rs1, 'x});
|
||||
str = $sformatf("p.%-14s x%0d, x%0d(x%0d!)", mnemonic, rd, rs2, rs1);
|
||||
end
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void printStoreInstr();
|
||||
string mnemonic;
|
||||
begin
|
||||
|
||||
case (instr[13:12])
|
||||
2'b00: mnemonic = "sb";
|
||||
2'b01: mnemonic = "sh";
|
||||
2'b10: mnemonic = "sw";
|
||||
2'b11: begin
|
||||
printMnemonic("INVALID");
|
||||
return;
|
||||
end
|
||||
endcase
|
||||
|
||||
if (instr[14] == 1'b0) begin
|
||||
// regular store
|
||||
if (instr[6:0] != OPCODE_STORE_POST) begin
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
str = $sformatf("%-16s x%0d, %0d(x%0d)", mnemonic, rs2, $signed(imm_s_type), rs1);
|
||||
end else begin
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_write.push_back('{rs1, 'x});
|
||||
str = $sformatf("p.%-14s x%0d, %0d(x%0d!)", mnemonic, rs2, $signed(imm_s_type), rs1);
|
||||
end
|
||||
end else begin
|
||||
// reg-reg store
|
||||
if (instr[6:0] != OPCODE_STORE_POST) begin
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
regs_read.push_back('{rs3, rs3_value});
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
str = $sformatf("p.%-14s x%0d, x%0d(x%0d)", mnemonic, rs2, rs3, rs1);
|
||||
end else begin
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
regs_read.push_back('{rs3, rs3_value});
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_write.push_back('{rs1, 'x});
|
||||
str = $sformatf("p.%-14s x%0d, x%0d(x%0d!)", mnemonic, rs2, rs3, rs1);
|
||||
end
|
||||
end
|
||||
end
|
||||
endfunction // printSInstr
|
||||
|
||||
function void printHwloopInstr();
|
||||
string mnemonic;
|
||||
begin
|
||||
// set mnemonic
|
||||
case (instr[14:12])
|
||||
3'b000: mnemonic = "lp.starti";
|
||||
3'b001: mnemonic = "lp.endi";
|
||||
3'b010: mnemonic = "lp.count";
|
||||
3'b011: mnemonic = "lp.counti";
|
||||
3'b100: mnemonic = "lp.setup";
|
||||
3'b101: mnemonic = "lp.setupi";
|
||||
3'b111: begin
|
||||
printMnemonic("INVALID");
|
||||
return;
|
||||
end
|
||||
endcase
|
||||
|
||||
// decode and print instruction
|
||||
case (instr[14:12])
|
||||
// lp.starti and lp.endi
|
||||
3'b000,
|
||||
3'b001: str = $sformatf("%-16s 0x%0d, 0x%0h", mnemonic, rd, imm_iz_type);
|
||||
// lp.count
|
||||
3'b010: begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
str = $sformatf("%-16s 0x%0d, x%0d", mnemonic, rd, rs1);
|
||||
end
|
||||
// lp.counti
|
||||
3'b011: str = $sformatf("%-16s x%0d, 0x%0h", mnemonic, rd, imm_iz_type);
|
||||
// lp.setup
|
||||
3'b100: begin
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
str = $sformatf("%-16s 0x%0d, x%0d, 0x%0h", mnemonic, rd, rs1, imm_iz_type);
|
||||
end
|
||||
// lp.setupi
|
||||
3'b101: begin
|
||||
str = $sformatf("%-16s 0x%0d, 0x%0h, 0x%0h", mnemonic, rd, imm_iz_type, rs1);
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void printMulInstr();
|
||||
string mnemonic;
|
||||
string str_suf;
|
||||
string str_imm;
|
||||
string str_asm;
|
||||
begin
|
||||
|
||||
// always read rs1 and rs2 and write rd
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
regs_write.push_back('{rd, 'x});
|
||||
|
||||
if (instr[12])
|
||||
regs_read.push_back('{rd, rs3_value});
|
||||
|
||||
case ({instr[31:30], instr[14]})
|
||||
3'b000: str_suf = "u";
|
||||
3'b001: str_suf = "uR";
|
||||
3'b010: str_suf = "hhu";
|
||||
3'b011: str_suf = "hhuR";
|
||||
3'b100: str_suf = "s";
|
||||
3'b101: str_suf = "sR";
|
||||
3'b110: str_suf = "hhs";
|
||||
3'b111: str_suf = "hhsR";
|
||||
endcase
|
||||
|
||||
if (instr[12])
|
||||
mnemonic = "p.mac";
|
||||
else
|
||||
mnemonic = "p.mul";
|
||||
|
||||
if (imm_s3_type[4:0] != 5'b00000)
|
||||
str_asm = $sformatf("%s%sN", mnemonic, str_suf);
|
||||
else
|
||||
str_asm = $sformatf("%s%s", mnemonic, str_suf);
|
||||
|
||||
if (instr[29:25] != 5'b00000)
|
||||
str = $sformatf("%-16s x%0d, x%0d, x%0d, %0d", str_asm, rd, rs1, rs2, $unsigned(imm_s3_type[4:0]));
|
||||
else
|
||||
str = $sformatf("%-16s x%0d, x%0d, x%0d", str_asm, rd, rs1, rs2);
|
||||
end
|
||||
endfunction
|
||||
|
||||
function void printVecInstr();
|
||||
string mnemonic;
|
||||
string str_asm;
|
||||
string str_args;
|
||||
string str_hb;
|
||||
string str_sci;
|
||||
string str_imm;
|
||||
begin
|
||||
|
||||
// always read rs1 and write rd
|
||||
regs_read.push_back('{rs1, rs1_value});
|
||||
regs_write.push_back('{rd, 'x});
|
||||
|
||||
case (instr[14:13])
|
||||
2'b00: str_sci = "";
|
||||
2'b10: str_sci = ".sc";
|
||||
2'b11: str_sci = ".sci";
|
||||
endcase
|
||||
|
||||
if (instr[12])
|
||||
str_hb = ".b";
|
||||
else
|
||||
str_hb = ".h";
|
||||
|
||||
// set mnemonic
|
||||
case (instr[31:26])
|
||||
6'b000000: begin mnemonic = "pv.add"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b000010: begin mnemonic = "pv.sub"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b000100: begin mnemonic = "pv.avg"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b000110: begin mnemonic = "pv.avgu"; str_imm = $sformatf("0x%0d", imm_vu_type); end
|
||||
6'b001000: begin mnemonic = "pv.min"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b001010: begin mnemonic = "pv.minu"; str_imm = $sformatf("0x%0d", imm_vu_type); end
|
||||
6'b001100: begin mnemonic = "pv.max"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b001110: begin mnemonic = "pv.maxu"; str_imm = $sformatf("0x%0d", imm_vu_type); end
|
||||
6'b010000: begin mnemonic = "pv.srl"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b010010: begin mnemonic = "pv.sra"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b010100: begin mnemonic = "pv.sll"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b010110: begin mnemonic = "pv.or"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b011000: begin mnemonic = "pv.xor"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b011010: begin mnemonic = "pv.and"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b011100: begin mnemonic = "pv.abs"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b011110: begin mnemonic = "pv.extract"; str_imm = $sformatf("0x%0d", imm_vs_type); str_sci = ""; end
|
||||
6'b100000: begin mnemonic = "pv.extractu"; str_imm = $sformatf("0x%0d", imm_vu_type); str_sci = ""; end
|
||||
6'b100010: begin mnemonic = "pv.insert"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
|
||||
// shuffle/pack
|
||||
6'b110000: begin mnemonic = "pv.shuffle"; str_imm = $sformatf("N/A"); end
|
||||
6'b110010: begin mnemonic = "pv.shuffle2"; end
|
||||
6'b110100: begin mnemonic = "pv.pack"; end
|
||||
6'b110110: begin mnemonic = "pv.packhi"; end
|
||||
6'b111000: begin mnemonic = "pv.packlo"; end
|
||||
|
||||
// comparisons
|
||||
6'b000001: begin mnemonic = "pv.cmpeq"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b000011: begin mnemonic = "pv.cmpne"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b000101: begin mnemonic = "pv.cmpgt"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b000111: begin mnemonic = "pv.cmpge"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b001001: begin mnemonic = "pv.cmplt"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b001011: begin mnemonic = "pv.cmple"; str_imm = $sformatf("0x%0d", imm_vs_type); end
|
||||
6'b001101: begin mnemonic = "pv.cmpgtu"; str_imm = $sformatf("0x%0d", imm_vu_type); end
|
||||
6'b001111: begin mnemonic = "pv.cmpgeu"; str_imm = $sformatf("0x%0d", imm_vu_type); end
|
||||
6'b010001: begin mnemonic = "pv.cmpltu"; str_imm = $sformatf("0x%0d", imm_vu_type); end
|
||||
6'b010011: begin mnemonic = "pv.cmpleu"; str_imm = $sformatf("0x%0d", imm_vu_type); end
|
||||
|
||||
default: begin
|
||||
printMnemonic("INVALID");
|
||||
return;
|
||||
end
|
||||
endcase
|
||||
|
||||
if (str_sci == "") begin
|
||||
regs_read.push_back('{rs2, rs2_value});
|
||||
str_args = $sformatf("x%0d, x%0d, x%0d", rd, rs1, rs2);
|
||||
end else if (str_sci == ".sc") begin
|
||||
regs_read.push_back('{rs2, rs2_value_vec});
|
||||
str_args = $sformatf("x%0d, x%0d, x%0d", rd, rs1, rs2);
|
||||
end else if (str_sci == ".sci") begin
|
||||
str_args = $sformatf("x%0d, x%0d, %s", rd, rs1, str_imm);
|
||||
end
|
||||
|
||||
str_asm = $sformatf("%s%s%s", mnemonic, str_sci, str_hb);
|
||||
|
||||
str = $sformatf("%-16s %s", str_asm, str_args);
|
||||
end
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
mailbox #(instr_trace_t) instr_ex = new ();
|
||||
mailbox #(instr_trace_t) instr_wb = new ();
|
||||
|
||||
// cycle counter
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0)
|
||||
cycles = 0;
|
||||
else
|
||||
cycles = cycles + 1;
|
||||
end
|
||||
|
||||
// open/close output file for writing
|
||||
initial
|
||||
begin
|
||||
wait(rst_n == 1'b1);
|
||||
wait(fetch_enable == 1'b1);
|
||||
$sformat(fn, "trace_core_%h_%h.log", cluster_id, core_id);
|
||||
$display("[TRACER] Output filename is: %s", fn);
|
||||
f = $fopen(fn, "w");
|
||||
$fwrite(f, " Time Cycles PC Instr Mnemonic\n");
|
||||
|
||||
end
|
||||
|
||||
final
|
||||
begin
|
||||
$fclose(f);
|
||||
end
|
||||
|
||||
assign rd = instr[`REG_D];
|
||||
assign rs1 = instr[`REG_S1];
|
||||
assign rs2 = instr[`REG_S2];
|
||||
assign rs3 = instr[`REG_S3];
|
||||
|
||||
// log execution
|
||||
always @(negedge clk)
|
||||
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 && is_decoding ) || pipe_flush || (ex_data_req && is_decoding))
|
||||
begin
|
||||
trace = new ();
|
||||
|
||||
trace.simtime = $time;
|
||||
trace.cycles = cycles;
|
||||
trace.pc = pc;
|
||||
trace.instr = instr;
|
||||
|
||||
// use casex instead of case inside due to ModelSim bug
|
||||
casex (instr)
|
||||
// Aliases
|
||||
32'h00_00_00_13: trace.printMnemonic("nop");
|
||||
// Regular opcodes
|
||||
INSTR_LUI: trace.printUInstr("lui");
|
||||
INSTR_AUIPC: trace.printUInstr("auipc");
|
||||
INSTR_JAL: trace.printUJInstr("jal");
|
||||
INSTR_JALR: trace.printIInstr("jalr");
|
||||
// BRANCH
|
||||
INSTR_BEQ: trace.printSBInstr("beq");
|
||||
INSTR_BNE: trace.printSBInstr("bne");
|
||||
INSTR_BLT: trace.printSBInstr("blt");
|
||||
INSTR_BGE: trace.printSBInstr("bge");
|
||||
INSTR_BLTU: trace.printSBInstr("bltu");
|
||||
INSTR_BGEU: trace.printSBInstr("bgeu");
|
||||
// OPIMM
|
||||
INSTR_ADDI: trace.printIInstr("addi");
|
||||
INSTR_SLTI: trace.printIInstr("slti");
|
||||
INSTR_SLTIU: trace.printIInstr("sltiu");
|
||||
INSTR_XORI: trace.printIInstr("xori");
|
||||
INSTR_ORI: trace.printIInstr("ori");
|
||||
INSTR_ANDI: trace.printIInstr("andi");
|
||||
INSTR_SLLI: trace.printIuInstr("slli");
|
||||
INSTR_SRLI: trace.printIuInstr("srli");
|
||||
INSTR_SRAI: trace.printIuInstr("srai");
|
||||
// OP
|
||||
INSTR_ADD: trace.printRInstr("add");
|
||||
INSTR_SUB: trace.printRInstr("sub");
|
||||
INSTR_SLL: trace.printRInstr("sll");
|
||||
INSTR_SLT: trace.printRInstr("slt");
|
||||
INSTR_SLTU: trace.printRInstr("sltu");
|
||||
INSTR_XOR: trace.printRInstr("xor");
|
||||
INSTR_SRL: trace.printRInstr("srl");
|
||||
INSTR_SRA: trace.printRInstr("sra");
|
||||
INSTR_OR: trace.printRInstr("or");
|
||||
INSTR_AND: trace.printRInstr("and");
|
||||
INSTR_EXTHS: trace.printRInstr("p.exths");
|
||||
INSTR_EXTHZ: trace.printRInstr("p.exthz");
|
||||
INSTR_EXTBS: trace.printRInstr("p.extbs");
|
||||
INSTR_EXTBZ: trace.printRInstr("p.extbz");
|
||||
INSTR_PAVG: trace.printRInstr("p.avg");
|
||||
INSTR_PAVGU: trace.printRInstr("p.avgu");
|
||||
INSTR_PADDN: trace.printAddNInstr("p.addN");
|
||||
INSTR_PADDUN: trace.printAddNInstr("p.adduN");
|
||||
INSTR_PADDRN: trace.printAddNInstr("p.addRN");
|
||||
INSTR_PADDURN: trace.printAddNInstr("p.adduRN");
|
||||
INSTR_PSUBN: trace.printAddNInstr("p.subN");
|
||||
INSTR_PSUBUN: trace.printAddNInstr("p.subuN");
|
||||
INSTR_PSUBRN: trace.printAddNInstr("p.subRN");
|
||||
INSTR_PSUBURN: trace.printAddNInstr("p.subuRN");
|
||||
INSTR_PSLET: trace.printRInstr("p.slet");
|
||||
INSTR_PSLETU: trace.printRInstr("p.sletu");
|
||||
INSTR_PMIN: trace.printRInstr("p.min");
|
||||
INSTR_PMINU: trace.printRInstr("p.minu");
|
||||
INSTR_PMAX: trace.printRInstr("p.max");
|
||||
INSTR_PMAXU: trace.printRInstr("p.maxu");
|
||||
INSTR_PABS: trace.printR1Instr("p.abs");
|
||||
INSTR_PCLIP: trace.printClipInstr("p.clip");
|
||||
INSTR_PCLIPU: trace.printClipInstr("p.clipu");
|
||||
INSTR_PBEXT: trace.printBit1Instr("p.extract");
|
||||
INSTR_PBEXTU: trace.printBit1Instr("p.extractu");
|
||||
INSTR_PBINS: trace.printBit2Instr("p.insert");
|
||||
INSTR_PBCLR: trace.printBit1Instr("p.bclr");
|
||||
INSTR_PBSET: trace.printBit1Instr("p.bset");
|
||||
// FENCE
|
||||
INSTR_FENCE: trace.printMnemonic("fence");
|
||||
INSTR_FENCEI: trace.printMnemonic("fencei");
|
||||
// SYSTEM (CSR manipulation)
|
||||
INSTR_CSRRW: trace.printCSRInstr("csrrw");
|
||||
INSTR_CSRRS: trace.printCSRInstr("csrrs");
|
||||
INSTR_CSRRC: trace.printCSRInstr("csrrc");
|
||||
INSTR_CSRRWI: trace.printCSRInstr("csrrwi");
|
||||
INSTR_CSRRSI: trace.printCSRInstr("csrrsi");
|
||||
INSTR_CSRRCI: trace.printCSRInstr("csrrci");
|
||||
// SYSTEM (others)
|
||||
INSTR_ECALL: trace.printMnemonic("ecall");
|
||||
INSTR_EBREAK: trace.printMnemonic("ebreak");
|
||||
INSTR_ERET: trace.printMnemonic("mret");
|
||||
INSTR_WFI: trace.printMnemonic("wfi");
|
||||
// PULP MULTIPLIER
|
||||
INSTR_PMUL: trace.printRInstr("p.mul");
|
||||
INSTR_PMAC: trace.printR3Instr("p.mac");
|
||||
INSTR_DIV: trace.printRInstr("div");
|
||||
INSTR_DIVU: trace.printRInstr("divu");
|
||||
INSTR_REM: trace.printRInstr("rem");
|
||||
INSTR_REMU: trace.printRInstr("remu");
|
||||
// opcodes with custom decoding
|
||||
{25'b?, OPCODE_LOAD}: trace.printLoadInstr();
|
||||
{25'b?, OPCODE_LOAD_POST}: trace.printLoadInstr();
|
||||
{25'b?, OPCODE_STORE}: trace.printStoreInstr();
|
||||
{25'b?, OPCODE_STORE_POST}: trace.printStoreInstr();
|
||||
{25'b?, OPCODE_HWLOOP}: trace.printHwloopInstr();
|
||||
{25'b?, OPCODE_VECOP}: trace.printVecInstr();
|
||||
INSTR_PMULRN: trace.printMulInstr();
|
||||
default: trace.printMnemonic("INVALID");
|
||||
endcase // unique case (instr)
|
||||
|
||||
// replace register written back
|
||||
foreach(trace.regs_write[i]) begin
|
||||
if ((trace.regs_write[i].addr == ex_reg_addr) && ex_reg_we)
|
||||
trace.regs_write[i].value = ex_reg_wdata;
|
||||
end
|
||||
// look for data accesses and log them
|
||||
if (ex_data_req) begin
|
||||
|
||||
if(~ex_data_gnt) begin
|
||||
//we wait until the the gnt comes
|
||||
do @(negedge clk);
|
||||
while (!ex_data_gnt);
|
||||
end
|
||||
|
||||
mem_acc.addr = ex_data_addr;
|
||||
mem_acc.we = ex_data_we;
|
||||
|
||||
if (mem_acc.we)
|
||||
mem_acc.wdata = ex_data_wdata;
|
||||
else
|
||||
mem_acc.wdata = 'x;
|
||||
//we wait until the the data instruction ends
|
||||
do @(negedge clk);
|
||||
while (!data_valid_lsu);
|
||||
|
||||
if (~mem_acc.we)
|
||||
//load operations
|
||||
foreach(trace.regs_write[i])
|
||||
trace.regs_write[i].value = wb_reg_wdata;
|
||||
trace.mem_access.push_back(mem_acc);
|
||||
end
|
||||
trace.printInstrTrace();
|
||||
|
||||
end
|
||||
end // always @ (posedge clk)
|
||||
|
||||
endmodule
|
Loading…
Add table
Add a link
Reference in a new issue