Transformation - fpgadataflow

Transformations (fpgadataflow)

finn.transformation.fpgadataflow.annotate_cycles

class finn.transformation.fpgadataflow.annotate_cycles.AnnotateCycles

Bases: Transformation

Annotate the estimate of clock cycles per sample taken by each fpgadataflow node as an attribute on the node.

apply(model)

finn.transformation.fpgadataflow.annotate_resources

class finn.transformation.fpgadataflow.annotate_resources.AnnotateResources(mode, fpgapart, override_res_dict=None)

Bases: Transformation

Annotate the amount of FPGA resources taken by each fpgadataflow node as an attribute on the node, depending on the mode parameter: * ‘estimate’ – use the analytical estimation model * ‘hls’ – use results from the HLS synthesis report * ‘synth’ – use post-synthesis (Vivado or Vitis) report

No annotations can be provided unless the relevant transformation for the chosen mode (e.g. HLSSynthIP for hls) was previously run.

apply(model)

finn.transformation.fpgadataflow.cleanup

class finn.transformation.fpgadataflow.cleanup.CleanUp

Bases: Transformation

Remove any generated files for fpgadataflow nodes.

apply(model)

finn.transformation.fpgadataflow.compile_cppsim

class finn.transformation.fpgadataflow.compile_cppsim.CompileCppSim(num_workers=None)

Bases: NodeLocalTransformation

For every node: compile C++ code in node attribute “code_gen_dir_cppsim” and save path to executables in node attribute “executable_path”. All nodes in the graph must have the fpgadataflow backend attribute.

To use these executables, exec_mode must be set to “cppsim” (using transformation SetExecMode) and the model has to be executed using execute_onnx() from finn.core.onnx_exec

  • num_workers (int or None) number of parallel workers, see documentation in NodeLocalTransformation for more details.

applyNodeLocal(node)

finn.transformation.fpgadataflow.convert_to_hw_layers

finn.transformation.fpgadataflow.create_dataflow_partition

class finn.transformation.fpgadataflow.create_dataflow_partition.CreateDataflowPartition(partition_model_dir=None)

Bases: Transformation

Split a graph into two graphs; one which contains non-FINN-dataflow nodes and a StreamingDataflowPartition node, and another which only contains FINN dataflow nodes. The StreamingDataflowPartition has a model attribute that indicates the filename for the second graph that only contains dataflow nodes. No action is taken if there are no dataflow nodes.

apply(model)

finn.transformation.fpgadataflow.create_stitched_ip

class finn.transformation.fpgadataflow.create_stitched_ip.CreateStitchedIP(fpgapart, clk_ns, ip_name='finn_design', run_synth=False, run_pnr=False, signature=[])

Bases: Transformation

Create a Vivado IP Block Design project from all the generated IPs of a graph. All nodes in the graph must have the fpgadataflow backend attribute, and the PrepareIP transformation must have been previously run on the graph. The resulting block design is also packaged as IP. The transformation gets the fpgapart as a string.

Outcome if successful: sets the vivado_stitch_proj attribute in the ONNX ModelProto’s metadata_props field, with the created project dir as the value. A make_project.tcl script is also placed under the same folder, which is called to instantiate the per-layer IPs and stitch them together. The packaged block design IP can be found under the ip subdirectory.

apply(model)
connect_ap_none_external(node)
connect_axi(node, model)
connect_clk_rst(node)
connect_m_axis_external(node, idx=None)
connect_s_axis_external(node, idx=None)
insert_signature(checksum_count)
is_double_pumped(node)
finn.transformation.fpgadataflow.create_stitched_ip.is_external_input(model, node, i)
finn.transformation.fpgadataflow.create_stitched_ip.is_external_output(model, node, i)

finn.transformation.fpgadataflow.derive_characteristic

class finn.transformation.fpgadataflow.derive_characteristic.DeriveCharacteristic(period, num_workers=None, manual_bypass=False)

Bases: NodeLocalTransformation

For each node in the graph, run rtlsim to obtain the i/o characteristic function for FIFO sizing and set the attribute. It is assumed that the PrepareRTLSim transformation was already called on the graph.

This transformation performs rtlsim for each node, so it will run for some time (minutes to hours depending on configuration).

  • period (int) desired period over which the characteristic function will be derived.

  • num_workers (int or None) number of parallel workers, see documentation in NodeLocalTransformation for more details.

apply(model: ModelWrapper)
applyNodeLocal(node)
class finn.transformation.fpgadataflow.derive_characteristic.DeriveFIFOSizes(num_workers=None, io_fifo_depth=32)

Bases: NodeLocalTransformation

Prerequisite: DeriveCharacteristic already called on graph. For each node in the graph, use the accumulated I/O characteristic function to perform FIFO sizing, setting the in/outFIFODepths attributes of HLSCustomOp nodes.

  • num_workers (int or None) number of parallel workers, see documentation in NodeLocalTransformation for more details.

applyNodeLocal(node)

finn.transformation.fpgadataflow.externalize_params

class finn.transformation.fpgadataflow.externalize_params.ExternalizeParams

Bases: Transformation

Create top-level graph inputs for IODMAs serving layers where weights are marked as external using mem_mode=”external”.

apply(model)

finn.transformation.fpgadataflow.floorplan

class finn.transformation.fpgadataflow.floorplan.Floorplan(floorplan=None)

Bases: Transformation

Perform Floorplanning of the dataflow design:

floorplan: 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.

The transform applies the properties in the supplied JSON then: -Separates DMAs into their own partitions IDs, -If not explicitly assigned, assigns DWCs to SLRs to minimize SLLs required -If not explicitly assigned, assigns FIFOs to the SLR of the upstream node

apply(model)

finn.transformation.fpgadataflow.hlssynth_ip

class finn.transformation.fpgadataflow.hlssynth_ip.HLSSynthIP(fpgapart=None, num_workers=None)

Bases: NodeLocalTransformation

For each HLS node: generate IP block from code in folder that is referenced in node attribute “code_gen_dir_ipgen” and save path of generated project in node attribute “ipgen_path”. All nodes in the graph must have the fpgadataflow backend attribute. Any nodes that already have a ipgen_path attribute pointing to a valid path will be skipped.

This transformation calls Vitis HLS for synthesis, so it will run for some time (minutes to hours depending on configuration).

  • num_workers (int or None) number of parallel workers, see documentation in NodeLocalTransformation for more details.

applyNodeLocal(node)

finn.transformation.fpgadataflow.infer_pixel_padding_deconv

class finn.transformation.fpgadataflow.infer_pixel_padding_deconv.InferPixelPaddingDeconv

Bases: Transformation

Lowering and conversion of ConvTranspose (NCHW) nodes to FMPadding_Pixel + Im2Col + MatMul (NHWC) surrounded by Transpose nodes note: this transformation produces a mix of hw layers and non hw layers to implement this on an FPGA the Im2Col and MatMul nodes need to be converted to hw layers after applying this transformation and the resulting transpose nodes need to be streamlined. See deconv test case under tests/fpgadataflow for an example.

apply(model)

finn.transformation.fpgadataflow.insert_dwc

class finn.transformation.fpgadataflow.insert_dwc.InsertDWC

Bases: Transformation

Add data width converters between layers where necessary.

apply(model)

finn.transformation.fpgadataflow.insert_fifo

class finn.transformation.fpgadataflow.insert_fifo.InsertFIFO(create_shallow_fifos=False, max_qsrl_depth=None, vivado_ram_style='auto')

Bases: Transformation

Inserting FIFOs in the beginning and end of the graph as well as between fpgadataflow nodes.

Takes the setting for the depth from the surrounding nodes by extracting node attribute ‘outFIFODepths’ of the previous and node attribute ‘inFIFODepths’ of the subsequent node. max() of these two values sets the FIFO depth.

Constructor arguments:

Parameters:
  • max_qsrl_depth – FIFOs deeper than this will use Vivado IP instead of Verilog FIFOs (Q_srl.v)

  • vivado_ram_style – the StreamingFIFO.ram_style attribute to be used for large FIFOs implemented by Vivado

  • create_shallow_fifos – Normally, shallow-depth (<=2) FIFOs won’t be created since HLS streaming interfaces already have a degree of buffering. Override with this parameter.

The other node attributes necessary to create a FIFO node are taken from the node the FIFO node is inserted after: ‘folded_shape’ and ‘dtype’

apply(model)

finn.transformation.fpgadataflow.insert_hook

class finn.transformation.fpgadataflow.insert_hook.InsertHook

Bases: Transformation

Inserting hook layer after each layer that has the node attribute ‘output_hook’ specified

apply(model)

finn.transformation.fpgadataflow.insert_iodma

class finn.transformation.fpgadataflow.insert_iodma.InsertIODMA(max_intfwidth=32, insert_input=True, insert_output=True, insert_extmemw=True)

Bases: Transformation

Insert DMA nodes on inputs and outputs, or as specified by filters in the constructor.

apply(model)
get_mem_init(weights, pe, simd)

Returns matrix ready for pack_innermost_dim_as_hex_string with reverse=False (finn.util.data_packing) to return the memory init file little endian packed. That is, get_mem_init returns: elem(pe,simd) addr = 0: [(pe-1,simd-1),(pe-1,simd-2),…(0,1),(0,0)] addr = 1: [(pe-1,simd*2-1),…….(0,simd+1),(0,simd)] .

finn.transformation.fpgadataflow.insert_tlastmarker

class finn.transformation.fpgadataflow.insert_tlastmarker.InsertTLastMarker(both=False, external=True, dynamic=True)

Bases: Transformation

Ensure that the graph is started/terminated with a TLastMarker_hls node, inserting one if necessary. Use constructor args to determine type of TLastMarker to be inserted. More information available on the TLastMarker documentation.

apply(model)

finn.transformation.fpgadataflow.loop_rolling

class finn.transformation.fpgadataflow.loop_rolling.LoopBodyInputType(value)

Bases: Enum

An enumeration.

ACTIVATION = 1
CONDITION = 5
CONSTANT = 2
ITERATOR = 4
PARAMETER = 3
UNDEFINED = 0
class finn.transformation.fpgadataflow.loop_rolling.LoopBodyTemplate(filename)

Bases: object

build_function_match_pattern(graph, use_iteration_ext=True)
load(filename)
property output_signature
save(filename)
set_signature_index(index, stype)
update()
class finn.transformation.fpgadataflow.loop_rolling.LoopExtraction(hierarchy_list: List[List[str]])

Bases: Transformation

apply(model: ModelWrapper) Tuple[ModelWrapper, bool]
class finn.transformation.fpgadataflow.loop_rolling.LoopRolling(loop_body_template)

Bases: Transformation

Boilerplate Transformation for loop rolling in fpgadataflow.

apply(model: ModelWrapper) Tuple[ModelWrapper, bool]
finn.transformation.fpgadataflow.loop_rolling.add_finn_datatype_if_needed(tensor)
finn.transformation.fpgadataflow.loop_rolling.build_loop_replace_pattern(graph, LoopBody)
finn.transformation.fpgadataflow.loop_rolling.finn_datatypes_match(datatype_a, datatype_b)
finn.transformation.fpgadataflow.loop_rolling.get_constant_from_value(value)

Get the constant value of a tensor.

finn.transformation.fpgadataflow.loop_rolling.same_values(inputs)

Check if all inputs have the same constant value.

finn.transformation.fpgadataflow.loop_rolling.tensor_has_finn_datatype(tensor)
finn.transformation.fpgadataflow.loop_rolling.tensor_shapes_match(value_a, value_b)
finn.transformation.fpgadataflow.loop_rolling.tensor_types_match(value_a, value_b)
finn.transformation.fpgadataflow.loop_rolling.validate_loop_attributes(loop_node: Node)
finn.transformation.fpgadataflow.loop_rolling.validate_loop_io_tensor_pair(tensor_a, tensor_b)
finn.transformation.fpgadataflow.loop_rolling.validate_loop_io_tensors(loop_node: Node)
finn.transformation.fpgadataflow.loop_rolling.validate_loop_node(loop_node: Node)
finn.transformation.fpgadataflow.loop_rolling.validate_loop_type(loop_node: Node)

finn.transformation.fpgadataflow.make_pynq_driver

class finn.transformation.fpgadataflow.make_driver.MakeCPPDriver(platform: str, version: str)

Bases: Transformation

Create CPP code to correctly interface the generated accelerator, including data packing/unpacking. Should be called after conversion to HLS layers, folding and the creation of dataflow partitions for correct operation. platform: has to be “vitis-xrt”, otherwise an error is thrown Outcome if successful: sets the cpp_driver_dir attribute in the ONNX ModelProto’s metadata_props field, with the created driver dir as the value. runtime writeable weights not yet supported.

apply(model: ModelWrapper) Tuple[ModelWrapper, bool]
resolve_dt_name() str
class finn.transformation.fpgadataflow.make_driver.MakePYNQDriver(platform)

Bases: Transformation

Create PYNQ Python code to correctly interface the generated accelerator, including data packing/unpacking. Should be called after conversion to HLS layers, folding and the creation of dataflow partitions for correct operation.

platform: one of [“zynq-iodma”, “vitis-xrt”]

Outcome if successful: sets the pynq_driver_dir attribute in the ONNX ModelProto’s metadata_props field, with the created driver dir as the value. If any layers use runtime-writable parameters, those will be gathered under the runtime_weights/ subfolder of the pynq_driver_dir.

apply(model)

finn.transformation.fpgadataflow.make_zynq_proj

finn.transformation.fpgadataflow.minimize_accumulator_width

class finn.transformation.fpgadataflow.minimize_accumulator_width.MinimizeAccumulatorWidth

Bases: Transformation

For relevant nodes, call the accumulator width minimization functions to save on resources. May alter tensor DataType for certain nodes if they produce an accumulator as result.

apply(model)

finn.transformation.fpgadataflow.minimize_weight_bit_width

class finn.transformation.fpgadataflow.minimize_weight_bit_width.MinimizeWeightBitWidth

Bases: Transformation

For relevant nodes, call the weight bit width minimization functions to save on resources. May alter tensor weightDataType if the node does not have runtime writeable weights.

apply(model)

finn.transformation.fpgadataflow.prepare_cppsim

class finn.transformation.fpgadataflow.prepare_cppsim.PrepareCppSim(num_workers=None)

Bases: Transformation

Call custom implementation to generate code for single custom node and create folder that contains all the generated files. All nodes in the graph must have the fpgadataflow backend attribute.

Outcome if succesful: Node attribute “code_gen_dir_cppsim” contains path to folder that contains generated C++ code that can be used to simulate node using cppsim. The subsequent transformation is CompileCppSim

apply(model)
prepareCppSim_node(node)

finn.transformation.fpgadataflow.prepare_ip

class finn.transformation.fpgadataflow.prepare_ip.PrepareIP(fpgapart, clk)

Bases: Transformation

Call custom implementation to generate code for single custom node and create folder that contains all the generated files. All nodes in the graph must have the fpgadataflow backend attribute and transformation gets additional arguments:

  • fpgapart (string)

  • clk in ns (int)

Any nodes that already have a code_gen_dir_ipgen attribute pointing to a valid path will be skipped.

Outcome if succesful: Node attribute “code_gen_dir_ipgen” contains path to folder that contains:

  • For HLS layers: generated C++ code that can be used to generate a Vivado IP block. The necessary subsequent transformation is HLSSynthIP.

  • For RTL layers: filled template verilog files that can be used to instantiate as module during IP stitching.

apply(model)

finn.transformation.fpgadataflow.prepare_rtlsim

class finn.transformation.fpgadataflow.prepare_rtlsim.PrepareRTLSim(behav=False, num_workers=None)

Bases: NodeLocalTransformation

For a graph with generated RTL sources (after HLSSynthIP), create an emulation library for each node to prepare for rtlsim execution and set the rtlsim_so property to the path to the generated emulation library.

To use these libraries, exec_mode must be set to “rtlsim” (using SetExecMode) and the model has to be executed using execute_onnx() from finn.core.onnx_exec

  • num_workers (int or None) number of parallel workers, see documentation in NodeLocalTransformation for more details.

apply(model)
applyNodeLocal(node)

finn.transformation.fpgadataflow.raise_scalar_to_rank1

finn.transformation.fpgadataflow.replace_verilog_relpaths

class finn.transformation.fpgadataflow.replace_verilog_relpaths.ReplaceVerilogRelPaths

Bases: Transformation

Convert ./ relative file paths to absolute ones for generated Verilog

apply(model)

finn.transformation.fpgadataflow.set_exec_mode

class finn.transformation.fpgadataflow.set_exec_mode.SetExecMode(mode)

Bases: Transformation

Set attribute exec_mode in all fpgadataflow nodes to specify which kind of execution should be used (“cppsim” or “rtlsim”). Note that RTL components do not support cppsim. When cppsim is selected for RTL components, by default the execution of the HW op parent is executed.

apply(model)

finn.transformation.fpgadataflow.set_fifo_depths

finn.transformation.fpgadataflow.set_folding

finn.transformation.fpgadataflow.set_loop_boundary

class finn.transformation.fpgadataflow.set_loop_boundary.SetLoopBoundary(node_metadata, node_range=None, tensor_range=None)

Bases: Transformation

Sets metadata attributes to nodes between defined node or tensor ranges in an ONNX model.

Parameters:
  • node_metadata – Dictionary containing metadata attributes to set on the nodes.

  • node_range – Tuple containing start and end node names (start_node, end_node).

  • tensor_range – Tuple containing start and end tensor names (start_tensor, end_tensor).

apply(model)

finn.transformation.fpgadataflow.specialize_layers

finn.transformation.fpgadataflow.synth_ooc

finn.transformation.fpgadataflow.template_driver

finn.transformation.fpgadataflow.templates

finn.transformation.fpgadataflow.alveo_build