blob: a4598f2f1112a5d7a810e20d10bb74613dd007bf [file] [log] [blame]
`ifndef HDL_VERILOG_RVV_DESIGN_RVV_SVH
`include "rvv_backend.svh"
`endif
`ifndef RVV_ASSERT__SVH
`include "rvv_backend_sva.svh"
`endif
module rvv_backend
(
clk,
rst_n,
insts_valid_rvs2cq,
insts_rvs2cq,
insts_ready_cq2rvs,
remaining_count_cq2rvs,
uop_lsu_valid_rvv2lsu,
uop_lsu_rvv2lsu,
uop_lsu_ready_lsu2rvv,
uop_lsu_valid_lsu2rvv,
uop_lsu_lsu2rvv,
uop_lsu_ready_rvv2lsu,
rt_xrf_rvv2rvs,
rt_xrf_valid_rvv2rvs,
rt_xrf_ready_rvs2rvv,
wr_vxsat_valid,
wr_vxsat,
wr_vxsat_ready,
trap_valid_rvs2rvv,
trap_ready_rvv2rvs,
vcsr_valid,
vector_csr,
vcsr_ready,
rvv_idle,
rd_rob2rt_o
);
// global signal
input logic clk;
input logic rst_n;
// vector instruction and scalar operand input.
input logic [`ISSUE_LANE-1:0] insts_valid_rvs2cq;
input RVVCmd [`ISSUE_LANE-1:0] insts_rvs2cq;
output logic [`ISSUE_LANE-1:0] insts_ready_cq2rvs;
output logic [$clog2(`CQ_DEPTH):0] remaining_count_cq2rvs;
// load/store unit interface
// RVV send LSU uop to RVS
output logic [`NUM_LSU-1:0] uop_lsu_valid_rvv2lsu;
output UOP_RVV2LSU_t [`NUM_LSU-1:0] uop_lsu_rvv2lsu;
input logic [`NUM_LSU-1:0] uop_lsu_ready_lsu2rvv;
// LSU feedback to RVV
input logic [`NUM_LSU-1:0] uop_lsu_valid_lsu2rvv;
input UOP_LSU2RVV_t [`NUM_LSU-1:0] uop_lsu_lsu2rvv;
output logic [`NUM_LSU-1:0] uop_lsu_ready_rvv2lsu;
// RT to XRF. RVS arbitrates write ports of XRF by itself.
output logic [`NUM_RT_UOP-1:0] rt_xrf_valid_rvv2rvs;
output RT2XRF_t [`NUM_RT_UOP-1:0] rt_xrf_rvv2rvs;
input logic [`NUM_RT_UOP-1:0] rt_xrf_ready_rvs2rvv;
// RT to VCSR.vxsat
output logic wr_vxsat_valid;
output logic [`VCSR_VXSAT_WIDTH-1:0] wr_vxsat;
input logic wr_vxsat_ready;
// exception handler
// trap signal handshake
input logic trap_valid_rvs2rvv;
output logic trap_ready_rvv2rvs;
// the vcsr of last retired uop in last cycle
output logic vcsr_valid;
output RVVConfigState vector_csr;
input logic vcsr_ready;
// rvv_backend is not active.(IDLE)
output logic rvv_idle;
output ROB2RT_t [`NUM_RT_UOP-1:0] rd_rob2rt_o;
`ifdef TB_BRINGUP
// inst queue
logic [5:0] src1_idx [3:0];
logic [5:0] src2_idx [3:0];
logic [5:0] dest_idx [3:0];
logic inst_valid [3:0];
logic [31:0] inst_queue [3:0];
always_ff @(posedge clk) begin
if(!rst_n) begin
insts_ready_cq2rvs[0] <= 1'b0;
insts_ready_cq2rvs[1] <= 1'b0;
insts_ready_cq2rvs[2] <= 1'b0;
insts_ready_cq2rvs[3] <= 1'b0;
rt_xrf_valid_wb2rvs[0] <= 1'b0;
rt_xrf_valid_wb2rvs[1] <= 1'b0;
rt_xrf_valid_wb2rvs[2] <= 1'b0;
rt_xrf_valid_wb2rvs[3] <= 1'b0;
end else begin
insts_ready_cq2rvs[0] <= 1'b1;
insts_ready_cq2rvs[1] <= 1'b1;
insts_ready_cq2rvs[2] <= 1'b0;
insts_ready_cq2rvs[3] <= 1'b0;
rt_xrf_valid_wb2rvs[0] <= 1'b0;
rt_xrf_valid_wb2rvs[1] <= 1'b0;
rt_xrf_valid_wb2rvs[2] <= 1'b0;
rt_xrf_valid_wb2rvs[3] <= 1'b0;
end
end
always_ff @(posedge clk) begin
if(!rst_n) begin
inst_valid[0] <= 1'b0;
inst_valid[1] <= 1'b0;
inst_valid[2] <= 1'b0;
inst_valid[3] <= 1'b0;
end else begin
inst_valid[0] <= insts_ready_cq2rvs[0] & insts_valid_rvs2cq[0];
inst_valid[1] <= insts_ready_cq2rvs[1] & insts_valid_rvs2cq[1];
inst_valid[2] <= insts_ready_cq2rvs[2] & insts_valid_rvs2cq[2];
inst_valid[3] <= insts_ready_cq2rvs[3] & insts_valid_rvs2cq[3];
inst_queue[0] <= (insts_ready_cq2rvs[0] & insts_valid_rvs2cq[0]) ? {insts_rvs2cq[0].bits,insts_rvs2cq[0].opcode,5'b0} : inst_queue[0];
inst_queue[1] <= (insts_ready_cq2rvs[1] & insts_valid_rvs2cq[1]) ? {insts_rvs2cq[1].bits,insts_rvs2cq[1].opcode,5'b0} : inst_queue[1];
inst_queue[2] <= (insts_ready_cq2rvs[2] & insts_valid_rvs2cq[2]) ? {insts_rvs2cq[2].bits,insts_rvs2cq[2].opcode,5'b0} : inst_queue[2];
inst_queue[3] <= (insts_ready_cq2rvs[3] & insts_valid_rvs2cq[3]) ? {insts_rvs2cq[3].bits,insts_rvs2cq[3].opcode,5'b0} : inst_queue[3];
end
end
always_comb begin
for(int i=0;i<4;i++) begin
src1_idx[i] = inst_queue[i][19:15];
src2_idx[i] = inst_queue[i][24:20];
dest_idx[i] = inst_queue[i][11:7];
end
end
// vrf
logic [127:0] vreg [31:0];
logic [127:0] vreg_init_data [31:0];
logic [3:0] rt_last_uop;
always_ff @(posedge clk) begin
if(!rst_n) begin
for(int i=0; i<32; i++) begin
vreg[i] <= vreg_init_data[i];
end
for(int i=0; i<4; i++) begin
rt_last_uop[i] <= 1'b0;
end
end else begin
for(int i=0; i<4; i++) begin
if(inst_valid[i]) begin
for(int elm_idx=0; elm_idx<16; elm_idx++) begin
// sew 8b, lmul 1, vl=16
vreg[dest_idx[i]][elm_idx*8+:8] <= vreg[src1_idx[i]][elm_idx*8+:8] + vreg[src2_idx[i]][elm_idx*8+:8];
end
rt_last_uop[i] <= 1'b1;
end else begin
rt_last_uop[i] <= 1'b0;
end
end
end
end
initial begin
forever begin
@(posedge clk);
for(int i=0; i<3; i++) begin
if(insts_valid_rvs2cq[i] && insts_ready_cq2rvs[i]) begin
$display("[RTL INFO] @ %0t Got a instruction packet in insts_rvs2cq[%0d]", $time, i);
$display("insts_rvs2cq[i].pc = 0x%8x", insts_rvs2cq[i].inst_pc);
$display("insts_rvs2cq[i].insts = 0x%8x", {insts_rvs2cq[i].bits,insts_rvs2cq[i].opcode,5'b0});
end
end
end
end
`else
// ---internal signals definition-------------------------------------
// RVV frontend to command queue
logic cq_full;
logic [`ISSUE_LANE-1:0] cq_almost_full;
logic [`ISSUE_LANE-1:0] insts_ready;
logic [$clog2(`CQ_DEPTH):0] used_count_cq;
// Command queue to Decode
RVVCmd [`NUM_DE_INST-1:0] inst_pkg_cq2de;
logic fifo_empty_cq2de;
logic [`NUM_DE_INST-1:0] fifo_almost_empty_cq2de;
logic [`NUM_DE_INST-1:0] pop_de2cq;
// Decode to uop queue
logic [`NUM_DE_UOP-1:0] push_de2uq;
UOP_QUEUE_t [`NUM_DE_UOP-1:0] data_de2uq;
logic fifo_full_uq2de;
logic [`NUM_DE_UOP-1:0] fifo_almost_full_uq2de;
// Uop queue to dispatch
logic uq_empty;
logic [`NUM_DP_UOP-1:0] uq_almost_empty;
logic [`NUM_DP_UOP-1:0] uop_valid_uop2dp;
UOP_QUEUE_t [`NUM_DP_UOP-1:0] uop_uop2dp;
logic [`NUM_DP_UOP-1:0] uop_ready_dp2uop;
// Dispatch to RS
// ALU_RS
logic alu_rs_full;
logic [`NUM_DP_UOP-1:0] alu_rs_almost_full;
logic [`NUM_DP_UOP-1:0] rs_valid_dp2alu;
ALU_RS_t [`NUM_DP_UOP-1:0] rs_dp2alu;
logic [`NUM_DP_UOP-1:0] rs_ready_alu2dp;
// PMTRDT_RS
logic pmtrdt_rs_full;
logic [`NUM_DP_UOP-1:0] pmtrdt_rs_almost_full;
logic [`NUM_DP_UOP-1:0] rs_valid_dp2pmtrdt;
PMT_RDT_RS_t [`NUM_DP_UOP-1:0] rs_dp2pmtrdt;
logic [`NUM_DP_UOP-1:0] rs_ready_pmtrdt2dp;
// MUL_RS
logic mul_rs_full;
logic [`NUM_DP_UOP-1:0] mul_rs_almost_full;
logic [`NUM_DP_UOP-1:0] rs_valid_dp2mul;
MUL_RS_t [`NUM_DP_UOP-1:0] rs_dp2mul;
logic [`NUM_DP_UOP-1:0] rs_ready_mul2dp;
// DIV_RS
logic div_rs_full;
logic [`NUM_DP_UOP-1:0] div_rs_almost_full;
logic [`NUM_DP_UOP-1:0] rs_valid_dp2div;
DIV_RS_t [`NUM_DP_UOP-1:0] rs_dp2div;
logic [`NUM_DP_UOP-1:0] rs_ready_div2dp;
// LSU_RS
logic lsu_rs_full;
logic [`NUM_DP_UOP-1:0] lsu_rs_almost_full;
logic lsu_rs_empty;
logic [`NUM_LSU-1:0] lsu_rs_almost_empty;
logic [`NUM_DP_UOP-1:0] rs_valid_dp2lsu;
UOP_RVV2LSU_t [`NUM_DP_UOP-1:0] rs_dp2lsu;
logic [`NUM_DP_UOP-1:0] rs_ready_lsu2dp;
// LSU MAP INFO
logic mapinfo_full;
logic [`NUM_DP_UOP-1:0] mapinfo_almost_full;
logic [`NUM_DP_UOP-1:0] mapinfo_valid_dp2lsu;
LSU_MAP_INFO_t [`NUM_DP_UOP-1:0] mapinfo_dp2lsu;
logic [`NUM_DP_UOP-1:0] mapinfo_ready_lsu2dp;
// Dispatch to ROB
logic [`NUM_DP_UOP-1:0] uop_valid_dp2rob;
DP2ROB_t [`NUM_DP_UOP-1:0] uop_dp2rob;
logic [`NUM_DP_UOP-1:0] uop_ready_rob2dp;
logic [`ROB_DEPTH_WIDTH-1:0] uop_index_rob2dp;
// RS to excution unit
// ALU_RS to ALU
logic [`NUM_ALU-1:0] pop_alu2rs;
ALU_RS_t [`NUM_ALU-1:0] uop_rs2alu;
logic fifo_empty_rs2alu;
logic [`NUM_ALU-1:0] fifo_almost_empty_rs2alu;
// PMTRDT_RS to PMTRDT
logic [`NUM_PMTRDT-1:0] pop_pmtrdt2rs;
PMT_RDT_RS_t [`NUM_PMTRDT-1:0] uop_rs2pmtrdt;
logic fifo_empty_rs2pmtrdt;
logic [`NUM_PMTRDT-1:0] fifo_almost_empty_rs2pmtrdt;
PMT_RDT_RS_t [`PMTRDT_RS_DEPTH-1:0] all_uop_rs2pmtrdt;
logic [$clog2(`PMTRDT_RS_DEPTH):0] valid_cnt_rs2pmtrdt;
// MUL_RS to MUL
logic [`NUM_MUL-1:0] pop_mul2rs;
MUL_RS_t [`NUM_MUL-1:0] uop_rs2mul;
logic fifo_empty_rs2mul;
logic [`NUM_MUL-1:0] fifo_almost_empty_rs2mul;
// DIV_RS to DIV
logic [`NUM_DIV-1:0] pop_div2rs;
DIV_RS_t [`NUM_DIV-1:0] uop_rs2div;
logic fifo_empty_rs2div;
logic [`NUM_DIV-1:0] fifo_almost_empty_rs2div;
// LSU mapinfo
logic [`NUM_LSU-1:0] pop_mapinfo;
LSU_MAP_INFO_t [`NUM_LSU-1:0] mapinfo;
logic mapinfo_empty;
logic [`NUM_LSU-1:0] mapinfo_almost_empty;
// LSU result
logic [`NUM_LSU-1:0] pop_lsu_res;
UOP_LSU_t [`NUM_LSU-1:0] lsu_res;
logic lsu_res_full;
logic [`NUM_LSU-1:0] lsu_res_almost_full;
logic lsu_res_empty;
logic [`NUM_LSU-1:0] lsu_res_almost_empty;
logic [`NUM_LSU-1:0] uop_lsu_valid;
UOP_LSU_t [`NUM_LSU-1:0] uop_lsu;
logic [`NUM_LSU-1:0] uop_lsu_ready;
logic trap_valid_rmp2rob;
logic [`ROB_DEPTH_WIDTH-1:0] trap_rob_entry_rmp2rob;
// execution unit submit result to ROB
// ALU to ROB
logic [`NUM_ALU-1:0] wr_valid_alu2rob;
PU2ROB_t [`NUM_ALU-1:0] wr_alu2rob;
logic [`NUM_ALU-1:0] wr_ready_rob2alu;
// PMTRDT to ROB
logic [`NUM_PMTRDT-1:0] wr_valid_pmtrdt2rob;
PU2ROB_t [`NUM_PMTRDT-1:0] wr_pmtrdt2rob;
logic [`NUM_PMTRDT-1:0] wr_ready_rob2pmtrdt;
// MUL to ROB
logic [`NUM_MUL-1:0] wr_valid_mul2rob;
PU2ROB_t [`NUM_MUL-1:0] wr_mul2rob;
logic [`NUM_MUL-1:0] wr_ready_rob2mul;
// DIV to ROB
logic [`NUM_DIV-1:0] wr_valid_div2rob;
PU2ROB_t [`NUM_DIV-1:0] wr_div2rob;
logic [`NUM_DIV-1:0] wr_ready_rob2div;
// LSU to ROB
logic [`NUM_LSU-1:0] wr_valid_lsu2rob;
PU2ROB_t [`NUM_LSU-1:0] wr_lsu2rob;
logic [`NUM_LSU-1:0] wr_ready_rob2lsu;
// DP to VRF
logic [`NUM_DP_VRF-1:0][`REGFILE_INDEX_WIDTH-1:0] rd_index_dp2vrf;
logic [`NUM_DP_VRF-1:0][`VLEN-1:0] rd_data_vrf2dp;
logic [`VLEN-1:0] v0_mask_vrf2dp;
// ROB to dispatch
ROB2DP_t [`ROB_DEPTH-1:0] uop_rob2dp;
logic rob_empty;
// ROB to RT
logic [`NUM_RT_UOP-1:0] rd_valid_rob2rt;
ROB2RT_t [`NUM_RT_UOP-1:0] rd_rob2rt;
logic [`NUM_RT_UOP-1:0] rd_ready_rt2rob;
// RT to VRF
logic [`NUM_RT_UOP-1:0] wr_valid_rt2vrf;
RT2VRF_t [`NUM_RT_UOP-1:0] wr_data_rt2vrf;
// trap handler
logic trap_en;
logic is_trapping;
logic trap_ready_rob2rmp;
logic trap_flush_rvv;
genvar i;
// ---code start------------------------------------------------------
// Command queue
multi_fifo #(
.T (RVVCmd),
.M (`ISSUE_LANE),
.N (`NUM_DE_INST),
.DATAOUT_REG (1'b1),
.DEPTH (`CQ_DEPTH)
) u_command_queue (
// global
.clk (clk),
.rst_n (rst_n),
// write
.push (insts_valid_rvs2cq & insts_ready_cq2rvs),
.datain (insts_rvs2cq),
// read
.pop (pop_de2cq),
.dataout (inst_pkg_cq2de),
// fifo status
.full (cq_full),
.almost_full (cq_almost_full),
.empty (fifo_empty_cq2de),
.almost_empty (fifo_almost_empty_cq2de),
.clear (trap_flush_rvv),
.fifo_data (),
.wptr (),
.rptr (),
.entry_count (used_count_cq)
);
assign insts_ready[0] = ~cq_full;
generate
for (i=1;i<`ISSUE_LANE;i++) begin: cmq_ready
assign insts_ready[i] = !cq_almost_full[i];
end
endgenerate
assign insts_ready_cq2rvs = is_trapping ? 'b0 : insts_ready;
// output the remaining count in CQ
assign remaining_count_cq2rvs = `CQ_DEPTH - used_count_cq;
`ifdef ASSERT_ON
PushToCMDQueue: `rvv_expect((insts_valid_rvs2cq & insts_ready_cq2rvs) inside {4'b1111, 4'b0111, 4'b0011, 4'b0001, 4'b0000})
else $error("Push to command queue out-of-order: %4b.", $sampled(insts_valid_rvs2cq & insts_ready_cq2rvs));
PopFromCMDQueue: `rvv_expect(pop_de2cq inside {2'b11, 2'b01, 2'b00})
else $error("Pop from command queue out-of-order: %2b.", $sampled(pop_de2cq));
`endif // ASSERT_ON
// Decode unit
rvv_backend_decode #(
) u_decode (
// global
.clk (clk),
.rst_n (rst_n),
// cq2de
.inst_pkg_cq2de (inst_pkg_cq2de),
.fifo_empty_cq2de (fifo_empty_cq2de),
.fifo_almost_empty_cq2de (fifo_almost_empty_cq2de),
.pop_de2cq (pop_de2cq),
// de2uq
.push_de2uq (push_de2uq),
.data_de2uq (data_de2uq),
.fifo_full_uq2de (fifo_full_uq2de),
.fifo_almost_full_uq2de (fifo_almost_full_uq2de),
// trap-flush
.trap_flush_rvv (trap_flush_rvv)
);
// Uop queue
multi_fifo #(
.T (UOP_QUEUE_t),
.M (`NUM_DE_UOP),
.N (`NUM_DP_UOP),
.DEPTH (`UQ_DEPTH)
) u_uop_queue (
// global
.clk (clk),
.rst_n (rst_n),
// write
.push (push_de2uq),
.datain (data_de2uq),
// read
.pop (uop_valid_uop2dp & uop_ready_dp2uop),
.dataout (uop_uop2dp),
// fifo status
.full (fifo_full_uq2de),
.almost_full (fifo_almost_full_uq2de),
.empty (uq_empty),
.almost_empty (uq_almost_empty),
.clear (trap_flush_rvv),
.fifo_data (),
.wptr (),
.rptr (),
.entry_count ()
);
assign uop_valid_uop2dp[0] = ~uq_empty;
generate
for (i=1;i<`NUM_DP_UOP;i++) begin: uop_queue_valid
assign uop_valid_uop2dp[i] = !uq_almost_empty[i];
end
endgenerate
`ifdef ASSERT_ON
`ifdef ISSUE_3_READ_PORT_6
PushToUopQueue: `rvv_expect(push_de2uq inside {6'b111111, 6'b011111, 6'b001111, 6'b000111, 6'b000011, 6'b000001, 6'b000000})
else $error("Push to uops queue out-of-order: %6b", $sampled(push_de2uq));
PopFromUopQueue: `rvv_expect((uop_valid_uop2dp & uop_ready_dp2uop) inside {3'b111, 3'b011, 3'b001,3'b000})
else $error("Pop from uops queue out-of-order: %3b", $sampled(uop_valid_uop2dp & uop_ready_dp2uop));
`else //ISSUE_2
PushToUopQueue: `rvv_expect(push_de2uq inside {4'b1111, 4'b0111, 4'b0011, 4'b0001, 4'b0000})
else $error("Push to uops queue out-of-order: %4b", $sampled(push_de2uq));
PopFromUopQueue: `rvv_expect((uop_valid_uop2dp & uop_ready_dp2uop) inside {2'b11, 2'b01, 2'b00})
else $error("Pop from uops queue out-of-order: %2b", $sampled(uop_valid_uop2dp & uop_ready_dp2uop));
`endif
`endif // ASSERT_ON
// Dispatch unit
rvv_backend_dispatch #(
) u_dispatch (
// global
.clk (clk),
.rst_n (rst_n),
// Uop queue to dispatch
.uop_valid_uop2dp (uop_valid_uop2dp),
.uop_uop2dp (uop_uop2dp),
.uop_ready_dp2uop (uop_ready_dp2uop),
// Dispatch to RS
// ALU_RS
.rs_valid_dp2alu (rs_valid_dp2alu),
.rs_dp2alu (rs_dp2alu),
.rs_ready_alu2dp (rs_ready_alu2dp),
// PMTRDT_RS
.rs_valid_dp2pmtrdt (rs_valid_dp2pmtrdt),
.rs_dp2pmtrdt (rs_dp2pmtrdt),
.rs_ready_pmtrdt2dp (rs_ready_pmtrdt2dp),
// MUL_RS
.rs_valid_dp2mul (rs_valid_dp2mul),
.rs_dp2mul (rs_dp2mul),
.rs_ready_mul2dp (rs_ready_mul2dp),
// DIV_RS
.rs_valid_dp2div (rs_valid_dp2div),
.rs_dp2div (rs_dp2div),
.rs_ready_div2dp (rs_ready_div2dp),
// LSU_RS
.rs_valid_dp2lsu (rs_valid_dp2lsu),
.rs_dp2lsu (rs_dp2lsu),
.rs_ready_lsu2dp (rs_ready_lsu2dp),
// LSU MAP INFO
.mapinfo_valid_dp2lsu (mapinfo_valid_dp2lsu),
.mapinfo_dp2lsu (mapinfo_dp2lsu),
.mapinfo_ready_lsu2dp (mapinfo_ready_lsu2dp),
// Dispatch to ROB
.uop_valid_dp2rob (uop_valid_dp2rob),
.uop_dp2rob (uop_dp2rob),
.uop_ready_rob2dp (uop_ready_rob2dp),
.uop_index_rob2dp (uop_index_rob2dp),
// VRF to dispatch
.rd_index_dp2vrf (rd_index_dp2vrf),
.rd_data_vrf2dp (rd_data_vrf2dp),
.v0_mask_vrf2dp (v0_mask_vrf2dp),
// ROB to dispatch
.rob_entry (uop_rob2dp)
);
// RS, Reserve station
// ALU RS
multi_fifo #(
.T (ALU_RS_t),
.M (`NUM_DP_UOP),
.N (`NUM_ALU),
.DEPTH (`ALU_RS_DEPTH),
.CHAOS_PUSH (1'b1),
.DATAOUT_REG (1'b1)
) u_alu_rs (
// global
.clk (clk),
.rst_n (rst_n),
// write
.push (rs_valid_dp2alu),
.datain (rs_dp2alu),
// read
.pop (pop_alu2rs),
.dataout (uop_rs2alu),
// fifo status
.full (alu_rs_full),
.almost_full (alu_rs_almost_full),
.empty (fifo_empty_rs2alu),
.almost_empty (fifo_almost_empty_rs2alu),
.clear (trap_flush_rvv),
.fifo_data (),
.wptr (),
.rptr (),
.entry_count ()
);
assign rs_ready_alu2dp[0] = ~alu_rs_full;
generate
for (i=1;i<`NUM_DP_UOP;i++) begin: alu_rs_ready
assign rs_ready_alu2dp[i] = !alu_rs_almost_full[i];
end
endgenerate
`ifdef ASSERT_ON
PopFromAluRSQueue: `rvv_expect((pop_alu2rs) inside {2'b11, 2'b01, 2'b00})
else $error("Pop from ALU Reservation Station out-of-order: %2b", $sampled(pop_alu2rs));
`endif // ASSERT_ON
// PMTRDT RS, Permutation + Reduction
multi_fifo #(
.T (PMT_RDT_RS_t),
.M (`NUM_DP_UOP),
.N (`NUM_PMTRDT),
.DEPTH (`PMTRDT_RS_DEPTH),
.CHAOS_PUSH (1'b1),
.DATAOUT_REG (1'b1)
) u_pmtrdt_rs (
// global
.clk (clk),
.rst_n (rst_n),
// write
.push (rs_valid_dp2pmtrdt),
.datain (rs_dp2pmtrdt),
// read
.pop (pop_pmtrdt2rs),
.dataout (uop_rs2pmtrdt),
// fifo status
.full (pmtrdt_rs_full),
.almost_full (pmtrdt_rs_almost_full),
.empty (fifo_empty_rs2pmtrdt),
.almost_empty (fifo_almost_empty_rs2pmtrdt),
.clear (trap_flush_rvv),
.fifo_data (all_uop_rs2pmtrdt),
.wptr (),
.rptr (),
.entry_count (valid_cnt_rs2pmtrdt)
);
assign rs_ready_pmtrdt2dp[0] = ~pmtrdt_rs_full;
generate
for (i=1;i<`NUM_DP_UOP;i++) begin: pmtrdt_rs_ready
assign rs_ready_pmtrdt2dp[i] = !pmtrdt_rs_almost_full[i];
end
endgenerate
`ifdef ASSERT_ON
PopFromPmtrdtRSQueue: `rvv_expect((pop_pmtrdt2rs) inside {1'b1, 1'b0})
else $error("Pop from PMTRDT Reservation Station out-of-order: %1b", $sampled(pop_pmtrdt2rs));
`endif // ASSERT_ON
// MUL RS, Multiply + Multiply-accumulate
multi_fifo #(
.T (MUL_RS_t),
.M (`NUM_DP_UOP),
.N (`NUM_MUL),
.DEPTH (`MUL_RS_DEPTH),
.CHAOS_PUSH (1'b1)
) u_mul_rs (
// global
.clk (clk),
.rst_n (rst_n),
// write
.push (rs_valid_dp2mul),
.datain (rs_dp2mul),
// read
.pop (pop_mul2rs),
.dataout (uop_rs2mul),
// fifo status
.full (mul_rs_full),
.almost_full (mul_rs_almost_full),
.empty (fifo_empty_rs2mul),
.almost_empty (fifo_almost_empty_rs2mul),
.clear (trap_flush_rvv),
.fifo_data (),
.wptr (),
.rptr (),
.entry_count ()
);
assign rs_ready_mul2dp[0] = ~mul_rs_full;
generate
for (i=1;i<`NUM_DP_UOP;i++) begin: mul_rs_ready
assign rs_ready_mul2dp[i] = !mul_rs_almost_full[i];
end
endgenerate
`ifdef ASSERT_ON
// PopFromMulRSQueue: `rvv_expect((pop_mul2rs) inside {2'b11, 2'b01, 2'b00})
// else $error("Pop from MUL Reservation Station out-of-order: %2b", $sampled(pop_mul2rs));
`endif // ASSERT_ON
// DIV RS
multi_fifo #(
.T (DIV_RS_t),
.M (`NUM_DP_UOP),
.N (`NUM_DIV),
.DEPTH (`DIV_RS_DEPTH),
.CHAOS_PUSH (1'b1)
) u_div_rs (
// global
.clk (clk),
.rst_n (rst_n),
// write
.push (rs_valid_dp2div),
.datain (rs_dp2div),
// read
.pop (pop_div2rs),
.dataout (uop_rs2div),
// fifo status
.full (div_rs_full),
.almost_full (div_rs_almost_full),
.empty (fifo_empty_rs2div),
.almost_empty (fifo_almost_empty_rs2div),
.clear (trap_flush_rvv),
.fifo_data (),
.wptr (),
.rptr (),
.entry_count ()
);
assign rs_ready_div2dp[0] = ~div_rs_full;
generate
for (i=1;i<`NUM_DP_UOP;i++) begin: div_rs_ready
assign rs_ready_div2dp[i] = !div_rs_almost_full[i];
end
endgenerate
`ifdef ASSERT_ON
PopFromDivRSQueue: `rvv_expect((pop_div2rs) inside {1'b1, 1'b0})
else $error("Pop from DIV Reservation Station out-of-order: %1b", $sampled(pop_div2rs));
`endif // ASSERT_ON
// LSU RS
multi_fifo #(
.T (UOP_RVV2LSU_t),
.M (`NUM_DP_UOP),
.N (`NUM_LSU),
.DEPTH (`LSU_RS_DEPTH),
.CHAOS_PUSH (1'b1)
) u_lsu_rs (
// global
.clk (clk),
.rst_n (rst_n),
// write
.push (rs_valid_dp2lsu),
.datain (rs_dp2lsu),
// read
.pop (uop_lsu_valid_rvv2lsu & uop_lsu_ready_lsu2rvv),
.dataout (uop_lsu_rvv2lsu),
// fifo status
.full (lsu_rs_full),
.almost_full (lsu_rs_almost_full),
.empty (lsu_rs_empty),
.almost_empty (lsu_rs_almost_empty),
.clear (trap_flush_rvv),
.fifo_data (),
.wptr (),
.rptr (),
.entry_count ()
);
// LSU RS full signal for dispatch unit
assign rs_ready_lsu2dp[0] = ~lsu_rs_full;
generate
for (i=1;i<`NUM_DP_UOP;i++) begin: lsu_rs_ready
assign rs_ready_lsu2dp[i] = !lsu_rs_almost_full[i];
end
endgenerate
// output valid and data to LSU
assign uop_lsu_valid_rvv2lsu[0] = ~lsu_rs_empty;
generate
for (i=1;i<`NUM_LSU;i++) begin: gen_uop_lsu_valid
assign uop_lsu_valid_rvv2lsu[i] = ~lsu_rs_almost_empty[i];
end
endgenerate
// LSU MAP INFO
multi_fifo #(
.T (LSU_MAP_INFO_t),
.M (`NUM_DP_UOP),
.N (`NUM_LSU),
.DEPTH (`LSU_RS_DEPTH),
.CHAOS_PUSH (1'b1)
) u_lsu_map_info (
// global
.clk (clk),
.rst_n (rst_n),
// write
.push (mapinfo_valid_dp2lsu),
.datain (mapinfo_dp2lsu),
// read
.pop (pop_mapinfo),
.dataout (mapinfo),
// fifo status
.full (mapinfo_full),
.almost_full (mapinfo_almost_full),
.empty (mapinfo_empty),
.almost_empty (mapinfo_almost_empty),
.clear (trap_flush_rvv),
.fifo_data (),
.wptr (),
.rptr (),
.entry_count ()
);
assign mapinfo_ready_lsu2dp[0] = ~mapinfo_full;
generate
for (i=1;i<`NUM_DP_UOP;i++) begin: mapinfo_ready
assign mapinfo_ready_lsu2dp[i] = !mapinfo_almost_full[i];
end
endgenerate
// trap handler
// make sure all lsu uops before the trapping uop have been pushed into LSU_RES_FIFO
assign trap_en = trap_valid_rvs2rvv & (uop_lsu_valid_lsu2rvv=='b0) & (!lsu_res_full) & (!is_trapping);
cdffr
trap_valid
(
.clk (clk),
.rst_n (rst_n),
.e (trap_en),
.c (trap_flush_rvv),
.d (1'b1),
.q (is_trapping)
);
// LSU feedback result
assign uop_lsu_valid = trap_en ? 'b1 : uop_lsu_valid_lsu2rvv;
generate
assign uop_lsu[0].trap_valid = trap_en;
assign uop_lsu[0].uop_lsu2rvv = trap_en ? 'b0 : uop_lsu_lsu2rvv[0];
for (i=1;i<`NUM_LSU;i++) begin: get_uop_lsu
assign uop_lsu[i].trap_valid = 'b0;
assign uop_lsu[i].uop_lsu2rvv = uop_lsu_lsu2rvv[i];
end
endgenerate
multi_fifo #(
.T (UOP_LSU_t),
.M (`NUM_LSU),
.N (`NUM_LSU),
.DEPTH (`NUM_LSU*2),
.CHAOS_PUSH (1'b1)
) u_lsu_res (
// global
.clk (clk),
.rst_n (rst_n),
// write
.push (uop_lsu_valid&uop_lsu_ready_rvv2lsu),
.datain (uop_lsu),
// read
.pop (pop_lsu_res),
.dataout (lsu_res),
// fifo status
.full (lsu_res_full),
.almost_full (lsu_res_almost_full),
.empty (lsu_res_empty),
.almost_empty (lsu_res_almost_empty),
.clear (trap_flush_rvv),
.fifo_data (),
.wptr (),
.rptr (),
.entry_count ()
);
// ready signal for LSU
assign uop_lsu_ready[0] = !lsu_res_full;
generate
for (i=1;i<`NUM_LSU;i++) begin: lsu_res_ready
assign uop_lsu_ready[i] = !lsu_res_almost_full[i];
end
endgenerate
assign uop_lsu_ready_rvv2lsu = is_trapping ? 'b0 : uop_lsu_ready;
// PU, Process unit
// ALU
rvv_backend_alu #(
) u_alu (
// ALU_RS to ALU
.clk (clk),
.rst_n (rst_n),
.pop_ex2rs (pop_alu2rs),
.alu_uop_rs2ex (uop_rs2alu),
.fifo_empty_rs2ex (fifo_empty_rs2alu),
.fifo_almost_empty_rs2ex (fifo_almost_empty_rs2alu),
// ALU to ROB
.result_valid_ex2rob (wr_valid_alu2rob),
.result_ex2rob (wr_alu2rob),
.result_ready_rob2alu (wr_ready_rob2alu),
// trap-flush
.trap_flush_rvv (trap_flush_rvv)
);
// PMTRDT
rvv_backend_pmtrdt #(
) u_pmtrdt (
.clk (clk),
.rst_n (rst_n),
// PMTRDT_RS to PMTRDT
.pop_ex2rs (pop_pmtrdt2rs),
.pmtrdt_uop_rs2ex (uop_rs2pmtrdt),
.fifo_empty_rs2ex (fifo_empty_rs2pmtrdt),
.fifo_almost_empty_rs2ex (fifo_almost_empty_rs2pmtrdt),
.all_uop_data (all_uop_rs2pmtrdt),
.all_uop_cnt (valid_cnt_rs2pmtrdt),
// PMTRDT to ROB
.result_valid_ex2rob (wr_valid_pmtrdt2rob),
.result_ex2rob (wr_pmtrdt2rob),
.result_ready_rob2ex (wr_ready_rob2pmtrdt),
// trap-flush
.trap_flush_rvv (trap_flush_rvv)
);
// MULMAC
rvv_backend_mulmac u_mulmac (
.clk (clk),
.rst_n (rst_n),
// MUL_RS to MULMAC
.ex2rs_fifo_pop (pop_mul2rs),
.rs2ex_uop_data (uop_rs2mul),
.rs2ex_fifo_empty (fifo_empty_rs2mul),
.rs2ex_fifo_1left_to_empty (fifo_almost_empty_rs2mul[1]),
//MULMAC to ROB
.ex2rob_valid (wr_valid_mul2rob),
.ex2rob_data (wr_mul2rob),
.rob2ex_ready (wr_ready_rob2mul),
// trap-flush
.trap_flush_rvv (trap_flush_rvv)
);
// DIV
rvv_backend_div u_div
(
.clk (clk),
.rst_n (rst_n),
// DIV_RS to DIV
.pop_ex2rs (pop_div2rs),
.div_uop_rs2ex (uop_rs2div),
.fifo_empty_rs2ex (fifo_empty_rs2div),
.fifo_almost_empty_rs2ex (fifo_almost_empty_rs2div),
// DIV to ROB
.result_valid_ex2rob (wr_valid_div2rob),
.result_ex2rob (wr_div2rob),
.result_ready_rob2div (wr_ready_rob2div),
// trap-flush
.trap_flush_rvv (trap_flush_rvv)
);
// LSU remap
rvv_backend_lsu_remap
u_lsu_remap
(
.mapinfo (mapinfo),
.lsu_res (lsu_res),
.mapinfo_empty (mapinfo_empty),
.mapinfo_almost_empty (mapinfo_almost_empty),
.lsu_res_empty (lsu_res_empty),
.lsu_res_almost_empty (lsu_res_almost_empty),
.pop_mapinfo (pop_mapinfo),
.pop_lsu_res (pop_lsu_res),
.result_valid_lsu2rob (wr_valid_lsu2rob),
.result_lsu2rob (wr_lsu2rob),
.result_ready_rob2lsu (wr_ready_rob2lsu),
.trap_valid_rmp2rob (trap_valid_rmp2rob),
.trap_rob_entry_rmp2rob (trap_rob_entry_rmp2rob),
.trap_ready_rob2rmp (trap_ready_rob2rmp)
);
// ROB, Re-Order Buffer
rvv_backend_rob #(
) u_rob (
// global signal
.clk (clk),
.rst_n (rst_n),
// Dispatch to ROB
.uop_valid_dp2rob (uop_valid_dp2rob),
.uop_dp2rob (uop_dp2rob),
.uop_ready_rob2dp (uop_ready_rob2dp),
.rob_empty (rob_empty),
.uop_index_rob2dp (uop_index_rob2dp),
// ALU to ROB
.wr_valid_alu2rob (wr_valid_alu2rob),
.wr_alu2rob (wr_alu2rob),
.wr_ready_rob2alu (wr_ready_rob2alu),
// PMTRDT to ROB
.wr_valid_pmtrdt2rob (wr_valid_pmtrdt2rob),
.wr_pmtrdt2rob (wr_pmtrdt2rob),
.wr_ready_rob2pmtrdt (wr_ready_rob2pmtrdt),
// MUL to ROB
.wr_valid_mul2rob (wr_valid_mul2rob),
.wr_mul2rob (wr_mul2rob),
.wr_ready_rob2mul (wr_ready_rob2mul),
// DIV to ROB
.wr_valid_div2rob (wr_valid_div2rob),
.wr_div2rob (wr_div2rob),
.wr_ready_rob2div (wr_ready_rob2div),
// LSU to ROB
.wr_valid_lsu2rob (wr_valid_lsu2rob),
.wr_lsu2rob (wr_lsu2rob),
.wr_ready_rob2lsu (wr_ready_rob2lsu),
// ROB to RT
.rd_valid_rob2rt (rd_valid_rob2rt),
.rd_rob2rt (rd_rob2rt),
.rd_ready_rt2rob (rd_ready_rt2rob),
// ROB to DP
.uop_rob2dp (uop_rob2dp),
// Trap
.trap_valid_rmp2rob (trap_valid_rmp2rob),
.trap_rob_entry_rmp2rob (trap_rob_entry_rmp2rob),
.trap_ready_rob2rmp (trap_ready_rob2rmp),
.trap_ready_rvv2rvs (trap_ready_rvv2rvs),
.trap_flush_rvv (trap_flush_rvv)
);
// RT, Retire
rvv_backend_retire #(
) u_retire (
// ROB to RT
.rob2rt_write_valid (rd_valid_rob2rt),
.rob2rt_write_data (rd_rob2rt),
.rt2rob_write_ready (rd_ready_rt2rob),
// RT to RVS.XRF
.rt2xrf_write_valid (rt_xrf_valid_rvv2rvs),
.rt2xrf_write_data (rt_xrf_rvv2rvs),
.xrf2rt_write_ready (rt_xrf_ready_rvs2rvv),
// RT to VRF
.rt2vrf_write_valid (wr_valid_rt2vrf),
.rt2vrf_write_data (wr_data_rt2vrf),
// write to update vcsr
.rt2vcsr_write_valid (vcsr_valid),
.rt2vcsr_write_data (vector_csr),
.vcsr2rt_write_ready (vcsr_ready),
// update to vxsat
.rt2vxsat_write_valid (wr_vxsat_valid),
.rt2vxsat_write_data (wr_vxsat),
.vxsat2rt_write_ready (wr_vxsat_ready)
);
// VRF, Vector Register File
rvv_backend_vrf #(
) u_vrf (
// global signal
.clk (clk),
.rst_n (rst_n),
// DP to VRF
.dp2vrf_rd_index (rd_index_dp2vrf),
// VRF to DP
.vrf2dp_rd_data (rd_data_vrf2dp),
.vrf2dp_v0_data (v0_mask_vrf2dp),
// RT to VRF
.rt2vrf_wr_valid (wr_valid_rt2vrf),
.rt2vrf_wr_data (wr_data_rt2vrf)
);
// rvv_backend IDLE
assign rvv_idle = fifo_empty_cq2de&uq_empty&rob_empty;
assign rd_rob2rt_o = rd_rob2rt;
`endif // TB_BRINGUP
endmodule