3232import json
3333import logging
3434import os
35+ from pathlib import Path
3536from typing import Callable
3637
3738import pdb # isort: split
4344
4445from finn .builder .build_dataflow_config import DataflowBuildConfig , default_build_dataflow_steps
4546from finn .builder .build_dataflow_steps import build_dataflow_step_lookup
47+ from finn .util .exception import FINNConfigurationError , FINNDataflowError , FINNError , FINNUserError
4648
4749
4850# adapted from https://stackoverflow.com/a/39215961
@@ -140,12 +142,20 @@ def resolve_build_steps(cfg: DataflowBuildConfig, partial: bool = True) -> list[
140142
141143def resolve_step_filename (step_name : str , cfg : DataflowBuildConfig , step_delta : int = 0 ):
142144 step_names = list (map (lambda x : x .__name__ , resolve_build_steps (cfg , partial = False )))
143- assert step_name in step_names , "start_step %s not found" + step_name
145+ if step_name not in step_names :
146+ raise FINNConfigurationError (
147+ f"Cannot restart from step { step_name } .Step { step_name } for restarting not found."
148+ )
144149 step_no = step_names .index (step_name ) + step_delta
145- assert step_no >= 0 , "Invalid step+delta combination"
146- assert step_no < len ( step_names ), "Invalid step+delta combination"
150+ if step_no < 0 or step_no >= len ( step_names ):
151+ raise FINNDataflowError ( "Invalid step+delta combination" )
147152 filename = cfg .output_dir + "/intermediate_models/"
148153 filename += "%s.onnx" % (step_names [step_no ])
154+ if not Path (filename ).exists ():
155+ raise FINNConfigurationError (
156+ f"Expected model file at { filename } to start from step "
157+ f"{ step_name } , but could not find it!"
158+ )
149159 return filename
150160
151161
@@ -155,19 +165,6 @@ def build_dataflow_cfg(model_filename, cfg: DataflowBuildConfig):
155165 :param model_filename: ONNX model filename to build
156166 :param cfg: Build configuration
157167 """
158- # if start_step is specified, override the input model
159- if cfg .start_step is None :
160- print (f"Building dataflow accelerator from { model_filename } " )
161- model = ModelWrapper (model_filename )
162- else :
163- intermediate_model_filename = resolve_step_filename (cfg .start_step , cfg , - 1 )
164- out = (
165- f"Building dataflow accelerator from intermediate"
166- f" checkpoint { intermediate_model_filename } "
167- )
168- print (out )
169- model = ModelWrapper (intermediate_model_filename )
170- assert type (model ) is ModelWrapper
171168 finn_build_dir = os .environ ["FINN_BUILD_DIR" ]
172169
173170 print (f"Intermediate outputs will be generated in { finn_build_dir } " )
@@ -205,27 +202,50 @@ def build_dataflow_cfg(model_filename, cfg: DataflowBuildConfig):
205202
206203 if cfg .console_log_level != "NONE" :
207204 # set up console logger
208- console = RichHandler (show_time = True , show_path = False , console = console )
205+ consoleHandler = RichHandler (show_time = True , show_path = False , console = console )
209206
210207 if cfg .console_log_level == "DEBUG" :
211- console .setLevel (logging .DEBUG )
208+ consoleHandler .setLevel (logging .DEBUG )
212209 elif cfg .console_log_level == "INFO" :
213- console .setLevel (logging .INFO )
210+ consoleHandler .setLevel (logging .INFO )
214211 elif cfg .console_log_level == "WARNING" :
215- console .setLevel (logging .WARNING )
212+ consoleHandler .setLevel (logging .WARNING )
216213 elif cfg .console_log_level == "ERROR" :
217- console .setLevel (logging .ERROR )
214+ consoleHandler .setLevel (logging .ERROR )
218215 elif cfg .console_log_level == "CRITICAL" :
219- console .setLevel (logging .CRITICAL )
220- logging .getLogger ().addHandler (console )
221-
222- # start processing
223- step_num = 1
224- time_per_step = dict ()
225- build_dataflow_steps = resolve_build_steps (cfg )
216+ consoleHandler .setLevel (logging .CRITICAL )
217+ logging .getLogger ().addHandler (consoleHandler )
226218
227- for transform_step in build_dataflow_steps :
228- try :
219+ # Setup done, start processing
220+ try :
221+ # if start_step is specified, override the input model
222+ if cfg .start_step is None :
223+ print (f"Building dataflow accelerator from { model_filename } " )
224+ model = ModelWrapper (model_filename )
225+ else :
226+ if model_filename != "" :
227+ log .warning (
228+ "When using a start-step, FINN automatically searches "
229+ "for the correct model to use from previous runs, overwriting your "
230+ "passed model file (but still using it's path for the location of the "
231+ "temporary file directory, etc.). This behaviour might change "
232+ "in future versions!"
233+ )
234+ intermediate_model_filename = resolve_step_filename (cfg .start_step , cfg , - 1 )
235+ out = (
236+ f"Building dataflow accelerator from intermediate"
237+ f" checkpoint { intermediate_model_filename } "
238+ )
239+ print (out )
240+ model = ModelWrapper (intermediate_model_filename )
241+ assert type (model ) is ModelWrapper
242+
243+ # start processing
244+ step_num = 1
245+ time_per_step = dict ()
246+ build_dataflow_steps = resolve_build_steps (cfg )
247+
248+ for transform_step in build_dataflow_steps :
229249 step_name = transform_step .__name__
230250 print (f"Running step: { step_name } [{ step_num } /{ len (build_dataflow_steps )} ]" )
231251
@@ -241,17 +261,33 @@ def build_dataflow_cfg(model_filename, cfg: DataflowBuildConfig):
241261 os .makedirs (intermediate_model_dir )
242262 model .save (os .path .join (intermediate_model_dir , chkpt_name ))
243263 step_num += 1
244- except : # noqa
264+ except KeyboardInterrupt :
265+ print ("KeyboardInterrupt detected. Aborting..." )
266+ print ("Build failed" )
267+ return - 1
268+ except (Exception , FINNError ) as e :
269+ # Print full traceback if we are on debug log level
270+ # or encountered a non-user error
271+ print_full_traceback = True
272+ if issubclass (type (e ), FINNUserError ) and log .level != logging .DEBUG :
273+ print_full_traceback = False
274+
275+ extype , value , tb = sys .exc_info ()
276+ if print_full_traceback :
245277 # print exception info and traceback
246- extype , value , tb = sys . exc_info ( )
278+ log . error ( "FINN Internal compiler error:" )
247279 console .print_exception (show_locals = False )
248- # start postmortem debug if configured
249- if cfg .enable_build_pdb_debug :
250- pdb .post_mortem (tb )
251- else :
252- print ("enable_build_pdb_debug not set in build config, exiting..." )
280+ else :
281+ console .print (f"[bold red]FINN Error: [/bold red]{ e } " )
282+ log .error (f"{ e } " )
253283 print ("Build failed" )
254- return - 1
284+ return - 1 # A user error shouldn't be need to be fixed using PDB
285+
286+ # start postmortem debug if configured
287+ if cfg .enable_build_pdb_debug :
288+ pdb .post_mortem (tb )
289+ print ("Build failed" )
290+ return - 1
255291
256292 with open (os .path .join (cfg .output_dir , "time_per_step.json" ), "w" ) as f :
257293 json .dump (time_per_step , f , indent = 2 )
0 commit comments