2222import glob
2323import json
2424import math
25+ from pathlib import Path
2526import os
2627import re
2728import shutil
28- import subprocess
29+ from subprocess import check_call
2930import sys
3031import time
3132
3233from utils .utils import Timed , have_exec , get_file_dict
3334
34- TOOLCHAIN_MAP = {
35- 'vpr' : ('yosys' , 'vpr' ),
36- 'vpr-fasm2bels' : ('yosys' , 'vpr' ),
37- 'yosys-vivado' : ('yosys' , 'vivado' ),
38- 'yosys-vivado-uhdm' : ('yosys' , 'vivado' ),
39- 'vivado' : ('vivado' , 'vivado' ),
40- 'nextpnr-ice40' : ('yosys' , 'nextpnr' ),
41- 'nextpnr-xilinx' : ('yosys' , 'nextpnr' ),
42- 'nextpnr-nexus' : ('yosys' , 'nextpnr' ),
43- 'nextpnr-fpga-interchange' : ('yosys' , 'nextpnr' ),
44- 'nextpnr-xilinx-fasm2bels' : ('yosys' , 'nextpnr' ),
45- 'quicklogic' : ('yosys' , 'vpr' ),
46- 'lse-radiant' : ('lse' , 'radiant' ),
47- 'synpro-radiant' : ('synplify' , 'radiant' )
48- }
49-
5035
5136class Toolchain :
5237 '''A toolchain takes in verilog files and produces a .bitstream'''
@@ -136,7 +121,6 @@ def add_common_files(self):
136121
137122 def optstr (self ):
138123 tokens = []
139-
140124 if self .pcf :
141125 tokens .append ('pcf' )
142126 if self .sdc :
@@ -240,7 +224,7 @@ def cmd(self, cmd, argstr, env=None):
240224 print (" cwd: %s" % self .out_dir )
241225 else :
242226 cmdstr = "(%s %s) >& %s.txt" % (cmd , argstr , cmd_base )
243- subprocess . check_call (
227+ check_call (
244228 cmdstr ,
245229 shell = True ,
246230 executable = 'bash' ,
@@ -277,22 +261,17 @@ def get_runtimes(self):
277261 'phys opt design' : ['phys_opt_design' ]
278262 }
279263
264+ runtimes = {k : None for k in RUNTIME_ALIASES .keys ()}
265+
280266 def get_standard_runtime (runtime ):
281267 for k , v in RUNTIME_ALIASES .items ():
282268 for alias in v :
283269 if runtime == alias :
284270 return k
285-
286- assert False , "Couldn't find the standard name for {}" .format (
287- runtime
288- )
289-
290- runtimes = {k : None for k in RUNTIME_ALIASES .keys ()}
271+ raise Exception (f"Couldn't find the standard name for { runtime !s} " )
291272
292273 for k , v in self .runtimes .items ():
293- runtime = get_standard_runtime (k )
294-
295- runtimes [runtime ] = round (v , 3 )
274+ runtimes [get_standard_runtime (k )] = round (v , 3 )
296275
297276 return runtimes
298277
@@ -302,10 +281,9 @@ def get_resources_count(self, resources):
302281 resources count from the various log files.
303282 """
304283
305- if "families" in self .resources_map :
306- res_map = self .resources_map ["families" ][self .family ]
307- else :
308- res_map = self .resources_map
284+ res_map = self .resources_map ["families" ][
285+ self .family
286+ ] if "families" in self .resources_map else self .resources_map
309287
310288 resources_count = dict ([(x , 0 ) for x in res_map ])
311289
@@ -371,69 +349,80 @@ def get_metrics(self):
371349 return max_freq , resources
372350
373351 def write_metadata (self , output_error ):
374- out_dir = self .out_dir
375-
376- synth_tool , pr_tool = TOOLCHAIN_MAP [self .toolchain ]
377-
378- date_str = self .date .replace (microsecond = 0 ).isoformat ()
379-
380- json_data = dict ()
352+ synth_tool , pr_tool = {
353+ 'vpr' : ('yosys' , 'vpr' ),
354+ 'vpr-fasm2bels' : ('yosys' , 'vpr' ),
355+ 'yosys-vivado' : ('yosys' , 'vivado' ),
356+ 'yosys-vivado-uhdm' : ('yosys' , 'vivado' ),
357+ 'vivado' : ('vivado' , 'vivado' ),
358+ 'nextpnr-ice40' : ('yosys' , 'nextpnr' ),
359+ 'nextpnr-xilinx' : ('yosys' , 'nextpnr' ),
360+ 'nextpnr-nexus' : ('yosys' , 'nextpnr' ),
361+ 'nextpnr-fpga-interchange' : ('yosys' , 'nextpnr' ),
362+ 'nextpnr-xilinx-fasm2bels' : ('yosys' , 'nextpnr' ),
363+ 'quicklogic' : ('yosys' , 'vpr' ),
364+ 'lse-radiant' : ('lse' , 'radiant' ),
365+ 'synpro-radiant' : ('synplify' , 'radiant' )
366+ }[self .toolchain ]
381367
382368 max_freq , resources = (None ,
383369 None ) if output_error else self .get_metrics ()
384- runtimes = None if output_error else self .get_runtimes ()
385-
386- tools = dict (synth_tool = synth_tool , pr_tool = pr_tool )
387370
388371 # Meta information
389- json_data ['date' ] = date_str
390- json_data ['status' ] = "failed" if output_error else "succeeded"
391- json_data ['error_msg' ] = output_error
392-
393- # Task information
394- json_data ['design' ] = self .design ()
395- json_data ['family' ] = self .family
396- json_data ['device' ] = self .device
397- json_data ['package' ] = self .package
398- json_data ['board' ] = self .board
399- json_data ['vendor' ] = self .vendor
400- json_data ['project' ] = self .project_name
401- json_data ['toolchain' ] = {self .toolchain : tools }
402-
403- # Detailed task information
404- json_data ['optstr' ] = self .optstr ()
405- json_data ['pcf' ] = os .path .basename (self .pcf ) if self .pcf else None
406- json_data ['sdc' ] = os .path .basename (self .sdc ) if self .sdc else None
407- json_data ['xdc' ] = os .path .basename (self .xdc ) if self .xdc else None
408- json_data ['seed' ] = self .seed
409- json_data ['build' ] = self .build
410- json_data ['build_type' ] = self .build_type
411- json_data ['strategy' ] = self .strategy
412- json_data ['parameters' ] = self .params_file or self .params_string
413- json_data ['sources' ] = [x .replace (os .getcwd (), '.' ) for x in self .srcs ]
414- json_data ['top' ] = self .top
415- json_data ['versions' ] = self .versions ()
416- json_data ['cmds' ] = self .cmds
417-
418- # Results
419- json_data ['runtime' ] = runtimes
420- json_data ['max_freq' ] = max_freq
421- json_data ['resources' ] = resources
422- json_data ['wirelength' ] = self .wirelength
423- json_data ['maximum_memory_use' ] = self .maximum_memory_use
424-
425- with open (out_dir + '/meta.json' , 'w' ) as f :
426- json .dump (json_data , f , sort_keys = True , indent = 4 )
372+ json_data = {
373+ 'date' : self .date .replace (microsecond = 0 ).isoformat (),
374+ 'status' : "failed" if output_error else "succeeded" ,
375+ 'error_msg' : output_error ,
376+
377+ # Task information
378+ 'design' : self .design (),
379+ 'family' : self .family ,
380+ 'device' : self .device ,
381+ 'package' : self .package ,
382+ 'board' : self .board ,
383+ 'vendor' : self .vendor ,
384+ 'project' : self .project_name ,
385+ 'toolchain' :
386+ {
387+ self .toolchain :
388+ {
389+ 'synth_tool' : synth_tool ,
390+ 'pr_tool' : pr_tool
391+ }
392+ },
393+
394+ # Detailed task information
395+ 'optstr' : self .optstr (),
396+ 'pcf' : os .path .basename (self .pcf ) if self .pcf else None ,
397+ 'sdc' : os .path .basename (self .sdc ) if self .sdc else None ,
398+ 'xdc' : os .path .basename (self .xdc ) if self .xdc else None ,
399+ 'seed' : self .seed ,
400+ 'build' : self .build ,
401+ 'build_type' : self .build_type ,
402+ 'strategy' : self .strategy ,
403+ 'parameters' : self .params_file or self .params_string ,
404+ 'sources' : [x .replace (os .getcwd (), '.' ) for x in self .srcs ],
405+ 'top' : self .top ,
406+ 'versions' : self .versions (),
407+ 'cmds' : self .cmds ,
408+
409+ # Results
410+ 'runtime' : None if output_error else self .get_runtimes (),
411+ 'max_freq' : max_freq ,
412+ 'resources' : resources ,
413+ 'wirelength' : self .wirelength ,
414+ 'maximum_memory_use' : self .maximum_memory_use ,
415+ }
416+
417+ with (Path (self .out_dir ) / 'meta.json' ).open ('w' ) as wfptr :
418+ json .dump (json_data , wfptr , sort_keys = True , indent = 4 )
427419
428420 # Provide some context when comparing runtimes against systems
429- subprocess .check_call (
430- 'uname -a >uname.txt' ,
431- shell = True ,
432- executable = 'bash' ,
433- cwd = self .out_dir
434- )
435- subprocess .check_call (
436- 'lscpu >lscpu.txt' ,
421+ check_call (
422+ """
423+ uname -a >uname.txt
424+ lscpu >lscpu.txt
425+ """ ,
437426 shell = True ,
438427 executable = 'bash' ,
439428 cwd = self .out_dir
0 commit comments