@@ -54,29 +54,32 @@ def _register_flows(self):
5454 ]
5555 quantization_flow = register_flow ('quantization' , quantization_passes , requires = [init_flow ], backend = self .name )
5656
57+ optimization_passes = []
58+ optimization_flow = register_flow ('optimize' , optimization_passes , requires = [init_flow ], backend = self .name )
59+
5760 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 )
5962
6063 writer_passes = [
6164 'make_stamp' ,
6265 'quartus:write_hls'
6366 ]
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 )
6669
6770 all_passes = get_backend_passes (self .name )
6871
6972 extras = [
7073 # 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
7275 ]
7376
7477 if len (extras ) > 0 :
7578 extras_flow = register_flow ('extras' , extras , requires = [init_flow ], backend = self .name )
7679 else :
7780 extras_flow = None
7881
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 ]
8083 ip_flow_requirements = list (filter (None , ip_flow_requirements ))
8184
8285 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
97100
98101 return config
99102
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+
101105 """
102106 Builds the project using Intel HLS compiler.
103107
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-
107108 Args:
108109 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
112114 Errors raise exceptions
113115 """
116+
117+ # Check software needed is present
114118 found = os .system ('command -v i++ > /dev/null' )
115119 if found != 0 :
116120 raise Exception ('Intel HLS installation not found. Make sure "i++" is on PATH.' )
117121
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' )
124125 found = os .system ('command -v quartus_sh > /dev/null' )
125126 if found != 0 :
126127 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 ()))
129141
130142 return parse_quartus_report (model .config .get_output_dir ())
131143
0 commit comments