Skip to content

Commit

Permalink
Merge pull request #230 from thesps/bestof_220
Browse files Browse the repository at this point in the history
Best of PR #220
  • Loading branch information
thesps authored Oct 30, 2020
2 parents 06d569f + 37c20fe commit 521deb1
Show file tree
Hide file tree
Showing 11 changed files with 53 additions and 16 deletions.
3 changes: 3 additions & 0 deletions hls4ml/converters/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,8 @@ def convert_from_keras_model(model, output_dir='my-hls-test', project_name='mypr

if 'Optimizers' in hls_config:
config['HLSConfig']['Optimizers'] = hls_config['Optimizers']

if 'SkipOptimizers' in hls_config:
config['HLSConfig']['SkipOptimizers'] = hls_config['SkipOptimizers']

return keras_to_hls(config)
1 change: 1 addition & 0 deletions hls4ml/model/hls_layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,7 @@ def _get_transforms_config(self, params):
params['sublayer_configs'] = '\n'.join(sublayer_configs)

layer_map = {
'Input' : Input,
'InputLayer' : Input,
'Activation' : Activation,
'QActivation' : Activation,
Expand Down
25 changes: 23 additions & 2 deletions hls4ml/model/hls_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from hls4ml.model.hls_layers import *
from hls4ml.templates import get_backend
from hls4ml.writer import get_writer
from hls4ml.model.optimizer import optimize_model
from hls4ml.model.optimizer import optimize_model, get_available_passes

class HLSConfig(object):
def __init__(self, config):
Expand Down Expand Up @@ -143,7 +143,20 @@ def get_compression(self, layer):

def _parse_hls_config(self):
hls_config = self.config['HLSConfig']

self.optimizers = hls_config.get('Optimizers')
if 'SkipOptimizers' in hls_config:
if self.optimizers is not None:
raise Exception('Invalid optimizer configuration, please use either "Optimizers" or "SkipOptimizers".')
skip_optimizers = hls_config.get('SkipOptimizers')
selected_optimizers = get_available_passes()
for opt in skip_optimizers:
try:
selected_optimizers.remove(opt)
except ValueError:
pass
self.optimizers = selected_optimizers

model_cfg = hls_config.get('Model')
if model_cfg is not None:
precision_cfg = model_cfg.get('Precision')
Expand Down Expand Up @@ -355,6 +368,14 @@ def get_layer_output_variable(self, output_name):
return self.output_vars[output_name]

def write(self):
def make_stamp():
from string import hexdigits
from random import choice
length = 8
return ''.join(choice(hexdigits) for m in range(length))

self.config.config['Stamp'] = make_stamp()

self.config.writer.write_hls(self)

def compile(self):
Expand All @@ -367,7 +388,7 @@ def compile(self):
ret_val = os.system('bash build_lib.sh')
if ret_val != 0:
raise Exception('Failed to compile project "{}"'.format(self.config.get_project_name()))
lib_name = 'firmware/{}.so'.format(self.config.get_project_name())
lib_name = 'firmware/{}-{}.so'.format(self.config.get_project_name(), self.config.get_config_value('Stamp'))
if self._top_function_lib is not None:

if platform.system() == "Linux":
Expand Down
2 changes: 1 addition & 1 deletion hls4ml/model/optimizer/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import absolute_import

from hls4ml.model.optimizer.optimizer import OptimizerPass, register_pass, get_optimizer, optimize_model
from hls4ml.model.optimizer.optimizer import OptimizerPass, register_pass, get_optimizer, optimize_model, get_available_passes


from hls4ml.model.optimizer.passes.nop import EliminateLinearActivation
Expand Down
3 changes: 3 additions & 0 deletions hls4ml/model/optimizer/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ def register_pass(name, opt_cls):
def get_optimizer(name):
return optimizer_map[name]()

def get_available_passes():
return list(optimizer_map.keys())

def optimize_model(model, passes=None):
if passes is None:
passes = optimizer_map.keys()
Expand Down
3 changes: 2 additions & 1 deletion hls4ml/templates/vivado/build_lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ fi
LDFLAGS=
INCFLAGS="-Ifirmware/ap_types/"
PROJECT=myproject
LIB_STAMP=mystamp

${CC} ${CFLAGS} ${INCFLAGS} -c firmware/${PROJECT}.cpp -o ${PROJECT}.o
${CC} ${CFLAGS} ${INCFLAGS} -c ${PROJECT}_bridge.cpp -o ${PROJECT}_bridge.o
${CC} ${CFLAGS} ${INCFLAGS} -shared ${PROJECT}.o ${PROJECT}_bridge.o -o firmware/${PROJECT}.so
${CC} ${CFLAGS} ${INCFLAGS} -shared ${PROJECT}.o ${PROJECT}_bridge.o -o firmware/${PROJECT}-${LIB_STAMP}.so
rm -f *.o
2 changes: 2 additions & 0 deletions hls4ml/templates/vivado/build_prj.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ if {$opt(cosim)} {
set time_start [clock clicks -milliseconds]
cosim_design -trace_level all
set time_end [clock clicks -milliseconds]
puts "INFO:"
puts [read [open myproject_prj/solution1/sim/report/myproject_cosim.rpt r]]
report_time "C/RTL SIMULATION" $time_start $time_end
}

Expand Down
2 changes: 1 addition & 1 deletion hls4ml/templates/vivado/myproject_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ int main(int argc, char **argv)
if (fin.is_open() && fpr.is_open()) {
while ( std::getline(fin,iline) && std::getline (fpr,pline) ) {
if (e % CHECKPOINT == 0) std::cout << "Processing input " << e << std::endl;
e++;
char* cstr=const_cast<char*>(iline.c_str());
char* current;
std::vector<float> in;
Expand Down Expand Up @@ -85,6 +84,7 @@ int main(int argc, char **argv)
std::cout << "Quantized predictions" << std::endl;
//hls-fpga-machine-learning insert quantized
}
e++;
}
fin.close();
fpr.close();
Expand Down
23 changes: 15 additions & 8 deletions hls4ml/utils/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,12 @@ def config_from_keras_model(model, granularity='model', default_precision='ap_fi
keras_layer_config = model_arch['config']
if 'layers' in keras_layer_config: # Newer Keras versions have 'layers' in 'config' key
keras_layer_config = keras_layer_config['layers']
# Sequential doesn't have InputLayer
input_layer = {}
input_layer['name'] = 'input1'
input_layer['class_name'] = 'InputLayer'
layer_list.append(input_layer)
# Sequential doesn't have InputLayer in TF < 2.3 (Keras 2.4.0)
if keras_layer_config[0]['class_name'] != 'InputLayer':
input_layer = {}
input_layer['name'] = 'input1'
input_layer['class_name'] = 'Input'
layer_list.append(input_layer)
elif model_arch['class_name'] in ['Model', 'Functional']:
print('Interpreting Model')
keras_layer_config = model_arch['config']['layers']
Expand All @@ -108,6 +109,9 @@ def config_from_keras_model(model, granularity='model', default_precision='ap_fi
layer['class_name'] = keras_layer['class_name']
layer['config'] = keras_layer['config']

if layer['class_name'] == 'InputLayer':
layer['class_name'] = 'Input'

if layer['class_name'] in qkeras_layers:
layer['precision'] = {}
for qname, qclass in layer['config'].items():
Expand Down Expand Up @@ -169,6 +173,11 @@ def make_layer_config(layer):
print('WARNING: Found no precision information in QKeras layer {} ({})'.format(layer['name'], layer['class_name']))
layer_config['Precision'] = default_precision
layer_config['ReuseFactor'] = default_reuse_factor

elif layer['class_name'] == 'Input':
layer_config['Precision'] = {}
layer_config['Precision']['result'] = default_precision

else:
layer_config['Precision'] = default_precision

Expand All @@ -189,7 +198,7 @@ def make_layer_config(layer):
elif granularity.lower() == 'type':
type_config = {}
for layer in layer_list:
if layer['class_name'] in type_config or layer['class_name'] == 'InputLayer':
if layer['class_name'] in type_config:
continue
layer_config = make_layer_config(layer)
type_config[layer['class_name']] = layer_config
Expand All @@ -199,8 +208,6 @@ def make_layer_config(layer):
elif granularity.lower() == 'name':
name_config = {}
for layer in layer_list:
if layer['class_name'] == 'InputLayer': # Skip INputLayer
continue
layer_config = make_layer_config(layer)
name_config[layer['name']] = layer_config

Expand Down
1 change: 1 addition & 0 deletions hls4ml/writer/vivado_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ def write_build_script(self, model):

for line in f.readlines():
line = line.replace('myproject', model.config.get_project_name())
line = line.replace('mystamp', model.config.get_config_value('Stamp'))

fout.write(line)
f.close()
Expand Down
4 changes: 1 addition & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
long_description = f.read()

setup(name='hls4ml',
version='0.3.0',
version='0.4.0',
description='Machine learning in FPGAs using HLS',
long_description=long_description,
long_description_content_type='text/markdown',
Expand Down Expand Up @@ -36,8 +36,6 @@
'Intended Audience :: Science/Research',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: C++',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Topic :: Software Development :: Libraries',
Expand Down

0 comments on commit 521deb1

Please sign in to comment.