From 08840f6d48485157adcc6b81dfa0f8c4bd2ac0e4 Mon Sep 17 00:00:00 2001 From: Matteo Perotti Date: Sat, 18 May 2024 19:42:09 +0200 Subject: [PATCH] controller, spatz: Fix chaining for multiple interfaces --- hw/ip/spatz/src/spatz.sv | 5 ++- hw/ip/spatz/src/spatz_controller.sv | 48 +++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/hw/ip/spatz/src/spatz.sv b/hw/ip/spatz/src/spatz.sv index 28072413..4411eacf 100644 --- a/hw/ip/spatz/src/spatz.sv +++ b/hw/ip/spatz/src/spatz.sv @@ -226,6 +226,7 @@ module spatz import spatz_pkg::*; import rvv_pkg::*; import fpnew_pkg::*; #( spatz_id_t [NrReadPorts+NrWritePorts-1:0] sb_id; spatz_controller #( + .NrMemPorts (NrMemPorts ), .NrVregfilePorts (NrReadPorts+NrWritePorts), .NrWritePorts (NrWritePorts ), .RegisterRsp (RegisterRsp ), @@ -330,7 +331,9 @@ module spatz import spatz_pkg::*; import rvv_pkg::*; import fpnew_pkg::*; #( .vrf_re_o (sb_re[VLSU_VD_RD1:VLSU_VS2_RD0] ), .vrf_rdata_i (vrf_rdata[VLSU_VD_RD1:VLSU_VS2_RD0] ), .vrf_rvalid_i (vrf_rvalid[VLSU_VD_RD1:VLSU_VS2_RD0] ), - .vrf_id_o ({sb_id[SB_VLSU_VD_WD1:SB_VLSU_VD_WD0], sb_id[VLSU_VD_RD1:VLSU_VS2_RD0]}), + // .vrf_id_o ({sb_id[SB_VLSU_VD_WD1:SB_VLSU_VD_WD0], sb_id[VLSU_VD_RD1:VLSU_VS2_RD0]}), + .vrf_id_o ({sb_id[SB_VLSU_VD_WD1], sb_id[VLSU_VD_RD1], sb_id[VLSU_VS2_RD1], + sb_id[SB_VLSU_VD_WD0], sb_id[VLSU_VD_RD0], sb_id[VLSU_VS2_RD0]}), // Interface Memory .spatz_mem_req_o (spatz_mem_req_o ), .spatz_mem_req_valid_o (spatz_mem_req_valid_o ), diff --git a/hw/ip/spatz/src/spatz_controller.sv b/hw/ip/spatz/src/spatz_controller.sv index 013294ca..3e5e66d0 100644 --- a/hw/ip/spatz/src/spatz_controller.sv +++ b/hw/ip/spatz/src/spatz_controller.sv @@ -14,12 +14,15 @@ module spatz_controller import fpnew_pkg::roundmode_e; import fpnew_pkg::fmt_mode_t; #( + parameter int unsigned NrMemPorts = 1, parameter int unsigned NrVregfilePorts = 1, parameter int unsigned NrWritePorts = 1, parameter bit RegisterRsp = 0, parameter type spatz_issue_req_t = logic, parameter type spatz_issue_rsp_t = logic, - parameter type spatz_rsp_t = logic + parameter type spatz_rsp_t = logic, + // Dependant parameters. DO NOT CHANGE! + localparam int unsigned NrInterfaces = NrMemPorts / spatz_pkg::N_FU ) ( input logic clk_i, input logic rst_ni, @@ -238,13 +241,23 @@ module spatz_controller `FF(scoreboard_q, scoreboard_d, '0) // Did the instruction write to the VRF in the previous cycle? - logic [NrParallelInstructions-1:0] wrote_result_q, wrote_result_d; + logic [NrInterfaces-1:0] [NrParallelInstructions-1:0] wrote_result_q, wrote_result_d; + // Did the instruction write to the VRF in the previous cycle with all its interfaces? + logic [NrParallelInstructions-1:0] wrote_result_all_intf_q; `FF(wrote_result_q, wrote_result_d, '0) + // Did the instruction write twice to the VRF in the previous two cycles? + logic [NrParallelInstructions-1:0] wrote_result_twice_d, wrote_result_twice_q; + `FF(wrote_result_twice_q, wrote_result_twice_d, '0) + // Is this instruction a narrowing or widening instruction? logic [NrParallelInstructions-1:0] narrow_wide_q, narrow_wide_d; `FF(narrow_wide_q, narrow_wide_d, '0) + // Is this an instruction that reads the VRF with more than one interface? + logic [NrParallelInstructions-1:0] is_multi_intf_rd_d, is_multi_intf_rd_q; + `FF(is_multi_intf_rd_q, is_multi_intf_rd_d, '0) + // Did this narrowing instruction write to the VRF in the previous cycle? logic [NrParallelInstructions-1:0] wrote_result_narrowing_q, wrote_result_narrowing_d; `FF(wrote_result_narrowing_q, wrote_result_narrowing_d, '0) @@ -255,32 +268,42 @@ module spatz_controller write_table_d = write_table_q; scoreboard_d = scoreboard_q; narrow_wide_d = narrow_wide_q; + is_multi_intf_rd_d = is_multi_intf_rd_q; wrote_result_narrowing_d = wrote_result_narrowing_q; // Nobody wrote to the VRF yet - wrote_result_d = '0; - sb_enable_o = '0; + wrote_result_twice_d = '0; + wrote_result_d = '0; + sb_enable_o = '0; + + wrote_result_all_intf_q = '1; + for (int unsigned intf = 0; intf < NrInterfaces; intf++) + wrote_result_all_intf_q &= wrote_result_q[intf]; for (int unsigned port = 0; port < NrVregfilePorts; port++) // Enable the VRF port if the dependant instructions wrote in the previous cycle - sb_enable_o[port] = sb_enable_i[port] && &(~scoreboard_q[sb_id_i[port]].deps | wrote_result_q) && (!(|scoreboard_q[sb_id_i[port]].deps) || !scoreboard_q[sb_id_i[port]].prevent_chaining); + sb_enable_o[port] = sb_enable_i[port] && &(~scoreboard_q[sb_id_i[port]].deps | (is_multi_intf_rd_q[sb_id_i[port]] ? wrote_result_twice_q : wrote_result_all_intf_q)) && (!(|scoreboard_q[sb_id_i[port]].deps) || !scoreboard_q[sb_id_i[port]].prevent_chaining); // Store the decisions if (sb_enable_o[SB_VFU_VD_WD]) begin + wrote_result_twice_d[sb_id_i[SB_VFU_VD_WD]] = wrote_result_all_intf_q[sb_id_i[SB_VFU_VD_WD]] && sb_wrote_result_i[SB_VFU_VD_WD - SB_VFU_VD_WD] && !wrote_result_twice_q[sb_id_i[SB_VFU_VD_WD]]; wrote_result_narrowing_d[sb_id_i[SB_VFU_VD_WD]] = sb_wrote_result_i[SB_VFU_VD_WD - SB_VFU_VD_WD] ^ narrow_wide_q[sb_id_i[SB_VFU_VD_WD]]; - wrote_result_d[sb_id_i[SB_VFU_VD_WD]] = sb_wrote_result_i[SB_VFU_VD_WD - SB_VFU_VD_WD] && (!narrow_wide_q[sb_id_i[SB_VFU_VD_WD]] || wrote_result_narrowing_q[sb_id_i[SB_VFU_VD_WD]]); + wrote_result_d[sb_id_i[SB_VFU_VD_WD]] = {2{sb_wrote_result_i[SB_VFU_VD_WD - SB_VFU_VD_WD] && (!narrow_wide_q[sb_id_i[SB_VFU_VD_WD]] || wrote_result_narrowing_q[sb_id_i[SB_VFU_VD_WD]])}}; end if (sb_enable_o[SB_VLSU_VD_WD0]) begin + wrote_result_twice_d[sb_id_i[SB_VLSU_VD_WD0]] = wrote_result_all_intf_q[sb_id_i[SB_VLSU_VD_WD0]] && sb_wrote_result_i[SB_VLSU_VD_WD0 - SB_VFU_VD_WD] && !wrote_result_twice_q[sb_id_i[SB_VLSU_VD_WD0]]; wrote_result_narrowing_d[sb_id_i[SB_VLSU_VD_WD0]] = sb_wrote_result_i[SB_VLSU_VD_WD0 - SB_VFU_VD_WD] ^ narrow_wide_q[sb_id_i[SB_VLSU_VD_WD0]]; - wrote_result_d[sb_id_i[SB_VLSU_VD_WD0]] = sb_wrote_result_i[SB_VLSU_VD_WD0 - SB_VFU_VD_WD] && (!narrow_wide_q[sb_id_i[SB_VLSU_VD_WD0]] || wrote_result_narrowing_q[sb_id_i[SB_VLSU_VD_WD0]]); + wrote_result_d[0][sb_id_i[SB_VLSU_VD_WD0]] = sb_wrote_result_i[SB_VLSU_VD_WD0 - SB_VFU_VD_WD] && (!narrow_wide_q[sb_id_i[SB_VLSU_VD_WD0]] || wrote_result_narrowing_q[sb_id_i[SB_VLSU_VD_WD0]]); end if (sb_enable_o[SB_VLSU_VD_WD1]) begin + wrote_result_twice_d[sb_id_i[SB_VLSU_VD_WD1]] = wrote_result_all_intf_q[sb_id_i[SB_VLSU_VD_WD1]] && sb_wrote_result_i[SB_VLSU_VD_WD1 - SB_VFU_VD_WD] && !wrote_result_twice_q[sb_id_i[SB_VLSU_VD_WD1]]; wrote_result_narrowing_d[sb_id_i[SB_VLSU_VD_WD1]] = sb_wrote_result_i[SB_VLSU_VD_WD1 - SB_VFU_VD_WD] ^ narrow_wide_q[sb_id_i[SB_VLSU_VD_WD1]]; - wrote_result_d[sb_id_i[SB_VLSU_VD_WD1]] = sb_wrote_result_i[SB_VLSU_VD_WD1 - SB_VFU_VD_WD] && (!narrow_wide_q[sb_id_i[SB_VLSU_VD_WD1]] || wrote_result_narrowing_q[sb_id_i[SB_VLSU_VD_WD1]]); + wrote_result_d[1][sb_id_i[SB_VLSU_VD_WD1]] = sb_wrote_result_i[SB_VLSU_VD_WD1 - SB_VFU_VD_WD] && (!narrow_wide_q[sb_id_i[SB_VLSU_VD_WD1]] || wrote_result_narrowing_q[sb_id_i[SB_VLSU_VD_WD1]]); end if (sb_enable_o[SB_VSLDU_VD_WD]) begin + wrote_result_twice_d[sb_id_i[SB_VSLDU_VD_WD]] = wrote_result_all_intf_q[sb_id_i[SB_VSLDU_VD_WD]] && sb_wrote_result_i[SB_VSLDU_VD_WD - SB_VFU_VD_WD] && !wrote_result_twice_q[sb_id_i[SB_VSLDU_VD_WD]]; wrote_result_narrowing_d[sb_id_i[SB_VSLDU_VD_WD]] = sb_wrote_result_i[SB_VSLDU_VD_WD - SB_VFU_VD_WD] ^ narrow_wide_q[sb_id_i[SB_VSLDU_VD_WD]]; - wrote_result_d[sb_id_i[SB_VSLDU_VD_WD]] = sb_wrote_result_i[SB_VSLDU_VD_WD - SB_VFU_VD_WD] && (!narrow_wide_q[sb_id_i[SB_VSLDU_VD_WD]] || wrote_result_narrowing_q[sb_id_i[SB_VSLDU_VD_WD]]); + wrote_result_d[sb_id_i[SB_VSLDU_VD_WD]] = {2{sb_wrote_result_i[SB_VSLDU_VD_WD - SB_VFU_VD_WD] && (!narrow_wide_q[sb_id_i[SB_VSLDU_VD_WD]] || wrote_result_narrowing_q[sb_id_i[SB_VSLDU_VD_WD]])}}; end // A unit has finished its VRF access. Reset the scoreboard. For each instruction, check @@ -295,6 +318,7 @@ module spatz_controller scoreboard_d[vfu_rsp_i.id] = '0; narrow_wide_d[vfu_rsp_i.id] = 1'b0; + is_multi_intf_rd_d[vfu_rsp_i.id] = 1'b0; wrote_result_narrowing_d[vfu_rsp_i.id] = 1'b0; for (int unsigned insn = 0; insn < NrParallelInstructions; insn++) scoreboard_d[insn].deps[vfu_rsp_i.id] = 1'b0; @@ -309,6 +333,7 @@ module spatz_controller scoreboard_d[vlsu_rsp_i.id] = '0; narrow_wide_d[vlsu_rsp_i.id] = 1'b0; + is_multi_intf_rd_d[vfu_rsp_i.id] = 1'b0; wrote_result_narrowing_d[vlsu_rsp_i.id] = 1'b0; for (int unsigned insn = 0; insn < NrParallelInstructions; insn++) scoreboard_d[insn].deps[vlsu_rsp_i.id] = 1'b0; @@ -323,6 +348,7 @@ module spatz_controller scoreboard_d[vsldu_rsp_i.id] = '0; narrow_wide_d[vsldu_rsp_i.id] = 1'b0; + is_multi_intf_rd_d[vfu_rsp_i.id] = 1'b0; wrote_result_narrowing_d[vsldu_rsp_i.id] = 1'b0; for (int unsigned insn = 0; insn < NrParallelInstructions; insn++) scoreboard_d[insn].deps[vsldu_rsp_i.id] = 1'b0; @@ -358,6 +384,10 @@ module spatz_controller // Is this a narrowing or widening instruction? if (spatz_req.op_arith.is_narrowing || spatz_req.op_arith.widen_vs1 || spatz_req.op_arith.widen_vs2) narrow_wide_d[spatz_req.id] = 1'b1; + + // Is this an instruction that reads the VRF with more than one interface? + if (spatz_req.op inside {VSE, VSSE, VSXE}) + is_multi_intf_rd_d[spatz_req.id] = 1'b1; end // An instruction never depends on itself