Skip to content
Snippets Groups Projects
Commit 680ca436 authored by Tobi-Alonso's avatar Tobi-Alonso
Browse files

[fpgadataflow] Move MakePYNQDriver pass CreateDataflowPartition in prep for ext_weights support

parent 5ad35261
No related branches found
No related tags found
No related merge requests found
...@@ -125,15 +125,16 @@ class FINNExampleOverlay(Overlay): ...@@ -125,15 +125,16 @@ class FINNExampleOverlay(Overlay):
layer_w = np.fromiter( layer_w = np.fromiter(
[int(x, 16) for x in dat.strip().split()], dtype=np.uint32 [int(x, 16) for x in dat.strip().split()], dtype=np.uint32
) )
layer_ind = int(w_filename.split("_")[0]) sdp_ind = int(w_filename.split("_")[0])
rt_weight_dict[layer_ind] = layer_w layer_ind = int(w_filename.split("_")[1])
for layer_ind in rt_weight_dict.keys(): rt_weight_dict[(sdp_ind,layer_ind)] = layer_w
cand_if_name = "StreamingDataflowPartition_1/s_axilite_%d" % layer_ind for sdp_ind,layer_ind in rt_weight_dict.keys():
cand_if_name = "StreamingDataflowPartition_%d/s_axilite_%d" % (sdp_ind,layer_ind)
if cand_if_name in self.ip_dict.keys(): if cand_if_name in self.ip_dict.keys():
layer_mmio = getattr( layer_mmio = getattr(
self.StreamingDataflowPartition_1, "s_axilite_%d" % layer_ind getattr(self,"StreamingDataflowPartition_%d" % sdp_ind), "s_axilite_%d" % layer_ind
).mmio ).mmio
layer_w = rt_weight_dict[layer_ind] layer_w = rt_weight_dict[(sdp_ind,layer_ind)]
layer_mmio.write_mm(0, layer_w.tobytes()) layer_mmio.write_mm(0, layer_w.tobytes())
if verify: if verify:
new_w = np.copy(layer_mmio.array[: layer_w.shape[0]]) new_w = np.copy(layer_mmio.array[: layer_w.shape[0]])
......
...@@ -37,12 +37,12 @@ import os ...@@ -37,12 +37,12 @@ import os
import warnings import warnings
import pkg_resources as pk import pkg_resources as pk
from . import template_driver from . import template_driver
from finn.core.modelwrapper import ModelWrapper
class MakePYNQDriver(Transformation): class MakePYNQDriver(Transformation):
"""Create PYNQ Python code to correctly interface the generated """Create PYNQ Python code to correctly interface the generated
accelerator, including data packing/unpacking. Should be called accelerator, including data packing/unpacking. Should be called
after conversion to HLS layers and folding, but prior to the creation of after conversion to HLS layers, folding and the creation of
dataflow partitions for correct operation. dataflow partitions for correct operation.
platform: one of ["zynq-iodma", "alveo"] platform: one of ["zynq-iodma", "alveo"]
...@@ -149,24 +149,29 @@ class MakePYNQDriver(Transformation): ...@@ -149,24 +149,29 @@ class MakePYNQDriver(Transformation):
# generate weight files for runtime-writable layers # generate weight files for runtime-writable layers
weights_dir = pynq_driver_dir + "/runtime_weights" weights_dir = pynq_driver_dir + "/runtime_weights"
rt_layer_ind = 0
os.makedirs(weights_dir) os.makedirs(weights_dir)
for node in model.graph.node: for sdp_ind, sdp_node in enumerate(model.graph.node):
if node.op_type in ["StreamingFCLayer_Batch", "Thresholding_Batch"]: assert sdp_node.op_type == "StreamingDataflowPartition"
node_inst = getCustomOp(node) # get dataflow model
is_rt_weights = node_inst.get_nodeattr("runtime_writeable_weights") sdp_node = getCustomOp(sdp_node)
if is_rt_weights == 1: dataflow_model_filename = sdp_node.get_nodeattr("model")
fcl_w = model.get_initializer(node.input[1]) dataflow_model = ModelWrapper(dataflow_model_filename)
w_filename = weights_dir + "/%d_%s.dat" % (rt_layer_ind, node.name) rt_layer_ind = 0
node_inst.make_weight_file(fcl_w, "decoupled_runtime", w_filename) for node in dataflow_model.graph.node:
rt_layer_ind += 1 if node.op_type in ["StreamingFCLayer_Batch", "Thresholding_Batch"]:
elif node.op_type == "StreamingDataflowPartition": node_inst = getCustomOp(node)
warnings.warn( is_rt_weights = node_inst.get_nodeattr("runtime_writeable_weights")
"""Please call MakePYNQDriver prior to if is_rt_weights == 1:
CreateDataflowPartition. Can only extract runtime-writable fcl_w = dataflow_model.get_initializer(node.input[1])
weights from HLSCustomOp instances and not StreamingDataflowPartition. w_filename = weights_dir + "/%d_%d_%s.dat" % (sdp_ind,rt_layer_ind, node.name)
""" node_inst.make_weight_file(fcl_w, "decoupled_runtime", w_filename)
) rt_layer_ind += 1
else: elif node.op_type == "StreamingDataflowPartition":
continue warnings.warn(
return (model, False) """Nested StreamingDataflowPartition are not supported
"""
)
else:
continue
return (model, False)
\ No newline at end of file
...@@ -276,7 +276,10 @@ class MakeZYNQProject(Transformation): ...@@ -276,7 +276,10 @@ class MakeZYNQProject(Transformation):
class ZynqBuild(Transformation): class ZynqBuild(Transformation):
"""Best-effort attempt at building the accelerator for Zynq.""" """Best-effort attempt at building the accelerator for Zynq.
It assumes the model has only fpgadataflow nodes
"""
def __init__(self, platform, period_ns, enable_debug=False): def __init__(self, platform, period_ns, enable_debug=False):
super().__init__() super().__init__()
...@@ -290,7 +293,6 @@ class ZynqBuild(Transformation): ...@@ -290,7 +293,6 @@ class ZynqBuild(Transformation):
model = model.transform(InferDataLayouts()) model = model.transform(InferDataLayouts())
# prepare at global level, then break up into kernels # prepare at global level, then break up into kernels
prep_transforms = [ prep_transforms = [
MakePYNQDriver(platform="zynq-iodma"),
InsertIODMA(64), InsertIODMA(64),
InsertDWC(), InsertDWC(),
Floorplan(), Floorplan(),
...@@ -325,6 +327,10 @@ class ZynqBuild(Transformation): ...@@ -325,6 +327,10 @@ class ZynqBuild(Transformation):
model = model.transform( model = model.transform(
MakeZYNQProject(self.platform, enable_debug=self.enable_debug) MakeZYNQProject(self.platform, enable_debug=self.enable_debug)
) )
# set platform attribute for correct remote execution # set platform attribute for correct remote execution
model.set_metadata_prop("platform", "zynq-iodma") model.set_metadata_prop("platform", "zynq-iodma")
# create driver
model = model.transform(MakePYNQDriver(platform="zynq-iodma"))
return (model, False) return (model, False)
...@@ -330,6 +330,7 @@ class VitisLink(Transformation): ...@@ -330,6 +330,7 @@ class VitisLink(Transformation):
class VitisBuild(Transformation): class VitisBuild(Transformation):
"""Best-effort attempt at building the accelerator with Vitis. """Best-effort attempt at building the accelerator with Vitis.
It assumes the model has only fpgadataflow nodes
fpga_part: string identifying the target FPGA fpga_part: string identifying the target FPGA
period_ns: target clock period period_ns: target clock period
...@@ -365,7 +366,6 @@ class VitisBuild(Transformation): ...@@ -365,7 +366,6 @@ class VitisBuild(Transformation):
model = model.transform(InferDataLayouts()) model = model.transform(InferDataLayouts())
# prepare at global level, then break up into kernels # prepare at global level, then break up into kernels
prep_transforms = [ prep_transforms = [
MakePYNQDriver(platform="alveo"),
InsertIODMA(512), InsertIODMA(512),
InsertDWC(), InsertDWC(),
] ]
...@@ -416,4 +416,6 @@ class VitisBuild(Transformation): ...@@ -416,4 +416,6 @@ class VitisBuild(Transformation):
# set platform attribute for correct remote execution # set platform attribute for correct remote execution
model.set_metadata_prop("platform", "alveo") model.set_metadata_prop("platform", "alveo")
#create driver
model = model.transform(MakePYNQDriver(platform="alveo"))
return (model, False) return (model, False)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment