@@ -54,29 +54,32 @@ def _register_flows(self):
54
54
]
55
55
quantization_flow = register_flow ('quantization' , quantization_passes , requires = [init_flow ], backend = self .name )
56
56
57
+ optimization_passes = []
58
+ optimization_flow = register_flow ('optimize' , optimization_passes , requires = [init_flow ], backend = self .name )
59
+
57
60
templates = self ._get_layer_templates ()
58
- template_flow = register_flow ('apply_templates' , templates , requires = [init_flow ], backend = self .name )
61
+ template_flow = register_flow ('apply_templates' , self . _get_layer_templates , requires = [init_flow ], backend = self .name )
59
62
60
63
writer_passes = [
61
64
'make_stamp' ,
62
65
'quartus:write_hls'
63
66
]
64
- writer_flow_requirements = [ 'optimize' , quartus_types_flow , template_flow ]
65
- self ._writer_flow = register_flow ('write' , writer_passes , requires = writer_flow_requirements , backend = self .name )
67
+
68
+ self ._writer_flow = register_flow ('write' , writer_passes , requires = [ 'quartus:ip' ] , backend = self .name )
66
69
67
70
all_passes = get_backend_passes (self .name )
68
71
69
72
extras = [
70
73
# Ideally this should be empty
71
- opt_pass for opt_pass in all_passes if opt_pass not in initializers + quartus_types + templates + writer_passes
74
+ opt_pass for opt_pass in all_passes if opt_pass not in initializers + streaming_passes + quartus_types + quantization_passes + templates + optimization_passes + writer_passes
72
75
]
73
76
74
77
if len (extras ) > 0 :
75
78
extras_flow = register_flow ('extras' , extras , requires = [init_flow ], backend = self .name )
76
79
else :
77
80
extras_flow = None
78
81
79
- ip_flow_requirements = ['optimize' , init_flow , streaming_flow , quantization_flow , quartus_types_flow , extras_flow , template_flow ]
82
+ ip_flow_requirements = ['optimize' , init_flow , streaming_flow , quantization_flow , optimization_flow , quartus_types_flow , extras_flow , template_flow ]
80
83
ip_flow_requirements = list (filter (None , ip_flow_requirements ))
81
84
82
85
self ._default_flow = register_flow ('ip' , None , requires = ip_flow_requirements , backend = self .name )
@@ -97,35 +100,44 @@ def create_initial_config(self, part='Arria10', clock_period=5, io_type='io_para
97
100
98
101
return config
99
102
100
- def build (self , model , synth = True , fpgasynth = False ):
103
+ def build (self , model , synth = True , fpgasynth = False , log_level = 1 , cont_if_large_area = False ):
104
+
101
105
"""
102
106
Builds the project using Intel HLS compiler.
103
107
104
- Users should generally not call this function directly but instead use `ModelGraph.build()`.
105
- This function assumes the model was written with a call to `ModelGraph.write()`
106
-
107
108
Args:
108
109
model (ModelGraph): The model to build
109
- synth, optional: Whether to run synthesis
110
- fpgasynth, optional: Whether to run fpga synthesis
111
-
110
+ synth, optional: Whether to run HLS synthesis
111
+ fpgasynth, optional: Whether to run FPGA synthesis (Quartus Compile)
112
+ log_level, optional: Logging level to be displayed during HLS synthesis (0, 1, 2)
113
+ cont_if_large_area: Instruct the HLS compiler to continue synthesis if the estimated resource usaga exceeds device resources
112
114
Errors raise exceptions
113
115
"""
116
+
117
+ # Check software needed is present
114
118
found = os .system ('command -v i++ > /dev/null' )
115
119
if found != 0 :
116
120
raise Exception ('Intel HLS installation not found. Make sure "i++" is on PATH.' )
117
121
118
- with chdir (model .config .get_output_dir ()):
119
- if synth :
120
- os .system ('make {}-fpga' .format (model .config .get_project_name ()))
121
- os .system ('./{}-fpga' .format (model .config .get_project_name ()))
122
-
123
- if fpgasynth :
122
+ if fpgasynth :
123
+ if fpgasynth and not synth :
124
+ raise Exception ('HLS Synthesis needs to be run before FPGA synthesis' )
124
125
found = os .system ('command -v quartus_sh > /dev/null' )
125
126
if found != 0 :
126
127
raise Exception ('Quartus installation not found. Make sure "quartus_sh" is on PATH.' )
127
- os .chdir (model .config .get_project_name () + '-fpga.prj/quartus' )
128
- os .system ('quartus_sh --flow compile quartus_compile' )
128
+
129
+ with chdir (model .config .get_output_dir ()):
130
+ if synth :
131
+ quartus_compile = 'QUARTUS_COMPILE=--quartus-compile' if fpgasynth else ''
132
+ cont_synth = 'CONT_IF_LARGE_AREA=--dont-error-if-large-area-est' if cont_if_large_area else ''
133
+ log_1 = 'LOGGING_1=-v ' if log_level >= 1 else ''
134
+ log_2 = 'LOGGING_2=-v ' if log_level >= 2 else ''
135
+ os .system (f'make { model .config .get_project_name ()} -fpga { log_1 } { log_2 } { cont_synth } { quartus_compile } ' )
136
+
137
+ # If running i++ through a container, such a singularity, this command will throw an exception, because the host OS doesn't have access to HLS simulation tools
138
+ # To avoid the exception, shell into the container (e.g. singularity shell ....) and then execute the following command manually
139
+ # This command simply tests the IP using a simulation tool and obtains the latency and initiation interval
140
+ os .system ('./{}-fpga' .format (model .config .get_project_name ()))
129
141
130
142
return parse_quartus_report (model .config .get_output_dir ())
131
143
0 commit comments