Skip to content

Commit dee4378

Browse files
hw: add support for misaligned vector length in 2x VLSU Spatz
1 parent 0a20143 commit dee4378

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

hw/ip/spatz/src/spatz_doublebw_vlsu.sv

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ module spatz_doublebw_vlsu
2121
parameter type spatz_mem_rsp_t = logic,
2222
// Dependant parameters. DO NOT CHANGE!
2323
localparam int unsigned NrInterfaces = NrMemPorts / spatz_pkg::N_FU,
24-
localparam int unsigned IdWidth = idx_width(NrOutstandingLoads)
24+
localparam int unsigned IdWidth = idx_width(NrOutstandingLoads),
25+
localparam int unsigned SpatzMemBytes = NrMemPorts * ELENB
2526
) (
2627
input logic clk_i,
2728
input logic rst_ni,
@@ -482,7 +483,10 @@ module spatz_doublebw_vlsu
482483
// The second interface starts from half of the vector to straighten the write-back VRF access pattern
483484
// To ensure that the 2 interfaces do not also conflict at the TCDM, there is HW scrambling of addresses to TCDM
484485
// such that they access different superbanks.
485-
if (!mem_is_indexed && !mem_is_strided && intf == 1) offset += (mem_spatz_req.vl / 2);
486+
if (!mem_is_indexed && !mem_is_strided && intf == 1) begin
487+
// Align the vector length with SpatzMemBytes bytes
488+
offset += ((mem_spatz_req.vl + (SpatzMemBytes / 2)) >> $clog2(SpatzMemBytes) << $clog2(SpatzMemBytes)) / 2;
489+
end
486490

487491
addr = mem_spatz_req.rs1 + offset;
488492
mem_req_addr[intf][fu] = (addr >> MAXEW) << MAXEW;
@@ -504,7 +508,7 @@ module spatz_doublebw_vlsu
504508

505509
// The second interface starts from half of the vector to straighten the write-back VRF access pattern
506510
if (intf == 1) begin
507-
vd_vreg_addr[intf] += commit_insn_q.vl / (2 * N_FU * ELENB);
511+
vd_vreg_addr[intf] += (commit_insn_q.vl + (SpatzMemBytes / 2)) >> $clog2(SpatzMemBytes);
508512
vs2_vreg_idx_addr[intf] += ((mem_spatz_req.vl >> (mem_spatz_req.vtype.vsew - int'(mem_spatz_req.op_mem.ew))) / (2 * N_FU * ELENB));
509513
end
510514

@@ -643,6 +647,15 @@ module spatz_doublebw_vlsu
643647
logic [NrInterfaces-1:0] vrf_commit_intf_valid, vrf_commit_intf_valid_q;
644648
logic [NrInterfaces-1:0] resp_overlap;
645649

650+
// Some metadata tracking to handle small vector length scenario
651+
commit_metadata_t commit_insn_q_rsp;
652+
`FF(commit_insn_q_rsp, commit_insn_q, '0)
653+
654+
// Check if the vector length is small such that only one of the interface is participating,
655+
// In this case bypass check for a valid response from the second interface
656+
logic vrf_commit_bypass;
657+
assign vrf_commit_bypass = commit_insn_q_rsp.vl <= ( NrMemPorts * ELENB / 2) ? 1'b1 : 1'b0;
658+
646659
for (genvar intf = 0; intf < NrInterfaces; intf++) begin : gen_vrf_req_register_intf
647660
spill_register #(
648661
.T(vrf_req_t)
@@ -675,12 +688,13 @@ module spatz_doublebw_vlsu
675688

676689
// To track a valid response on an interface until both interfaces finish and can send to the VRF
677690
// When this happens the FF is cleared
678-
// `FFLARNC(vrf_valid_rsp_q[intf], 1'b1, vrf_valid_rsp[intf], vlsu_rsp_valid_o & ~resp_overlap[intf], 1'b0, clk_i, rst_ni)
679691
assign vrf_valid_rsp_d[intf] = (vlsu_rsp_valid_o & ~resp_overlap[intf]) ? 1'b0 : (vrf_valid_rsp[intf] ? 1'b1 : vrf_valid_rsp_q[intf]);
680692
`FF(vrf_valid_rsp_q[intf], vrf_valid_rsp_d[intf], 1'b0)
681693

694+
// vrf_commit_intf_valid tracks if an interface is ready for completion
695+
// If only one of the interface has completed, track the completion in vrf_commit_intf_valid_q
682696
// Check if either a previously tracked response or there is a response in the current cycle
683-
assign vrf_commit_intf_valid[intf] = vrf_valid_rsp[intf] | vrf_valid_rsp_q[intf];
697+
assign vrf_commit_intf_valid[intf] = vrf_valid_rsp[intf] | vrf_valid_rsp_q[intf] | (intf == 1 ? vrf_commit_bypass : 1'b0);
684698
`FF(vrf_commit_intf_valid_q[intf], vrf_commit_intf_valid[intf], 1'b0);
685699
end
686700

@@ -694,11 +708,14 @@ module spatz_doublebw_vlsu
694708
// Check if interface 1 is the interface trying to commit, if so take resp information from interface 1
695709
// If both interfaces in sync, interface 1 is given priority
696710
assign resp_intf = vrf_commit_intf_valid_q [1] == 1'b0 ? 1'b1 : 1'b0;
711+
712+
// Check is both interfaces has reached to a completion and if the last write to the VRF is also done
713+
// Assign the instruction id from the interface that completes the last
697714
assign vlsu_rsp_o = &vrf_commit_intf_valid && |vrf_req_valid_q ? vrf_req_q[resp_intf].rsp : '{id: commit_insn_q.id, default: '0};
698715

699716
// Send response back to the controller to indicate end of request
700717
// Check if both the interfaces have completed request and have a valid response to send
701-
// Check if atleast one interface has a valid (interfaces can send responses asynchronously, but they finish the request together)
718+
// Check if atleast one interface has a valid (interfaces can send responses asynchronously to the VRF)
702719
// Set reponse high if one of the interfaces has a ready indicating the response has been written to the VRF
703720
assign vlsu_rsp_valid_o = &vrf_commit_intf_valid && |vrf_req_valid_q ? |vrf_req_ready_q : vlsu_finished_req && !commit_insn_q.is_load;
704721

0 commit comments

Comments
 (0)