finn-base¶
Note
finn-base is currently under active development. APIs will likely change.
finn-base
is part of the FINN
project and provides the core
infrastructure for the FINN
compiler, including:
wrapper around ONNX models for easier manipulation
infrastructure for applying transformation and analysis passes on ONNX graphs
infrastructure for defining and executing custom ONNX ops (for verification and code generation)
extensions to ONNX models using annotations, including few-bit data types, sparsity and data layout specifiers
several transformation passes, including topological sorting, constant folding and convolution lowering
several custom ops including im2col and multi-thresholding for quantized activations
several utility functions, including packing for few-bit integers
Installation¶
Install with full functionality including documentation building:
pip install finn-base[onnx,pyverilator,docs]
Lightweight install for e.g. access to data packing utility functions:
pip install finn-base
Testing¶
With Docker CE installed, execute the following in the repo root:
./run-docker.sh tests
Alternatively, pull requests to dev will trigger GitHub Actions for the above.
Overview¶
finn-base
is part of the FINN
project and provides the core
infrastructure for the FINN
compiler, including:
wrapper around ONNX models for easier manipulation
infrastructure for applying transformation and analysis passes on ONNX graphs
infrastructure for defining and executing custom ONNX ops (for verification and code generation)
extensions to ONNX models using annotations, including few-bit data types, sparsity and data layout specifiers
several transformation passes, including topological sorting, constant folding and convolution lowering
several custom ops including im2col and multi-thresholding for quantized activations
several utility functions, including packing for few-bit integers
While the FINN compiler itself is focused on producing customized
streaming dataflow hardware architectures from quantized neural network (QNN)
descriptions, the infrastructure offered by finn-base
is more generic and
can be used for developing compilers and code generators for QNN inference.
Intermediate Representation: FINN-ONNX¶
We use ONNX as an intermediate representation (IR) for neural networks. As such, almost every component inside FINN uses ONNX and its Python API, so you may want to familiarize yourself with how ONNX represents DNNs. Specifically, the ONNX protobuf description (or its human-readable documentation and the operator schemas are useful as reference documents. We also provide a Jupyter notebook that can help to get familiar with ONNX by showing how to work with a simple ONNX model in FINN, see chapter Tutorials for details.
Note
FINN uses ONNX is a specific way that we refer to as FINN-ONNX, and not all ONNX graphs are supported by FINN (and vice versa).
Custom Quantization Annotations¶
ONNX does not support datatypes smaller than 8-bit integers, whereas in FINN we are interested in smaller integers down to ternary and bipolar. To make this work, FINN uses the quantization_annotation field in ONNX to annotate tensors with their FINN DataType (finn.core.datatype.DataType
) information. However, all tensors are expected to use single-precision floating point (float32) storage in FINN. This means we store even a 1-bit value as floating point for the purposes of representation. The FINN compiler flow is responsible for eventually producing a packed representation for the target hardware, where the 1-bit is actually stored as 1-bit.
Note that FINN uses floating point tensors as a carrier data type to represent integers. Floating point arithmetic can introduce rounding errors, e.g. (int_num * float_scale) / float_scale is not always equal to int_num.
When using the custom ONNX execution flow, FINN will attempt to sanitize any rounding errors for integer tensors. See (finn.util.basic.sanitize_quant_values
) for more information.
This behavior can be disabled (not recommended!) by setting the environment variable SANITIZE_QUANT_TENSORS=0.
Custom Operations/Nodes¶
FINN uses many custom operations (op_type in ONNX NodeProto) that are not defined in the ONNX operator schema. These custom nodes are marked with domain=”finn.*” in the protobuf to identify them as such. These nodes can represent specific operations that we need for low-bit networks, or operations that are specific to a particular hardware backend. To get more familiar with custom operations and how they are created, please take a look in the Jupyter notebook about CustomOps (see chapter Tutorials for details) or directly in the module finn.custom_op
.
Note
See the description of this PR for more on how the operator wrapper library is organized.
Custom ONNX Execution Flow¶
To verify correct operation of FINN-ONNX graphs, FINN provides its own ONNX execution flow (finn.core.onnx_exec
). This flow supports the standard set of ONNX operations as well as the custom FINN operations.
Warning
This execution flow is only meant for checking the correctness of models after applying transformations, and not for high performance inference.
ModelWrapper¶
FINN provides a ModelWrapper class (finn.core.modelwrapper.ModelWrapper
) as a thin wrapper around ONNX to make it easier to analyze and manipulate ONNX graphs. This wrapper provides many helper functions, while still giving full access to the ONNX protobuf representation.
Some of the helper functions are described in more detail below.
Create a ModelWrapper instance¶
The ModelWrapper instance can be created using a model in .onnx format or by directly passing a ModelProto instance to the wrapper. The code block below gives an example of how to use the wrapper on a model in .onnx format.
from finn.core.modelwrapper import ModelWrapper
model = ModelWrapper("model.onnx")
Access the ONNX GraphProto through ModelWrapper¶
The ONNX ModelProto can be accessed with following command:
modelproto = model.model
The graph can be accessed using:
graphproto = model.graph
The node list is accessed by:
nodes = model.graph.node
The individual nodes can be selected via their indices.
# first node
nodes[0]
The number of all nodes can be determined with the len() function in Python.
# number of nodes in the graph
len(nodes)
Helper functions for tensors¶
A list of all tensors (names) can easily be accessed using:
tensor_list = model.get_all_tensor_names()
If we take a single tensor from that list (by index), we can determine their producer or consumer node by using one of the following functions. Note that it may be that a tensor does not have a producer or consumer node, for example if the tensor represents a constant that is already set. In that case None will be returned.
# find producer of third tensor in model tensor list
model.find_producer(tensor_list[2])
# find consumer of third tensor in model tensor list
model.find_consumer(tensor_list[2])
Every tensor has a specific shape, to get or to set this shape these functions can be used:
# get tensor shape of third tensor in model tensor list
model.get_tensor_shape(tensor_list[2])
# set tensor shape of third tensor in model tensor list
tensor_shape = [1, 1, 28, 28]
model.set_tensor_shape(tensor_list[2], tensor_shape)
Optionally, the dtype (container datatype) of the tensor can also be specified as third argument in the set function. By default it is set to TensorProto.FLOAT.
As mentioned above there are FINN DataTypes additional to the container datatype, these can be accessed and set for a tensor with the following functions:
# get tensor dataype of third tensor in model tensor list
model.get_tensor_datatype(tensor_list[2])
# set tensor datatype of third tensor in model tensor list
from finn.core.datatype import DataType
finn_dtype = DataType.BIPOLAR
model.set_tensor_datatype(tensor_list[2], finn_dtype)
ModelWrapper contains two helper functions for tensor initializers, one to determine the current initializer and one to set the initializer of a tensor. If there is no initializer, None is returned.
# get tensor initializer of third tensor in model tensor list
model.get_initializer(tensor_list[2])
ModelWrapper contains more useful functions, if you are interested please have a look at the ModelWrapper module (finn.core.modelwrapper.ModelWrapper
) directly.
Analysis Pass¶
An analysis pass traverses the graph structure and produces information about certain properties. It gets the model in the ModelWrapper as input and returns a dictionary of the properties the analysis extracts. If you are interested in how to write an analysis pass for FINN, please take a look at the Jupyter notebook about how to write an analysis pass, see chapter Tutorials for details. For more information about existing analysis passes in finn-base, see module finn.analysis
.
Transformation Pass¶
A transformation passes changes (transforms) the given model, it gets the model in the ModelWrapper as input and returns the changed model (ModelWrapper) to the FINN flow. Additional the flag model_was_changed which indicates if a transformation has to be performed more than once, is returned. If you are interested in how to write a transformation pass for FINN, please take a look at the Jupyter notebook about how to write a transformation pass, see chapter Tutorials for details. For more information about existing transformation passes in finn-base, see module finn.transformation
.
Tutorials¶
The FINN compiler repository FINN provides several Jupyter notebooks that can help to get familiar with the basics, the internals and the end-to-end flow in FINN.
All Jupyter notebooks can be found in the FINN compiler repository under the notebook folder.
Some of those notebooks are specific to FPGA dataflow-style deployment,
but the ones highlighted below are more generic, relating to the core
infrastructure that finn-base
provides.
Basics¶
The notebooks in this folder should give a basic insight into FINN, how to get started and the basic concepts.
0_how_to_work_with_onnx
This notebook can help you to learn how to create and manipulate a simple ONNX model, also by using FINN
Advanced¶
The notebooks in this folder are more developer oriented. They should help you to get familiar with the principles in FINN and how to add new content regarding these concepts.
0_custom_analysis_pass
This notebook explains what an analysis pass is and how to write one for FINN.
1_custom_transformation_pass
This notebook explains what a transformation pass is and how to write one for FINN.
finn¶
The finn-base sources are divided into different modules. They are listed below.
finn.analysis (namespace)¶
Submodules:
finn.analysis.base (module)¶
How to write an analysis pass for FINN¶
An analysis pass traverses the graph structure and produces information about certain properties. The convention is to take in a ModelWrapper, and return a dictionary of named properties that the analysis extracts.
finn.analysis.topology (module)¶
-
finn.analysis.topology.
all_tensors_f32
(model)¶ Checks whether all tensors have a float32 dtype, extra quantization annotations notwithstanding.
Returns {“all_tensors_f32”: Bool}.
-
finn.analysis.topology.
get_per_tensor_fanouts
(model)¶ Returns a dictionary of {tensor_name: tensor_fanout} for the model.
-
finn.analysis.topology.
is_linear
(model)¶ Checks whether the given model graph is linear. This is done by looking at the fan-out of each tensor. All tensors have a fan-out <= 1 in a linear graph.
Returns {“is_linear”: Bool}.
-
finn.analysis.topology.
node_inputs_in_expected_order
(model)¶ Verifies that the node inputs are ordered in the way that FINN expects them. When a node has a mixture of static (= constant, initialized) inputs and dynamic inputs, the dynamic input should come first, followed by the static one. Only verifiable for a small subset of op_types for now.
Returns {“node_inputs_in_expected_order”: Bool}.
-
finn.analysis.topology.
nodes_topologically_sorted
(model)¶ Verifies that graph.node is topologically sorted. This is required by the ONNX specification.
Returns {“nodes_topologically_sorted”: Bool}.
finn.core (namespace)¶
Submodules:
finn.core.data_layout (module)¶
finn.core.datatype (module)¶
-
class
finn.core.datatype.
DataType
(value)¶ Bases:
enum.Enum
Enum class that contains FINN data types to set the quantization annotation. ONNX does not support data types smaller than 8-bit integers, whereas in FINN we are interested in smaller integers down to ternary and bipolar.
Assignment of DataTypes to indices based on following ordering:
unsigned to signed
fewer to more bits
Currently supported DataTypes:
-
BINARY
= 1¶
-
BIPOLAR
= 34¶
-
FLOAT32
= 68¶
-
INT10
= 44¶
-
INT11
= 45¶
-
INT12
= 46¶
-
INT13
= 47¶
-
INT14
= 48¶
-
INT15
= 49¶
-
INT16
= 50¶
-
INT17
= 51¶
-
INT18
= 52¶
-
INT19
= 53¶
-
INT2
= 36¶
-
INT20
= 54¶
-
INT21
= 55¶
-
INT22
= 56¶
-
INT23
= 57¶
-
INT24
= 58¶
-
INT25
= 59¶
-
INT26
= 60¶
-
INT27
= 61¶
-
INT28
= 62¶
-
INT29
= 63¶
-
INT3
= 37¶
-
INT30
= 64¶
-
INT31
= 65¶
-
INT32
= 66¶
-
INT4
= 38¶
-
INT5
= 39¶
-
INT6
= 40¶
-
INT64
= 67¶
-
INT7
= 41¶
-
INT8
= 42¶
-
INT9
= 43¶
-
TERNARY
= 35¶
-
UINT10
= 10¶
-
UINT11
= 11¶
-
UINT12
= 12¶
-
UINT13
= 13¶
-
UINT14
= 14¶
-
UINT15
= 15¶
-
UINT16
= 16¶
-
UINT17
= 17¶
-
UINT18
= 18¶
-
UINT19
= 19¶
-
UINT2
= 2¶
-
UINT20
= 20¶
-
UINT21
= 21¶
-
UINT22
= 22¶
-
UINT23
= 23¶
-
UINT24
= 24¶
-
UINT25
= 25¶
-
UINT26
= 26¶
-
UINT27
= 27¶
-
UINT28
= 28¶
-
UINT29
= 29¶
-
UINT3
= 3¶
-
UINT30
= 30¶
-
UINT31
= 31¶
-
UINT32
= 32¶
-
UINT4
= 4¶
-
UINT5
= 5¶
-
UINT6
= 6¶
-
UINT64
= 33¶
-
UINT7
= 7¶
-
UINT8
= 8¶
-
UINT9
= 9¶
-
allowed
(value)¶ Check whether given value is allowed for this DataType.
value (float32): value to be checked
-
bitwidth
()¶ Returns the number of bits required for this DataType.
-
get_hls_datatype_str
()¶ Returns the corresponding Vivado HLS datatype name.
-
get_num_possible_values
()¶ Returns the number of possible values this DataType can take. Only implemented for integer types for now.
-
get_smallest_possible
()¶ Returns smallest (fewest bits) possible DataType that can represent value. Prefers unsigned integers where possible.
-
is_integer
()¶ Returns whether this DataType represents integer values only.
-
max
()¶ Returns the largest possible value allowed by this DataType.
-
min
()¶ Returns the smallest possible value allowed by this DataType.
-
signed
()¶ Returns whether this DataType can represent negative numbers.
finn.core.execute_custom_node (module)¶
-
finn.core.execute_custom_node.
execute_custom_node
(node, context, graph)¶ Call custom implementation to execute a single custom node. Input/output provided via context.
finn.core.modelwrapper (module)¶
-
class
finn.core.modelwrapper.
ModelWrapper
(onnx_model_proto, make_deepcopy=False)¶ Bases:
object
A wrapper around ONNX ModelProto that exposes some useful utility functions for graph manipulation and exploration.
Creates a ModelWrapper instance. onnx_model_proto can be either a ModelProto instance, or a string with the path to a stored .onnx file on disk, or serialized bytes.
make_deepcopy: controls whether a deep copy of the ModelProto is made internally.
-
analysis
(analysis_fxn)¶ Runs given anaylsis_fxn on this model and return resulting dict.
-
check_all_tensor_shapes_specified
()¶ Checks whether all tensors have a specified shape (ValueInfo). The ONNX standard allows for intermediate activations to have no associated ValueInfo, but FINN expects this.
-
check_compatibility
()¶ Checks this model for FINN compatibility:
no embedded subgraphs
all tensor shapes are specified, including activations
all constants are initializers
-
cleanup
()¶ Run cleanup transformations on the model.
-
find_consumer
(tensor_name)¶ Finds and returns the node that consumes the tensor with given name. Currently only works for linear graphs.
-
find_consumers
(tensor_name)¶ Finds and returns a list of the nodes that consume tensor with given name.
-
find_direct_predecessors
(node)¶ Finds and returns a list of the nodes that are predecessors of given node.
-
find_direct_successors
(node)¶ Finds and returns a list of the nodes that are successors of given node.
-
find_producer
(tensor_name)¶ Finds and returns the node that produces the tensor with given name.
-
find_upstream
(tensor_name, finder_fxn)¶ Follow the producer chain upstream, calling finder_fxn on each upstream node until it returns True or there are no nodes left. Returns the list of nodes visited, or None if finder_fxn did not return True.
-
get_all_tensor_names
()¶ Returns a list of all (input, output and value_info) tensor names in the graph.
-
get_finn_nodes
()¶ Returns a list of nodes where domain == ‘finn.*’.
-
get_initializer
(tensor_name)¶ Gets the initializer value for tensor with given name, if any.
-
get_metadata_prop
(key)¶ Returns the value associated with metadata_prop with given key, or None otherwise.
-
get_node_index
(node)¶ Returns current index of given node.
-
get_nodes_by_op_type
(op_type)¶ Returns a list of nodes with specified op_type.
-
get_non_finn_nodes
()¶ Returns a list of nodes where domain != ‘finn.*’.
-
get_tensor_datatype
(tensor_name)¶ Returns the FINN DataType of tensor with given name.
-
get_tensor_fanout
(tensor_name)¶ Returns the number of nodes for which the tensor with given name is as input.
-
get_tensor_layout
(tensor_name)¶ Returns the data layout annotation of tensor with given name. The data layout is expressed as a list of strings with as many elements as the number of dimensions in the tensor shape. Each string annotates what is contained in that dimension. If there is no data layout annotation, None will be returned. Examples of data layout annotations: [“N”, “C”] is tensor[batch][channel] [“N”, “C”, “H”, “W”] is tensor[batch][channel][height][width] [“N”, “H”, “W”, “C”] is tensor[batch][height][width][channel]
-
get_tensor_shape
(tensor_name)¶ Returns the shape of tensor with given name, if it has ValueInfoProto.
-
get_tensor_sparsity
(tensor_name)¶ Returns the sparsity of a given tensor as dictionary.
-
get_tensor_valueinfo
(tensor_name)¶ Returns ValueInfoProto of tensor with given name, if it has one.
-
property
graph
¶ Returns the graph of the model.
-
is_fork_node
(node)¶ Checks if the given node is a fork, that is, the node has multiple direct successors
-
is_join_node
(node)¶ Checks if the given node is a join, that is, the node has multiple direct predecessors
-
make_empty_exec_context
()¶ Creates an empty execution context for this model.
The execution context is a dictionary of all tensors used for the inference computation. Any initializer values will be taken into account, all other tensors will be zero.
-
make_new_valueinfo_name
()¶ Returns a name that can be used for a new value_info.
-
property
model
¶ Returns the model.
-
rename_tensor
(old_name, new_name)¶ Renames a tensor from old_name to new_name.
-
save
(filename)¶ Saves the wrapper ONNX ModelProto into a file with given name.
-
set_initializer
(tensor_name, tensor_value)¶ Sets the initializer value for tensor with given name.
-
set_metadata_prop
(key, value)¶ Sets metadata property with given key to the given value.
-
set_tensor_datatype
(tensor_name, datatype)¶ Sets the FINN DataType of tensor with given name.
-
set_tensor_layout
(tensor_name, data_layout)¶ Sets the data layout annotation of tensor with given name. See get_tensor_layout for examples.
-
set_tensor_shape
(tensor_name, tensor_shape, dtype=1)¶ Assigns shape in ValueInfoProto for tensor with given name.
-
set_tensor_sparsity
(tensor_name, sparsity_dict)¶ Sets the sparsity annotation of a tensor with given name.
-
temporary_fix_oldstyle_domain
()¶
-
transform
(transformation, make_deepcopy=True, cleanup=True, fix_float64=True)¶ Applies given Transformation repeatedly until no more changes can be made and returns a transformed ModelWrapper instance.
make_deepcopy : operates on a new (deep)copy of model.
fix_float64 : DoubleToSingleFloat correction before starting
cleanup : execute cleanup transformations before returning
-
finn.core.onnx_exec (module)¶
-
finn.core.onnx_exec.
compare_execution
(model_a, model_b, input_dict, compare_fxn=<function <lambda>>)¶ Executes two ONNX models and compare their outputs using given function.
compare_fxn should take in two tensors and return a Boolean
-
finn.core.onnx_exec.
execute_node
(node, context, graph, return_full_exec_context=False)¶ Executes a single node by using onnxruntime, with custom function or if dataflow partition by using remote execution or rtlsim.
Input/output provided via context.
-
finn.core.onnx_exec.
execute_onnx
(model, input_dict, return_full_exec_context=False, start_node=None, end_node=None)¶ Executes given ONNX ModelWrapper with given named inputs.
If return_full_exec_context is False, a dict of named outputs is returned as indicated by the model.graph.output.
If return return_full_exec_context is True, the full set of tensors used by the execution (including inputs, weights, activations and final outputs) will be returned as a dict.
When start_node and end_node are set to None, the whole graph is executed. If they are set to particular ONNX nodes, only the subgraph between (and including) those nodes is executed.
-
finn.core.onnx_exec.
execute_onnx_and_make_model
(model, input_dict)¶ Executes given ONNX ModelWrapper with given named inputs and return a new ModelWrapper where an initializer is provided for each tensor as taken from the execution. This new model is useful for debugging, since it contains all the intermediate activation values.
finn.core.remote_exec (module)¶
-
finn.core.remote_exec.
remote_exec
(model, execution_context)¶ Executes the given model remotely on the pynq board. The metadata properties related to the pynq board have to be set. The execution context contains the input values.
finn.core.rtlsim_exec (module)¶
-
finn.core.rtlsim_exec.
rtlsim_exec
(model, execution_context, pre_hook=None, post_hook=None)¶ Use PyVerilator to execute given model with stitched IP. The execution context contains the input values. Hook functions can be optionally specified to observe/alter the state of the circuit, receiving the PyVerilator sim object as their first argument: - pre_hook : hook function to be called before sim start (after reset) - post_hook : hook function to be called after sim end
finn.core.throughput_test (module)¶
-
finn.core.throughput_test.
throughput_test_remote
(model, batchsize=1000)¶ Runs the throughput test for the given model remotely on the pynq board. The metadata properties related to the pynq board have to be set. Returns a dictionary with results of the throughput test. Returns None if the test fails.
-
finn.core.throughput_test.
throughput_test_rtlsim
(model, batchsize=100)¶ Runs a throughput test for the given IP-stitched model. When combined with tracing, useful to determine bottlenecks and required FIFO sizes.
finn.custom_op (namespace)¶
Subpackages:
finn.custom_op.general (package)¶
Submodules:
finn.custom_op.general.debugmarker (module)¶
-
class
finn.custom_op.general.debugmarker.
DebugMarker
(onnx_node)¶ Bases:
finn.custom_op.base.CustomOp
-
execute_node
(context, graph)¶ Execute this CustomOp instance, given the execution context and ONNX graph.
-
get_nodeattr_types
()¶ Returns a dict of permitted attributes for node, where: ret_dict[attribute_name] = (dtype, require, default_value, <allowed_values>) - dtype indicates which member of the ONNX AttributeProto will be utilized - require indicates whether this attribute is required - default_val indicates the default value that will be used if the attribute is not set - <allowed_values> (if specified) indicates that this attribute can only be set to one of the values in the set <allowed_values>. If not specified, all values permitted by dtype are allowed.
-
infer_node_datatype
(model)¶ Set the DataType annotations corresponding to the outputs of this node.
-
make_shape_compatible_op
(model)¶ Returns a standard ONNX op which is compatible with this CustomOp for performing shape inference.
-
verify_node
()¶ Verifies that all attributes the node needs are there and that particular attributes are set correctly. Also checks if the number of inputs is equal to the expected number.
-
finn.custom_op.general.im2col (module)¶
-
class
finn.custom_op.general.im2col.
Im2Col
(onnx_node)¶ Bases:
finn.custom_op.base.CustomOp
-
execute_node
(context, graph)¶ Execute this CustomOp instance, given the execution context and ONNX graph.
-
get_nodeattr_types
()¶ Returns a dict of permitted attributes for node, where: ret_dict[attribute_name] = (dtype, require, default_value, <allowed_values>) - dtype indicates which member of the ONNX AttributeProto will be utilized - require indicates whether this attribute is required - default_val indicates the default value that will be used if the attribute is not set - <allowed_values> (if specified) indicates that this attribute can only be set to one of the values in the set <allowed_values>. If not specified, all values permitted by dtype are allowed.
-
infer_node_datatype
(model)¶ Set the DataType annotations corresponding to the outputs of this node.
-
make_shape_compatible_op
(model)¶ Returns a standard ONNX op which is compatible with this CustomOp for performing shape inference.
-
verify_node
()¶ Verifies that all attributes the node needs are there and that particular attributes are set correctly. Also checks if the number of inputs is equal to the expected number.
-
-
finn.custom_op.general.im2col.
compute_conv_output_dim
(ifm_dim, k, stride, pad=0)¶ Returns spatial output dimension size for convolution with given params.
-
finn.custom_op.general.im2col.
get_im2col_indices_nchw
(x_shape, field_height, field_width, padding=0, stride_y=1, stride_x=1)¶ Returns im2col indices.
-
finn.custom_op.general.im2col.
im2col_indices_nchw
(x, field_height, field_width, padding=0, stride_y=1, stride_x=1, pad_val=0)¶ Performs im2col on x with given field height and width, as well as values for padding and stride size. Returns result of im2col.
finn.custom_op.general.maxpoolnhwc (module)¶
-
class
finn.custom_op.general.maxpoolnhwc.
MaxPoolNHWC
(onnx_node)¶ Bases:
finn.custom_op.base.CustomOp
-
execute_node
(context, graph)¶ Execute this CustomOp instance, given the execution context and ONNX graph.
-
get_nodeattr_types
()¶ Returns a dict of permitted attributes for node, where: ret_dict[attribute_name] = (dtype, require, default_value, <allowed_values>) - dtype indicates which member of the ONNX AttributeProto will be utilized - require indicates whether this attribute is required - default_val indicates the default value that will be used if the attribute is not set - <allowed_values> (if specified) indicates that this attribute can only be set to one of the values in the set <allowed_values>. If not specified, all values permitted by dtype are allowed.
-
infer_node_datatype
(model)¶ Set the DataType annotations corresponding to the outputs of this node.
-
make_shape_compatible_op
(model)¶ Returns a standard ONNX op which is compatible with this CustomOp for performing shape inference.
-
verify_node
()¶ Verifies that all attributes the node needs are there and that particular attributes are set correctly. Also checks if the number of inputs is equal to the expected number.
-
-
finn.custom_op.general.maxpoolnhwc.
compute_pool_output_dim
(ifm_dim, k, stride, pad=0)¶ Return spatial output dimension size for pooling with given params.
finn.custom_op.general.multithreshold (module)¶
-
class
finn.custom_op.general.multithreshold.
MultiThreshold
(onnx_node)¶ Bases:
finn.custom_op.base.CustomOp
Class that corresponds to a multithresholding node.
-
execute_node
(context, graph)¶ Execute this CustomOp instance, given the execution context and ONNX graph.
-
get_nodeattr_types
()¶ Returns a dict of permitted attributes for node, where: ret_dict[attribute_name] = (dtype, require, default_value, <allowed_values>) - dtype indicates which member of the ONNX AttributeProto will be utilized - require indicates whether this attribute is required - default_val indicates the default value that will be used if the attribute is not set - <allowed_values> (if specified) indicates that this attribute can only be set to one of the values in the set <allowed_values>. If not specified, all values permitted by dtype are allowed.
-
infer_node_datatype
(model)¶ Set the DataType annotations corresponding to the outputs of this node.
-
make_shape_compatible_op
(model)¶ Returns a standard ONNX op which is compatible with this CustomOp for performing shape inference.
-
verify_node
()¶ Verifies that all attributes the node needs are there and that particular attributes are set correctly. Also checks if the number of inputs is equal to the expected number.
-
-
finn.custom_op.general.multithreshold.
multithreshold
(v, thresholds, out_scale=None, out_bias=None)¶ Given a set of threshold values t={t_0, t_1 … t_n} the successive thresholding maps any real number x to an integer in the interval [0, n], where the returned integer is the number of thresholds x is greater than or equal to.
The output tensor will be scaled by out_scale and biased by out_bias.
finn.custom_op.general.quantavgpool2d (module)¶
-
class
finn.custom_op.general.quantavgpool2d.
QuantAvgPool2d
(onnx_node)¶ Bases:
finn.custom_op.base.CustomOp
CustomOp that corresponds to the quantized average pooling layer from Brevitas
-
execute_node
(context, graph)¶ Execute this CustomOp instance, given the execution context and ONNX graph.
-
get_accum_size
()¶
-
get_nodeattr_types
()¶ Returns a dict of permitted attributes for node, where: ret_dict[attribute_name] = (dtype, require, default_value, <allowed_values>) - dtype indicates which member of the ONNX AttributeProto will be utilized - require indicates whether this attribute is required - default_val indicates the default value that will be used if the attribute is not set - <allowed_values> (if specified) indicates that this attribute can only be set to one of the values in the set <allowed_values>. If not specified, all values permitted by dtype are allowed.
-
get_shifts
()¶
-
infer_node_datatype
(model)¶ Set the DataType annotations corresponding to the outputs of this node.
-
make_shape_compatible_op
(model)¶ Returns a standard ONNX op which is compatible with this CustomOp for performing shape inference.
-
verify_node
()¶ Verifies that all attributes the node needs are there and that particular attributes are set correctly. Also checks if the number of inputs is equal to the expected number.
-
finn.custom_op.general.streamingdataflowpartition (module)¶
-
class
finn.custom_op.general.streamingdataflowpartition.
StreamingDataflowPartition
(onnx_node)¶ Bases:
finn.custom_op.base.CustomOp
Class that corresponds to the meta/container node StreamingDataflowPartition which is a placeholder for a group of fpgadataflow nodes that have been separated out into a FINN-ONNX model of its own. Note that is does not produce any HLS or bitfile by itself.
-
execute_node
(context, graph)¶ Execute this CustomOp instance, given the execution context and ONNX graph.
-
get_nodeattr_types
()¶ Returns a dict of permitted attributes for node, where: ret_dict[attribute_name] = (dtype, require, default_value, <allowed_values>) - dtype indicates which member of the ONNX AttributeProto will be utilized - require indicates whether this attribute is required - default_val indicates the default value that will be used if the attribute is not set - <allowed_values> (if specified) indicates that this attribute can only be set to one of the values in the set <allowed_values>. If not specified, all values permitted by dtype are allowed.
-
infer_node_datatype
(model)¶ Set the DataType annotations corresponding to the outputs of this node.
-
make_shape_compatible_op
(model)¶ Returns a standard ONNX op which is compatible with this CustomOp for performing shape inference.
-
verify_node
()¶ Verifies that all attributes the node needs are there and that particular attributes are set correctly. Also checks if the number of inputs is equal to the expected number.
-
finn.custom_op.general.xnorpopcount (module)¶
-
class
finn.custom_op.general.xnorpopcount.
XnorPopcountMatMul
(onnx_node)¶ Bases:
finn.custom_op.base.CustomOp
Class that corresponds to a XNOR-popcount matrix multiplication node.
-
execute_node
(context, graph)¶ Execute this CustomOp instance, given the execution context and ONNX graph.
-
get_nodeattr_types
()¶ Returns a dict of permitted attributes for node, where: ret_dict[attribute_name] = (dtype, require, default_value, <allowed_values>) - dtype indicates which member of the ONNX AttributeProto will be utilized - require indicates whether this attribute is required - default_val indicates the default value that will be used if the attribute is not set - <allowed_values> (if specified) indicates that this attribute can only be set to one of the values in the set <allowed_values>. If not specified, all values permitted by dtype are allowed.
-
infer_node_datatype
(model)¶ Set the DataType annotations corresponding to the outputs of this node.
-
make_shape_compatible_op
(model)¶ Returns a standard ONNX op which is compatible with this CustomOp for performing shape inference.
-
verify_node
()¶ Verifies that all attributes the node needs are there and that particular attributes are set correctly. Also checks if the number of inputs is equal to the expected number.
-
-
finn.custom_op.general.xnorpopcount.
xnorpopcountmatmul
(inp0, inp1)¶ Simulates XNOR-popcount matrix multiplication as a regular bipolar matrix multiplication followed by some post processing.
Module contents:
Submodules:
finn.custom_op.base (module)¶
-
class
finn.custom_op.base.
CustomOp
(onnx_node)¶ Bases:
abc.ABC
CustomOp class all custom op nodes are based on. Contains different functions every custom node should have. Some as abstract methods, these have to be filled when writing a new custom op node.
-
abstract
execute_node
(context, graph)¶ Execute this CustomOp instance, given the execution context and ONNX graph.
-
get_nodeattr
(name)¶ Get a node attribute by name. Data is stored inside the ONNX node’s AttributeProto container. Attribute must be part of get_nodeattr_types. Default value is returned if attribute is not set.
-
get_nodeattr_allowed_values
(name)¶ Return set of allowed values for given attribute, None if not specified.
-
get_nodeattr_def
(name)¶ Return 4-tuple (dtype, required, default_val, allowed_values) for attribute with name. allowed_values will be None if not specified.
-
abstract
get_nodeattr_types
()¶ Returns a dict of permitted attributes for node, where: ret_dict[attribute_name] = (dtype, require, default_value, <allowed_values>) - dtype indicates which member of the ONNX AttributeProto will be utilized - require indicates whether this attribute is required - default_val indicates the default value that will be used if the attribute is not set - <allowed_values> (if specified) indicates that this attribute can only be set to one of the values in the set <allowed_values>. If not specified, all values permitted by dtype are allowed.
-
abstract
infer_node_datatype
(model)¶ Set the DataType annotations corresponding to the outputs of this node.
-
abstract
make_shape_compatible_op
(model)¶ Returns a standard ONNX op which is compatible with this CustomOp for performing shape inference.
-
set_nodeattr
(name, value)¶ Set a node attribute by name. Data is stored inside the ONNX node’s AttributeProto container. Attribute must be part of get_nodeattr_types.
-
abstract
verify_node
()¶ Verifies that all attributes the node needs are there and that particular attributes are set correctly. Also checks if the number of inputs is equal to the expected number.
-
abstract
finn.transformation (namespace)¶
Submodules:
finn.transformation.base (module)¶
Guide to writing FINN transformations¶
Your transformation must inherit the Transformation abstract base class.
Your transformation’s apply function should take in a ModelWrapper, and return a tuple with (transformed_model: ModelWrapper, model_was_changed: Bool)
The transformations are meant to be applied using the .transform function in ModelWrapper. This makes a deep copy of the input model by default, so you don’t have to.
model_was_changed indicates whether your transformation made any changes to the model. If you know your transformation needs to be called only once and repeated calls have no further effect, you can return False even if the model was changed.
You MUST return model_was_changed=False at some point when your transformation is called multiple times, otherwise apply_repeated() will loop infinitely.
If you cannot guarantee that the transformation will reach a fixed point, you must declare this, return model_was_changed = False and let the user manually re-apply the transform.
-
class
finn.transformation.base.
NodeLocalTransformation
(num_workers=None)¶ Bases:
finn.transformation.base.Transformation
Parent class for transformations, which can be executed locally to one node by accessing and modifying the attributes of only that node. This class can then automatically parallelize the transformation. Transformations sublcassing NodeLocalTransformation must implement the abstract method applyNodeLocal().
To control the degree of parallelization, specify the num_workers argument in the constructor, using one of the following values: * None: use NUM_DEFAULT_WORKERS environment variable * 0: use all available CPU cores * (any other int>0): set number of parallel workers
-
apply
(model)¶
-
abstract
applyNodeLocal
(node)¶
-
finn.transformation.batchnorm_to_affine (module)¶
-
class
finn.transformation.batchnorm_to_affine.
BatchNormToAffine
¶ Bases:
finn.transformation.base.Transformation
Replaces any test-time BatchNorm layers with Mul-Add layers.
-
apply
(model)¶
-
finn.transformation.bipolar_to_xnor (module)¶
-
class
finn.transformation.bipolar_to_xnor.
ConvertBipolarMatMulToXnorPopcount
¶ Bases:
finn.transformation.base.Transformation
Convert MatMul nodes with all-bipolar inputs to XnorPopcountMatMul and associated result correction.
-
apply
(model)¶
-
finn.transformation.change_datalayout (module)¶
-
class
finn.transformation.change_datalayout.
ChangeDataLayoutQuantAvgPool2d
¶ Bases:
finn.transformation.base.Transformation
Replace QuantAvgPool2d with datalayout (N,C,H,W) with Transpose nodes and QuantAvgPool2dNHWC with datalayout (N,H,W,C)
-
apply
(model)¶
-
finn.transformation.double_to_single_float (module)¶
-
class
finn.transformation.double_to_single_float.
DoubleToSingleFloat
¶ Bases:
finn.transformation.base.Transformation
Convert any float64 initializers to float32.
-
apply
(model)¶
-
finn.transformation.fold_constants (module)¶
-
class
finn.transformation.fold_constants.
FoldConstants
¶ Bases:
finn.transformation.base.Transformation
Replace the output of a node with const-only inputs with a precomputed result.
-
apply
(model)¶
-
finn.transformation.general (module)¶
-
class
finn.transformation.general.
ApplyConfig
(config)¶ Bases:
finn.transformation.base.Transformation
Applies node properties (attributes) from either a config dict or its JSON representation given as a filename. The JSON file can specify default values for particular op_types, as well as values for nodes with particular names. Example dict:
{ # set kernel_size = 3 for all nodes with op_type=Im2Col "Defaults" : {"kernel_size" : [3, ["Im2Col"]]}, # set kernel_size = 7 for the particular node with name Im2Col_0 "Im2Col_0" : {"kernel_size" : 7} }
-
apply
(model)¶
-
-
class
finn.transformation.general.
ConvertDivToMul
¶ Bases:
finn.transformation.base.Transformation
Convert divide by constant nodes to multiply by constant nodes.
-
apply
(model)¶
-
-
class
finn.transformation.general.
ConvertSubToAdd
¶ Bases:
finn.transformation.base.Transformation
Convert subtract-a-constant nodes to add-a-constant nodes.
-
apply
(model)¶
-
-
class
finn.transformation.general.
GiveRandomTensorNames
¶ Bases:
finn.transformation.base.Transformation
Give random tensor names to all tensors.
-
apply
(model)¶
-
-
class
finn.transformation.general.
GiveReadableTensorNames
¶ Bases:
finn.transformation.base.Transformation
Give more human-readable names to all internal tensors. You should apply GiveUniqueNodeNames prior to this transform to avoid empty node names, as the readable names are based on the node names.
-
apply
(model)¶
-
-
class
finn.transformation.general.
GiveUniqueNodeNames
(prefix='')¶ Bases:
finn.transformation.base.Transformation
Give unique names to each node in the graph using enumeration, starting with given prefix (if specified in the constructor).
-
apply
(model)¶
-
-
class
finn.transformation.general.
GiveUniqueParameterTensors
¶ Bases:
finn.transformation.base.Transformation
Make every parameter tensor unique. The aim is to avoid affecting other nodes apart from the one the system is currently operating on.
-
apply
(model)¶
-
-
class
finn.transformation.general.
RemoveStaticGraphInputs
¶ Bases:
finn.transformation.base.Transformation
Remove any top-level graph inputs that have initializers.
-
apply
(model)¶
-
-
class
finn.transformation.general.
RemoveUnusedTensors
¶ Bases:
finn.transformation.base.Transformation
Remove any unused tensors in the graph by removing any initializers, ValueInfo and tensor annotations associated with it. Unused tensors do not appear as any input/output for any graph nodes.
-
apply
(model)¶
-
-
class
finn.transformation.general.
SortGraph
¶ Bases:
finn.transformation.base.Transformation
Returns the model with its node list sorted topologically. Any ONNX graph to be executed must have a topologically sorted node list, as dictated by the ONNX standard.
-
apply
(model)¶
-
finn.transformation.infer_data_layouts (module)¶
-
class
finn.transformation.infer_data_layouts.
InferDataLayouts
¶ Bases:
finn.transformation.base.Transformation
Try to infer data layout annotations info for all input/intermediate/output tensors based on inputs and node type.
-
apply
(model)¶
-
finn.transformation.infer_datatypes (module)¶
-
class
finn.transformation.infer_datatypes.
InferDataTypes
¶ Bases:
finn.transformation.base.Transformation
Infer FINN DataType info for all intermediate/output tensors based on inputs and node type.
-
apply
(model)¶
-
finn.transformation.infer_shapes (module)¶
-
class
finn.transformation.infer_shapes.
InferShapes
¶ Bases:
finn.transformation.base.Transformation
Ensure every tensor in the model has a specified shape (ValueInfo).
-
apply
(model)¶
-
finn.transformation.insert_topk (module)¶
-
class
finn.transformation.insert_topk.
InsertTopK
(k=5, axis=- 1, largest=1, sorted=1)¶ Bases:
finn.transformation.base.Transformation
Add TopK node at the network output and replace the graph output with the TopK indices.
-
apply
(model)¶
-
finn.transformation.lower_convs_to_matmul (module)¶
-
class
finn.transformation.lower_convs_to_matmul.
LowerConvsToMatMul
¶ Bases:
finn.transformation.base.Transformation
Replace Conv layers with pairs of Im2Col-MatMul layers, plus Transpose layers to keep the original data layout.
-
apply
(model)¶
-
finn.transformation.merge_onnx_models (module)¶
-
class
finn.transformation.merge_onnx_models.
MergeONNXModels
(pre_model)¶ Bases:
finn.transformation.base.Transformation
Merges two models. The model passed in the transformation will be inserted before the model the transformation is applied on, the resulting model is returned. This transformation will try to connect graph.output[0] of the pre model and graph.input[0] of the post model. If more than one input or output exists, a warning is raised.
-
apply
(model)¶
-
finn.util (namespace)¶
Submodules:
finn.util.basic (module)¶
-
class
finn.util.basic.
CppBuilder
¶ Bases:
object
Builds the g++ compiler command to produces the executable of the c++ code in code_gen_dir which is passed to the function build() of this class.
-
append_includes
(library_path)¶ Adds given library path to include_paths list.
-
append_sources
(cpp_file)¶ Adds given c++ file to cpp_files list.
-
build
(code_gen_dir)¶ Builds the g++ compiler command according to entries in include_paths and cpp_files lists. Saves it in bash script in given folder and executes it.
-
set_executable_path
(path)¶ Sets member variable “executable_path” to given path.
-
-
finn.util.basic.
calculate_matvec_accumulator_range
(matrix, vec_dt)¶ Calculate the minimum and maximum possible result (accumulator) values for a dot product x * A, given matrix A of dims (MW, MH), and vector (1, MW) with datatype vec_dt. Returns (acc_min, acc_max).
-
finn.util.basic.
calculate_signed_dot_prod_range
(dt_a, dt_b, len)¶ Returns the (min,max) values a dot product between two signed vectors of types dt_a and dt_b of len elements can take.
-
finn.util.basic.
gen_finn_dt_tensor
(finn_dt, tensor_shape)¶ Generates random tensor in given shape and with given FINN DataType.
-
finn.util.basic.
get_by_name
(container, name, name_field='name')¶ Return item from container by .name field if it exists, None otherwise. Will throw an Exception if multiple items are found, since this violates the ONNX standard.
-
finn.util.basic.
get_execution_error_thresh
()¶ Return the max error that is allowed for rounding in FINN execution.
-
finn.util.basic.
get_finn_root
()¶ Return the root directory that FINN is cloned into.
-
finn.util.basic.
get_num_default_workers
()¶ Return the number of workers for parallel transformations. Controllable via the NUM_DEFAULT_WORKERS environment variable. If the env.var. is undefined, the default value of 1 is returned.
-
finn.util.basic.
get_remote_vivado
()¶ Return the address of the remote Vivado synthesis server as set by the, REMOTE_VIVADO environment variable, otherwise return None
-
finn.util.basic.
get_rtlsim_trace_depth
()¶ Return the trace depth for rtlsim via PyVerilator. Controllable via the RTLSIM_TRACE_DEPTH environment variable. If the env.var. is undefined, the default value of 1 is returned. A trace depth of 1 will only show top-level signals and yield smaller .vcd files.
The following depth values are of interest for whole-network stitched IP rtlsim: - level 1 shows top-level input/output streams - level 2 shows per-layer input/output streams - level 3 shows per full-layer I/O including FIFO count signals
-
finn.util.basic.
get_sanitize_quant_tensors
()¶ Return whether tensors with quantization annotations should be sanitized. Enabled by default, disabling will yield faster ONNX execution but may give incorrect results. Use with caution.
-
finn.util.basic.
interleave_matrix_outer_dim_from_partitions
(matrix, n_partitions)¶ Interleave the outermost dimension of a matrix from given partitions (n_partitions).
-
finn.util.basic.
is_finn_op
(op_type)¶ Return whether given op_type string is a FINN custom op
-
finn.util.basic.
make_build_dir
(prefix='')¶ Creates a temporary folder with given prefix to be used as a build dir. Use this function instead of tempfile.mkdtemp to ensure any generated files will survive on the host after the FINN Docker container exits.
-
finn.util.basic.
pad_tensor_to_multiple_of
(ndarray, pad_to_dims, val=0, distr_pad=False)¶ Pad each dimension of given NumPy ndarray using val, so that each dimension is a multiple of the respective value in pad_to_dims. -1 means do not pad that particular dimension. If distr_pad is False, all padding will be inserted after the existing values; otherwise it will be split evenly between before and after the existing values, with one extra value inserted after if the padding amount is not divisible by two.
-
finn.util.basic.
random_string
(stringLength=6)¶ Randomly generate a string of letters and digits.
-
finn.util.basic.
remove_by_name
(container, name, name_field='name')¶ Remove item from container by .name field if it exists.
-
finn.util.basic.
roundup_to_integer_multiple
(x, factor)¶ Round up integer x to the nearest integer multiple of integer factor. Returns x if factor is set to -1. Both x and factor must otherwise be positive.
-
finn.util.basic.
sanitize_quant_values
(model, node_tensors, execution_context, check_values=False)¶ Sanitize given list of tensors in execution_context by rounding values that are supposed to be integers (as indicated by their quantization annotation). Will raise an assertion if the amount of rounding is too large. Returns the sanitized execution context.
If check_values is specified, an extra DataType.allowed() check will be performed on any rounded tensors.
Background: FINN uses floating point tensors as a carrier data type to represent integers. Floating point arithmetic can introduce rounding errors, e.g. (int_num * float_scale) / float_scale is not always equal to int_num. We use this function to ensure that the values that are supposed to be integers are indeed integers.
finn.util.data_packing (module)¶
-
finn.util.data_packing.
array2hexstring
(array, dtype, pad_to_nbits, prefix='0x', reverse=False)¶ Pack given one-dimensional NumPy array with FINN DataType dtype into a hex string. Any BIPOLAR values will be converted to a single bit with a 0 representing -1. pad_to_nbits is used to prepend leading zeros to ensure packed strings of fixed width. The minimum value for pad_to_nbits is 4, since a single hex digit is four bits. reverse can be used to reverse the array prior to packing.
Examples:
array2hexstring([1, 1, 1, 0], DataType.BINARY, 4) = “0xe”
array2hexstring([1, 1, 1, 0], DataType.BINARY, 8) = “0x0e”
array2hexstring([1, 1, 0, 1], DataType.BINARY, 4, reverse=True) = “0xb”
array2hexstring([1, 1, 1, 0], DataType.BINARY, 8, reverse=True) = “0x07”
-
finn.util.data_packing.
finnpy_to_packed_bytearray
(ndarray, dtype, reverse_inner=False, reverse_endian=False)¶ Given a numpy ndarray with FINN DataType dtype, pack the innermost dimension and return the packed representation as an ndarray of uint8. The packed innermost dimension will be padded to the nearest multiple of 8 bits. The returned ndarray has the same number of dimensions as the input.
-
finn.util.data_packing.
hexstring2npbytearray
(hexstring, remove_prefix='0x')¶ Convert a hex string into a NumPy array of dtype uint8.
Example:
hexstring2npbytearray(“0f01”) = array([15, 1], dtype=uint8)
-
finn.util.data_packing.
npbytearray2hexstring
(npbytearray, prefix='0x')¶ Convert a NumPy array of uint8 dtype into a hex string.
Example:
npbytearray2hexstring(array([15, 1], dtype=uint8)) = “0x0f01”
-
finn.util.data_packing.
npy_to_rtlsim_input
(input_file, input_dtype, pad_to_nbits, reverse_inner=True)¶ Convert the multidimensional NumPy array of integers (stored as floats) from input_file into a flattened sequence of Python arbitrary-precision integers, packing the innermost dimension. See finn.util.basic.pack_innermost_dim_as_hex_string() for more info on how the packing works. If reverse_inner is set, the innermost dimension will be reversed prior to packing.
-
finn.util.data_packing.
numpy_to_hls_code
(ndarray, dtype, hls_var_name, pack_innermost_dim=True, no_decl=False)¶ Return C++ code representation of a numpy ndarray with FINN DataType dtype, using hls_var_name as the resulting C++ variable name. If pack_innermost_dim is specified, the innermost dimension of the ndarray will be packed into a hex string using array2hexstring. If no_decl is set to True, no variable name and type will be generated as part of the emitted string.
-
finn.util.data_packing.
pack_innermost_dim_as_hex_string
(ndarray, dtype, pad_to_nbits, reverse_inner=False, prefix='0x')¶ Pack the innermost dimension of the given numpy ndarray into hex strings using array2hexstring.
Examples:
A = [[1, 1, 1, 0], [0, 1, 1, 0]]
eA = [“0e”, “06”]
pack_innermost_dim_as_hex_string(A, DataType.BINARY, 8) == eA
B = [[[3, 3], [3, 3]], [[1, 3], [3, 1]]]
eB = [[ “0f”, “0f”], [“07”, “0d”]]
pack_innermost_dim_as_hex_string(B, DataType.UINT2, 8) == eB
-
finn.util.data_packing.
packed_bytearray_to_finnpy
(packed_bytearray, dtype, output_shape=None, reverse_inner=False, reverse_endian=False)¶ Given a packed numpy uint8 ndarray, unpack it into a FINN array of given DataType.
output_shape can be specified to remove padding from the packed dimension, or set to None to be inferred from the input.
-
finn.util.data_packing.
rtlsim_output_to_npy
(output, path, dtype, shape, packedBits, targetBits, reverse_inner=True)¶ Convert a flattened sequence of Python arbitrary-precision integers output into a NumPy array, saved as npy file at path. Each arbitrary-precision integer is assumed to be a packed array of targetBits-bit elements, which will be unpacked as the innermost dimension of the NumPy array. If path is not None it will also be saved as a npy file.
-
finn.util.data_packing.
unpack_innermost_dim_from_hex_string
(ndarray, dtype, out_shape, packedBits, reverse_inner=False)¶ Convert a NumPy array of hex strings into a FINN NumPy array by unpacking the hex strings into the specified data type. out_shape can be specified such that any padding in the packing dimension is removed. If reverse_inner is set, the innermost unpacked dimension will be reversed.
finn.util.fpgadataflow (module)¶
-
class
finn.util.fpgadataflow.
IPGenBuilder
¶ Bases:
object
Builds the bash script to generate IP blocks using Vivado HLS.
-
append_tcl
(tcl_script)¶ Sets member variable “tcl_script” to given tcl script.
-
build
(code_gen_dir)¶ Builds the bash script with given parameters and saves it in given folder. To guarantee the generation in the correct folder the bash script contains a cd command.
-
set_ipgen_path
(path)¶ Sets member variable ipgen_path to given path.
-
-
finn.util.fpgadataflow.
is_fpgadataflow_node
(node)¶ Returns True if given node is fpgadataflow node. Otherwise False.
-
finn.util.fpgadataflow.
pyverilate_get_liveness_threshold_cycles
()¶ Return the number of no-output cycles rtlsim will wait before assuming the simulation is not finishing and throwing an exception.
-
finn.util.fpgadataflow.
pyverilate_stitched_ip
(model, read_internal_signals=True)¶ Given a model with stitched IP, return a PyVerilator sim object. If read_internal_signals is True, it will be possible to examine the internal (not only port) signals of the Verilog module, but this may slow down compilation and emulation. Trace depth is also controllable, see get_rtlsim_trace_depth()
-
finn.util.fpgadataflow.
rtlsim_multi_io
(sim, io_dict, num_out_values, trace_file='')¶ Runs the pyverilator simulation by passing the input values to the simulation, toggle the clock and observing the execution time. Function contains also an observation loop that can abort the simulation if no output value is produced after a set number of cycles. Can handle multiple i/o streams. See function implementation for details on how the top-level signals should be named.
Arguments:
sim: the PyVerilator object for simulation
io_dict: a dict of dicts in the following format: {“inputs” : {“in0” : <input_data>, “in1” : <input_data>}, “outputs” : {“out0” : [], “out1” : []} } <input_data> is a list of Python arbitrary-precision ints indicating what data to push into the simulation, and the output lists are similarly filled when the simulation is complete
num_out_values: number of total values to be read from the simulation to finish the simulation and return.
Returns: number of clock cycles elapsed for completion
finn.util.onnx (module)¶
-
finn.util.onnx.
nchw_to_nhwc
(t, model, idx, reverse=False)¶ Converts between NCHW <-> NHWC layouts for tensor t by inserting a transpose. If reverse=False, t is assumed NCHW and we insert transpose to convert NCHW -> NHWC If reverse=True, t is assumed NHWC and we insert transpose to convert NHWC -> NCHW.
-
finn.util.onnx.
valueinfo_to_tensor
(vi)¶ Creates an all-zeroes numpy tensor from a ValueInfoProto.
finn.util.pyverilator (module)¶
-
finn.util.pyverilator.
axilite_read
(sim, addr, basename='s_axi_control_')¶ Read val from addr on AXI lite interface given by basename.
Arguments: - sim : PyVerilator sim object - addr : address for read - basename : prefix for AXI lite interface name
Returns: read value from AXI lite interface at given addr
-
finn.util.pyverilator.
axilite_write
(sim, addr, val, basename='s_axi_control_', wstrb=15, sim_addr_and_data=True)¶ Write val to addr on AXI lite interface given by basename.
Arguments: - sim : PyVerilator sim object - addr : address for write - val : value to be written at addr - basename : prefix for AXI lite interface name - wstrb : write strobe value to do partial writes, see AXI protocol reference - sim_addr_and_data : handshake AW and W channels simultaneously
-
finn.util.pyverilator.
multi_handshake
(sim, ifnames, basename='s_axi_control_')¶ Perform a handshake on list of interfaces given by ifnames. Will assert VALID and de-assert after READY observed, in as few cycles as possible.
-
finn.util.pyverilator.
reset_rtlsim
(sim, rst_name='ap_rst_n', active_low=True)¶ Sets reset input in pyverilator to zero, toggles the clock and set it back to one
-
finn.util.pyverilator.
toggle_clk
(sim, clk_name='ap_clk')¶ Toggles the clock input in pyverilator once.
-
finn.util.pyverilator.
wait_for_handshake
(sim, ifname, basename='s_axi_control_', dataname='DATA')¶ Wait for handshake (READY and VALID high at the same time) on given interface on PyVerilator sim object.
Arguments: - sim : PyVerilator sim object - ifname : name for decoupled interface to wait for handshake on - basename : prefix for decoupled interface name - dataname : interface data sig name, will be return value if it exists
Returns: value of interface data signal during handshake (if given by dataname), None otherwise (e.g. if there is no data signal associated with interface)
License¶
Copyright (c) 2020 Xilinx, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of Xilinx nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Contributors¶
Yaman Umuroglu <yamanu@xilinx.com> (maintainer)
Sambhav Jain <sambhavj@xilinx.com> (maintainer)
Jakoba Petri-Koenig (@auphelia)
Lucian Petrica (@quetric)
Tobias Alonso (@Tobi-Alonso)
Hendrik Borras (@HenniOVP)