@@ -46,10 +46,22 @@ def is_top_file(filename, top):
4646
4747def get_dependent_files (filename ):
4848 headers = []
49+ headers_decl = []
4950 with open (filename , 'r' ) as f :
5051 for line in f :
5152 if '#include' in line :
52- headers .append (line )
53+ headers_decl .append (line )
54+ for h in headers_decl :
55+ match = re .search ('"(.*?)"' , h )
56+ if match is not None :
57+ for m in match .groups ():
58+ headers .append (m .replace ('"' , '' ))
59+ match = re .search ('<(.*?)>' , h )
60+ if match is not None :
61+ for m in match .groups ():
62+ tmp = m .replace ('<' , '' )
63+ tmp = tmp .replace ('>' , '' )
64+ headers .append (tmp )
5365 return headers
5466
5567def main ():
@@ -67,13 +79,15 @@ def main():
6779 parser .add_argument ('--script_name' , type = str , default = 'run_hls_test.tcl' , help = 'Generated TCL filename. Default: run_hls.tcl.' )
6880 parser .add_argument ('--run_hls' , action = 'store_true' , help = 'Run th generated TCL file. Default: False.' )
6981
70- parser .add_argument ('--board' , type = str , choices = avail_fpgas .keys (), default = 'ZedBoard' , help = 'The target FPGA board.' )
82+ parser .add_argument ('--board' , type = str , choices = avail_fpgas .keys (), default = 'ZedBoard' , help = 'The target FPGA board. Default: ZedBoard ' )
7183 parser .add_argument ('--period' , type = str , default = '10' , help = 'Clock period in ns. Default: 10.' )
7284 # Actions
7385 parser .add_argument ('--use_vivado_hls' , action = 'store_true' , help = 'Use Vivado HLS. Default is Vitis HLS.' )
7486 parser .add_argument ('--no_synthesis' , action = 'store_true' , help = 'Do not run synthesis.' )
7587 parser .add_argument ('--csim' , action = 'store_true' , help = 'Run C/C++ simulation.' )
7688 parser .add_argument ('--cosim' , action = 'store_true' , help = 'Run C/C++ co-simulation.' )
89+ parser .add_argument ('--cosim-all' , action = 'store_true' , help = 'Run C/C++ co-simulation and track all signals.' )
90+ parser .add_argument ('--cosim-port' , action = 'store_true' , help = 'Run C/C++ co-simulation and track ports.' )
7791 parser .add_argument ('--export' , action = 'store_true' , help = 'Export IP.' )
7892 parser .add_argument ('--place_and_route' , action = 'store_true' , help = 'Export IP and check place-and-route.' )
7993 parser .add_argument ('--no_reset_prj' , action = 'store_true' , help = 'Do not reset HLS project.' )
@@ -96,7 +110,8 @@ def main():
96110
97111 args = parser .parse_args ()
98112
99- if args .csim and args .tb_file == '' or args .cosim and args .tb_file == '' :
113+ run_cosim = args .cosim or args .cosim_port or args .cosim_all
114+ if args .csim and args .tb_file == '' or run_cosim and args .tb_file == '' :
100115 parser .error ('The --csim and --cosim arguments requires --tb_file.' )
101116 # ==========================================================================
102117 # Setup
@@ -106,11 +121,11 @@ def main():
106121 hls_report_dir = hls_prj_dir + '/reports'
107122 hls_tool = 'vhls' if args .use_vivado_hls else 'vitis'
108123 prj_name = f'{ hls_tool } _{ args .board } _{ args .top } '
109- reset_string = ' -reset ' if args .no_reset_prj else ''
124+ reset_string = '' if args .no_reset_prj else ' -reset '
110125 # ==========================================================================
111126 # Adjust CFLAGS and add defines
112127 # ==========================================================================
113- cflags = args .cflags + ' -I' + curr_dir + args .include
128+ cflags = args .cflags + ' -I' + curr_dir + args .include + ' -I/usr/local/include'
114129 if hls_tool == 'vhls' :
115130 cflags = '-fno-builtin ' + cflags .replace ('c++14' , 'c++0x' )
116131 print (f'[WARNING] Replacing C++14 with C++11 in Vivado HLS. CFLAGS: { cflags } ' )
@@ -126,7 +141,7 @@ def main():
126141 f .write (f'set_top "{ args .top } "\n ' )
127142 if not args .no_reset_prj :
128143 pass
129- if args .csim or args . cosim :
144+ if args .csim or run_cosim :
130145 pass
131146 if hls_tool == 'vitis' :
132147 f .write (f'open_solution -flow_target vivado { reset_string } "solution_{ args .top } "\n ' )
@@ -148,52 +163,146 @@ def main():
148163 # Add only significant files to synthesis
149164 # ======================================================================
150165 # TODO: Recursively include only the files from which the top function depends on.
166+
167+ def loadtxt (filename ):
168+ with open (filename ) as f :
169+ txt = '' .join (f .readlines ())
170+ return txt
171+
172+ # ======================================================================
173+ # Search for the top function in the C++ or Header files
174+ # ======================================================================
175+ # regex group1, name group2, arguments group3
176+ rproc = r"((?<=[\s:~])(\w+)\s*\(([\w\s,<>\[\].=&':/*]*?)\)\s*(const)?\s*(?={))"
177+ prog = re .compile (rproc )
178+ syn_files = []
179+ tb_files = []
151180 headers = []
152- if args .top_file :
181+
182+ def find_top_file (starting_dir ):
183+ for fpath , subdirs , files in os .walk (starting_dir ):
184+ for fname in files :
185+ unix_filename = curr_dir + '/' + fpath .replace ('\\ ' , '/' ) + '/' + fname
186+ is_cpp_file = fname .endswith ('.cpp' ) or fname .endswith ('.cc' )
187+ is_h_file = fname .endswith ('.hpp' ) or fname .endswith ('.h' )
188+ if is_cpp_file or is_h_file :
189+ code = loadtxt (unix_filename )
190+ cppwords = ['if' , 'while' , 'do' , 'for' , 'switch' ]
191+ procs = [(i .group (2 ), i .group (3 )) for i in prog .finditer (code ) \
192+ if i .group (2 ) not in cppwords ]
193+ for i in procs :
194+ if i [0 ] == args .top :
195+ return unix_filename
196+
197+ def get_headers (headers , top_filename , starting_dir = args .src ):
198+ added_headers = 0
199+ src_dir = curr_dir + starting_dir .replace ('\\ ' , '/' ) + '/'
200+ found_file = False
201+ for fpath , subdirs , files in os .walk (starting_dir ):
202+ for fname in files :
203+ unix_filename = curr_dir + '/' + fpath .replace ('\\ ' , '/' ) + '/' + fname
204+ unix_filename = unix_filename .replace ('//' , '/' )
205+ top_filename = top_filename .replace ('//' , '/' )
206+ if unix_filename == top_filename :
207+ found_file = True
208+ hfiles = get_dependent_files (unix_filename )
209+ for h in hfiles :
210+ if h not in headers :
211+ headers .append (h )
212+ added_headers += 1
213+ return added_headers , found_file
214+
215+ top_file = find_top_file (args .src )
216+ if top_file is not None :
217+ get_headers (headers , top_file , starting_dir = args .src )
218+ get_headers (headers , top_file , starting_dir = args .include )
219+ else :
220+ top_file = find_top_file (args .include )
221+ if top_file is None :
222+ print (f'[ERROR] Top function { args .top } not found in files. Exiting.' )
223+ exit (1 )
224+ get_headers (headers , top_file , starting_dir = args .src )
225+ get_headers (headers , top_file , starting_dir = args .include )
226+
227+ for h in headers :
228+ inc_dir = curr_dir + args .include .replace ('\\ ' , '/' ) + '/'
229+ if os .path .isfile (inc_dir + h ):
230+ syn_files .append (inc_dir + h )
231+ # Recursive search
232+ added_headers = 1
233+ while (added_headers != 0 ):
234+ added_headers = 0
235+ for h in headers :
236+ inc_dir = curr_dir + args .include .replace ('\\ ' , '/' ) + '/'
237+ src_dir = curr_dir + args .src .replace ('\\ ' , '/' ) + '/'
238+ num_headers , found_file = get_headers (headers , inc_dir + h , starting_dir = args .include )
239+ added_headers += num_headers
240+ if found_file and h not in tb_files :
241+ syn_files .append (inc_dir + h )
242+ tb_files .append (inc_dir + h )
243+ # Adding the corresponding C++ files
244+ for hext in ['.h' , '.hpp' ]:
245+ for cppext in ['.cc' , '.cpp' ]:
246+ cppfile = h .replace (hext , cppext )
247+ found_file = False
248+ num_headers , found_file = get_headers (headers , src_dir + cppfile , args .src )
249+ added_headers += num_headers
250+ if found_file and cppfile not in headers :
251+ headers .append (cppfile )
252+ syn_files .append (src_dir + cppfile )
253+ tb_files .append (src_dir + cppfile )
254+ f .write (f'# Synthesis files\n ' )
255+ for filename in syn_files :
256+ f .write (f'add_files { filename } -cflags "{ cflags } "\n ' )
257+
258+ if args .tb_file != '' :
259+ f .write (f'# TB files\n ' )
260+ # Search in src files
153261 for fpath , subdirs , files in os .walk (args .src ):
154262 for fname in files :
155- if args .top_file .replace ('.cpp' , '' ) == fname .replace ('.cpp' , '' ) or \
156- args .top_file .replace ('.h' , '' ) == fname .replace ('.h' , '' ):
157- headers_decl = get_dependent_files (fpath + '/' + fname )
158- for h in headers_decl :
159- match = re .search ('"(.*?)"' , h )
160- if match is not None :
161- for m in match .groups ():
162- headers .append (m .replace ('"' , '' ))
163- match = re .search ('<(.*?)>' , h )
164- if match is not None :
165- for m in match .groups ():
166- tmp = m .replace ('<' , '' )
167- tmp = tmp .replace ('>' , '' )
168- headers .append (tmp )
169- print (headers )
170- # ======================================================================
171- # Add files
172- # ======================================================================
173- f .write (f'# Source files\n ' )
174- for fpath , subdirs , files in os .walk (args .src ):
175- for fname in files :
176- unix_filename = curr_dir + '/' + fpath .replace ('\\ ' , '/' ) + '/' + fname
177- if fname .endswith ('.cpp' ) or fname .endswith ('.cc' ):
178- if args .tb_dir .replace ('\\ ' , '/' ) not in fpath :
179- print (f'[INFO] Adding synthesis file: { unix_filename } ' )
180- f .write (f'add_files { unix_filename } -cflags "{ cflags } "\n ' )
181- else :
182- if fname .startswith (args .tb_file ):
183- print (f'[INFO] Adding simulation file: { unix_filename } ' )
184- f .write (f'add_files -tb { unix_filename } -cflags "{ cflags } "\n ' )
185- f .write (f'# Include files\n ' )
186- for fpath , subdirs , files in os .walk (args .include ):
187- for fname in files :
188- unix_filename = curr_dir + '/' + fpath .replace ('\\ ' , '/' ) + '/' + fname
189- if fname .endswith ('.h' ):
190- if args .tb_dir .replace ('\\ ' , '/' ) not in fpath :
191- print (f'[INFO] Adding synthesis file: { unix_filename } ' )
192- f .write (f'add_files { unix_filename } -cflags "{ cflags } "\n ' )
193- else :
194- if fname .startswith (args .tb_file ):
195- print (f'[INFO] Adding simulation file: { unix_filename } ' )
196- f .write (f'add_files -tb { unix_filename } -cflags "{ cflags } "\n ' )
263+ unix_filename = curr_dir + '/' + fpath .replace ('\\ ' , '/' ) + '/' + fname
264+ if fname .startswith (args .tb_file ):
265+ f .write (f'add_files -tb { unix_filename } -cflags "{ cflags } "\n ' )
266+ # Search in include files
267+ for fpath , subdirs , files in os .walk (args .include ):
268+ for fname in files :
269+ unix_filename = curr_dir + '/' + fpath .replace ('\\ ' , '/' ) + '/' + fname
270+ if fname .startswith (args .tb_file ):
271+ f .write (f'add_files -tb { unix_filename } -cflags "{ cflags } "\n ' )
272+
273+ # for filename in tb_files:
274+ # f.write(f'add_files -tb {filename} -cflags "{cflags}"\n')
275+
276+ # # ======================================================================
277+ # # Add files
278+ # # ======================================================================
279+ # f.write(f'# Source files\n')
280+ # for fpath, subdirs, files in os.walk(args.src):
281+ # for fname in files:
282+ # unix_filename = curr_dir + '/' + fpath.replace('\\', '/') + '/' + fname
283+ # if fname.endswith('.cpp') or fname.endswith('.cc'):
284+ # if args.tb_dir.replace('\\', '/') not in fpath:
285+ # # print(f'[INFO] Adding synthesis file: {unix_filename}')
286+ # f.write(f'add_files {unix_filename} -cflags "{cflags}"\n')
287+ # else:
288+ # if fname.startswith(args.tb_file):
289+ # # print(f'[INFO] Adding simulation file: {unix_filename}')
290+ # f.write(f'add_files -tb {unix_filename} -cflags "{cflags}"\n')
291+
292+
293+ # f.write(f'# Include files\n')
294+ # for fpath, subdirs, files in os.walk(args.include):
295+ # for fname in files:
296+ # unix_filename = curr_dir + '/' + fpath.replace('\\', '/') + '/' + fname
297+ # if fname.endswith('.hpp') or fname.endswith('.h'):
298+ # if args.tb_dir.replace('\\', '/') not in fpath:
299+ # # print(f'[INFO] Adding synthesis file: {unix_filename}')
300+ # f.write(f'add_files {unix_filename} -cflags "{cflags}"\n')
301+ # else:
302+ # if fname.startswith(args.tb_file):
303+ # # print(f'[INFO] Adding simulation file: {unix_filename}')
304+ # f.write(f'add_files -tb {unix_filename} -cflags "{cflags}"\n')
305+
197306 # ======================================================================
198307 # Start CSim
199308 # ======================================================================
@@ -224,8 +333,12 @@ def main():
224333 # ======================================================================
225334 # Run Cosim and report
226335 # ======================================================================
227- if args .cosim :
228- cosim_cmd = f'cosim_design -trace_level port -ldflags "{ args .ldflags } " -argv "{ args .argv } "'
336+ if run_cosim :
337+ cosim_cmd = f'cosim_design -ldflags "{ args .ldflags } " -argv "{ args .argv } "'
338+ if args .cosim_all :
339+ cosim_cmd += ' -trace_level all'
340+ if args .cosim_port :
341+ cosim_cmd += ' -trace_level port'
229342 if hls_tool == 'vitis' and args .debug_dataflow :
230343 cosim_cmd += ' -enable_dataflow_profiling=1 -enable_fifo_sizing=1'
231344
0 commit comments