Parameterization and other fixes for downstream project (#1950)

* Bender fixes and switch to `cva6_fifo_v3`
* cfg: Fix verilator warnings
* Bender: Fix yml
* acc_dispatcher: Add `csr_addr_i`
* parameterization: Fox AXI_USER_EN warning
* wb_cache: Fix Verilator Lint warnings
* cva6_fifo_v3: Add to Flist
* parameterization: Address review concerns
* Switch to `cva6_fifo_v3`
* tracer: Remove tracer interface

The interface made a bunch of problems with the
typedefs so I've removed it.

---------

Co-authored-by: JeanRochCoulon <jean-roch.coulon@thalesgroup.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Florian Zaruba 2024-04-05 13:02:18 +02:00 committed by GitHub
parent f886713754
commit 38e8c059b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 335 additions and 233 deletions

View file

@ -17,9 +17,11 @@ dependencies:
frozen: true
sources:
- files:
- include_dirs:
- core/include
files:
- core/include/config_pkg.sv
- core/include/build_config_pkg.sv
- target: cv64a6_imafdcv_sv39
files:
- core/include/cv64a6_imafdcv_sv39_config_pkg.sv
@ -107,7 +109,6 @@ sources:
# Packages
- core/include/wt_cache_pkg.sv
- core/include/std_cache_pkg.sv
- core/include/acc_pkg.sv
# for all the below files use Flist.cva6 as baseline and also look at Makefile pd/synth
# CVXIF
@ -118,11 +119,12 @@ sources:
- core/cvxif_example/cvxif_example_coprocessor.sv
- core/cvxif_example/instr_decoder.sv
- core/cva6_rvfi_probes.sv
- core/cva6_fifo_v3.sv
# vendored deps
# - include_dirs: [vendor/pulp-platform/common_cells/include/, vendor/pulp-platform/common_cells/src/]
# files:
# - vendor/pulp-platform/common_cells/src/cf_math_pkg.sv
# - vendor/pulp-platform/common_cells/src/fifo_v3.sv
# - vendor/pulp-platform/common_cells/src/lfsr.sv
# - vendor/pulp-platform/common_cells/src/lzc.sv
# - vendor/pulp-platform/common_cells/src/rr_arb_tree.sv
@ -244,7 +246,6 @@ sources:
# Tracer (behavioral code, not RTL)
- core/include/instr_tracer_pkg.sv
- common/local/util/instr_tracer.sv
- common/local/util/instr_tracer_if.sv
# TODO target define FPGA target + verification etc
# - target: test

View file

@ -161,7 +161,6 @@ vendor/openhwgroup/cvfpu/src/fpnew_top.sv
core/pmp/src/pmp.sv
core/pmp/src/pmp_entry.sv
common/local/util/instr_tracer.sv
common/local/util/instr_tracer_if.sv
core/cvxif_example/cvxif_example_coprocessor.sv
core/cvxif_example/instr_decoder.sv
vendor/pulp-platform/common_cells/src/counter.sv

View file

@ -699,7 +699,6 @@ fpga_filter := $(addprefix $(root-dir), corev_apu/bootrom/bootrom.sv)
fpga_filter += $(addprefix $(root-dir), core/include/instr_tracer_pkg.sv)
fpga_filter += $(addprefix $(root-dir), src/util/ex_trace_item.sv)
fpga_filter += $(addprefix $(root-dir), src/util/instr_trace_item.sv)
fpga_filter += $(addprefix $(root-dir), common/local/util/instr_tracer_if.sv)
fpga_filter += $(addprefix $(root-dir), common/local/util/instr_tracer.sv)
fpga_filter += $(addprefix $(root-dir), vendor/pulp-platform/tech_cells_generic/src/rtl/tc_sram.sv)
fpga_filter += $(addprefix $(root-dir), common/local/util/tc_sram_wrapper.sv)

View file

@ -22,9 +22,34 @@ module instr_tracer #(
parameter type bp_resolve_t = logic,
parameter type scoreboard_entry_t = logic,
parameter type interrupts_t = logic,
parameter type exception_t = logic,
parameter interrupts_t INTERRUPTS = '0
)(
instr_tracer_if tracer_if,
input logic pck,
input logic rstn,
input logic flush_unissued,
input logic flush_all,
input logic [31:0] instruction,
input logic fetch_valid,
input logic fetch_ack,
input logic issue_ack, // issue acknowledged
input scoreboard_entry_t issue_sbe, // issue scoreboard entry
input logic [1:0][4:0] waddr, // WB stage
input logic [1:0][63:0] wdata,
input logic [1:0] we_gpr,
input logic [1:0] we_fpr,
input scoreboard_entry_t [1:0] commit_instr, // commit instruction
input logic [1:0] commit_ack,
input logic st_valid, // stores - address translation
input logic [CVA6Cfg.PLEN-1:0] st_paddr,
input logic ld_valid, // loads
input logic ld_kill,
input logic [CVA6Cfg.PLEN-1:0] ld_paddr,
input bp_resolve_t resolve_branch, // misprediction
input exception_t commit_exception,
input riscv::priv_lvl_t priv_lvl, // current privilege level
input logic debug_mode,
input logic[CVA6Cfg.XLEN-1:0] hart_id_i
);
@ -34,7 +59,7 @@ module instr_tracer #(
logic [31:0] issue_queue [$];
// issue scoreboard entries
scoreboard_entry_t issue_sbe_queue [$];
scoreboard_entry_t issue_sbe;
scoreboard_entry_t issue_sbe_item;
// store resolved branches, get (mis-)predictions
bp_resolve_t bp [$];
// shadow copy of the register files
@ -69,7 +94,7 @@ module instr_tracer #(
forever begin
automatic bp_resolve_t bp_instruction = '0;
// new cycle, we are only interested if reset is de-asserted
@(tracer_if.pck) if (tracer_if.pck.rstn !== 1'b1) begin
@(pck) if (rstn !== 1'b1) begin
flush();
continue;
end
@ -81,8 +106,8 @@ module instr_tracer #(
// Instruction Decode
// -------------------
// we are decoding an instruction
if (tracer_if.pck.fetch_valid && tracer_if.pck.fetch_ack) begin
decode_instruction = tracer_if.pck.instruction;
if (fetch_valid && fetch_ack) begin
decode_instruction = instruction;
decode_queue.push_back(decode_instruction);
end
// -------------------
@ -90,85 +115,85 @@ module instr_tracer #(
// -------------------
// we got a new issue ack, so put the element from the decode queue to
// the issue queue
if (tracer_if.pck.issue_ack && !tracer_if.pck.flush_unissued) begin
if (issue_ack && !flush_unissued) begin
issue_instruction = decode_queue.pop_front();
issue_queue.push_back(issue_instruction);
// also save the scoreboard entry to a separate issue queue
issue_sbe_queue.push_back(scoreboard_entry_t'(tracer_if.pck.issue_sbe));
issue_sbe_queue.push_back(scoreboard_entry_t'(issue_sbe));
end
// --------------------
// Address Translation
// --------------------
if (tracer_if.pck.st_valid) begin
store_mapping.push_back(tracer_if.pck.st_paddr);
if (st_valid) begin
store_mapping.push_back(st_paddr);
end
if (tracer_if.pck.ld_valid && !tracer_if.pck.ld_kill) begin
load_mapping.push_back(tracer_if.pck.ld_paddr);
if (ld_valid && !ld_kill) begin
load_mapping.push_back(ld_paddr);
end
// ----------------------
// Store predictions
// ----------------------
if (tracer_if.pck.resolve_branch.valid) begin
bp.push_back(tracer_if.pck.resolve_branch);
if (resolve_branch.valid) begin
bp.push_back(resolve_branch);
end
// --------------
// Commit
// --------------
// we are committing an instruction
for (int i = 0; i < 2; i++) begin
if (tracer_if.pck.commit_ack[i]) begin
commit_instruction = scoreboard_entry_t'(tracer_if.pck.commit_instr[i]);
if (commit_ack[i]) begin
commit_instruction = scoreboard_entry_t'(commit_instr[i]);
issue_commit_instruction = issue_queue.pop_front();
issue_sbe = issue_sbe_queue.pop_front();
issue_sbe_item = issue_sbe_queue.pop_front();
// check if the instruction retiring is a load or store, get the physical address accordingly
if (tracer_if.pck.commit_instr[i].fu == ariane_pkg::LOAD)
if (commit_instr[i].fu == ariane_pkg::LOAD)
address_mapping = load_mapping.pop_front();
else if (tracer_if.pck.commit_instr[i].fu == ariane_pkg::STORE)
else if (commit_instr[i].fu == ariane_pkg::STORE)
address_mapping = store_mapping.pop_front();
if (tracer_if.pck.commit_instr[i].fu == ariane_pkg::CTRL_FLOW)
if (commit_instr[i].fu == ariane_pkg::CTRL_FLOW)
bp_instruction = bp.pop_front();
// the scoreboards issue entry still contains the immediate value as a result
// check if the write back is valid, if not we need to source the result from the register file
// as the most recent version of this register will be there.
if (tracer_if.pck.we_gpr[i] || tracer_if.pck.we_fpr[i]) begin
printInstr(issue_sbe, issue_commit_instruction, tracer_if.pck.wdata[i], address_mapping, tracer_if.pck.priv_lvl, tracer_if.pck.debug_mode, bp_instruction);
if (we_gpr[i] || we_fpr[i]) begin
printInstr(issue_sbe_item, issue_commit_instruction, wdata[i], address_mapping, priv_lvl, debug_mode, bp_instruction);
end else if (ariane_pkg::is_rd_fpr(commit_instruction.op)) begin
printInstr(issue_sbe, issue_commit_instruction, fp_reg_file[commit_instruction.rd], address_mapping, tracer_if.pck.priv_lvl, tracer_if.pck.debug_mode, bp_instruction);
printInstr(issue_sbe_item, issue_commit_instruction, fp_reg_file[commit_instruction.rd], address_mapping, priv_lvl, debug_mode, bp_instruction);
end else begin
printInstr(issue_sbe, issue_commit_instruction, gp_reg_file[commit_instruction.rd], address_mapping, tracer_if.pck.priv_lvl, tracer_if.pck.debug_mode, bp_instruction);
printInstr(issue_sbe_item, issue_commit_instruction, gp_reg_file[commit_instruction.rd], address_mapping, priv_lvl, debug_mode, bp_instruction);
end
end
end
// --------------
// Exceptions
// --------------
if (tracer_if.pck.exception.valid && !(tracer_if.pck.debug_mode && tracer_if.pck.exception.cause == riscv::BREAKPOINT)) begin
if (commit_exception.valid && !(debug_mode && commit_exception.cause == riscv::BREAKPOINT)) begin
// print exception
printException(tracer_if.pck.commit_instr[0].pc, tracer_if.pck.exception.cause, tracer_if.pck.exception.tval);
printException(commit_instr[0].pc, commit_exception.cause, commit_exception.tval);
end
// ----------------------
// Commit Registers
// ----------------------
// update shadow reg files here
for (int i = 0; i < 2; i++) begin
if (tracer_if.pck.we_gpr[i] && tracer_if.pck.waddr[i] != 5'b0) begin
gp_reg_file[tracer_if.pck.waddr[i]] = tracer_if.pck.wdata[i];
end else if (tracer_if.pck.we_fpr[i]) begin
fp_reg_file[tracer_if.pck.waddr[i]] = tracer_if.pck.wdata[i];
if (we_gpr[i] && waddr[i] != 5'b0) begin
gp_reg_file[waddr[i]] = wdata[i];
end else if (we_fpr[i]) begin
fp_reg_file[waddr[i]] = wdata[i];
end
end
// --------------
// Flush Signals
// --------------
// flush un-issued instructions
if (tracer_if.pck.flush_unissued) begin
if (flush_unissued) begin
flushDecode();
end
// flush whole pipeline
if (tracer_if.pck.flush) begin
if (flush_all) begin
flush();
end
end

View file

@ -1,72 +0,0 @@
// Copyright 2018 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.
//
// Author: Florian Zaruba, ETH Zurich
// Date: 16.05.2017
// Description: Instruction Tracer Interface
`ifndef VERILATOR
`ifndef INSTR_TRACER_IF_SV
`define INSTR_TRACER_IF_SV
interface instr_tracer_if #(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type bp_resolve_t = logic,
parameter type exception_t = logic,
parameter type scoreboard_entry_t = logic
)(
input clk
);
logic rstn;
logic flush_unissued;
logic flush;
// Decode
logic [31:0] instruction;
logic fetch_valid;
logic fetch_ack;
// Issue stage
logic issue_ack; // issue acknowledged
scoreboard_entry_t issue_sbe; // issue scoreboard entry
// WB stage
logic [1:0][4:0] waddr;
logic [1:0][63:0] wdata;
logic [1:0] we_gpr;
logic [1:0] we_fpr;
// commit stage
scoreboard_entry_t [1:0] commit_instr; // commit instruction
logic [1:0] commit_ack;
// address translation
// stores
logic st_valid;
logic [CVA6Cfg.PLEN-1:0] st_paddr;
// loads
logic ld_valid;
logic ld_kill;
logic [CVA6Cfg.PLEN-1:0] ld_paddr;
// misprediction
bp_resolve_t resolve_branch;
// exceptions
exception_t exception;
// current privilege level
riscv::priv_lvl_t priv_lvl;
logic debug_mode;
// the tracer just has a passive interface we do not drive anything with it
//pragma translate_off
clocking pck @(posedge clk);
input rstn, flush_unissued, flush, instruction, fetch_valid, fetch_ack, issue_ack, issue_sbe, waddr,
st_valid, st_paddr, ld_valid, ld_kill, ld_paddr, resolve_branch,
wdata, we_gpr, we_fpr, commit_instr, commit_ack, exception, priv_lvl, debug_mode;
endclocking
//pragma translate_on
endinterface
`endif
`endif

View file

@ -133,6 +133,7 @@ ${CVA6_REPO_DIR}/core/commit_stage.sv
${CVA6_REPO_DIR}/core/axi_shim.sv
${CVA6_REPO_DIR}/core/cva6_accel_first_pass_decoder_stub.sv
${CVA6_REPO_DIR}/core/acc_dispatcher.sv
${CVA6_REPO_DIR}/core/cva6_fifo_v3.sv
// What is "frontend"?
${CVA6_REPO_DIR}/core/frontend/btb.sv
@ -178,7 +179,6 @@ ${CVA6_REPO_DIR}/core/pmp/src/pmp.sv
${CVA6_REPO_DIR}/core/pmp/src/pmp_entry.sv
// Tracer (behavioral code, not RTL)
${CVA6_REPO_DIR}/common/local/util/instr_tracer_if.sv
${CVA6_REPO_DIR}/common/local/util/instr_tracer.sv
${CVA6_REPO_DIR}/common/local/util/tc_sram_wrapper.sv
${CVA6_REPO_DIR}/vendor/pulp-platform/tech_cells_generic/src/rtl/tc_sram.sv

View file

@ -90,6 +90,7 @@ module acc_dispatcher
input dcache_req_i_t [2:0] dcache_req_ports_i,
// Interface with the controller
output logic ctrl_halt_o,
input logic [11:0] csr_addr_i,
input logic flush_unissued_instr_i,
input logic flush_ex_i,
output logic flush_pipeline_o,
@ -165,7 +166,7 @@ module acc_dispatcher
assign acc_data = acc_valid_ex_o ? fu_data_i : '0;
fifo_v3 #(
cva6_fifo_v3 #(
.DEPTH (InstructionQueueDepth),
.FALL_THROUGH(1'b1),
.dtype (fu_data_t),

View file

@ -62,7 +62,7 @@ module amo_buffer #(
// e.g.: it is not speculative anymore
assign flush_amo_buffer = flush_i & !amo_valid_commit_i;
fifo_v3 #(
cva6_fifo_v3 #(
.DEPTH (1),
.dtype (amo_op_t),
.FPGA_EN(CVA6Cfg.FpgaEn)

View file

@ -433,6 +433,9 @@ module cache_ctrl
state_d = IDLE;
end
end
default:;
endcase
if (req_port_i.kill_req) begin

View file

@ -160,6 +160,10 @@ module miss_handler
ariane_pkg::amo_t amo_op;
logic [ 63:0] amo_operand_b;
// 32b request
logic [31:0] halfword;
logic [$clog2(CVA6Cfg.DCACHE_LINE_WIDTH)-1:0] cl_offset;
// ------------------------------
// Cache Management
// ------------------------------
@ -221,6 +225,9 @@ module miss_handler
amo_resp_o.result = '0;
amo_operand_b = '0;
halfword = '0;
cl_offset = '0;
case (state_q)
IDLE: begin
@ -303,7 +310,6 @@ module miss_handler
// ~> replace the cacheline
SAVE_CACHELINE: begin
// calculate cacheline offset
automatic logic [$clog2(CVA6Cfg.DCACHE_LINE_WIDTH)-1:0] cl_offset;
cl_offset = mshr_q.addr[CVA6Cfg.DCACHE_OFFSET_WIDTH-1:3] << 6;
// we've got a valid response from refill unit
if (valid_miss_fsm) begin
@ -474,8 +480,6 @@ module miss_handler
amo_resp_o.ack = 1'b1;
// Request is assumed to be still valid (ack not granted yet)
if (amo_req_i.size == 2'b10) begin
// 32b request
logic [31:0] halfword;
if (amo_req_i.operand_a[2:0] == '0) begin
// 64b aligned -> activate lower 4 byte lanes
halfword = amo_bypass_rsp.rdata[31:0];
@ -491,6 +495,8 @@ module miss_handler
end
end
end
default:;
endcase
end

View file

@ -179,7 +179,7 @@ module std_cache_subsystem
end
// W Channel
fifo_v3 #(
cva6_fifo_v3 #(
.DATA_WIDTH (2),
// we can have a maximum of 4 oustanding transactions as each port is blocking
.DEPTH (4),

View file

@ -310,7 +310,7 @@ module wt_axi_adapter
end
end
fifo_v3 #(
cva6_fifo_v3 #(
.dtype (icache_req_t),
.DEPTH (ReqFifoDepth),
.FPGA_EN(CVA6Cfg.FpgaEn)
@ -328,7 +328,7 @@ module wt_axi_adapter
.pop_i (arb_ack[0])
);
fifo_v3 #(
cva6_fifo_v3 #(
.dtype (dcache_req_t),
.DEPTH (ReqFifoDepth),
.FPGA_EN(CVA6Cfg.FpgaEn)
@ -353,7 +353,7 @@ module wt_axi_adapter
logic icache_rtrn_rd_en, dcache_rtrn_rd_en;
logic icache_rtrn_vld_d, icache_rtrn_vld_q, dcache_rtrn_vld_d, dcache_rtrn_vld_q;
fifo_v3 #(
cva6_fifo_v3 #(
.DATA_WIDTH(CVA6Cfg.MEM_TID_WIDTH),
.DEPTH (MetaFifoDepth),
.FPGA_EN (CVA6Cfg.FpgaEn)
@ -371,7 +371,7 @@ module wt_axi_adapter
.pop_i (icache_rtrn_vld_d)
);
fifo_v3 #(
cva6_fifo_v3 #(
.DATA_WIDTH(CVA6Cfg.MEM_TID_WIDTH),
.DEPTH (MetaFifoDepth),
.FPGA_EN (CVA6Cfg.FpgaEn)
@ -389,7 +389,7 @@ module wt_axi_adapter
.pop_i (dcache_rd_pop)
);
fifo_v3 #(
cva6_fifo_v3 #(
.DATA_WIDTH(CVA6Cfg.MEM_TID_WIDTH),
.DEPTH (MetaFifoDepth),
.FPGA_EN (CVA6Cfg.FpgaEn)
@ -419,7 +419,7 @@ module wt_axi_adapter
assign axi_wr_rdy = ~b_full;
assign b_push = axi_wr_valid & axi_wr_rdy;
fifo_v3 #(
cva6_fifo_v3 #(
.DATA_WIDTH (CVA6Cfg.AxiIdWidth + 1),
.DEPTH (MetaFifoDepth),
.FALL_THROUGH(1'b1),

View file

@ -299,7 +299,7 @@ module wt_dcache_wbuffer
///////////////////////////////////////////////////////
// TODO: todo: make this fall through if timing permits it
fifo_v3 #(
cva6_fifo_v3 #(
.FALL_THROUGH(1'b0),
.DATA_WIDTH ($clog2(CVA6Cfg.DCACHE_MAX_TX)),
.DEPTH (CVA6Cfg.DCACHE_MAX_TX),

View file

@ -1407,6 +1407,7 @@ module cva6
.acc_no_st_pending_i (no_st_pending_commit),
.dcache_req_ports_i (dcache_req_ports_ex_cache),
.ctrl_halt_o (halt_acc_ctrl),
.csr_addr_i (csr_addr_ex_csr),
.acc_dcache_req_ports_o(dcache_req_ports_acc_cache),
.acc_dcache_req_ports_i(dcache_req_ports_cache_acc),
.inval_ready_i (inval_ready),
@ -1503,59 +1504,40 @@ module cva6
`endif // PITON_ARIANE
`ifndef VERILATOR
instr_tracer_if #(
.CVA6Cfg(CVA6Cfg),
.bp_resolve_t(bp_resolve_t),
.exception_t(exception_t),
.scoreboard_entry_t(scoreboard_entry_t)
) tracer_if (
clk_i
);
// assign instruction tracer interface
// control signals
assign tracer_if.rstn = rst_ni;
assign tracer_if.flush_unissued = flush_unissued_instr_ctrl_id;
assign tracer_if.flush = flush_ctrl_ex;
// fetch
assign tracer_if.instruction = id_stage_i.fetch_entry_i.instruction;
assign tracer_if.fetch_valid = id_stage_i.fetch_entry_valid_i;
assign tracer_if.fetch_ack = id_stage_i.fetch_entry_ready_o;
// Issue
assign tracer_if.issue_ack = issue_stage_i.i_scoreboard.issue_ack_i;
assign tracer_if.issue_sbe = issue_stage_i.i_scoreboard.issue_instr_o;
// write-back
assign tracer_if.waddr = waddr_commit_id;
assign tracer_if.wdata = wdata_commit_id;
assign tracer_if.we_gpr = we_gpr_commit_id;
assign tracer_if.we_fpr = we_fpr_commit_id;
// commit
assign tracer_if.commit_instr = commit_instr_id_commit;
assign tracer_if.commit_ack = commit_ack;
// branch predict
assign tracer_if.resolve_branch = resolved_branch;
// address translation
// stores
assign tracer_if.st_valid = ex_stage_i.lsu_i.i_store_unit.store_buffer_i.valid_i;
assign tracer_if.st_paddr = ex_stage_i.lsu_i.i_store_unit.store_buffer_i.paddr_i;
// loads
assign tracer_if.ld_valid = ex_stage_i.lsu_i.i_load_unit.req_port_o.tag_valid;
assign tracer_if.ld_kill = ex_stage_i.lsu_i.i_load_unit.req_port_o.kill_req;
assign tracer_if.ld_paddr = ex_stage_i.lsu_i.i_load_unit.paddr_i;
// exceptions
assign tracer_if.exception = commit_stage_i.exception_o;
// assign current privilege level
assign tracer_if.priv_lvl = priv_lvl;
assign tracer_if.debug_mode = debug_mode;
instr_tracer #(
.CVA6Cfg(CVA6Cfg),
.bp_resolve_t(bp_resolve_t),
.scoreboard_entry_t(scoreboard_entry_t),
.interrupts_t(interrupts_t),
.exception_t(exception_t),
.INTERRUPTS(INTERRUPTS)
) instr_tracer_i (
.tracer_if(tracer_if),
.hart_id_i
// .tracer_if(tracer_if),
.pck (clk_i),
.rstn (rst_ni),
.flush_unissued (flush_unissued_instr_ctrl_id),
.flush_all (flush_ctrl_ex),
.instruction (id_stage_i.fetch_entry_i.instruction),
.fetch_valid (id_stage_i.fetch_entry_valid_i),
.fetch_ack (id_stage_i.fetch_entry_ready_o),
.issue_ack (issue_stage_i.i_scoreboard.issue_ack_i),
.issue_sbe (issue_stage_i.i_scoreboard.issue_instr_o),
.waddr (waddr_commit_id),
.wdata (wdata_commit_id),
.we_gpr (we_gpr_commit_id),
.we_fpr (we_fpr_commit_id),
.commit_instr (commit_instr_id_commit),
.commit_ack (commit_ack),
.st_valid (ex_stage_i.lsu_i.i_store_unit.store_buffer_i.valid_i),
.st_paddr (ex_stage_i.lsu_i.i_store_unit.store_buffer_i.paddr_i),
.ld_valid (ex_stage_i.lsu_i.i_load_unit.req_port_o.tag_valid),
.ld_kill (ex_stage_i.lsu_i.i_load_unit.req_port_o.kill_req),
.ld_paddr (ex_stage_i.lsu_i.i_load_unit.paddr_i),
.resolve_branch (resolved_branch),
.commit_exception (commit_stage_i.exception_o),
.priv_lvl (priv_lvl),
.debug_mode (debug_mode),
.hart_id_i (hart_id_i)
);
// mock tracer for Verilator, to be used with spike-dasm

192
core/cva6_fifo_v3.sv Normal file
View file

@ -0,0 +1,192 @@
// Copyright 2018 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.
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
module cva6_fifo_v3 #(
parameter bit FALL_THROUGH = 1'b0, // fifo is in fall-through mode
parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic
parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32
parameter type dtype = logic [DATA_WIDTH-1:0],
parameter bit FPGA_EN = 1'b0,
// DO NOT OVERWRITE THIS PARAMETER
parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1
)(
input logic clk_i, // Clock
input logic rst_ni, // Asynchronous reset active low
input logic flush_i, // flush the queue
input logic testmode_i, // test_mode to bypass clock gating
// status flags
output logic full_o, // queue is full
output logic empty_o, // queue is empty
output logic [ADDR_DEPTH-1:0] usage_o, // fill pointer
// as long as the queue is not full we can push new data
input dtype data_i, // data to push into the queue
input logic push_i, // data is valid and can be pushed to the queue
// as long as the queue is not empty we can pop new elements
output dtype data_o, // output data
input logic pop_i // pop head from queue
);
// local parameter
// FIFO depth - handle the case of pass-through, synthesizer will do constant propagation
localparam int unsigned FifoDepth = (DEPTH > 0) ? DEPTH : 1;
// clock gating control
logic gate_clock;
// pointer to the read and write section of the queue
logic [ADDR_DEPTH - 1:0] read_pointer_n, read_pointer_q, write_pointer_n, write_pointer_q;
// keep a counter to keep track of the current queue status
// this integer will be truncated by the synthesis tool
logic [ADDR_DEPTH:0] status_cnt_n, status_cnt_q;
// actual memory
dtype [FifoDepth - 1:0] mem_n, mem_q;
// fifo ram signals for fpga target
logic fifo_ram_we;
logic [ADDR_DEPTH-1:0] fifo_ram_read_address;
logic [ADDR_DEPTH-1:0] fifo_ram_write_address;
logic [$bits(dtype)-1:0] fifo_ram_wdata;
logic [$bits(dtype)-1:0] fifo_ram_rdata;
assign usage_o = status_cnt_q[ADDR_DEPTH-1:0];
if (DEPTH == 0) begin : gen_pass_through
assign empty_o = ~push_i;
assign full_o = ~pop_i;
end else begin : gen_fifo
assign full_o = (status_cnt_q == FifoDepth[ADDR_DEPTH:0]);
assign empty_o = (status_cnt_q == 0) & ~(FALL_THROUGH & push_i);
end
// status flags
// read and write queue logic
always_comb begin : read_write_comb
// default assignment
read_pointer_n = read_pointer_q;
write_pointer_n = write_pointer_q;
status_cnt_n = status_cnt_q;
if (FPGA_EN) begin
fifo_ram_we = '0;
fifo_ram_read_address = read_pointer_q;
fifo_ram_write_address = '0;
fifo_ram_wdata = '0;
data_o = (DEPTH == 0) ? data_i : fifo_ram_rdata;
end else begin
data_o = (DEPTH == 0) ? data_i : mem_q[read_pointer_q];
mem_n = mem_q;
gate_clock = 1'b1;
end
// push a new element to the queue
if (push_i && ~full_o) begin
if (FPGA_EN) begin
fifo_ram_we = 1'b1;
fifo_ram_write_address = write_pointer_q;
fifo_ram_wdata = data_i;
end else begin
// push the data onto the queue
mem_n[write_pointer_q] = data_i;
// un-gate the clock, we want to write something
gate_clock = 1'b0;
end
// increment the write counter
if (write_pointer_q == FifoDepth[ADDR_DEPTH-1:0] - 1)
write_pointer_n = '0;
else
write_pointer_n = write_pointer_q + 1;
// increment the overall counter
status_cnt_n = status_cnt_q + 1;
end
if (pop_i && ~empty_o) begin
// read from the queue is a default assignment
// but increment the read pointer...
if (read_pointer_n == FifoDepth[ADDR_DEPTH-1:0] - 1)
read_pointer_n = '0;
else
read_pointer_n = read_pointer_q + 1;
// ... and decrement the overall count
status_cnt_n = status_cnt_q - 1;
end
// keep the count pointer stable if we push and pop at the same time
if (push_i && pop_i && ~full_o && ~empty_o)
status_cnt_n = status_cnt_q;
// FIFO is in pass through mode -> do not change the pointers
if (FALL_THROUGH && (status_cnt_q == 0) && push_i) begin
data_o = data_i;
if (pop_i) begin
status_cnt_n = status_cnt_q;
read_pointer_n = read_pointer_q;
write_pointer_n = write_pointer_q;
end
end
end
// sequential process
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
read_pointer_q <= '0;
write_pointer_q <= '0;
status_cnt_q <= '0;
end else begin
if (flush_i) begin
read_pointer_q <= '0;
write_pointer_q <= '0;
status_cnt_q <= '0;
end else begin
read_pointer_q <= read_pointer_n;
write_pointer_q <= write_pointer_n;
status_cnt_q <= status_cnt_n;
end
end
end
if (FPGA_EN) begin : gen_fpga_queue
AsyncDpRam #(
.ADDR_WIDTH (ADDR_DEPTH),
.DATA_DEPTH (DEPTH),
.DATA_WIDTH ($bits(dtype))
) fifo_ram (
.Clk_CI ( clk_i ),
.WrEn_SI ( fifo_ram_we ),
.RdAddr_DI ( fifo_ram_read_address ),
.WrAddr_DI ( fifo_ram_write_address ),
.WrData_DI ( fifo_ram_wdata ),
.RdData_DO ( fifo_ram_rdata )
);
end else begin : gen_asic_queue
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
mem_q <= '0;
end else if (!gate_clock) begin
mem_q <= mem_n;
end
end
end
// pragma translate_off
`ifndef VERILATOR
initial begin
assert (DEPTH > 0) else $error("DEPTH must be greater than 0.");
end
full_write : assert property(
@(posedge clk_i) disable iff (~rst_ni) (full_o |-> ~push_i))
else $fatal (1, "Trying to push new data although the FIFO is full.");
empty_read : assert property(
@(posedge clk_i) disable iff (~rst_ni) (empty_o |-> ~pop_i))
else $fatal (1, "Trying to pop data although the FIFO is empty.");
`endif
// pragma translate_on
endmodule // fifo_v3

View file

@ -110,7 +110,7 @@ module cvxif_example_coprocessor
end
end
fifo_v3 #(
cva6_fifo_v3 #(
.FALL_THROUGH(1), //data_o ready and pop in the same cycle
.DATA_WIDTH (64),
.DEPTH (8),

View file

@ -411,7 +411,7 @@ ariane_pkg::FETCH_FIFO_DEPTH
for (genvar i = 0; i < CVA6Cfg.INSTR_PER_FETCH; i++) begin : gen_instr_fifo
// Make sure we don't save any instructions if we couldn't save the address
assign push_instr_fifo[i] = push_instr[i] & ~address_overflow;
fifo_v3 #(
cva6_fifo_v3 #(
.DEPTH (ariane_pkg::FETCH_FIFO_DEPTH),
.dtype (instr_data_t),
.FPGA_EN(CVA6Cfg.FpgaEn)
@ -439,7 +439,7 @@ ariane_pkg::FETCH_FIFO_DEPTH
end
end
fifo_v3 #(
cva6_fifo_v3 #(
.DEPTH (ariane_pkg::FETCH_FIFO_DEPTH), // TODO(zarubaf): Fork out to separate param
.DATA_WIDTH(CVA6Cfg.VLEN),
.FPGA_EN (CVA6Cfg.FpgaEn)

View file

@ -196,10 +196,12 @@ module id_stage #(
// ------------------
// Pipeline Register
// ------------------
assign issue_entry_o = issue_q.sbe;
assign issue_entry_valid_o = issue_q.valid;
assign is_ctrl_flow_o = issue_q.is_ctrl_flow;
assign orig_instr_o = issue_q.orig_instr;
always_comb begin
issue_entry_o = issue_q.sbe;
issue_entry_valid_o = issue_q.valid;
is_ctrl_flow_o = issue_q.is_ctrl_flow;
orig_instr_o = issue_q.orig_instr;
end
always_comb begin
issue_n = issue_q;

View file

@ -102,7 +102,7 @@ package build_config_pkg;
cfg.CachedRegionLength = CVA6Cfg.CachedRegionLength;
cfg.MaxOutstandingStores = CVA6Cfg.MaxOutstandingStores;
cfg.DebugEn = CVA6Cfg.DebugEn;
cfg.NonIdemPotenceEn = CVA6Cfg.NrNonIdempotentRules && CVA6Cfg.NonIdempotentLength;
cfg.NonIdemPotenceEn = (CVA6Cfg.NrNonIdempotentRules > 0) && (CVA6Cfg.NonIdempotentLength > 0);
cfg.AxiBurstWriteEn = CVA6Cfg.AxiBurstWriteEn;
cfg.ICACHE_SET_ASSOC = CVA6Cfg.IcacheSetAssoc;

View file

@ -270,7 +270,7 @@ package config_pkg;
int unsigned DATA_USER_EN;
int unsigned FETCH_USER_WIDTH;
int unsigned FETCH_USER_EN;
int unsigned AXI_USER_EN;
bit AXI_USER_EN;
int unsigned FETCH_WIDTH;
int unsigned INSTR_PER_FETCH;
@ -288,7 +288,7 @@ package config_pkg;
/// Empty configuration to sanity check proper parameter passing. Whenever
/// you develop a module that resides within the core, assign this constant.
localparam cva6_cfg_t cva6_cfg_empty = '0;
localparam cva6_cfg_t cva6_cfg_empty = cva6_cfg_t'(0);
/// Utility function being called to check parameters. Not all values make
/// sense for all parameters, here is the place to sanity check them.

View file

@ -15,7 +15,6 @@ module fifo_v3 #(
parameter int unsigned DATA_WIDTH = 32, // default data width if the fifo is of type logic
parameter int unsigned DEPTH = 8, // depth can be arbitrary from 0 to 2**32
parameter type dtype = logic [DATA_WIDTH-1:0],
parameter bit FPGA_EN = 1'b0,
// DO NOT OVERWRITE THIS PARAMETER
parameter int unsigned ADDR_DEPTH = (DEPTH > 1) ? $clog2(DEPTH) : 1
)(
@ -47,13 +46,6 @@ module fifo_v3 #(
// actual memory
dtype [FifoDepth - 1:0] mem_n, mem_q;
// fifo ram signals for fpga target
logic fifo_ram_we;
logic [ADDR_DEPTH-1:0] fifo_ram_read_address;
logic [ADDR_DEPTH-1:0] fifo_ram_write_address;
logic [$bits(dtype)-1:0] fifo_ram_wdata;
logic [$bits(dtype)-1:0] fifo_ram_rdata;
assign usage_o = status_cnt_q[ADDR_DEPTH-1:0];
if (DEPTH == 0) begin : gen_pass_through
@ -71,32 +63,18 @@ module fifo_v3 #(
read_pointer_n = read_pointer_q;
write_pointer_n = write_pointer_q;
status_cnt_n = status_cnt_q;
if (FPGA_EN) begin
fifo_ram_we = '0;
fifo_ram_read_address = read_pointer_q;
fifo_ram_write_address = '0;
fifo_ram_wdata = '0;
data_o = (DEPTH == 0) ? data_i : fifo_ram_rdata;
end else begin
data_o = (DEPTH == 0) ? data_i : mem_q[read_pointer_q];
mem_n = mem_q;
gate_clock = 1'b1;
end
data_o = (DEPTH == 0) ? data_i : mem_q[read_pointer_q];
mem_n = mem_q;
gate_clock = 1'b1;
// push a new element to the queue
if (push_i && ~full_o) begin
if (FPGA_EN) begin
fifo_ram_we = 1'b1;
fifo_ram_write_address = write_pointer_q;
fifo_ram_wdata = data_i;
end else begin
// push the data onto the queue
mem_n[write_pointer_q] = data_i;
// un-gate the clock, we want to write something
gate_clock = 1'b0;
end
// push the data onto the queue
mem_n[write_pointer_q] = data_i;
// un-gate the clock, we want to write something
gate_clock = 1'b0;
// increment the write counter
// this is dead code when DEPTH is a power of two
if (write_pointer_q == FifoDepth[ADDR_DEPTH-1:0] - 1)
write_pointer_n = '0;
else
@ -108,6 +86,7 @@ module fifo_v3 #(
if (pop_i && ~empty_o) begin
// read from the queue is a default assignment
// but increment the read pointer...
// this is dead code when DEPTH is a power of two
if (read_pointer_n == FifoDepth[ADDR_DEPTH-1:0] - 1)
read_pointer_n = '0;
else
@ -150,31 +129,16 @@ module fifo_v3 #(
end
end
if (FPGA_EN) begin : gen_fpga_queue
AsyncDpRam #(
.ADDR_WIDTH (ADDR_DEPTH),
.DATA_DEPTH (DEPTH),
.DATA_WIDTH ($bits(dtype))
) fifo_ram (
.Clk_CI ( clk_i ),
.WrEn_SI ( fifo_ram_we ),
.RdAddr_DI ( fifo_ram_read_address ),
.WrAddr_DI ( fifo_ram_write_address ),
.WrData_DI ( fifo_ram_wdata ),
.RdData_DO ( fifo_ram_rdata )
);
end else begin : gen_asic_queue
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
mem_q <= '0;
end else if (!gate_clock) begin
mem_q <= mem_n;
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
mem_q <= '0;
end else if (!gate_clock) begin
mem_q <= mem_n;
end
end
// pragma translate_off
`ifndef VERILATOR
`ifndef SYNTHESIS
`ifndef COMMON_CELLS_ASSERTS_OFF
initial begin
assert (DEPTH > 0) else $error("DEPTH must be greater than 0.");
end
@ -187,6 +151,6 @@ module fifo_v3 #(
@(posedge clk_i) disable iff (~rst_ni) (empty_o |-> ~pop_i))
else $fatal (1, "Trying to pop data although the FIFO is empty.");
`endif
// pragma translate_on
`endif
endmodule // fifo_v3