ModelGraph
The ModelGraph class represents the network being processed by hls4ml. It manages layers as nodes in a directed graph and provides methods for compilation, prediction, and synthesis.
class ModelGraph:
def __init__(self, config, inputs=None, outputs=None, initial_index=0)
Parameters
Configuration object containing backend and conversion settings.
List of input variable names. If None, determined automatically.
List of output variable names. If None, determined automatically.
Starting index for layer numbering.
Attributes
Dictionary mapping layer names to Layer objects.
List of input layer names.
List of output layer names.
Dictionary mapping output names to Variable objects.
Creating ModelGraph
from_layer_list
Create a ModelGraph from a list of layer dictionaries.
@classmethod
ModelGraph.from_layer_list(
config_dict,
layer_list,
inputs=None,
outputs=None,
initial_index=0
)
Configuration dictionary.
List of layer dictionaries with ‘name’ and ‘class_name’ keys.
The constructed ModelGraph instance.
Example
import hls4ml
layer_list = [
{'name': 'input', 'class_name': 'InputLayer', 'input_shape': [10]},
{'name': 'dense1', 'class_name': 'Dense', 'n_in': 10, 'n_out': 64},
{'name': 'relu1', 'class_name': 'Activation', 'activation': 'relu'},
{'name': 'output', 'class_name': 'Dense', 'n_in': 64, 'n_out': 1}
]
config = hls4ml.utils.config.create_config(
output_dir='my-hls-test',
project_name='myproject'
)
model = hls4ml.model.ModelGraph.from_layer_list(
config,
layer_list,
inputs=['input'],
outputs=['output']
)
Core Methods
write
Write the generated C++ project to disk.
Generates HLS C++ code and writes to the output directory specified in config.
compile
Compile the generated project for simulation.
Writes the project to disk and compiles it into a shared library that can be used for predict().
Example
import hls4ml
import numpy as np
# Convert model
hls_model = hls4ml.converters.convert_from_keras_model(
keras_model,
output_dir='my-hls-test'
)
# Compile
hls_model.compile()
# Test
X_test = np.random.rand(100, 10)
y_pred = hls_model.predict(X_test)
predict
Run inference on the compiled model.
model.predict(x, *args, **kwargs)
x
numpy.ndarray | list
required
Input data. For single input models, provide a numpy array. For multi-input models, provide a list of arrays.
Model predictions. Single array for single output, list of arrays for multiple outputs.
Example
import numpy as np
# Single input/output
X = np.random.rand(10, 784).astype(np.float32)
y_pred = hls_model.predict(X)
# Multiple inputs
X1 = np.random.rand(10, 32).astype(np.float32)
X2 = np.random.rand(10, 16).astype(np.float32)
y_pred = hls_model.predict([X1, X2])
# Multiple outputs
y_pred1, y_pred2 = hls_model.predict(X)
build
Synthesize the design with HLS tools.
model.build(
reset=False,
csim=True,
synth=True,
cosim=False,
validation=False,
export=False,
vsynth=False
)
Reset/clean the project before building.
Run Vivado synthesis (place and route).
Synthesis report with resource usage and timing information.
Example
import hls4ml
# Convert model
hls_model = hls4ml.converters.convert_from_keras_model(
keras_model,
output_dir='my-hls-test'
)
# Run synthesis
report = hls_model.build(
csim=True,
synth=True,
cosim=True,
export=True
)
print(f"Latency: {report['LatencyBest']} - {report['LatencyWorst']} cycles")
print(f"Interval: {report['IntervalMin']} - {report['IntervalMax']} cycles")
print(f"LUTs: {report['LUT']}")
print(f"FFs: {report['FF']}")
print(f"DSPs: {report['DSP']}")
print(f"BRAMs: {report['BRAM_18K']}")
trace
Run inference with layer-by-layer tracing.
Returns (predictions, trace_output) where trace_output is a dict mapping layer names to their outputs.
Example
import numpy as np
X_test = np.random.rand(5, 10).astype(np.float32)
predictions, trace = hls_model.trace(X_test)
# Inspect layer outputs
for layer_name, output in trace.items():
print(f"{layer_name}: shape={output.shape}, mean={np.mean(output):.4f}")
Graph Manipulation
make_node
Create a new node (layer) for the graph.
model.make_node(
kind,
name,
attributes,
inputs,
outputs=None,
initialize=True
)
Layer type (class name or class).
Unique name for the layer.
Layer attributes and configuration.
List of input variable names.
List of output variable names. Defaults to [name].
Call the layer’s initialize() method.
Example
# Create a Dense layer node
node = model.make_node(
kind='Dense',
name='new_dense',
attributes={
'n_in': 64,
'n_out': 32,
'weight_data': weights,
'bias_data': bias
},
inputs=['prev_layer'],
outputs=['new_dense']
)
insert_node
Insert a node into the graph.
model.insert_node(node, before=None, input_idx=0)
Node to insert (created with make_node).
Insert before this node. If None, inserts after the node’s input.
Input index for multi-input nodes.
remove_node
Remove a node from the graph.
Automatically connects the previous node to the next node.
replace_node
Replace a node with another.
model.replace_node(old_node, new_node)
Example: Adding Quantization
# Get a layer
dense_layer = model.graph['dense_1']
# Create quantization node
quant_attrs = {
'n_in': dense_layer.get_attr('n_out'),
'precision': 'ap_fixed<8,4>'
}
quant_node = model.make_node(
kind='ApplyAlpha',
name='quant_dense_1',
attributes=quant_attrs,
inputs=dense_layer.outputs,
outputs=['quant_dense_1']
)
# Insert after dense layer
model.insert_node(quant_node)
Layer Access
get_layers
Get all layers in the model.
View of all Layer objects in the graph.
Example
for layer in model.get_layers():
print(f"{layer.name}: {layer.class_name}")
if hasattr(layer, 'weights'):
for weight in layer.get_weights():
print(f" {weight.name}: {weight.shape}")
Get input variables of the model.
model.get_input_variables()
List of input Variable objects.
get_output_variables
Get output variables of the model.
model.get_output_variables()
List of output Variable objects.
get_weight_variables
Get all weight variables in the model.
model.get_weight_variables()
List of all weight Variable objects.
Example
# Print input/output info
for var in model.get_input_variables():
print(f"Input: {var.name}, shape: {var.shape}, type: {var.type.precision}")
for var in model.get_output_variables():
print(f"Output: {var.name}, shape: {var.shape}, type: {var.type.precision}")
# Count total parameters
total_params = sum(var.data_length for var in model.get_weight_variables())
print(f"Total parameters: {total_params}")
Optimization
apply_flow
Apply an optimization flow (collection of optimizer passes).
model.apply_flow(flow, reapply='single')
Name of the flow to apply.
Reapplication strategy:
'all': Reapply flow and all requirements
'single': Apply flow, skip applied requirements
'none': Skip if already applied
Example
import hls4ml
# Get model
hls_model = hls4ml.converters.convert_from_keras_model(keras_model)
# Apply optimization flow
hls_model.apply_flow('vivado:optimize')
# Apply custom optimization
hls_model.apply_flow('quantization')
Serialization
save
Save the ModelGraph to a file.
Path to save the model (.fml format).
Example
# Save model
hls_model.save('my_model.fml')
# Load model
import hls4ml
loaded_model = hls4ml.converters.load_saved_model('my_model.fml')
# Use loaded model
loaded_model.compile()
predictions = loaded_model.predict(test_data)
HLSConfig
Configuration object managing model settings.
class HLSConfig:
def __init__(self, config)
Methods
get_precision
Get precision for a layer and variable.
config.get_precision(layer, var='default')
Returns (precision, type_name) tuple.
get_reuse_factor
Get reuse factor for a layer.
config.get_reuse_factor(layer)
get_strategy
Get implementation strategy for a layer.
config.get_strategy(layer)
Strategy: 'latency' or 'resource'.
Example
for layer in model.get_layers():
rf = model.config.get_reuse_factor(layer)
strategy = model.config.get_strategy(layer)
precision, type_name = model.config.get_precision(layer)
print(f"{layer.name}:")
print(f" ReuseFactor: {rf}")
print(f" Strategy: {strategy}")
print(f" Precision: {precision}")
See Also