Skip to content

Commit

Permalink
Merge pull request #11 from dgburnette/sigmoid_branch
Browse files Browse the repository at this point in the history
Sigmoid branch
  • Loading branch information
BLMartin99 authored Jul 6, 2023
2 parents 2a96acd + ef2aaa6 commit 19ca16b
Show file tree
Hide file tree
Showing 14 changed files with 453 additions and 3 deletions.
9 changes: 9 additions & 0 deletions example-prjs/sigmoid/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
This is small conv2d 1 layer applying a sigmoid activation function example. To run it:
1. Run the run_catapult.sh script.
2. Remove "#define USE_AC_MATH" in nnet_activation.h.
3. Replace the sigmoid_test.cpp in the my-Catapult-test with the sigmoid_test.cpp a level up (if you would like the testbench to be self-checking).
4. Move tb_input_features.dat and tb_output_predictions.dat to my-Catapult-test/tb_data (if you want two pre-computed examples).
5. Compile:
/wv/hlsb/CATAPULT/TOT/CURRENT/aol/Mgc_home/bin/g++ -g -std=c++11 -DSC_INCLUDE_DYNAMIC_PROCESSES -Wl,-rpath=/wv/hlsb/CATAPULT/TOT/CURRENT/aol/Mgc_home/lib,-rpath=/wv/hlsb/CATAPULT/TOT/CURRENT/aol/Mgc_home/shared/lib ./sigmoid_test.cpp ./firmware/sigmoid.cpp -I/wv/USER/venv/hls4ml/example-prjs/sigmoid/my-Catapult-test -I/wv/hlsb/CATAPULT/TOT/CURRENT/aol/Mgc_home/shared/include -L/wv/hlsb/CATAPULT/TOT/CURRENT/aol/Mgc_home/shared/lib -Wl,-Bstatic -lsystemc -Wl,-Bdynamic -lpthread -o /wv/USER/venv/hls4ml/example-prjs/sigmoid/my-Catapult-test/sigmoid

Note: You can create your own array and get the predictions by editing then running sigmoid.py.
43 changes: 43 additions & 0 deletions example-prjs/sigmoid/catapult.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

import hls4ml
# import pprint
import yaml
import numpy as np

print(hls4ml.__version__)

with open('config.yml', 'r') as ymlfile:
config = yaml.safe_load(ymlfile)

# try tweaking the reuse_factor on one layer to get different pipelining
# config['HLSConfig']['LayerName']['fc1']['ReuseFactor'] = 4

print('NETWORK')
print(config)

config['OutputDir'] = 'my-Catapult-test'
config['Backend'] = 'Catapult'
config['IOType'] = 'io_stream'

config['HLSConfig']['Model']['Strategy'] = 'Latency'
#config['HLSConfig']['Model']['Strategy'] = 'Resource'

# default threshold is infinity
config['HLSConfig']['Model']['BramFactor'] = np.inf
# set to zero to force all weights onto (external function) interface
config['HLSConfig']['Model']['BramFactor'] = 0

print('CURRENT CONFIGURATION')
print('Backend='+config['Backend'])
print('IOType='+config['IOType'])
print('BramFactor={bf}'.format(bf=config['HLSConfig']['Model']['BramFactor']))

# pprint.pprint(config)

#Convert it to a hls project
hls_model = hls4ml.converters.keras_to_hls(config)

hls_model.build(vsynth=False)

# URL for this info: https://fastmachinelearning.org/hls4ml/setup/QUICKSTART.html

15 changes: 15 additions & 0 deletions example-prjs/sigmoid/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Backend: Vivado
KerasJson: sigmoid.json
KerasH5: sigmoid_weights.h5
OutputDir: my-Catapult-test
ProjectName: sigmoid
XilinxPart: xcku115-flvb2104-2-i
Part: xcku115-flvb2104-2-i
ClockPeriod: 5

IOType : io_parallel
HLSConfig:
Model:
Precision: ap_fixed<16, 6>
ReuseFactor: 1
Strategy: Latency
44 changes: 44 additions & 0 deletions example-prjs/sigmoid/run_catapult.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#! /bin/bash

# This script runs the Catapult flows to generate the HLS.

VENV=../../../../venv

MGC_HOME=/wv/hlsb/CATAPULT/TOT/CURRENT/aol/Mgc_home
export MGC_HOME

export PATH=/wv/hlstools/python/python37/bin:$PATH:$XILINX_VIVADO/bin:$MGC_HOME/bin
export LD_LIBRARY_PATH=/wv/hlstools/python/python37/lib:$XILINX_VIVADO/lib/lnx64.o:$MGC_HOME/lib
export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python

# needed for pytest
export OSTYPE=linux-gnu

echo "Activating Virtual Environment..."
# bash
source $VENV/bin/activate

rm -rf ./my-Catapult-test*

# to run catapult+vivado_rtl
sed -e 's/Vivado/Catapult/g' vivado.py >catapult.py
# to only run catapult
# sed -e 's/Vivado/Catapult/g' vivado.py | sed -e 's/vsynth=True/vsynth=False/g' >catapult.py

# actually run HLS4ML + Catapult (+ optional vivado RTL)
python3 catapult.py

# run just the C++ execution
echo ""
echo "====================================================="
echo "====================================================="
echo "C++ EXECUTION"
pushd my-Catapult-test; rm -f a.out; $MGC_HOME/bin/g++ -std=c++17 -I. -DWEIGHTS_DIR=\"firmware/weights\" -Ifirmware -I$MGC_HOME/shared/include firmware/sigmoid.cpp sigmoid_test.cpp; a.out; popd

# Using VSCode setup generated by Catapult
echo ""
echo "====================================================="
echo "====================================================="
echo "To launch VSCode on the C++ generated by hls4ml:"
echo "setenv LD_LIBRARY_PATH $MGC_HOME/lib:$MGC_HOME/shared/lib"
echo "pushd my-Catapult-test; /wv/hlstools/vscode/LATEST/code Catapult.code-workspace"
39 changes: 39 additions & 0 deletions example-prjs/sigmoid/run_vivado.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#! /bin/bash

# This script runs the Vivado flows to generate the HLS.

VENV=/wv/scratch-baimar9c/venv

MGC_HOME=/wv/hlsb/CATAPULT/TOT/CURRENT/aol/Mgc_home
export MGC_HOME

export PATH=/wv/hlstools/python/python37/bin:$PATH:$XILINX_VIVADO/bin:$MGC_HOME/bin
export LD_LIBRARY_PATH=/wv/hlstools/python/python37/lib:$XILINX_VIVADO/lib/lnx64.o:$MGC_HOME/lib
export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python

# needed for pytest
export OSTYPE=linux-gnu

echo "Activating Virtual Environment..."
# bash
source $VENV/bin/activate

rm -rf ./my-Vivado-test*

mkdir -p tb_data

# to run catapult+vivado_rtl
sed -e 's/Vivado/Catapult/g' vivado.py >catapult.py
# to only run catapult
# sed -e 's/Vivado/Catapult/g' vivado.py | sed -e 's/vsynth=True/vsynth=False/g' >catapult.py

# actually run HLS4ML + Vivado HLS
python vivado.py

# run just the C++ execution
echo ""
echo "====================================================="
echo "====================================================="
echo "C++ EXECUTION"
pushd my-Vivado-test; rm -f a.out; $MGC_HOME/bin/g++ -g -std=c++11 -I. -DWEIGHTS_DIR=\"firmware/weights\" -Ifirmware -Ifirmware/ap_types -I$MGC_HOME/shared/include firmware/sigmoid.cpp sigmoid_test.cpp; a.out; popd

Binary file added example-prjs/sigmoid/sigmoid.h5
Binary file not shown.
1 change: 1 addition & 0 deletions example-prjs/sigmoid/sigmoid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"class_name": "Sequential", "config": {"name": "sequential", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": [null, 5, 5, 1], "dtype": "float32", "sparse": false, "ragged": false, "name": "conv2d_input"}}, {"class_name": "Conv2D", "config": {"name": "conv2d", "trainable": true, "dtype": "float32", "batch_input_shape": [null, 5, 5, 1], "filters": 1, "kernel_size": [3, 3], "strides": [1, 1], "padding": "valid", "data_format": "channels_last", "dilation_rate": [1, 1], "groups": 1, "activation": "sigmoid", "use_bias": true, "kernel_initializer": "random_kernel", "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "keras_version": "2.11.0", "backend": "tensorflow"}
112 changes: 112 additions & 0 deletions example-prjs/sigmoid/sigmoid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import tensorflow as tf
import numpy as np

# Sources:
# https://www.geeksforgeeks.org/python-tensorflow-tf-keras-layers-conv2d-function/
# https://jiafulow.github.io/blog/2021/02/17/simple-fully-connected-nn-firmware-using-hls4ml/
# https://stackoverflow.com/questions/51930312/how-to-include-a-custom-filter-in-a-keras-based-cnn

# Create custom kernel
# NOTE: This kernel is random and purely for testing small examples
def random_kernel(shape=(3,3,1), dtype=None):

f = np.array([
[[[1]], [[-1]], [[1]]],
[[[-1]], [[1]], [[-1]]],
[[[1]], [[-1]], [[1]]]
])
assert f.shape == shape
return f

# Create model with one conv2d layer for small example
def create_model():
# Create a model
model = tf.keras.Sequential()

# First layer args.:
# filters: Number of output filters.
# kernel_size: Convolution window size width and height.
# strides: Stride of the convolution.
# padding: "same" adds padding if needed to ensure output dimensions are equal to input dimensions. "valid" means no padding.
# activation: Non-linear functions (i.e. relu).
# use_bias: Boolean or bias vectors.
# dilation_rate: Dilation rate for dilated convolutions.
# kernel_initializer: Default is glorot_uniform, meaning it initializes acrossed an uniform distribution.
# bias_initializer: Initializer for bias vectors.
# kernel_constraint: Constraint function for the kernel.
# bias_constraint: Constraint function for the bias vectors.

# NOTE: Input size indicates a 5x5 pixel image (matrix) with one channel (i.e. just the red channel from RGB).
# Image (matrix) size is equal to kernel size since this is a very small example.
model.add(tf.keras.layers.Conv2D(1, 3, 1, padding="valid", activation="sigmoid", kernel_initializer=random_kernel, input_shape=(5, 5, 1)))

return model

# Save model to forms for hls4ml
def save_model(model, name=None):
# Save as model.h5, model_weights.h5, and model.json
if name is None:
name = model.name
model.save(name + '.h5')
model.save_weights(name + '_weights.h5')
with open(name + '.json', 'w') as outfile:
outfile.write(model.to_json())
return

if __name__ == '__main__':
model = create_model()
save_model(model, name='sigmoid')

# Image Matrix
image_mat = np.array([
[ [1], [2], [3], [4], [5] ],
[ [6], [7], [8], [9], [10] ],
[ [11], [12], [13], [14], [15] ],
[ [16], [17], [18], [19], [20] ],
[ [21], [22], [23], [24], [25] ]
])

image_mat = image_mat.reshape((1, 5, 5, 1))

# Get prediction
prediction = model.predict(image_mat)
print("Image Matrix\n")
print(image_mat)
print("Prediction\n")
print(prediction)

image_mat2 = np.array([
[ [1], [2], [3], [4], [5] ],
[ [5], [1], [2], [3], [4] ],
[ [4], [5], [1], [2], [3] ],
[ [3], [4], [5], [1], [2] ],
[ [2], [3], [4], [5], [1] ]
])

image_mat2 = image_mat2.reshape((1, 5, 5, 1))

# Get prediction
prediction = model.predict(image_mat2)
print("Image Matrix\n")
print(image_mat2)
print("Prediction\n")
print(prediction)

image_mat3 = np.array([
[ [-1], [2], [-3], [4], [-5] ],
[ [5], [-1], [2], [-3], [4] ],
[ [-4], [5], [-1], [2], [-3] ],
[ [3], [-4], [5], [-1], [2] ],
[ [-2], [3], [-4], [5], [-1] ]
])

image_mat3 = image_mat3.reshape((1, 5, 5, 1))

# Get prediction
prediction = model.predict(image_mat3)
print("Image Matrix\n")
print(image_mat3)
print("Prediction\n")
print(prediction)


Loading

0 comments on commit 19ca16b

Please sign in to comment.