convert_from_onnx_model
Convert an ONNX model to an hls4ml ModelGraph.
hls4ml.converters.convert_from_onnx_model(
model,
output_dir='my-hls-test',
project_name='myproject',
input_data_tb=None,
output_data_tb=None,
backend='Vivado',
hls_config=None,
bit_exact=None,
**kwargs
)
Parameters
model
str | onnx.ModelProto
required
ONNX model to convert. Can be either a file path or an ONNX ModelProto object.
Output directory for the generated HLS project.
Name of the HLS project. Used as the top-level function name.
Path to input test data in .npy or .dat format for C simulation and co-simulation.
Path to expected output data in .npy or .dat format for verification.
Backend to use. Options: 'Vivado', 'Vitis', 'Quartus', 'Catapult'.
Target board from supported_board.json. Overrides part parameter.
FPGA part number. Backend-specific defaults used if not provided.
Clock period in nanoseconds.
Interface type: 'io_parallel' or 'io_stream'.
Enable model-wise fixed-point precision propagation. If None, automatically enabled for HGQ models.
Returns
The converted hls4ml model ready for compilation and synthesis.
Example
import onnx
import hls4ml
import numpy as np
# Load ONNX model
onnx_model = onnx.load('model.onnx')
# Configure HLS settings
hls_config = {
'Model': {
'Precision': 'ap_fixed<16,6>',
'ReuseFactor': 4
}
}
# Convert to HLS
hls_model = hls4ml.converters.convert_from_onnx_model(
onnx_model,
output_dir='my_onnx_prj',
project_name='my_onnx_model',
backend='Vivado',
hls_config=hls_config
)
# Compile the model
hls_model.compile()
# Test predictions
X_test = np.random.rand(100, 10).astype(np.float32)
predictions = hls_model.predict(X_test)
onnx_to_hls
Lower-level function that performs the actual ONNX to HLS conversion.
hls4ml.converters.onnx_to_hls(config)
Parameters
Configuration dictionary containing model and conversion parameters with 'OnnxModel' key.
Returns
The hls4ml ModelGraph representation.
Example
import onnx
import hls4ml
onnx_model = onnx.load('model.onnx')
config = {
'OnnxModel': onnx_model,
'OutputDir': 'my-hls-test',
'ProjectName': 'myproject',
'Backend': 'Vivado',
'HLSConfig': {
'Model': {
'Precision': 'ap_fixed<16,6>',
'ReuseFactor': 1
}
}
}
hls_model = hls4ml.converters.onnx_to_hls(config)
parse_onnx_model
Parse an ONNX model and extract its layers.
hls4ml.converters.parse_onnx_model(onnx_model)
Parameters
Returns
Returns (layer_list, input_layers, output_layers) where:
layer_list: List of layer dictionaries
input_layers: List of input layer names
output_layers: List of output layer names
Example
import onnx
import hls4ml
onnx_model = onnx.load('model.onnx')
layer_list, inputs, outputs = hls4ml.converters.parse_onnx_model(onnx_model)
print(f"Input layers: {inputs}")
print(f"Output layers: {outputs}")
for layer in layer_list:
print(f"{layer['name']}: {layer['class_name']}")
Helper Functions
get_onnx_attribute
Extract an attribute from an ONNX operation node.
hls4ml.converters.onnx_to_hls.get_onnx_attribute(
operation,
name,
default=None
)
Name of the attribute to retrieve.
Default value if attribute not found.
Get the input shapes of a node.
hls4ml.converters.onnx_to_hls.get_input_shape(graph, node)
ONNX graph containing the node.
ONNX node to get input shapes for.
List of input shapes (as lists) for all inputs to the node.
get_constant_value
Retrieve the value of a constant tensor.
hls4ml.converters.onnx_to_hls.get_constant_value(graph, constant_name)
ONNX graph containing the constant.
Name of the constant tensor.
The constant value as a NumPy array.
Exporting ONNX from Frameworks
From PyTorch
import torch
import torch.onnx
# PyTorch model
model = MyPyTorchModel()
model.eval()
# Dummy input
dummy_input = torch.randn(1, 3, 224, 224)
# Export to ONNX
torch.onnx.export(
model,
dummy_input,
'model.onnx',
export_params=True,
opset_version=11,
input_names=['input'],
output_names=['output'],
dynamic_axes={
'input': {0: 'batch_size'},
'output': {0: 'batch_size'}
}
)
# Convert to hls4ml
import hls4ml
hls_model = hls4ml.converters.convert_from_onnx_model(
'model.onnx',
output_dir='onnx_prj'
)
From TensorFlow
import tensorflow as tf
import tf2onnx
# TensorFlow model
model = tf.keras.models.load_model('model.h5')
# Convert to ONNX
spec = (tf.TensorSpec((None, 224, 224, 3), tf.float32, name='input'),)
onnx_model, _ = tf2onnx.convert.from_keras(
model,
input_signature=spec,
opset=13
)
# Save ONNX model
import onnx
onnx.save(onnx_model, 'model.onnx')
# Convert to hls4ml
import hls4ml
hls_model = hls4ml.converters.convert_from_onnx_model(
'model.onnx',
output_dir='onnx_prj'
)
Supported Operations
ONNX converter supports:
Basic Operations
Gemm - General matrix multiplication (fully connected)
MatMul - Matrix multiplication
Add, Sub, Mul, Div - Element-wise arithmetic
Neg, Abs, Sqrt - Unary operations
Activation Functions
Relu, LeakyRelu, Elu, PRelu
Sigmoid, Tanh
Softmax, Softplus, Softsign
HardSigmoid, HardSwish
Convolutional Operations
Conv - Convolution (1D, 2D)
MaxPool, AveragePool - Pooling
GlobalAveragePool, GlobalMaxPool
Normalization
BatchNormalization
LayerNormalization
InstanceNormalization
Structural
Reshape, Flatten, Squeeze, Unsqueeze
Transpose, Concat, Split
Slice, Gather
Pad
Reduction Operations
ReduceSum, ReduceMean, ReduceMax, ReduceMin
Other
Clip - Clipping values
Cast - Type casting
Constant - Constant values
Identity (skipped)
Dropout (skipped)
Advanced Configuration
import onnx
import hls4ml
# Load and inspect ONNX model
onnx_model = onnx.load('complex_model.onnx')
# Create detailed configuration
hls_config = {
'Model': {
'Precision': 'ap_fixed<16,6>',
'ReuseFactor': 1,
'Strategy': 'Latency'
},
'LayerName': {}
}
# Get layer information
layer_list, _, _ = hls4ml.converters.parse_onnx_model(onnx_model)
# Configure each layer
for layer in layer_list:
layer_name = layer['name']
layer_type = layer['class_name']
if layer_type in ['Dense', 'Conv1D', 'Conv2D']:
hls_config['LayerName'][layer_name] = {
'Precision': {'weight': 'ap_fixed<8,4>', 'bias': 'ap_fixed<8,4>'},
'ReuseFactor': 4
}
elif layer_type == 'Activation':
hls_config['LayerName'][layer_name] = {
'Precision': 'ap_fixed<16,6>',
'table_size': 1024
}
# Convert with custom config
hls_model = hls4ml.converters.convert_from_onnx_model(
onnx_model,
output_dir='custom_onnx_prj',
backend='Vivado',
hls_config=hls_config
)
Padding Computation
ONNX auto-padding is automatically handled:
def compute_pads_2d(operation, layer):
"""Compute padding for 2D operations."""
auto_pad = get_onnx_attribute(operation, 'auto_pad', 'NOTSET')
if auto_pad != 'NOTSET':
# Compute padding based on input/output sizes
if auto_pad == 'SAME_UPPER':
# Padding applied more to bottom/right
pass
elif auto_pad == 'SAME_LOWER':
# Padding applied more to top/left
pass
else: # 'VALID'
pads = [0, 0, 0, 0]
else:
# Use explicit pads attribute
pads = get_onnx_attribute(operation, 'pads', [0, 0, 0, 0])
return pads
Debugging
Inspect ONNX Model
import onnx
from onnx import helper
model = onnx.load('model.onnx')
print("Model inputs:")
for inp in model.graph.input:
print(f" {inp.name}: {[d.dim_value for d in inp.type.tensor_type.shape.dim]}")
print("\nModel outputs:")
for out in model.graph.output:
print(f" {out.name}: {[d.dim_value for d in out.type.tensor_type.shape.dim]}")
print("\nOperations:")
for node in model.graph.node:
print(f" {node.name} ({node.op_type}): {node.input} -> {node.output}")
Verify Conversion
import onnx
import onnxruntime as ort
import numpy as np
import hls4ml
# Load ONNX
onnx_model = onnx.load('model.onnx')
# Run with ONNX Runtime
sess = ort.InferenceSession('model.onnx')
input_name = sess.get_inputs()[0].name
test_input = np.random.rand(1, 10).astype(np.float32)
onnx_output = sess.run(None, {input_name: test_input})[0]
# Convert and run with hls4ml
hls_model = hls4ml.converters.convert_from_onnx_model(
onnx_model,
output_dir='verify_prj'
)
hls_model.compile()
hls_output = hls_model.predict(test_input[0])
# Compare
diff = np.abs(onnx_output[0] - hls_output)
print(f"Max difference: {np.max(diff)}")
print(f"Mean difference: {np.mean(diff)}")
Limitations
- First dimension must be batch dimension
- Dynamic shapes not supported
- Some ONNX operators may not be implemented
- Control flow operations (If, Loop) not supported
See Also