diff --git a/docker/Dockerfile.finn_ci b/docker/Dockerfile.finn_ci index 02eb28fb64b8040b0bd281e2eb1539a432c5a257..654caa949d974e8fff0cd292f5651ce48e4d8d6f 100644 --- a/docker/Dockerfile.finn_ci +++ b/docker/Dockerfile.finn_ci @@ -58,6 +58,8 @@ RUN rm xrtdeps.sh # cloning dependency repos # finn-base RUN git clone https://github.com/Xilinx/finn-base.git /workspace/finn-base +# finn-experimental +RUN git clone https://github.com/Xilinx/finn-experimental.git /workspace/finn-experimental # Brevitas RUN git clone https://github.com/Xilinx/brevitas.git /workspace/brevitas # CNPY diff --git a/docker/Dockerfile.finn_dev b/docker/Dockerfile.finn_dev index b4d053676439bc133f18f00d6a1f4a05e9f4eb91..9c3fd39e548acffc3e5def62fac8587d6cc9dae5 100644 --- a/docker/Dockerfile.finn_dev +++ b/docker/Dockerfile.finn_dev @@ -86,6 +86,8 @@ USER $UNAME # cloning dependency repos (as user) # finn-base RUN git clone https://github.com/Xilinx/finn-base.git /workspace/finn-base +# finn-experimental +RUN git clone https://github.com/Xilinx/finn-experimental.git /workspace/finn-experimental # Brevitas RUN git clone https://github.com/Xilinx/brevitas.git /workspace/brevitas # CNPY diff --git a/docker/finn_entrypoint.sh b/docker/finn_entrypoint.sh index d8ffec7e18dd107c70fe8f01947188e4591e0594..fa47c693554635f3268bca58a831bc9cdc76f858 100644 --- a/docker/finn_entrypoint.sh +++ b/docker/finn_entrypoint.sh @@ -13,7 +13,8 @@ gecho () { # checkout the correct dependency repo commits # the repos themselves are cloned in the Dockerfile FINN_BASE_COMMIT=8908c6a3f6674c4fa790954bd41c23ee5bf053df -BREVITAS_COMMIT=9a5875390f4cf9720c64567d72a83c1023d4f951 +FINN_EXP_COMMIT=e9f97dcdb4db2f889b0f36af079a6a1792b7d4de +BREVITAS_COMMIT=14abbe1e7ef82485d79415871fcf5766b0a40a00 CNPY_COMMIT=4e8810b1a8637695171ed346ce68f6984e585ef4 HLSLIB_COMMIT=2e49322d1bbc4969ca293843bda1f3f9c05456fc PYVERILATOR_COMMIT=e2ff74030de3992dcac54bf1b6aad2915946e8cb @@ -25,6 +26,11 @@ gecho "finn-base @ $FINN_BASE_COMMIT" git -C /workspace/finn-base pull --quiet git -C /workspace/finn-base checkout $FINN_BASE_COMMIT --quiet pip install --user -e /workspace/finn-base +# finn-experimental +gecho "finn-experimental @ $FINN_EXP_COMMIT" +git -C /workspace/finn-experimental pull --quiet +git -C /workspace/finn-experimental checkout $FINN_EXP_COMMIT --quiet +pip install --user -e /workspace/finn-experimental # Brevitas gecho "brevitas @ $BREVITAS_COMMIT" git -C /workspace/brevitas pull --quiet diff --git a/src/finn/transformation/fpgadataflow/floorplan.py b/src/finn/transformation/fpgadataflow/floorplan.py index c6bedd466e31efb622640cbd203d344ff9b3d88f..3434183b1480eb38ee267328042aec33e87e0446 100644 --- a/src/finn/transformation/fpgadataflow/floorplan.py +++ b/src/finn/transformation/fpgadataflow/floorplan.py @@ -58,16 +58,21 @@ class Floorplan(Transformation): # read in a user-specified floorplan or generate a default one if self.user_floorplan is None: - floorplan = model.analysis(floorplan_params) + self.user_floorplan = model.analysis(floorplan_params) json_dir = make_build_dir(prefix="vitis_floorplan_") json_file = json_dir + "/floorplan.json" model.set_metadata_prop("floorplan_json", json_file) with open(json_file, "w") as f: - json.dump(floorplan, f, indent=4) + json.dump(self.user_floorplan, f, indent=4) else: model.set_metadata_prop("floorplan_json", self.user_floorplan) model = model.transform(ApplyConfig(self.user_floorplan)) + try: + default_slr = self.user_floorplan["Defaults"]["slr"][0] + except: + default_slr = -1 + # perform DWC and FIFO specific adjustments unassigned_nodes = 0 for node in model.graph.node: @@ -75,6 +80,7 @@ class Floorplan(Transformation): node_slr = node_inst.get_nodeattr("slr") if node_slr == -1: unassigned_nodes += 1 + node_inst.set_nodeattr("slr", default_slr) if node.op_type == "StreamingDataWidthConverter_Batch": # if we have SLR assignment already. use that if node_slr != -1: @@ -100,8 +106,8 @@ class Floorplan(Transformation): if unassigned_nodes > 0: warnings.warn( str(unassigned_nodes) - + " nodes have no entry in the provided floorplan " - + "and no default value was set" + + " nodes have no entry in the provided floorplan," + + " SLR was set to " + str(default_slr) ) # partition id generation diff --git a/src/finn/transformation/fpgadataflow/vitis_build.py b/src/finn/transformation/fpgadataflow/vitis_build.py index 0fe4276096852c08d0798be8e1ee715cc5769286..c52dfcf0cde4cbbb393786809852bc965c2856db 100644 --- a/src/finn/transformation/fpgadataflow/vitis_build.py +++ b/src/finn/transformation/fpgadataflow/vitis_build.py @@ -116,7 +116,7 @@ class CreateVitisXO(Transformation): ) arg_id += 1 args_string.append( - "{numReps:0:%s:%s:0x4:0x1C:uint:0}" + "{numReps:0:%s:%s:0x4:0x1C:uint:0}" % (str(arg_id), axilite_intf_name) ) arg_id += 1 @@ -207,8 +207,6 @@ class VitisLink(Transformation): # has axis, aximm and axilite # everything else is axis-only # assume only one connection from each ip to the next - # all aximm allocated to DDR[0] - # all kernels allocated to SLR0 producer = model.find_producer(node.input[0]) consumer = model.find_consumers(node.output[0]) # define kernel instances @@ -225,13 +223,35 @@ class VitisLink(Transformation): else: instance_names[node.name] = node.name config.append("nk=%s:1:%s" % (node.name, instance_names[node.name])) - # assign SLRs - config.append("slr=%s:SLR0" % instance_names[node.name]) + # explicitly assign SLRs if the slr attribute is not -1 + node_slr = sdp_node.get_nodeattr("slr") + if node_slr != -1: + config.append("slr=%s:SLR%d" % (instance_names[node.name], node_slr)) # assign memory banks if producer is None or consumer is None: - config.append( - "sp=%s.m_axi_gmem0:DDR[%d]" % (instance_names[node.name], 0) - ) + node_mem_port = sdp_node.get_nodeattr("mem_port") + if node_mem_port == "": + #configure good defaults based on board + if "u50" in self.platform or "u280" in self.platform: + # Use HBM where available (also U50 does not have DDR) + mem_type = "HBM" + mem_idx = 0 + elif "u200" in self.platform: + # Use DDR controller in static region of U200 + mem_type = "DDR" + mem_idx = 1 + elif "u250" in self.platform: + # Use DDR controller on the node's SLR if set, otherwise 0 + mem_type = "DDR" + if node_slr == -1: + mem_idx = 0 + else: + mem_idx = node_slr + else: + mem_type = "DDR" + mem_idx = 1 + node_mem_port = "%s[%d]" % (mem_type, mem_idx) + config.append("sp=%s.m_axi_gmem0:%s" % (instance_names[node.name], node_mem_port)) # connect streams if producer is not None: for i in range(len(node.input)): @@ -340,7 +360,8 @@ class VitisBuild(Transformation): floorplan_file: path to a JSON containing a dictionary with SLR assignments for each node in the ONNX graph. Must be parse-able by the ApplyConfig transform. - + enable_link: enable linking kernels (.xo files), otherwise just synthesize + them independently. """ def __init__( @@ -351,6 +372,7 @@ class VitisBuild(Transformation): strategy=VitisOptStrategy.PERFORMANCE, enable_debug=False, floorplan_file=None, + enable_link=True, ): super().__init__() self.fpga_part = fpga_part @@ -359,16 +381,14 @@ class VitisBuild(Transformation): self.strategy = strategy self.enable_debug = enable_debug self.floorplan_file = floorplan_file + self.enable_link = enable_link def apply(self, model): _check_vitis_envvars() # first infer layouts model = model.transform(InferDataLayouts()) # prepare at global level, then break up into kernels - prep_transforms = [ - InsertIODMA(512), - InsertDWC(), - ] + prep_transforms = [InsertIODMA(512), InsertDWC()] for trn in prep_transforms: model = model.transform(trn) model = model.transform(GiveUniqueNodeNames()) @@ -405,17 +425,18 @@ class VitisBuild(Transformation): kernel_model.set_metadata_prop("platform", "alveo") kernel_model.save(dataflow_model_filename) # Assemble design from kernels - model = model.transform( - VitisLink( - self.platform, - round(1000 / self.period_ns), - strategy=self.strategy, - enable_debug=self.enable_debug, + if self.enable_link: + model = model.transform( + VitisLink( + self.platform, + round(1000 / self.period_ns), + strategy=self.strategy, + enable_debug=self.enable_debug, + ) ) - ) # set platform attribute for correct remote execution model.set_metadata_prop("platform", "alveo") - #create driver + # create driver model = model.transform(MakePYNQDriver(platform="alveo")) return (model, False)