Skip to content

Commit a06608c

Browse files
committed
Merge branch 'bug_fixes' of https://github.com/vortexgpgpu/vortex into bug_fixes
2 parents ae446a4 + 6ec856d commit a06608c

5 files changed

Lines changed: 171 additions & 7 deletions

File tree

‎hw/rtl/core/VX_dispatch.sv‎

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright © 2019-2023
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
`include "VX_define.vh"
15+
16+
module VX_dispatch import VX_gpu_pkg::*; #(
17+
parameter `STRING INSTANCE_ID = "",
18+
parameter ISSUE_ID = 0
19+
) (
20+
input wire clk,
21+
input wire reset,
22+
23+
`ifdef PERF_ENABLE
24+
output wire [NUM_EX_UNITS-1:0][PERF_CTR_BITS-1:0] perf_stalls,
25+
output wire [NUM_EX_UNITS-1:0][PERF_CTR_BITS-1:0] perf_instrs,
26+
`endif
27+
// inputs
28+
VX_operands_if.slave operands_if,
29+
30+
// outputs
31+
VX_dispatch_if.master dispatch_if [NUM_EX_UNITS]
32+
);
33+
`UNUSED_SPARAM (INSTANCE_ID)
34+
`UNUSED_PARAM (ISSUE_ID)
35+
36+
localparam OUT_DATAW = $bits(dispatch_t);
37+
38+
wire [NUM_EX_UNITS-1:0] operands_ready_in;
39+
assign operands_if.ready = operands_ready_in[operands_if.data.ex_type];
40+
41+
for (genvar i = 0; i < NUM_EX_UNITS; ++i) begin : g_buffers
42+
VX_elastic_buffer #(
43+
.DATAW (OUT_DATAW),
44+
.SIZE (2),
45+
.OUT_REG (1)
46+
) buffer (
47+
.clk (clk),
48+
.reset (reset),
49+
.valid_in (operands_if.valid && (operands_if.data.ex_type == EX_BITS'(i))),
50+
.ready_in (operands_ready_in[i]),
51+
.data_in ({
52+
operands_if.data.uuid,
53+
operands_if.data.wis,
54+
operands_if.data.sid,
55+
operands_if.data.tmask,
56+
operands_if.data.PC,
57+
operands_if.data.wb,
58+
operands_if.data.wr_xregs,
59+
operands_if.data.rd,
60+
operands_if.data.op_type,
61+
operands_if.data.op_args,
62+
operands_if.data.rs1_data,
63+
operands_if.data.rs2_data,
64+
operands_if.data.rs3_data,
65+
operands_if.data.sop,
66+
operands_if.data.eop
67+
}),
68+
.data_out (dispatch_if[i].data),
69+
.valid_out (dispatch_if[i].valid),
70+
.ready_out (dispatch_if[i].ready)
71+
);
72+
end
73+
74+
`ifdef PERF_ENABLE
75+
reg [NUM_EX_UNITS-1:0][PERF_CTR_BITS-1:0] perf_stalls_r;
76+
reg [NUM_EX_UNITS-1:0][PERF_CTR_BITS-1:0] perf_instrs_r;
77+
78+
wire operands_if_fire = operands_if.valid && operands_if.ready;
79+
wire operands_if_stall = operands_if.valid && ~operands_if.ready;
80+
81+
for (genvar i = 0; i < NUM_EX_UNITS; ++i) begin : g_perf_stalls
82+
always @(posedge clk) begin
83+
if (reset) begin
84+
perf_stalls_r[i] <= '0;
85+
perf_instrs_r[i] <= '0;
86+
end else begin
87+
perf_stalls_r[i] <= perf_stalls_r[i] + PERF_CTR_BITS'(operands_if_stall && operands_if.data.ex_type == EX_BITS'(i));
88+
perf_instrs_r[i] <= perf_instrs_r[i] + PERF_CTR_BITS'(operands_if_fire && operands_if.data.ex_type == EX_BITS'(i) && operands_if.data.eop);
89+
end
90+
end
91+
assign perf_stalls[i] = perf_stalls_r[i];
92+
assign perf_instrs[i] = perf_instrs_r[i];
93+
end
94+
`endif
95+
96+
endmodule

‎hw/rtl/core/VX_schedule.sv‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ module VX_schedule import VX_gpu_pkg::*; #(
487487
end
488488
end
489489

490-
`RUNTIME_ASSERT(timeout_ctr < STALL_TIMEOUT, ("*** %s timeout: stalled_warps=%b", INSTANCE_ID, stalled_warps))
490+
`RUNTIME_ASSERT(timeout_ctr < STALL_TIMEOUT, ("*** %s timeout: active_warps=%b stalled_warps=%b pc0=0x%0h", INSTANCE_ID, active_warps, stalled_warps, to_fullPC(warp_pcs[0])))
491491

492492
`ifdef PERF_ENABLE
493493
reg [PERF_CTR_BITS-1:0] perf_sched_idles;

‎sim/simx/cluster.h‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class Cluster : public SimObject<Cluster> {
3535
struct AsyncClusterBarrier {
3636
static constexpr uint32_t MAX_CORES = 32;
3737

38-
CoreMask arrived_cores;
38+
CoreMask arrived_cores;
3939
CoreMask waiting_cores;
4040
uint32_t arrived_count;
4141
uint32_t expect_cores;
@@ -99,6 +99,9 @@ class Cluster : public SimObject<Cluster> {
9999

100100
uint32_t async_barrier_arrive(uint32_t bar_id, uint32_t count, uint32_t core_id);
101101
bool async_barrier_wait(uint32_t bar_id, uint32_t token, uint32_t core_id);
102+
uint32_t async_barrier_token(uint32_t bar_id) const {
103+
return async_barriers_.at(bar_id).generation;
104+
}
102105

103106
PerfStats perf_stats() const;
104107

‎sim/simx/emulator.cpp‎

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ Emulator::Emulator(const Arch &arch, const DCRS &dcrs, Core* core)
8080
, barriers_(arch.num_barriers(), 0)
8181
, ipdom_size_(arch.num_threads()-1)
8282
, async_barriers_(arch.num_barriers())
83+
, cluster_async_barriers_(arch.num_barriers())
8384
#ifdef EXT_TCU_ENABLE
8485
, tensor_unit_(core->tensor_unit())
8586
#endif
@@ -118,6 +119,10 @@ void Emulator::reset() {
118119
async_bar.reset_for_next_gen();
119120
}
120121

122+
for (auto& async_bar : cluster_async_barriers_) {
123+
async_bar.reset();
124+
}
125+
121126
#ifdef EXT_V_ENABLE
122127
vec_unit_->reset();
123128
#endif
@@ -291,7 +296,43 @@ uint32_t Emulator::barrier_arrive(uint32_t bar_id, uint32_t count, uint32_t wid)
291296
uint32_t bar_idx = bar_id & 0x7fffffff;
292297

293298
if (is_cluster) {
294-
return core_->socket()->async_barrier_arrive(bar_idx, count, core_->id());
299+
auto& b = cluster_async_barriers_.at(bar_idx);
300+
301+
if (b.expect_cores == 0) {
302+
b.expect_cores = count;
303+
} else {
304+
assert(b.expect_cores == count);
305+
}
306+
307+
uint32_t gen = core_->socket()->cluster()->async_barrier_token(bar_idx);
308+
if (b.token_valid && gen > b.token) {
309+
b.arrived_warps.reset();
310+
b.core_arrived = false;
311+
b.token_valid = false;
312+
b.token = 0;
313+
}
314+
315+
if (!b.token_valid) {
316+
b.token = gen;
317+
b.token_valid = true;
318+
} else {
319+
assert(gen == b.token);
320+
}
321+
322+
uint32_t token = b.token;
323+
324+
// Record warp arrival for this core.
325+
b.arrived_warps.set(wid);
326+
327+
// Count a core's arrival only once all its currently-active warps have arrived.
328+
if (!b.core_arrived && ((b.arrived_warps & active_warps_) == active_warps_)) {
329+
uint32_t token2 = core_->socket()->async_barrier_arrive(bar_idx, count, core_->id());
330+
assert(token2 == token);
331+
(void)token2;
332+
b.core_arrived = true;
333+
}
334+
335+
return token;
295336
}
296337

297338
auto& b = async_barriers_.at(bar_idx);
@@ -306,7 +347,6 @@ uint32_t Emulator::barrier_arrive(uint32_t bar_id, uint32_t count, uint32_t wid)
306347

307348
// If arrived in the same generation before, skip but still return token
308349
if (b.arrived_mask.test(wid)) {
309-
std::cout << " >> ARRIVE_DUP warp=" << wid << " (already arrived this gen)\n";
310350
return token;
311351
}
312352

@@ -350,7 +390,6 @@ bool Emulator::barrier_wait(uint32_t bar_id, uint32_t token, uint32_t wid) {
350390
stalled_warps_.set(wid);
351391
return false;
352392
}
353-
// stalled_warps_.reset(wid);
354393
return true;
355394
}
356395

@@ -362,7 +401,7 @@ bool Emulator::barrier_wait(uint32_t bar_id, uint32_t token, uint32_t wid) {
362401
uint32_t desired_gen = token + 1;
363402

364403
if (b.generation >= desired_gen) {
365-
404+
366405

367406
b.waiting_mask.reset(wid);
368407
// stalled_warps_.reset(wid);

‎sim/simx/emulator.h‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,32 @@ class Emulator {
201201

202202
std::vector<AsyncBarrier> async_barriers_;
203203

204+
struct ClusterAsyncBarrier {
205+
WarpMask arrived_warps;
206+
uint32_t expect_cores;
207+
uint32_t token;
208+
bool token_valid;
209+
bool core_arrived;
210+
211+
ClusterAsyncBarrier()
212+
: expect_cores(0)
213+
, token(0)
214+
, token_valid(false)
215+
, core_arrived(false) {
216+
arrived_warps.reset();
217+
}
218+
219+
void reset() {
220+
arrived_warps.reset();
221+
expect_cores = 0;
222+
token = 0;
223+
token_valid = false;
224+
core_arrived = false;
225+
}
226+
};
227+
228+
std::vector<ClusterAsyncBarrier> cluster_async_barriers_;
229+
204230

205231
#ifdef EXT_TCU_ENABLE
206232
TensorUnit::Ptr tensor_unit_;
@@ -215,4 +241,4 @@ std::vector<AsyncBarrier> async_barriers_;
215241

216242
}
217243

218-
#endif
244+
#endif

0 commit comments

Comments
 (0)