Skip to content

Commit 5a7a88f

Browse files
committed
Add simple auto floorplanning implementation
1 parent 4f3ba63 commit 5a7a88f

5 files changed

Lines changed: 576 additions & 32 deletions

File tree

ci/cfg/regression_basic.yml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,14 @@
22
# VGG-10 (1D CNN) (RadioML)
33
{
44
"dut": ["vgg10"],
5+
"board": ["RFSoC4x2"],
56
"generate_outputs": [["estimate_reports", "bitfile", "pynq_driver", "deployment_package"]]
67
},
78

89
# MobileNetV1 (ImageNet)
910
{
1011
"dut": ["mobilenetv1"],
11-
"generate_outputs": [["estimate_reports", "bitfile", "pynq_driver", "deployment_package"]]
12-
},
13-
14-
# Cybersecurity (MLP)
15-
{
16-
"dut": ["cybsec"],
12+
"board": ["RFSoC4x2"],
1713
"generate_outputs": [["estimate_reports", "bitfile", "pynq_driver", "deployment_package"]]
1814
},
1915
]

models/multi_dnn/vgg10/multi_dnn_cfgs/vgg10_multidnn_config_type4_half.json

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,43 +41,35 @@
4141
"pr_regions" : {
4242
"pr_mvau_0" : {
4343
"vgg10_A" : ["MVAU_hls_0", "Thresholding_rtl_0"],
44-
"vgg10_B" : ["MVAU_hls_0", "Thresholding_rtl_0"],
45-
"pblock" : "SLICE_X46Y0:SLICE_X60Y59 DSP48E2_X8Y0:DSP48E2_X10Y23 RAMB18_X5Y0:RAMB18_X5Y23 RAMB36_X5Y0:RAMB36_X5Y11"
44+
"vgg10_B" : ["MVAU_hls_0", "Thresholding_rtl_0"]
4645
},
4746
"pr_mvau_1" : {
4847
"vgg10_A" : ["MVAU_hls_1", "Thresholding_hls_0"],
49-
"vgg10_B" : ["MVAU_hls_1", "Thresholding_hls_0"],
50-
"pblock" : "SLICE_X31Y60:SLICE_X60Y179 DSP48E2_X4Y24:DSP48E2_X10Y71 FE_X0Y1:FE_X0Y2 RAMB18_X3Y24:RAMB18_X5Y71 RAMB36_X3Y12:RAMB36_X5Y35"
48+
"vgg10_B" : ["MVAU_hls_1", "Thresholding_hls_0"]
5149
},
5250
"pr_mvau_2" : {
5351
"vgg10_A" : ["MVAU_hls_2", "Thresholding_hls_1"],
54-
"vgg10_B" : ["MVAU_hls_2", "Thresholding_hls_1"],
55-
"pblock" : "SLICE_X46Y180:SLICE_X60Y299 DSP48E2_X8Y72:DSP48E2_X10Y119 RAMB18_X5Y72:RAMB18_X5Y119 RAMB36_X5Y36:RAMB36_X5Y59"
52+
"vgg10_B" : ["MVAU_hls_2", "Thresholding_hls_1"]
5653
},
5754
"pr_mvau_3" : {
5855
"vgg10_A" : ["MVAU_hls_3", "Thresholding_hls_2"],
59-
"vgg10_B" : ["MVAU_hls_3", "Thresholding_hls_2"],
60-
"pblock" : "SLICE_X61Y300:SLICE_X78Y359 DSP48E2_X11Y120:DSP48E2_X13Y143 RAMB18_X6Y120:RAMB18_X7Y143 RAMB36_X6Y60:RAMB36_X7Y71"
56+
"vgg10_B" : ["MVAU_hls_3", "Thresholding_hls_2"]
6157
},
6258
"pr_mvau_4" : {
6359
"vgg10_A" : ["MVAU_hls_4", "Thresholding_hls_3"],
64-
"vgg10_B" : ["MVAU_hls_4", "Thresholding_hls_3"],
65-
"pblock" : "SLICE_X86Y60:SLICE_X96Y119 DSP48E2_X16Y24:DSP48E2_X18Y47 RAMB18_X9Y24:RAMB18_X9Y47 RAMB36_X9Y12:RAMB36_X9Y23"
60+
"vgg10_B" : ["MVAU_hls_4", "Thresholding_hls_3"]
6661
},
6762
"pr_mvau_5" : {
6863
"vgg10_A" : ["MVAU_hls_5", "Thresholding_hls_4"],
69-
"vgg10_B" : ["MVAU_hls_5", "Thresholding_hls_4"],
70-
"pblock" : "SLICE_X86Y120:SLICE_X94Y179 DSP48E2_X16Y48:DSP48E2_X18Y71 RAMB18_X9Y48:RAMB18_X9Y71 RAMB36_X9Y24:RAMB36_X9Y35"
64+
"vgg10_B" : ["MVAU_hls_5", "Thresholding_hls_4"]
7165
},
7266
"pr_mvau_6" : {
7367
"vgg10_A" : ["MVAU_hls_6", "Thresholding_hls_5"],
74-
"vgg10_B" : ["MVAU_hls_6", "Thresholding_hls_5"],
75-
"pblock" : "SLICE_X86Y240:SLICE_X93Y299 DSP48E2_X16Y96:DSP48E2_X17Y119 RAMB18_X9Y96:RAMB18_X9Y119 RAMB36_X9Y48:RAMB36_X9Y59"
68+
"vgg10_B" : ["MVAU_hls_6", "Thresholding_hls_5"]
7669
},
7770
"pr_mvau_7" : {
7871
"vgg10_A" : ["MVAU_hls_7", "Thresholding_hls_6", "MVAU_hls_8", "Thresholding_hls_7", "MVAU_hls_9", "ElementwiseAdd_hls_0"],
79-
"vgg10_B" : ["MVAU_hls_7", "Thresholding_hls_6", "MVAU_hls_8", "Thresholding_hls_7", "MVAU_hls_9", "ElementwiseAdd_hls_0"],
80-
"pblock" : "SLICE_X82Y300:SLICE_X96Y359 DSP48E2_X15Y120:DSP48E2_X19Y143 RAMB18_X8Y120:RAMB18_X9Y143 RAMB36_X8Y60:RAMB36_X9Y71"
72+
"vgg10_B" : ["MVAU_hls_7", "Thresholding_hls_6", "MVAU_hls_8", "Thresholding_hls_7", "MVAU_hls_9", "ElementwiseAdd_hls_0"]
8173
}
8274
}
8375
}

src/finn/benchmarking/dut/bench_mvau_multi_dnn.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ def _create_multi_dnn_config_json(self, scenario, model_a_path, model_b_path, ba
259259
}
260260
elif scenario == 4:
261261
mvau_node_name = f"MVAU_{backend}_0"
262-
pblock = self._params.get("pblock", "CLOCKREGION_X1Y1:CLOCKREGION_X3Y5")
262+
# pblock = self._params.get("pblock", "CLOCKREGION_X1Y1:CLOCKREGION_X3Y5")
263263
generation = {
264264
"mode": "PartialReconfiguration",
265265
"kwargs": {
@@ -268,7 +268,7 @@ def _create_multi_dnn_config_json(self, scenario, model_a_path, model_b_path, ba
268268
"pr_mvau_0": {
269269
"mvau_A": [mvau_node_name],
270270
"mvau_B": [mvau_node_name],
271-
"pblock": pblock,
271+
# "pblock": pblock,
272272
}
273273
},
274274
},

src/finn/transformation/fpgadataflow/make_zynq_proj.py

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,7 +1264,9 @@ def _generate_pr_flow(self, model):
12641264
pr_config.append("launch_runs synth_1 -jobs 4")
12651265
pr_config.append("wait_on_run synth_1")
12661266

1267-
pr_config.append("open_run synth_1 -name synth_1")
1267+
# Collect pblock info for every PR SDP before choosing the mode.
1268+
# Each entry is (sdp_name, pblock_string_or_empty, pr_nodecontainer_inst).
1269+
pr_sdp_pblock_info = []
12681270
for pr_sdp in pr_sdp_nodes:
12691271
pr_sdp_inst = getCustomOp(pr_sdp)
12701272
sdp_name = pr_sdp.name
@@ -1277,15 +1279,57 @@ def _generate_pr_flow(self, model):
12771279
][0]
12781280
pr_nodecontainer_inst = getCustomOp(pr_nodecontainer)
12791281
pblock = pr_nodecontainer_inst.get_nodeattr("pblock")
1280-
assert pblock, "NodeContainer %s has no 'pblock' attribute set" % sdp_name
1281-
pblock_name = "pblock_Hier_%s" % sdp_name
1282-
cell_path = "top_i/Hier_%s" % sdp_name
1283-
pr_config.append("create_pblock %s" % pblock_name)
1282+
pr_sdp_pblock_info.append((sdp_name, pblock))
1283+
1284+
pblocks_specified = [pblock for _, pblock in pr_sdp_pblock_info]
1285+
all_empty = all(p == "" for p in pblocks_specified)
1286+
all_specified = all(p != "" for p in pblocks_specified)
1287+
1288+
if not all_empty and not all_specified:
1289+
raise FINNError(
1290+
"Mixed pblock specification: either ALL PR regions must have an explicit "
1291+
"'pblock' string, or ALL must omit it (auto-floorplanning mode). "
1292+
"Found a mix of specified and empty pblock attributes."
1293+
)
1294+
1295+
pr_config.append("open_run synth_1 -name synth_1")
1296+
1297+
if all_empty:
1298+
# ----------------------------------------------------------------
1299+
# Auto-floorplanning mode: query per-cell resource usage from the
1300+
# synthesised netlist and let generate_multi_dfx_pblocks size and
1301+
# place the pblocks automatically.
1302+
# ----------------------------------------------------------------
1303+
dfx_tcl_path = str(
1304+
Path(__file__).parent.parent.parent
1305+
/ "util"
1306+
/ "vivado_scripts"
1307+
/ "dfx_auto_floorplanning.tcl"
1308+
)
1309+
pr_config.append("source {%s}" % dfx_tcl_path)
1310+
1311+
cell_names = ["top_i/Hier_%s" % sdp_name for sdp_name, _ in pr_sdp_pblock_info]
1312+
pblock_names = ["pblock_Hier_%s" % sdp_name for sdp_name, _ in pr_sdp_pblock_info]
1313+
12841314
pr_config.append(
1285-
"add_cells_to_pblock [get_pblocks %s] [get_cells %s]" % (pblock_name, cell_path)
1315+
"auto_floorplan_from_synthesis {%s} {%s}"
1316+
% (" ".join(cell_names), " ".join(pblock_names))
12861317
)
1287-
pr_config.append("resize_pblock [get_pblocks %s] -add {%s}" % (pblock_name, pblock))
1288-
pr_config.append("set_property SNAPPING_MODE ON [get_pblocks %s]" % pblock_name)
1318+
else:
1319+
# ----------------------------------------------------------------
1320+
# Manual mode: use the pblock strings already set on each
1321+
# NodeContainer (existing behaviour).
1322+
# ----------------------------------------------------------------
1323+
for sdp_name, pblock in pr_sdp_pblock_info:
1324+
pblock_name = "pblock_Hier_%s" % sdp_name
1325+
cell_path = "top_i/Hier_%s" % sdp_name
1326+
pr_config.append("create_pblock %s" % pblock_name)
1327+
pr_config.append(
1328+
"add_cells_to_pblock [get_pblocks %s] [get_cells %s]" % (pblock_name, cell_path)
1329+
)
1330+
pr_config.append("resize_pblock [get_pblocks %s] -add {%s}" % (pblock_name, pblock))
1331+
pr_config.append("set_property SNAPPING_MODE ON [get_pblocks %s]" % pblock_name)
1332+
12891333
pr_config.append("save_constraints -force")
12901334
pr_config.append("close_design")
12911335

@@ -1297,6 +1341,16 @@ def _generate_pr_flow(self, model):
12971341

12981342
pr_config.append("launch_runs impl_1 -to_step write_bitstream -jobs 4")
12991343
pr_config.append("wait_on_run impl_1")
1344+
1345+
if all_empty:
1346+
# Auto mode: query post-implementation utilisation and write the JSON report.
1347+
pr_config.append("open_run impl_1 -name impl_1")
1348+
pr_config.append(
1349+
"write_pr_resource_report {%s} {%s}"
1350+
% (" ".join(cell_names), " ".join(pblock_names))
1351+
)
1352+
pr_config.append("close_design")
1353+
13001354
for body_id in range(1, num_bodies):
13011355
impl_run = "impl_body_%d" % body_id
13021356
pr_config.append("launch_runs %s -to_step write_bitstream -jobs 4" % impl_run)

0 commit comments

Comments
 (0)