feat(v2): M6 Dependency Manager, multi-dependency wake-up

Implements M6: dependency_manager.v tracks a table of node
descriptors (node_id/state/required_dependencies/resolved_
dependencies/producer_ids -- §10's exact field list), incrementing a
waiting node's resolved count whenever one of its listed producers
completes, transitioning it to READY once resolved==required, and
dispatching ready nodes to the Neural Director (M5) one at a time via
a backpressure-safe valid/ready interface.

Verified with Verilator on a small hand-built DAG: node0/node1 have no
dependencies (dispatch immediately); node2 depends on BOTH node0 AND
node1 ("dipendenze multiple") and stays WAITING until both complete,
confirmed via an explicit negative check after only one resolves;
node3 depends on node0 ALONE, demonstrating a single producer
("node0") satisfying two different consumers' dependencies
("risultati condivisi... piu' consumer") -- node3 fully, node2
partially. 4/4 tests pass.

Scope for this milestone (decisions.log DEC-0008): dependency
COUNTING/readiness only, no direct producer-to-consumer value
forwarding (§11 frames that as a "quando possibile" optimization, not
a correctness requirement -- deferred until real bandwidth
measurements justify it) and no node-slot reclamation after dispatch
(not exercised by any scenario built so far).

Real synthesis: 0 CHECK problems, 763 LUT4/474 FF/0 DSP/0 CCU2C. Real
place&route (module fits the TRELLIS_IO budget as a bare top-level
this time, no harness needed): Fmax 155.30 MHz, PASS at 80MHz.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013xXuuRUWZScuo1DeYJxs3v
This commit is contained in:
2026-09-05 14:51:02 +02:00
co-authored by Claude Sonnet 5
parent 2e4cedc761
commit 8af16d3a12
14 changed files with 101920 additions and 2 deletions
+5 -2
View File
@@ -31,8 +31,11 @@ reali, non solo scritto).
first-free. 4/4 test PASS (dispatch + coda + backpressure reale
su N_SLOTS=2). FSM ridotta a 4 stati, dependency rimandata a M6
(`logs/decisions.log` DEC-0007). Fmax 250.50 MHz.
- [ ] **M6 — Dependency Manager** (`dependency_manager.v`), ready/waiting
queue, dependency counters, wake-up, producer tracking.
- [x] **M6 — Dependency Manager** (`dependency_manager.v`), ready/waiting
queue, dependency counters, wake-up, producer tracking. 4/4 test
PASS (dipendenze multiple + produttore condiviso/piu' consumer).
Fmax 155.30 MHz. Forwarding di valori e riuso slot rimandati
(`logs/decisions.log` DEC-0008).
- [ ] **M7 — Dataflow Core** (`dataflow_core.v`), integrazione completa.
- [ ] **M8 — PSRAM integration**, controller V1 non modificato, misura reale.
- [ ] **M9 — Full benchmark**, tabella V1 vs V2 (§32 del mandato).
+7
View File
@@ -81,3 +81,10 @@ timing harness -- see errors.log ERR-0005)
| Module | Fmax (POST-P&R) | LUT | FF | DSP | CCU2C |
|------------------|------------------|-----|-----|-----|-------|
| neural_director (N_SLOTS=4) | 250.50 MHz | 382 | 366 | 0 | 4 |
[2026-09-05] M6 Dependency Manager (real standalone synthesis + P&R,
no harness needed)
| Module | Fmax (POST-P&R) | LUT | FF | DSP | CCU2C |
|----------------------|------------------|-----|-----|-----|-------|
| dependency_manager (N_NODES=16) | 155.30 MHz | 763 | 474 | 0 | 0 |
+66
View File
@@ -389,3 +389,69 @@ experimentally-driven milestone per §9's own text.
STATUS:
ACCEPTED
---
DEC-0008
DATE: 2026-09-05
DECISION:
dependency_manager.v (M6) does NOT implement §11's direct producer-
to-consumer VALUE forwarding (bypassing the Result Buffer/external-
memory round-trip). It tracks dependency COUNTS and READINESS only --
"has this node's data become available", resolved via a
producer_done_node_id tag matched against each waiting node's own
producer_ids list. A ready node's job descriptor still points at
result_addr (wherever the Memory Manager, M4, wrote the producer's
actual result), which is how a consumer finds its real input data
today. Additionally, node table slots are NOT reclaimed after
dispatch (ST_DISPATCHED is terminal) -- a full graph run allocates its
N_NODES once, not a reusable pool.
WHY:
§11 itself frames forwarding as an optimization ("quando possibile"),
not a correctness requirement -- the dependency-COUNTING mechanism
(§10's actual explicit field list: node_id/state/required_dependencies/
resolved_dependencies/producer_information) is what gates correct
scheduling; forwarding is a bandwidth/latency optimization on top of
an already-correct base. Implementing real value forwarding would
require reworking the Neural Processor's operand path (M1) and Memory
Manager's fetch path (M4) to support a bypass source in addition to
PSRAM -- a bigger change that should be justified by real measured
data (§22/§30: no invented results) showing memory bandwidth is
actually the bottleneck, not assumed now. Slot non-reclamation is
similarly a scope choice: reclaiming/reusing node table entries mid-run
only matters for graphs that run longer than N_NODES distinct node
launches, or that need dynamic re-registration -- not exercised by
this milestone's own test (a bounded DAG, registered once, run once).
EVIDENCE:
hardware/v2/sim/tb_dependency_manager.v -- 4/4 tests pass demonstrating
multi-dependency (node2 needs both node0 AND node1) and shared-
producer/multi-consumer wake-up (node0's single completion correctly
satisfies both node3 fully and node2 partially) using ONLY the
counting mechanism, no forwarded values -- confirming the counting-
only design is sufficient for correct scheduling.
ALTERNATIVES:
1. Implement value forwarding now (Producer -> Consumer FIFO directly,
per §11's diagram). Rejected: no measured evidence yet that the
PSRAM round-trip is a real bottleneck (§22 measurements are M9's
job); adding it now would be exactly the kind of unmeasured,
assumption-driven change §30 warns against.
2. Reclaim/reuse node table slots after dispatch. Rejected: adds
real complexity (a free-list, or requiring producer_done for a
DISPATCHED node to also clear it) for a scenario (graphs needing
more distinct node launches than N_NODES, or dynamic re-
registration) this milestone's test doesn't exercise -- revisit if
a real M7+ integration scenario needs it.
RESULT:
dependency_manager.v as implemented: pure dependency-count tracking,
first-found-ready dispatch to the Director (M5), no value forwarding,
no slot reclamation. Both explicitly noted as deferred, not silently
missing.
STATUS:
ACCEPTED
+22
View File
@@ -159,3 +159,25 @@ errors: nessun bug RTL, solo 2 bug di testbench (vedi experiments.log
EXP-0006).
decision: vedi decisions.log DEC-0007.
next_action: M6 -- dependency_manager.v.
[2026-09-05T18:00:00Z] commit=2e4cedc session=v2-M6-dependency-manager
module: hardware/v2/rtl/dependency_manager.v
action: implementato M6 -- tabella di dipendenze (node_id/state/
required/resolved/producer_ids, campi esatti §10), wake-up su
completamento produttore, dispatch first-found-ready verso il
Director (M5).
reason: roadmap M6.
result: 4/4 test PASS su un piccolo DAG a mano (node2 dipende da
ENTRAMBI node0+node1 -- dipendenze multiple; node3 dipende solo da
node0 -- risultato condiviso/piu' consumer). Confermato: node3 pronto
subito dopo node0, node2 resta WAITING finche' anche node1 non
completa. Sintesi reale: 0 problemi, 763 LUT4/474 FF/0 DSP/0 CCU2C.
Fmax reale (nessun harness necessario stavolta): 155.30 MHz.
errors: un errore di sintassi nel testbench (nested replication senza
livello di parentesi extra), non un bug RTL.
decision: vedi decisions.log DEC-0008 (nessun forwarding di valori
ancora, nessun riuso degli slot ancora -- entrambi rimandati
esplicitamente).
next_action: M7 -- dataflow_core.v, prima integrazione di
Director+Dependency Manager+Memory Manager+Processor Array+Buffer
in un unico top-level.
+43
View File
@@ -322,3 +322,46 @@ next_action: M6 -- dependency_manager.v (ready/waiting queue,
dependency counters, wake-up, producer tracking) -- the first
milestone where job READINESS itself, not just free-slot dispatch,
becomes the Director's actual gating condition.
EXP-0007
timestamp: 2026-09-05T18:00:00Z
git_commit: 2e4cedc (+ uncommitted M6 work)
session: v2-M6-dependency-manager
module: hardware/v2/rtl/dependency_manager.v
configuration: N_NODES=8 (sim), N_NODES=16 (synth default),
MAX_DEPS=4, ADDR_WIDTH=23
action: M6 -- dependency-count tracking table (node_id/state/
required_dependencies/resolved_dependencies/producer_ids, §10
exact field list), first-found-ready dispatch to the Director.
command (sim, Verilator): verilator --binary --timing -j 0 -Wno-fatal
--top-module tb -o /tmp/vtb_dep hardware/v2/rtl/dependency_manager.v
hardware/v2/sim/tb_dependency_manager.v && /tmp/vtb_dep
command (synth/timing): yosys -p "synth_ecp5 -json .../top.json -top
dependency_manager" hardware/v2/rtl/dependency_manager.v;
nextpnr-ecp5 --45k --package CABGA381 --speed 8 --freq 80
--lpf-allow-unconstrained (no timing harness needed this time --
module's ports fit within the TRELLIS_IO budget as a bare top-level).
result:
SIMULATED: 4/4 tests PASS on a small hand-built DAG (node0, node1:
no dependencies; node2: depends on BOTH node0 and node1 --
"dipendenze multiple"; node3: depends on node0 ALONE -- "risultati
condivisi... piu' consumer"): node0/node1 dispatch immediately;
node3 becomes READY the cycle node0's producer_done arrives (before
node1 completes); node2 stays WAITING until BOTH node0 AND node1
have completed, confirmed by an explicit negative check (still
WAITING after only one of its two dependencies resolved).
SYNTHESIZED: 0 CHECK problems, 763 LUT4, 474 TRELLIS_FF, 0 DSP,
0 CCU2C.
POST-P&R (real, no harness needed): Fmax = 155.30 MHz, PASS at
80MHz.
errors: one testbench syntax error (nested nonblocking nested-
replication `{(N){M{1'b0}}}` needs an extra brace level, Verilator
correctly rejected it) -- fixed by building reg_producer_ids via
explicit bit-slice assignment instead of one big concatenation
expression. Not an RTL bug.
decision: see decisions.log DEC-0008 (no value forwarding yet, no
slot reclamation yet -- both explicitly deferred, not missing by
oversight).
next_action: M7 -- dataflow_core.v, integrating Director + Dependency
Manager + Memory Manager + Processor Array + Buffers into one top-
level module for the first time.
+6
View File
@@ -54,3 +54,9 @@ test: 4 cases (3-jobs-2-slots first-free dispatch + queueing,
backpressure fill/recover)
simulator: Verilator 5.050 (--binary --timing)
PASS/FAIL: 4/4 PASS
[2026-09-05] EXP-0007 -- hardware/v2/sim/tb_dependency_manager.v
test: 4 cases on a 4-node DAG (2 independent + 1 dual-dependency +
1 single-dependency-shared-producer)
simulator: Verilator 5.050 (--binary --timing)
PASS/FAIL: 4/4 PASS
+3
View File
@@ -43,3 +43,6 @@ LUT4=851 TRELLIS_FF=789 CCU2C=108 MULT18X18D=0 (expected, no
[2026-09-05] EXP-0006 -- neural_director (N_SLOTS=4, standalone)
LUT4=382 TRELLIS_FF=366 CCU2C=4 DSP=0. CHECK: 0 problems.
[2026-09-05] EXP-0007 -- dependency_manager (N_NODES=16, MAX_DEPS=4)
LUT4=763 TRELLIS_FF=474 CCU2C=0 DSP=0. CHECK: 0 problems.
+5
View File
@@ -49,3 +49,8 @@ Fmax: 165.86 MHz -- PASS at 80MHz (real place&route measurement)
see errors.log ERR-0005 for why), real nextpnr-ecp5 --45k --package
CABGA381 --speed 8 --freq 80 --lpf-allow-unconstrained
Fmax: 250.50 MHz -- PASS at 80MHz (real place&route measurement)
[2026-09-05] EXP-0007 -- dependency_manager (N_NODES=16, standalone,
no harness needed), real nextpnr-ecp5 --45k --package CABGA381
--speed 8 --freq 80 --lpf-allow-unconstrained
Fmax: 155.30 MHz -- PASS at 80MHz (real place&route measurement)
+192
View File
@@ -0,0 +1,192 @@
`timescale 1ns/1ps
// ================================================================
// FPGA-Neural V2 -- Dependency Manager (M6, docs/v2-description.md §10)
//
// Holds a small table of N_NODES job descriptors, each tracking:
// node_id, state (EMPTY/WAITING/READY/DISPATCHED),
// required_dependencies, resolved_dependencies, producer_ids[MAX_DEPS]
// (§10's exact field list), plus the job descriptor fields
// (x_base/w_base/n_tiles/result_addr) needed to hand the node off to
// the Neural Director (M5) once it becomes READY.
//
// A node with required_dependencies==0 is immediately READY on
// registration (no producers to wait for -- a graph's own input
// nodes, or a fully-independent job). When a PRODUCER completes
// (producer_done_valid/producer_done_node_id, tagged by whichever
// node just finished -- fed from the Director's own job_out_done/
// job_out_slot, resolved back to a node_id by the caller), every
// OTHER node that lists that producer among its own producer_ids
// gets its resolved_dependencies incremented -- a single producer
// can satisfy MULTIPLE waiting consumers this way (§10 "risultati
// condivisi... più consumer"), and a node depending on several
// producers accumulates resolved_dependencies across separate
// producer-done events ("dipendenze multiple").
//
// Ready nodes are handed to the Director one at a time via a
// valid/ready producer interface (ready_valid/ready_ready), backpressure-
// safe (§10 "backpressure"): a node stays READY, occupying its table
// slot, until the consumer (Director) actually accepts it.
//
// Scope note (see hardware/v2/logs/decisions.log DEC-0008): §11's
// direct producer-to-consumer VALUE forwarding (bypassing the Result
// Buffer / external memory round-trip) is NOT implemented here --
// this module tracks dependency COUNTS/readiness only ("has this
// node's data become available", not the data itself), which is what
// actually gates scheduling; the job descriptor's result_addr already
// points at wherever the Memory Manager (M4) wrote the producer's
// result, which is how a ready consumer finds its inputs today. Real
// zero-copy forwarding is a possible future optimization (§11 itself:
// "quando possibile"), deferred until measured to matter (§22).
// ================================================================
module dependency_manager #(
parameter N_NODES = 16,
parameter MAX_DEPS = 4,
parameter ADDR_WIDTH = 23
)(
input wire clk,
input wire rst,
// ---- node registration (host / graph loader) ----
input wire reg_valid,
output wire reg_ready,
input wire [$clog2(N_NODES)-1:0] reg_node_id,
input wire [$clog2(MAX_DEPS+1)-1:0] reg_required,
input wire [MAX_DEPS*$clog2(N_NODES)-1:0] reg_producer_ids,
input wire [ADDR_WIDTH-1:0] reg_x_base,
input wire [ADDR_WIDTH-1:0] reg_w_base,
input wire [15:0] reg_n_tiles,
input wire [ADDR_WIDTH-1:0] reg_result_addr,
// ---- producer completion notification ----
input wire producer_done_valid,
input wire [$clog2(N_NODES)-1:0] producer_done_node_id,
// ---- ready job output (to neural_director.v's job_in_* port) ----
output reg ready_valid,
input wire ready_ready,
output reg [$clog2(N_NODES)-1:0] ready_node_id,
output reg [ADDR_WIDTH-1:0] ready_x_base,
output reg [ADDR_WIDTH-1:0] ready_w_base,
output reg [15:0] ready_n_tiles,
output reg [ADDR_WIDTH-1:0] ready_result_addr
);
localparam ST_EMPTY = 2'd0;
localparam ST_WAITING = 2'd1;
localparam ST_READY = 2'd2;
localparam ST_DISPATCHED = 2'd3;
localparam NODE_IDW = $clog2(N_NODES);
localparam REQW = $clog2(MAX_DEPS+1);
reg [1:0] node_state [0:N_NODES-1];
reg [REQW-1:0] node_required [0:N_NODES-1];
reg [REQW-1:0] node_resolved [0:N_NODES-1];
reg [NODE_IDW-1:0] node_producer_ids [0:N_NODES-1][0:MAX_DEPS-1];
reg [ADDR_WIDTH-1:0] node_x_base [0:N_NODES-1];
reg [ADDR_WIDTH-1:0] node_w_base [0:N_NODES-1];
reg [15:0] node_n_tiles [0:N_NODES-1];
reg [ADDR_WIDTH-1:0] node_result_addr [0:N_NODES-1];
// A node id doubles as its own table slot index (§10's example
// literally addresses nodes by id: "node 37") -- N_NODES must
// therefore cover the full id range a caller intends to use.
assign reg_ready = (node_state[reg_node_id] == ST_EMPTY);
// ---- priority-encoded first READY node (first-found scan, same
// idiom as neural_director's own free-slot scan) ----
reg [NODE_IDW-1:0] first_ready_idx;
reg any_ready;
integer ri;
always @(*) begin
first_ready_idx = {NODE_IDW{1'b0}};
any_ready = 1'b0;
for (ri = N_NODES-1; ri >= 0; ri = ri - 1) begin
if (node_state[ri] == ST_READY) begin
first_ready_idx = ri[NODE_IDW-1:0];
any_ready = 1'b1;
end
end
end
integer ni, di;
always @(posedge clk) begin
if (rst) begin
for (ni = 0; ni < N_NODES; ni = ni + 1) begin
node_state[ni] <= ST_EMPTY;
node_required[ni] <= {REQW{1'b0}};
node_resolved[ni] <= {REQW{1'b0}};
end
ready_valid <= 1'b0;
end else begin
// ---- registration: create a new WAITING (or immediately
// READY, if required==0) node entry. ----
if (reg_valid && reg_ready) begin
node_required[reg_node_id] <= reg_required;
node_resolved[reg_node_id] <= {REQW{1'b0}};
node_x_base[reg_node_id] <= reg_x_base;
node_w_base[reg_node_id] <= reg_w_base;
node_n_tiles[reg_node_id] <= reg_n_tiles;
node_result_addr[reg_node_id] <= reg_result_addr;
for (di = 0; di < MAX_DEPS; di = di + 1)
node_producer_ids[reg_node_id][di] <= reg_producer_ids[di*NODE_IDW +: NODE_IDW];
node_state[reg_node_id] <= (reg_required == {REQW{1'b0}}) ? ST_READY : ST_WAITING;
end
// ---- wake-up: a completed producer increments
// resolved_dependencies for EVERY WAITING node that lists
// it, independent of the registration above (a node can
// be registered and immediately woken by an in-flight
// producer-done event the same cycle, since both read the
// PRE-edge node_state/node_producer_ids consistently). ----
if (producer_done_valid) begin
for (ni = 0; ni < N_NODES; ni = ni + 1) begin
if (node_state[ni] == ST_WAITING) begin
for (di = 0; di < MAX_DEPS; di = di + 1) begin
if (di < node_required[ni] &&
node_producer_ids[ni][di] == producer_done_node_id) begin
if (node_resolved[ni] + 1'b1 >= node_required[ni])
node_state[ni] <= ST_READY;
node_resolved[ni] <= node_resolved[ni] + 1'b1;
end
end
end
end
end
// ---- dispatch: hand the first READY node to the
// Director, one at a time, backpressure-safe. ----
if (ready_valid && ready_ready) begin
node_state[ready_node_id] <= ST_DISPATCHED;
// ST_DISPATCHED is terminal here (M6 does not yet
// reclaim slots for re-use -- see decisions.log
// DEC-0008): a full graph run allocates N_NODES once.
ready_valid <= 1'b0;
end else if (!ready_valid && any_ready) begin
// Deliberately NOT combined with the dispatch branch
// above into "!ready_valid || (ready_valid&&ready_ready)"
// -- the scan for first_ready_idx is combinational
// over node_state's PRE-edge value, which still shows
// the about-to-be-dispatched node as READY this same
// edge; reloading in the same cycle as a dispatch
// could re-present the SAME node that is simultaneously
// transitioning to DISPATCHED. Reloading strictly the
// cycle AFTER (once ready_valid has genuinely gone
// low and node_state has committed) costs one extra
// idle cycle between consecutive dispatches but is
// unambiguously correct.
ready_valid <= 1'b1;
ready_node_id <= first_ready_idx;
ready_x_base <= node_x_base[first_ready_idx];
ready_w_base <= node_w_base[first_ready_idx];
ready_n_tiles <= node_n_tiles[first_ready_idx];
ready_result_addr <= node_result_addr[first_ready_idx];
end
end
end
endmodule
+192
View File
@@ -0,0 +1,192 @@
`timescale 1ns/1ps
// ============================================================
// M6 testbench (docs/v2-description.md §10/§20): dependency_manager.v
// -- a small DAG: node0 and node1 have no dependencies (immediately
// READY); node2 depends on BOTH node0 and node1 (required=2, "multiple
// dependencies"); node3 depends on node0 ALONE (required=1) --
// node0's single completion must satisfy BOTH node2 (partially) and
// node3 (fully), proving "risultati condivisi... piu' consumer" (a
// shared producer feeding multiple waiting consumers).
//
// node0 --+--> node2 (needs node0 AND node1)
// \-+--> node3 (needs node0 only)
// node1 ---+
//
// Verified with Verilator (decisions.log DEC-0004).
// ============================================================
module tb;
localparam N_NODES = 8;
localparam MAX_DEPS = 4;
localparam ADDR_WIDTH = 23;
localparam NODE_IDW = $clog2(N_NODES);
reg clk, rst;
initial begin clk = 0; forever #5 clk = ~clk; end
reg reg_valid;
wire reg_ready;
reg [NODE_IDW-1:0] reg_node_id;
reg [$clog2(MAX_DEPS+1)-1:0] reg_required;
reg [MAX_DEPS*NODE_IDW-1:0] reg_producer_ids;
reg [ADDR_WIDTH-1:0] reg_x_base, reg_w_base, reg_result_addr;
reg [15:0] reg_n_tiles;
reg producer_done_valid;
reg [NODE_IDW-1:0] producer_done_node_id;
wire ready_valid;
reg ready_ready;
wire [NODE_IDW-1:0] ready_node_id;
wire [ADDR_WIDTH-1:0] ready_x_base, ready_w_base, ready_result_addr;
wire [15:0] ready_n_tiles;
dependency_manager #(
.N_NODES(N_NODES), .MAX_DEPS(MAX_DEPS), .ADDR_WIDTH(ADDR_WIDTH)
) u_dm (
.clk(clk), .rst(rst),
.reg_valid(reg_valid), .reg_ready(reg_ready), .reg_node_id(reg_node_id),
.reg_required(reg_required), .reg_producer_ids(reg_producer_ids),
.reg_x_base(reg_x_base), .reg_w_base(reg_w_base), .reg_n_tiles(reg_n_tiles),
.reg_result_addr(reg_result_addr),
.producer_done_valid(producer_done_valid), .producer_done_node_id(producer_done_node_id),
.ready_valid(ready_valid), .ready_ready(ready_ready), .ready_node_id(ready_node_id),
.ready_x_base(ready_x_base), .ready_w_base(ready_w_base),
.ready_n_tiles(ready_n_tiles), .ready_result_addr(ready_result_addr)
);
integer errors, tests;
task automatic register_node(
input [NODE_IDW-1:0] nid,
input [$clog2(MAX_DEPS+1)-1:0] required,
input [NODE_IDW-1:0] p0, input [NODE_IDW-1:0] p1,
input [15:0] n_tiles_tag // used as a unique tag (via n_tiles field) to identify which node got dispatched
);
begin
@(posedge clk);
reg_node_id = nid;
reg_required = required;
reg_producer_ids = {NODE_IDW*MAX_DEPS{1'b0}};
reg_producer_ids[0*NODE_IDW +: NODE_IDW] = p0;
reg_producer_ids[1*NODE_IDW +: NODE_IDW] = p1;
reg_x_base = {ADDR_WIDTH{1'b0}} + nid;
reg_w_base = {ADDR_WIDTH{1'b0}} + nid + 100;
reg_n_tiles = n_tiles_tag;
reg_result_addr = {ADDR_WIDTH{1'b0}} + nid + 200;
reg_valid = 1'b1;
while (!reg_ready) @(posedge clk);
@(posedge clk);
reg_valid = 1'b0;
end
endtask
// Collect dispatched node ids (in order) into a small scoreboard.
reg [NODE_IDW-1:0] dispatched [0:15];
integer n_dispatched;
task automatic collect_one_dispatch(input integer watchdog_max);
integer wd;
begin
ready_ready = 1'b1;
wd = 0;
while (!ready_valid && wd < watchdog_max) begin @(posedge clk); wd = wd + 1; end
if (!ready_valid) begin
$display("FAIL: no ready_valid within watchdog (n_dispatched so far=%0d)", n_dispatched);
errors = errors + 1;
end else begin
dispatched[n_dispatched] = ready_node_id;
$display("DISPATCH node_id=%0d (n_tiles tag=%0d)", ready_node_id, ready_n_tiles);
n_dispatched = n_dispatched + 1;
@(posedge clk);
end
end
endtask
integer i;
initial begin
errors = 0; tests = 0; n_dispatched = 0;
rst = 1; reg_valid = 0; producer_done_valid = 0; ready_ready = 0;
reg_node_id = 0; reg_required = 0; reg_producer_ids = 0;
reg_x_base = 0; reg_w_base = 0; reg_n_tiles = 0; reg_result_addr = 0;
producer_done_node_id = 0;
repeat(4) @(posedge clk);
rst = 0;
@(posedge clk);
// node0, node1: no dependencies -> immediately READY
register_node(0, 0, 0, 0, 16'd1000);
register_node(1, 0, 0, 0, 16'd1001);
// node2: depends on BOTH node0 and node1 (multiple dependencies)
register_node(2, 2, 0, 1, 16'd1002);
// node3: depends on node0 ONLY (shared producer, multiple consumers)
register_node(3, 1, 0, 0, 16'd1003);
// ---- TEST 1: node0 and node1 must both be dispatched first
// (they were already READY at registration) -- order between
// them is not asserted (both are simultaneously ready,
// first-found scan is deterministic but not part of the
// contract), just that BOTH appear before node2/node3. ----
tests = tests + 1;
collect_one_dispatch(50);
collect_one_dispatch(50);
if (!((dispatched[0] == 0 && dispatched[1] == 1) || (dispatched[0] == 1 && dispatched[1] == 0))) begin
$display("FAIL: expected node0+node1 dispatched first (in either order), got %0d,%0d", dispatched[0], dispatched[1]);
errors = errors + 1;
end else $display("PASS: node0 and node1 (no dependencies) dispatched first, in either order");
// node2/node3 must NOT be ready yet (still WAITING)
tests = tests + 1;
ready_ready = 1'b0;
repeat(5) @(posedge clk);
if (ready_valid) begin
$display("FAIL: a node became ready before any producer_done -- got node_id=%0d", ready_node_id);
errors = errors + 1;
end else $display("PASS: node2/node3 correctly still WAITING (no producer_done yet)");
// ---- TEST 2: node0 completes -> node3 (needs only node0)
// becomes READY; node2 (needs node0 AND node1) does NOT yet. ----
tests = tests + 1;
producer_done_node_id = 0;
producer_done_valid = 1'b1;
@(posedge clk);
producer_done_valid = 1'b0;
collect_one_dispatch(50);
if (dispatched[2] !== 3) begin
$display("FAIL: expected node3 to become ready right after node0 completed, got node_id=%0d", dispatched[2]);
errors = errors + 1;
end else $display("PASS: node3 (single dependency on node0) became READY right after node0 completed");
ready_ready = 1'b0;
repeat(5) @(posedge clk);
if (ready_valid) begin
$display("FAIL: node2 became ready after only ONE of its two dependencies (node0) completed -- got node_id=%0d", ready_node_id);
errors = errors + 1;
end else $display("PASS: node2 correctly still WAITING (only 1/2 dependencies resolved)");
// ---- TEST 3: node1 completes -> node2 (needed BOTH) now
// becomes READY -- "multiple dependencies" fully resolved. ----
tests = tests + 1;
producer_done_node_id = 1;
producer_done_valid = 1'b1;
@(posedge clk);
producer_done_valid = 1'b0;
collect_one_dispatch(50);
if (dispatched[3] !== 2) begin
$display("FAIL: expected node2 to become ready after BOTH node0 and node1 completed, got node_id=%0d", dispatched[3]);
errors = errors + 1;
end else $display("PASS: node2 (two dependencies, node0+node1) became READY only after BOTH completed");
$display("========================================");
if (errors == 0)
$display("ALL %0d TESTS PASSED (dependency_manager -- multi-dependency + shared-producer/multi-consumer wake-up)", tests);
else
$display("FAILED: %0d/%0d test(s) had errors -- see messages above", errors, tests);
$display("========================================");
$finish;
end
endmodule
@@ -0,0 +1,294 @@
Info: Logic utilisation before packing:
Info: Total LUT4s: 895/43848 2%
Info: logic LUTs: 763/43848 1%
Info: carry LUTs: 0/43848 0%
Info: RAM LUTs: 88/ 5481 1%
Info: RAMW LUTs: 44/10962 0%
Info: Total DFFs: 474/43848 1%
Info: Packing IOs..
Info: Packing constants..
Info: Packing carries...
Info: Packing LUTs...
Info: Packing LUT5-7s...
Info: Packing FFs...
Info: 153 FFs paired with LUTs.
Info: Generating derived timing constraints...
Info: Promoting globals...
Info: promoting clock net clk$TRELLIS_IO_IN to global network
Info: Checksum: 0x50c6183f
Info: Device utilisation:
Info: TRELLIS_IO: 208/ 245 84%
Info: DCCA: 1/ 56 1%
Info: DP16KD: 0/ 108 0%
Info: MULT18X18D: 0/ 72 0%
Info: ALU54B: 0/ 36 0%
Info: EHXPLLL: 0/ 4 0%
Info: EXTREFB: 0/ 2 0%
Info: DCUA: 0/ 2 0%
Info: PCSCLKDIV: 0/ 2 0%
Info: IOLOGIC: 0/ 160 0%
Info: SIOLOGIC: 0/ 85 0%
Info: GSR: 0/ 1 0%
Info: JTAGG: 0/ 1 0%
Info: OSCG: 0/ 1 0%
Info: SEDGA: 0/ 1 0%
Info: DTR: 0/ 1 0%
Info: USRMCLK: 0/ 1 0%
Info: CLKDIVF: 0/ 4 0%
Info: ECLKSYNCB: 0/ 10 0%
Info: DLLDELD: 0/ 8 0%
Info: DDRDLL: 0/ 4 0%
Info: DQSBUFM: 0/ 10 0%
Info: TRELLIS_ECLKBUF: 0/ 8 0%
Info: ECLKBRIDGECS: 0/ 2 0%
Info: DCSC: 0/ 2 0%
Info: TRELLIS_FF: 474/ 43848 1%
Info: TRELLIS_COMB: 897/ 43848 2%
Info: TRELLIS_RAMW: 22/ 5481 0%
Info: Placed 0 cells based on constraints.
Info: Creating initial analytic placement for 865 cells, random placement wirelen = 74923.
Info: at initial placer iter 0, wirelen = 13090
Info: at initial placer iter 1, wirelen = 12009
Info: at initial placer iter 2, wirelen = 11811
Info: at initial placer iter 3, wirelen = 11643
Info: Running main analytical placer, max placement attempts per cell = 320800.
Info: at iteration #1, type ALL: wirelen solved = 11564, spread = 14466, legal = 14653; time = 0.01s
Info: at iteration #2, type ALL: wirelen solved = 11814, spread = 13311, legal = 13596; time = 0.01s
Info: HeAP Placer Time: 0.06s
Info: of which solving equations: 0.03s
Info: of which spreading cells: 0.00s
Info: of which strict legalisation: 0.00s
Info: Running simulated annealing placer for refinement.
Info: at iteration #1: temp = 0.000000, timing cost = 459, wirelen = 13596
Info: at iteration #5: temp = 0.000000, timing cost = 406, wirelen = 13227
Info: at iteration #5: temp = 0.000000, timing cost = 386, wirelen = 13237
Info: SA placement time 0.08s
Info: Max frequency for clock '$glbnet$clk$TRELLIS_IO_IN': 140.71 MHz (PASS at 80.00 MHz)
Info: Max delay <async> -> <async> : 13.31 ns
Info: Max delay <async> -> posedge $glbnet$clk$TRELLIS_IO_IN: 12.60 ns
Info: Max delay posedge $glbnet$clk$TRELLIS_IO_IN -> <async> : 7.40 ns
Info: Slack histogram:
Info: legend: * represents 3 endpoint(s)
Info: + represents [1,3) endpoint(s)
Info: [ 5393, 5720) |***+
Info: [ 5720, 6047) |******************+
Info: [ 6047, 6374) |**************************************+
Info: [ 6374, 6701) |************************************************************
Info: [ 6701, 7028) |************************************+
Info: [ 7028, 7355) |*******************+
Info: [ 7355, 7682) |***************+
Info: [ 7682, 8009) |*********+
Info: [ 8009, 8336) |*********+
Info: [ 8336, 8663) |********+
Info: [ 8663, 8990) |****+
Info: [ 8990, 9317) |
Info: [ 9317, 9644) |+
Info: [ 9644, 9971) |
Info: [ 9971, 10298) |
Info: [ 10298, 10625) |
Info: [ 10625, 10952) |+
Info: [ 10952, 11279) |+
Info: [ 11279, 11606) |**+
Info: [ 11606, 11933) |*+
Info: Checksum: 0x1e213512
Info: Routing globals...
Info: routing clock net $glbnet$clk$TRELLIS_IO_IN using global 0
Info: Routing..
Info: Setting up routing queue.
Info: Routing 4648 arcs.
Info: | (re-)routed arcs | delta | remaining| time spent |
Info: IterCnt | w/ripup wo/ripup | w/r wo/r | arcs| batch(sec) total(sec)|
Info: 1000 | 74 925 | 74 925 | 3868| 0.08 0.08|
Info: 2000 | 262 1728 | 188 803 | 3087| 0.05 0.13|
Info: 3000 | 431 2485 | 169 757 | 2274| 0.04 0.17|
Info: 4000 | 528 3306 | 97 821 | 1372| 0.16 0.33|
Info: 5000 | 595 4225 | 67 919 | 442| 0.15 0.48|
Info: 5514 | 661 4665 | 66 440 | 0| 0.10 0.58|
Info: Routing complete.
Info: Router1 time 0.58s
Info: Checksum: 0xcf947290
Info: Critical path report for clock '$glbnet$clk$TRELLIS_IO_IN' (posedge -> posedge):
Info: type curr total name
Info: clk-to-q 0.40 0.40 Source node_state[2]_TRELLIS_FF_Q_1.Q
Info: routing 0.50 0.89 Net node_state[2][0] (49,29) -> (49,29)
Info: Sink node_state[0]_LUT4_D_1_Z_LUT4_Z.D
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 1.07 Source node_state[0]_LUT4_D_1_Z_LUT4_Z.F
Info: routing 0.56 1.63 Net node_state[0]_LUT4_D_1_Z[2] (49,29) -> (48,28)
Info: Sink first_ready_idx_LUT4_Z_2_B_LUT4_Z.D
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 1.81 Source first_ready_idx_LUT4_Z_2_B_LUT4_Z.F
Info: routing 0.56 2.37 Net first_ready_idx_LUT4_Z_2_B[1] (48,28) -> (47,27)
Info: Sink first_ready_idx_LUT4_Z_2_B_LUT4_D.D
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 2.55 Source first_ready_idx_LUT4_Z_2_B_LUT4_D.F
Info: routing 0.47 3.02 Net first_ready_idx_LUT4_Z_1_D[2] (47,27) -> (47,27)
Info: Sink first_ready_idx_LUT4_Z_1_D_LUT4_Z_D_LUT4_D_Z_LUT4_Z.D
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 3.20 Source first_ready_idx_LUT4_Z_1_D_LUT4_Z_D_LUT4_D_Z_LUT4_Z.F
Info: routing 0.78 3.98 Net first_ready_idx_LUT4_Z_1_D_LUT4_Z_D_LUT4_D_Z[2] (47,27) -> (51,27)
Info: Sink first_ready_idx_LUT4_Z.C
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 4.16 Source first_ready_idx_LUT4_Z.F
Info: routing 1.98 6.14 Net first_ready_idx[3] (51,27) -> (17,27)
Info: Sink node_w_base.0.3$DPRAM_COMB3.A
Info: Defined in:
Info: hardware/v2/rtl/dependency_manager.v:100.24-100.39
Info: logic 0.18 6.32 Source node_w_base.0.3$DPRAM_COMB3.F
Info: routing 0.12 6.44 Net node_w_base.0.3_DO[15] (17,27) -> (17,27)
Info: Sink ready_w_base_TRELLIS_FF_Q_6.DI
Info: setup 0.00 6.44 Source ready_w_base_TRELLIS_FF_Q_6.DI
Info: 1.48 ns logic, 4.96 ns routing
Info: Critical path report for cross-domain path '<async>' -> '<async>':
Info: type curr total name
Info: source 0.00 0.00 Source reg_node_id[0]$tr_io.O
Info: routing 4.21 4.21 Net node_state[14]_LUT4_D_Z[1] (6,71) -> (47,29)
Info: Sink reg_valid_LUT4_C_Z_LUT4_D_Z_PFUMX_ALUT_Z_L6MUX21_D0_Z_L6MUX21_D0_Z_LUT4_Z.D
Info: Defined in:
Info: hardware/v2/rtl/dependency_manager.v:54.51-54.62
Info: logic 0.18 4.39 Source reg_valid_LUT4_C_Z_LUT4_D_Z_PFUMX_ALUT_Z_L6MUX21_D0_Z_L6MUX21_D0_Z_LUT4_Z.F
Info: routing 1.13 5.52 Net node_required[3]_LUT4_B_Z_PFUMX_BLUT_Z[1] (47,29) -> (49,28)
Info: Sink reg_valid_LUT4_C_Z_PFUMX_Z_C0_LUT4_Z_1.C
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 5.70 Source reg_valid_LUT4_C_Z_PFUMX_Z_C0_LUT4_Z_1.F
Info: routing 0.56 6.26 Net reg_valid_LUT4_C_Z_PFUMX_Z_C0[4] (49,28) -> (48,29)
Info: Sink reg_valid_LUT4_C_Z_PFUMX_Z_BLUT_LUT4_Z.M
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.19 6.45 Source reg_valid_LUT4_C_Z_PFUMX_Z_BLUT_LUT4_Z.OFX
Info: routing 0.88 7.33 Net reg_valid_LUT4_C_Z[6] (48,29) -> (47,27)
Info: Sink reg_ready_PFUMX_Z_C0_LUT4_Z_1.D
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 7.51 Source reg_ready_PFUMX_Z_C0_LUT4_Z_1.F
Info: routing 0.74 8.26 Net reg_ready_PFUMX_Z_C0[4] (47,27) -> (47,25)
Info: Sink reg_ready_PFUMX_Z_BLUT_LUT4_Z.M
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.19 8.45 Source reg_ready_PFUMX_Z_BLUT_LUT4_Z.OFX
Info: routing 2.29 10.74 Net reg_ready$TRELLIS_IO_OUT (47,25) -> (56,0)
Info: Sink reg_ready$tr_io.I
Info: Defined in:
Info: hardware/v2/rtl/dependency_manager.v:53.52-53.61
Info: 0.93 ns logic, 9.81 ns routing
Info: Critical path report for cross-domain path '<async>' -> 'posedge $glbnet$clk$TRELLIS_IO_IN':
Info: type curr total name
Info: source 0.00 0.00 Source reg_node_id[0]$tr_io.O
Info: routing 3.83 3.83 Net node_state[14]_LUT4_D_Z[1] (6,71) -> (43,28)
Info: Sink node_state[6]_LUT4_D_Z_LUT4_Z_D_LUT4_Z.D
Info: Defined in:
Info: hardware/v2/rtl/dependency_manager.v:54.51-54.62
Info: logic 0.18 4.01 Source node_state[6]_LUT4_D_Z_LUT4_Z_D_LUT4_Z.F
Info: routing 1.31 5.32 Net node_producer_ids[4]_LUT4_D_Z_LUT4_D_Z_LUT4_D_Z_PFUMX_BLUT_Z[0] (43,28) -> (50,24)
Info: Sink node_state[6]_LUT4_D_Z_LUT4_Z.D
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 5.50 Source node_state[6]_LUT4_D_Z_LUT4_Z.F
Info: routing 0.46 5.96 Net node_state[6]_LUT4_D_Z[3] (50,24) -> (50,24)
Info: Sink reg_valid_LUT4_C_Z_LUT4_Z.D
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 6.14 Source reg_valid_LUT4_C_Z_LUT4_Z.F
Info: routing 1.02 7.16 Net reg_ready_PFUMX_Z_C0[3] (50,24) -> (45,27)
Info: Sink reg_valid_LUT4_C_Z_LUT4_D_Z_PFUMX_ALUT_Z_L6MUX21_D0_Z_L6MUX21_D0_D1_L6MUX21_Z_D1_PFUMX_Z_ALUT_LUT4_Z.M
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.19 7.36 Source reg_valid_LUT4_C_Z_LUT4_D_Z_PFUMX_ALUT_Z_L6MUX21_D0_Z_L6MUX21_D0_D1_L6MUX21_Z_D1_PFUMX_Z_ALUT_LUT4_Z.OFX
Info: routing 0.00 7.36 Net reg_valid_LUT4_C_Z_LUT4_D_Z_PFUMX_ALUT_Z_L6MUX21_D0_Z_L6MUX21_D0_D1 (45,27) -> (45,27)
Info: Sink reg_valid_LUT4_C_Z_LUT4_D_Z_PFUMX_ALUT_Z_L6MUX21_D0_Z_L6MUX21_D0_D1_L6MUX21_Z_D0_PFUMX_Z_ALUT_LUT4_Z.FXB
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:157.70-157.72
Info: logic 0.18 7.54 Source reg_valid_LUT4_C_Z_LUT4_D_Z_PFUMX_ALUT_Z_L6MUX21_D0_Z_L6MUX21_D0_D1_L6MUX21_Z_D0_PFUMX_Z_ALUT_LUT4_Z.OFX
Info: routing 1.02 8.55 Net node_producer_ids[4]_LUT4_D_Z_LUT4_D_Z_LUT4_D_Z_PFUMX_BLUT_Z[5] (45,27) -> (39,31)
Info: Sink node_resolved[8]_TRELLIS_FF_Q_LSR_LUT4_Z.D
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 8.73 Source node_resolved[8]_TRELLIS_FF_Q_LSR_LUT4_Z.F
Info: routing 0.49 9.22 Net node_resolved[8]_TRELLIS_FF_Q_LSR (39,31) -> (39,30)
Info: Sink node_resolved[8]_TRELLIS_FF_Q_2.LSR
Info: setup 0.29 9.51 Source node_resolved[8]_TRELLIS_FF_Q_2.LSR
Info: 1.38 ns logic, 8.13 ns routing
Info: Critical path report for cross-domain path 'posedge $glbnet$clk$TRELLIS_IO_IN' -> '<async>':
Info: type curr total name
Info: clk-to-q 0.40 0.40 Source node_state[0]_TRELLIS_FF_Q.Q
Info: routing 0.67 1.06 Net node_state[0][1] (48,29) -> (49,28)
Info: Sink reg_valid_LUT4_C_Z_PFUMX_Z_C0_LUT4_Z_1_D_LUT4_Z.C
Info: logic 0.18 1.24 Source reg_valid_LUT4_C_Z_PFUMX_Z_C0_LUT4_Z_1_D_LUT4_Z.F
Info: routing 0.45 1.70 Net reg_valid_LUT4_C_Z_PFUMX_Z_C0_LUT4_Z_1_D[3] (49,28) -> (49,28)
Info: Sink reg_valid_LUT4_C_Z_PFUMX_Z_C0_LUT4_Z_1.D
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 1.88 Source reg_valid_LUT4_C_Z_PFUMX_Z_C0_LUT4_Z_1.F
Info: routing 0.56 2.44 Net reg_valid_LUT4_C_Z_PFUMX_Z_C0[4] (49,28) -> (48,29)
Info: Sink reg_valid_LUT4_C_Z_PFUMX_Z_BLUT_LUT4_Z.M
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.19 2.63 Source reg_valid_LUT4_C_Z_PFUMX_Z_BLUT_LUT4_Z.OFX
Info: routing 0.88 3.51 Net reg_valid_LUT4_C_Z[6] (48,29) -> (47,27)
Info: Sink reg_ready_PFUMX_Z_C0_LUT4_Z_1.D
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.18 3.69 Source reg_ready_PFUMX_Z_C0_LUT4_Z_1.F
Info: routing 0.74 4.43 Net reg_ready_PFUMX_Z_C0[4] (47,27) -> (47,25)
Info: Sink reg_ready_PFUMX_Z_BLUT_LUT4_Z.M
Info: Defined in:
Info: /opt/homebrew/bin/../share/yosys/lattice/cells_map_trellis.v:108.23-108.24
Info: logic 0.19 4.63 Source reg_ready_PFUMX_Z_BLUT_LUT4_Z.OFX
Info: routing 2.29 6.92 Net reg_ready$TRELLIS_IO_OUT (47,25) -> (56,0)
Info: Sink reg_ready$tr_io.I
Info: Defined in:
Info: hardware/v2/rtl/dependency_manager.v:53.52-53.61
Info: 1.32 ns logic, 5.60 ns routing
Info: Max frequency for clock '$glbnet$clk$TRELLIS_IO_IN': 155.30 MHz (PASS at 80.00 MHz)
Info: Max delay <async> -> <async> : 10.74 ns
Info: Max delay <async> -> posedge $glbnet$clk$TRELLIS_IO_IN: 9.51 ns
Info: Max delay posedge $glbnet$clk$TRELLIS_IO_IN -> <async> : 6.92 ns
Info: Slack histogram:
Info: legend: * represents 4 endpoint(s)
Info: + represents [1,4) endpoint(s)
Info: [ 6061, 6340) |*+
Info: [ 6340, 6619) |******+
Info: [ 6619, 6898) |******+
Info: [ 6898, 7177) |****************+
Info: [ 7177, 7456) |************************************************************
Info: [ 7456, 7735) |*****************************+
Info: [ 7735, 8014) |*************+
Info: [ 8014, 8293) |***********+
Info: [ 8293, 8572) |*+
Info: [ 8572, 8851) |******+
Info: [ 8851, 9130) |***+
Info: [ 9130, 9409) |*+
Info: [ 9409, 9688) |+
Info: [ 9688, 9967) |+
Info: [ 9967, 10246) |
Info: [ 10246, 10525) |
Info: [ 10525, 10804) |
Info: [ 10804, 11083) |+
Info: [ 11083, 11362) |**+
Info: [ 11362, 11641) |*+
Info: Program finished normally.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff