-
Notifications
You must be signed in to change notification settings - Fork 384
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #509 from nicologhielmetti/fifo_depth_merge
FIFO depth optimization
- Loading branch information
Showing
10 changed files
with
329 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import json | ||
|
||
from pyDigitalWaveTools.vcd.parser import VcdParser | ||
|
||
from hls4ml.model.optimizer.optimizer import ConfigurableOptimizerPass, ModelOptimizerPass | ||
|
||
|
||
def populate_values(values, name, data, depth): | ||
values.append({'name': name, 'data': [], 'max': 0, 'depth': 0}) | ||
get_values = lambda x: int(x[1][1:], 2) | ||
values[-1]['data'] = [get_values(x) for x in data] | ||
values[-1]['max'] = max(values[-1]['data']) | ||
values[-1]['depth'] = int(depth[0][1][1:], 2) | ||
return values | ||
|
||
|
||
def set_big_fifos(vars_to_profile, profiling_fifo_depth): | ||
for k, v in vars_to_profile.items(): | ||
v.pragma = (v.pragma[0], profiling_fifo_depth) | ||
|
||
|
||
def get_vcd_data(model): | ||
model.write() | ||
model.build(reset=False, csim=True, synth=True, cosim=True, validation=False, export=False, vsynth=False, | ||
fifo_opt=True) | ||
|
||
with open( | ||
model.config.get_output_dir() + '/' + model.config.get_project_name() + '_prj' + '/solution1/sim/verilog/fifo_opt.vcd') as vcd_file: | ||
vcd = VcdParser() | ||
vcd.parse(vcd_file) | ||
data = vcd.scope.toJson() | ||
return data | ||
|
||
|
||
def generate_max_depth_file(model, maxs): | ||
with open(model.config.get_output_dir() + '/max_depth.json', 'w') as f: | ||
json.dump(maxs, f, indent=4) | ||
|
||
|
||
def set_fifo_depth(model, maxs): | ||
for k, v in model.output_vars.items(): | ||
filtered_max = [x['max'] for x in maxs if v.name in x['name']] | ||
if len(filtered_max) == 0: | ||
continue | ||
if len(filtered_max) > 1: | ||
print('WARNING! Check names of FIFOs') | ||
v.pragma = (v.pragma[0], filtered_max[0] + 1) | ||
|
||
|
||
class FifoDepthOptimization(ConfigurableOptimizerPass, ModelOptimizerPass): | ||
def __init__(self): | ||
self.values = [] | ||
|
||
def transform(self, model): | ||
# use `large_fifo_depth = 0` to keep the default fifo depth | ||
profiling_fifo_depth = getattr(self, 'profiling_fifo_depth', 100_000) | ||
|
||
# check axi-stream or io-stream, if not one the 2 exit | ||
if not (model.config.get_config_value('IOType') == 'io_stream'): | ||
raise Exception('To use this optimization you have to set `IOType` field to `io_stream` in the HLS config') | ||
|
||
# initialize all the fifos to `profiling_fifo_depth` so that they will be automatically implemented in BRAMs | ||
# and so they will be profiled | ||
if profiling_fifo_depth: | ||
vars_to_profile = {k: v for k, v in model.output_vars.items() if v != model.get_output_variables()[0] and | ||
v != model.get_input_variables()[0]} | ||
|
||
set_big_fifos(vars_to_profile, profiling_fifo_depth) | ||
|
||
data = get_vcd_data(model) | ||
|
||
if len(data['children']) == 0: | ||
print("FIFO depth optimization found no FIFOs implemented using BRAMs in the design, no optimization is possible. Consider increasing profiling_fifo_depth.") | ||
return False | ||
|
||
n_elem = len(data['children'][0]['children'][0]['children']) | ||
for i in range(n_elem): | ||
name = data['children'][0]['children'][0]['children'][i]['name'] | ||
data_p = data['children'][0]['children'][0]['children'][i]['children'][0]['data'] | ||
depth = data['children'][0]['children'][0]['children'][i]['children'][1]['data'] | ||
populate_values(self.values, name, data_p, depth) | ||
|
||
maxs = [{'name': i['name'], 'max': i['max'], 'depth': i['depth']} for i in self.values] | ||
|
||
generate_max_depth_file(model, maxs) | ||
|
||
set_fifo_depth(model, maxs) | ||
|
||
print('[hls4ml] - FIFO optimization completed') | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
58 changes: 58 additions & 0 deletions
58
hls4ml/backends/vivado_accelerator/passes/fifo_depth_optimization.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
from hls4ml.backends.vivado.passes.fifo_depth_optimization import set_big_fifos, get_vcd_data, populate_values, \ | ||
generate_max_depth_file, set_fifo_depth | ||
from hls4ml.model.optimizer.optimizer import ConfigurableOptimizerPass, ModelOptimizerPass | ||
|
||
|
||
class FifoDepthOptimization(ConfigurableOptimizerPass, ModelOptimizerPass): | ||
def __init__(self): | ||
self.values = [] | ||
|
||
def transform(self, model): | ||
# use `large_fifo_depth = 0` to keep the default fifo depth | ||
profiling_fifo_depth = getattr(self, 'profiling_fifo_depth', 100_000) | ||
|
||
# check axi-stream or io-stream, if not one the 2 exit | ||
if not(model.config.get_config_value('IOType') == 'io_stream' or | ||
model.config.get_config_value('AcceleratorConfig')['Interface'] == 'axi_stream' or | ||
model.config.get_config_value('AcceleratorConfig')['Interface'] == 'axi_master'): | ||
raise Exception('To use this optimization you have to set `IOType` field to `io_stream` in the HLS config ' | ||
'or `axi_stream` or `axi_master` in `AcceleratorConfig` interface field') | ||
|
||
# initialize all the fifos to 10000 so that they will be automatically implemented in BRAMs and so they will be | ||
# profiled | ||
|
||
if profiling_fifo_depth: | ||
set_big_fifos(model.output_vars, profiling_fifo_depth) | ||
|
||
data = get_vcd_data(model) | ||
|
||
for i in range(1, len(data['children'][0]['children'][0]['children'])): | ||
# wrapper fifos | ||
populate_values(self.values, | ||
data['children'][0]['children'][0]['children'][i]['name'], | ||
data['children'][0]['children'][0]['children'][i]['children'][0]['data'], | ||
data['children'][0]['children'][0]['children'][i]['children'][1]['data']) | ||
|
||
n_elem = len(data['children'][0]['children'][0]['children'][0]['children']) | ||
for i in range(n_elem): | ||
name = data['children'][0]['children'][0]['children'][0]['children'][i]['name'] | ||
data_p = data['children'][0]['children'][0]['children'][0]['children'][i]['children'][0]['data'] | ||
depth = data['children'][0]['children'][0]['children'][0]['children'][i]['children'][1]['data'] | ||
populate_values(self.values, name, data_p, depth) | ||
|
||
maxs = [{'name': i['name'], 'max': i['max'], 'depth': i['depth']} for i in self.values] | ||
|
||
generate_max_depth_file(model, maxs) | ||
|
||
set_fifo_depth(model, maxs) | ||
|
||
inp = model.get_input_variables()[0] | ||
out = model.get_output_variables()[0] | ||
for x in maxs: | ||
if 'in_local' in x['name']: | ||
inp.pragma = (inp.pragma[0], x['max'] + 1) | ||
elif 'out_local' in x['name']: | ||
out.pragma = (out.pragma[0], x['max'] + 1) | ||
|
||
print('[hls4ml] - FIFO optimization completed') | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.