exp: N=8 packed-core array real P&R, isolates placement density from interconnect (EXP-0060)
New hardware/v3/rtl/np_packed_array.v: flat array of 8 unmodified neural_processor_packed.v instances, fully independent I/O, zero shared arbiter/Director logic -- isolates exactly one variable (DSP/placement density) from EXP-0059's single-core baseline. Real Vivado post-route: 64/240 DSP48E1 (26.67%), WNS -2.592ns @ 200MHz -> Fmax ~131.7MHz, only -2.4% vs the single-core 134.9MHz. Placement density alone is NOT the main driver of the ECP5-era gap between isolated-core and full-system Fmax -- narrows the question for the still-unbuilt real Director/arbiter/memory integration. Full writeup in hardware/v2/logs/experiments.log EXP-0060. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MUG92aM9m68TRc4rG55BcC
This commit is contained in:
@@ -3713,3 +3713,51 @@ actually targeted (part number confirmed xc7a100tcsg324-1, package/
|
||||
board pinout not yet chosen) is still needed before any real bring-up,
|
||||
matching this project's own "no board target skipped" discipline from
|
||||
V2/STEP19.
|
||||
|
||||
EXP-0060 -- N=8 neural_processor_packed.v placement/routing density
|
||||
check, real Vivado P&R, isolating the congestion variable from any
|
||||
Director/arbiter/memory RTL (2026-09-17)
|
||||
|
||||
CONTEXT: EXP-0059's own next_action flagged that the isolated single-
|
||||
core Fmax (134.9MHz real post-route) is not the same question as real
|
||||
N-core system Fmax -- on V2/ECP5 the full board-level system Fmax
|
||||
(64-97MHz) was measurably lower than the isolated dataflow-core Fmax
|
||||
(92.63MHz). Before building the (larger, riskier, unverified) real
|
||||
Director+arbiter+memory integration, this experiment isolates ONE
|
||||
variable first, per this project's own "one variable at a time" rule:
|
||||
what does pure DSP/placement DENSITY alone do to Fmax, with zero
|
||||
shared interconnect logic between cores?
|
||||
|
||||
METHOD: new `hardware/v3/rtl/np_packed_array.v`, N_CORES=8 flat array
|
||||
of unmodified neural_processor_packed.v instances, each core's I/O fully
|
||||
independent (flattened N*WIDTH buses, sliced per-instance, generate
|
||||
block) -- deliberately NO arbiter/Director/shared bus, so any Fmax
|
||||
change vs EXP-0059's single-core number is attributable ONLY to
|
||||
placement/routing congestion from DSP/LUT/FF density, not to any new
|
||||
(unverified) integration logic. Real Vivado 2026.1 out-of-context
|
||||
synth + opt_design + place_design + route_design, same 200MHz
|
||||
(-period 5.000) constraint and part (xc7a100tcsg324-1) as EXP-0059,
|
||||
via `hardware/v3/synth/synth_np_packed_array_n8.tcl`.
|
||||
|
||||
RESULT (real, post-route, not estimated): 64/240 DSP48E1 (26.67%,
|
||||
exactly 8 cores x 8 DSP, matches EXP-0059's per-core count). WNS
|
||||
-2.592ns @ 200MHz -> real critical path 7.592ns -> Fmax ~131.7MHz.
|
||||
Vs EXP-0059's single-core 134.9MHz: a real but SMALL degradation,
|
||||
-2.4%, from placement/routing density alone at 8 independent cores /
|
||||
~27% DSP utilization.
|
||||
|
||||
DECISION: the earlier V2/ECP5 gap between isolated-core and full-
|
||||
system Fmax is NOT mostly explained by raw compute-array placement
|
||||
density (this experiment's -2.4% is far smaller than ECP5's ~30%+
|
||||
isolated-vs-system gap) -- the real driver is most likely the shared
|
||||
Director/arbiter/memory-path interconnect logic itself, not yet built
|
||||
or tested here. This narrows, not answers, the open question from
|
||||
EXP-0059 -- still no real system-level number exists.
|
||||
|
||||
next_action: build the real Director + memory-feed path for the
|
||||
packed 2-job-per-core model (neural_director.v needs real changes to
|
||||
dispatch PAIRS of jobs per core, not a 1:1 port) as a properly
|
||||
correctness-verified (isolated testbench, bit-exact vs golden model)
|
||||
integration BEFORE the next real P&R congestion check -- do not
|
||||
synthesize unverified integration RTL just to get another Fmax number,
|
||||
per this project's own correctness-first standard.
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
`timescale 1ns/1ps
|
||||
|
||||
// ============================================================
|
||||
// EXP-0059 follow-up -- N independent neural_processor_packed.v
|
||||
// cores, flat array, NO Director/arbiter/memory path yet.
|
||||
//
|
||||
// PURPOSE: isolate exactly one variable -- what real P&R placement/
|
||||
// routing congestion does to Fmax once N copies of the DSP48-packed
|
||||
// core sit side by side on XC7A100T -- before adding any new
|
||||
// (unverified) integration RTL (Director, arbiter, memory path).
|
||||
// Each core keeps its own independent, unshared I/O (flattened to
|
||||
// N*WIDTH buses, sliced per-instance below); there is deliberately NO
|
||||
// interconnect logic here to conflate with the placement-density
|
||||
// question this experiment is asking. Matches this project's own
|
||||
// "one variable at a time" convention (see decisions.log).
|
||||
// ============================================================
|
||||
module np_packed_array #(
|
||||
parameter DATA_WIDTH = 8,
|
||||
parameter P_IN = 8,
|
||||
parameter ACC_WIDTH = 32,
|
||||
parameter N_CORES = 8
|
||||
)(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
input wire [N_CORES-1:0] job_valid,
|
||||
output wire [N_CORES-1:0] job_ready,
|
||||
input wire [N_CORES*16-1:0] job_node_id_a,
|
||||
input wire [N_CORES*16-1:0] job_node_id_b,
|
||||
input wire [N_CORES*DATA_WIDTH-1:0] job_bias,
|
||||
input wire [N_CORES*2-1:0] job_activation,
|
||||
|
||||
input wire [N_CORES-1:0] operand_valid,
|
||||
output wire [N_CORES-1:0] operand_ready,
|
||||
input wire [N_CORES*DATA_WIDTH*P_IN-1:0] input_data_a,
|
||||
input wire [N_CORES*DATA_WIDTH*P_IN-1:0] input_data_b,
|
||||
input wire [N_CORES*DATA_WIDTH*P_IN-1:0] weight_data,
|
||||
input wire [N_CORES-1:0] tile_last,
|
||||
|
||||
output wire [N_CORES-1:0] result_valid,
|
||||
input wire [N_CORES-1:0] result_ready,
|
||||
output wire [N_CORES*DATA_WIDTH-1:0] result_data_a,
|
||||
output wire [N_CORES*DATA_WIDTH-1:0] result_data_b,
|
||||
output wire [N_CORES*16-1:0] result_node_id_a,
|
||||
output wire [N_CORES*16-1:0] result_node_id_b,
|
||||
|
||||
output wire [N_CORES*4-1:0] np_state,
|
||||
output wire [N_CORES-1:0] np_error
|
||||
);
|
||||
genvar gc;
|
||||
generate
|
||||
for (gc = 0; gc < N_CORES; gc = gc + 1) begin : GEN_CORE
|
||||
neural_processor_packed #(
|
||||
.DATA_WIDTH(DATA_WIDTH), .P_IN(P_IN), .ACC_WIDTH(ACC_WIDTH)
|
||||
) u_core (
|
||||
.clk(clk), .rst(rst),
|
||||
.job_valid(job_valid[gc]),
|
||||
.job_ready(job_ready[gc]),
|
||||
.job_node_id_a(job_node_id_a[gc*16 +: 16]),
|
||||
.job_node_id_b(job_node_id_b[gc*16 +: 16]),
|
||||
.job_bias(job_bias[gc*DATA_WIDTH +: DATA_WIDTH]),
|
||||
.job_activation(job_activation[gc*2 +: 2]),
|
||||
.operand_valid(operand_valid[gc]),
|
||||
.operand_ready(operand_ready[gc]),
|
||||
.input_data_a(input_data_a[gc*DATA_WIDTH*P_IN +: DATA_WIDTH*P_IN]),
|
||||
.input_data_b(input_data_b[gc*DATA_WIDTH*P_IN +: DATA_WIDTH*P_IN]),
|
||||
.weight_data(weight_data[gc*DATA_WIDTH*P_IN +: DATA_WIDTH*P_IN]),
|
||||
.tile_last(tile_last[gc]),
|
||||
.result_valid(result_valid[gc]),
|
||||
.result_ready(result_ready[gc]),
|
||||
.result_data_a(result_data_a[gc*DATA_WIDTH +: DATA_WIDTH]),
|
||||
.result_data_b(result_data_b[gc*DATA_WIDTH +: DATA_WIDTH]),
|
||||
.result_node_id_a(result_node_id_a[gc*16 +: 16]),
|
||||
.result_node_id_b(result_node_id_b[gc*16 +: 16]),
|
||||
.np_state(np_state[gc*4 +: 4]),
|
||||
.np_error(np_error[gc])
|
||||
);
|
||||
end
|
||||
endgenerate
|
||||
endmodule
|
||||
@@ -0,0 +1,11 @@
|
||||
read_verilog -sv /home/michele/Develop/FPGA-Neural/hardware/v3/rtl/neural_processor_packed.v
|
||||
read_verilog -sv /home/michele/Develop/FPGA-Neural/hardware/v3/rtl/np_packed_array.v
|
||||
synth_design -top np_packed_array -part xc7a100tcsg324-1 -mode out_of_context -generic N_CORES=8
|
||||
create_clock -name clk -period 5.000 [get_ports clk]
|
||||
opt_design
|
||||
report_utilization -file /tmp/util_np_array_n8_postsynth.rpt
|
||||
place_design
|
||||
route_design
|
||||
report_utilization -file /tmp/util_np_array_n8_postroute.rpt
|
||||
report_timing_summary -file /tmp/timing_np_array_n8_postroute.rpt
|
||||
write_checkpoint -force /tmp/np_array_n8_postroute.dcp
|
||||
Reference in New Issue
Block a user