def linkNGC(moduleList, module, firstPassLIGraph): return li_module.linkFirstPassObject(moduleList, module, firstPassLIGraph, 'GEN_NGCS', 'GEN_NGCS')
def __init__(self, moduleList, isPrimaryBuildTarget): # if we have a deps build, don't do anything... if(moduleList.isDependsBuild): return APM_NAME = moduleList.env['DEFS']['APM_NAME'] BSC = moduleList.env['DEFS']['BSC'] inc_paths = moduleList.swIncDir # we need to depend on libasim self.firstPassLIGraph = wrapper_gen_tool.getFirstPassLIGraph() # This is not correct for LIM builds and needs to be fixed. TMP_BSC_DIR = moduleList.env['DEFS']['TMP_BSC_DIR'] ALL_DIRS_FROM_ROOT = moduleList.env['DEFS']['ALL_HW_DIRS'] ALL_BUILD_DIRS_FROM_ROOT = model.transform_string_list(ALL_DIRS_FROM_ROOT, ':', '', '/' + TMP_BSC_DIR) ALL_LIB_DIRS_FROM_ROOT = ALL_DIRS_FROM_ROOT + ':' + ALL_BUILD_DIRS_FROM_ROOT # Due to the bluespec linker, for LI second pass builds, the final # verilog link step must occur in a different directory than the # bsc object code wrapper compilation step. However, non-LIM # linker builds need to build in the original .bsc directory to # pick up VPI. vexe_vdir = moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + moduleList.env['DEFS']['ROOT_DIR_MODEL'] + '/' + moduleList.env['DEFS']['TMP_BSC_DIR'] if(not self.firstPassLIGraph is None): vexe_vdir = vexe_vdir + '_vlog' if not os.path.isdir(vexe_vdir): os.mkdir(vexe_vdir) LI_LINK_DIR = "" if (not self.firstPassLIGraph is None): LI_LINK_DIR = model.get_build_path(moduleList, moduleList.topModule) + "/.li/" inc_paths += [LI_LINK_DIR] ALL_LIB_DIRS_FROM_ROOT = LI_LINK_DIR + ':' + ALL_LIB_DIRS_FROM_ROOT liCodeType = ['VERILOG', 'GIVEN_VERILOG_HS', 'GEN_VPI_CS', 'GEN_VPI_HS'] # This can be refactored as a function. if (not self.firstPassLIGraph is None): for moduleName in self.firstPassLIGraph.modules: moduleObject = self.firstPassLIGraph.modules[moduleName] # we also need the module list object moduleListObject = moduleList.modules[moduleName] for codeType in liCodeType: # If we're linking, clean out any previous code dependencies. These are guaranteed not to be used. moduleListObject.moduleDependency[codeType] = [] li_module.linkFirstPassObject(moduleList, moduleListObject, self.firstPassLIGraph, codeType, codeType, linkDirectory=vexe_vdir) bsc_version = bsv_tool.getBluespecVersion() ldflags = '' for ld_file in moduleList.getAllDependenciesWithPaths('GIVEN_BLUESIM_LDFLAGSS'): ldHandle = open(moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + ld_file, 'r') ldflags += ldHandle.read() + ' ' BSC_FLAGS_VERILOG = '-steps 10000000 +RTS -K1000M -RTS -keep-fires -aggressive-conditions -wait-for-license -no-show-method-conf -no-opt-bool -licenseWarning 7 -elab -show-schedule ' + ldflags + ' -verilog -v -vsim iverilog ' # Build in parallel. n_jobs = moduleList.env.GetOption('num_jobs') if (bsc_version >= 30006): BSC_FLAGS_VERILOG += '-parallel-sim-link ' + str(n_jobs) + ' ' for path in inc_paths: BSC_FLAGS_VERILOG += ' -I ' + path + ' ' #+ '-Xv -I' + path + ' ' LDFLAGS = moduleList.env['DEFS']['LDFLAGS'] TMP_BSC_DIR = moduleList.env['DEFS']['TMP_BSC_DIR'] ROOT_WRAPPER_SYNTH_ID = 'mk_' + moduleList.env['DEFS']['ROOT_DIR_MODEL'] + '_Wrapper' vexe_gen_command = \ BSC + ' ' + BSC_FLAGS_VERILOG + ' -vdir ' + vexe_vdir + ' -simdir ' + vexe_vdir + ' -bdir ' + vexe_vdir +' -p +:' + ALL_LIB_DIRS_FROM_ROOT + ' -vsearch +:' + ALL_LIB_DIRS_FROM_ROOT + ' ' + \ ' -o $TARGET' if (bsc_version >= 13013): # 2008.01.A compiler allows us to pass C++ arguments. if (model.getDebug(moduleList)): vexe_gen_command += ' -Xc++ -O0' else: vexe_gen_command += ' -Xc++ -O1' # g++ 4.5.2 is complaining about overflowing the var tracking table if (model.getGccVersion() >= 40501): vexe_gen_command += ' -Xc++ -fno-var-tracking-assignments' defs = (software_tool.host_defs()).split(" ") for definition in defs: vexe_gen_command += ' -Xc++ ' + definition + ' -Xc ' + definition # Hack to link against pthreads. Really we should have a better solution. vexe_gen_command += ' -Xl -lpthread ' # construct full path to BAs def modify_path(str): array = str.split('/') file = array.pop() return moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + '/'.join(array) + '/' + TMP_BSC_DIR + '/' + file # Use systemverilog 2005 if(moduleList.getAWBParam('verilog_tool', 'ENABLE_SYSTEM_VERILOG')): vexe_gen_command += ' -Xv -g2005-sv ' # Allow .vh/.sv file extensions etc. # vexe_gen_command += ' -Xv -Y.vh -Xv -Y.sv ' # Bluespec requires that source files terminate the command line. vexe_gen_command += '-verilog -e ' + ROOT_WRAPPER_SYNTH_ID + ' ' +\ moduleList.env['DEFS']['BDPI_CS'] if (model.getBuildPipelineDebug(moduleList) != 0): for m in moduleList.getAllDependencies('BA'): print 'BA dep: ' + str(m) for m in moduleList.getAllDependencies('VERILOG'): print 'VL dep: ' + str(m) for m in moduleList.getAllDependencies('VHDL'): print 'BA dep: ' + str(m) # Generate a thin wrapper around the verilog executable. This # wrapper is used to address a problem in iverilog in which the # simulator does not support shared library search paths. The # current wrapper only works for iverilog. Due to brokeness in # the iverilog argument parser, we must construct a correct # iverilog command line by analyzing its compiled script. Also, # this script is not passing through the arguments that it should # be passing through. def generate_vexe_wrapper(target, source, env): wrapper_handle = open(str(target[0]),'w') wrapper_handle.write('#!/usr/bin/perl\n') wrapper_handle.write('# generated by verilog.py\n') wrapper_handle.write('$platform = $ENV{"PLATFORM_DIRECTORY"};\n') wrapper_handle.write('@script = `cat $platform/' + TMP_BSC_DIR + '/' + APM_NAME + '_hw.exe' + '`;\n') wrapper_handle.write('$script[0] =~ s/#!/ /g;\n') wrapper_handle.write('$vvp = $script[0];\n') wrapper_handle.write('chomp($vvp);\n') wrapper_handle.write('exec("$vvp -m$platform/directc_mk_model_Wrapper.so $platform/' + TMP_BSC_DIR + '/' + APM_NAME + '_hw.exe' + ' +bscvcd \$* ");\n') wrapper_handle.close() def modify_path_ba_local(path): return bsv_tool.modify_path_ba(moduleList, path) # Bluesim builds apparently touch this code. This control block # preserves their behavior, but it is unclear why the verilog build is # involved. if (isPrimaryBuildTarget): vbinDeps = [] # If we got a lim graph, we'll pick up many of our dependencies from it. # These were annotated in the top module above. Really, this seems unclean. # we should build a graph during the second pass and just use it. if(not self.firstPassLIGraph is None): # Collect linked dependencies for every module for moduleName in self.firstPassLIGraph.modules: moduleListObject = moduleList.modules[moduleName] vbinDeps += moduleList.getDependencies(moduleListObject, 'VERILOG') + moduleList.getDependencies(moduleListObject, 'GIVEN_VERILOG_HS') + moduleList.getDependencies(moduleListObject, 'GEN_VPI_HS') + moduleList.getDependencies(moduleListObject, 'GEN_VPI_CS') + moduleList.getDependencies(moduleListObject, 'VHDL') + moduleList.getDependencies(moduleListObject, 'BA') + moduleList.getDependencies(moduleListObject, 'GEN_BAS') vbinDeps += moduleList.getDependencies(moduleList.topModule, 'VERILOG') + moduleList.getDependencies(moduleList.topModule, 'GIVEN_VERILOG_HS') + moduleList.getDependencies(moduleList.topModule, 'GEN_VPI_HS') + moduleList.getDependencies(moduleList.topModule, 'GEN_VPI_CS') +moduleList.getDependencies(moduleList.topModule, 'VHDL') + moduleList.getDependencies(moduleList.topModule, 'BA') + map(modify_path_ba_local, moduleList.getModuleDependenciesWithPaths(moduleList.topModule, 'GEN_BAS')) # collect dependencies from all awb modules else: vbinDeps += moduleList.getAllDependencies('VERILOG') + moduleList.getAllDependencies('VHDL') + moduleList.getAllDependencies('BA') + map(modify_path_ba_local, moduleList.getAllDependenciesWithPaths('GEN_BAS')) vbin = moduleList.env.Command( TMP_BSC_DIR + '/' + APM_NAME + '_hw.exe', vbinDeps, [ vexe_gen_command, SCons.Script.Delete('directc.sft') ]) vexe = moduleList.env.Command( APM_NAME + '_hw.exe', vbin, [ generate_vexe_wrapper, '@chmod a+x $TARGET', SCons.Script.Delete(APM_NAME + '_hw.errinfo') ]) moduleList.topDependency = moduleList.topDependency + [vexe] else: vbinDeps = moduleList.getAllDependencies('VERILOG') + moduleList.getAllDependencies('VHDL') + moduleList.getAllDependencies('BA') + map(modify_path_ba_local, moduleList.getAllDependenciesWithPaths('GEN_BAS')) vbin = moduleList.env.Command( TMP_BSC_DIR + '/' + APM_NAME + '_hw.vexe', vbinDeps, [ vexe_gen_command, SCons.Script.Delete('directc.sft') ]) vexe = moduleList.env.Command( APM_NAME + '_hw.vexe', vbin, [ generate_vexe_wrapper, '@chmod a+x $TARGET', SCons.Script.Delete(APM_NAME + '_hw.exe'), SCons.Script.Delete(APM_NAME + '_hw.errinfo') ]) moduleList.env.Alias('vexe', vexe)
def __init__(self, moduleList): # if we have a deps build, don't do anything... if(moduleList.isDependsBuild): return self.firstPassLIGraph = wrapper_gen_tool.getFirstPassLIGraph() # A collector for all of the checkpoint objects we will gather/build in the following code. dcps = [] # Construct the tcl file self.part = moduleList.getAWBParam('physical_platform_config', 'FPGA_PART_XILINX') apm_name = moduleList.compileDirectory + '/' + moduleList.apmName self.paramTclFile = moduleList.topModule.moduleDependency['PARAM_TCL'][0] # If the TMP_XILINX_DIR doesn't exist, create it. if not os.path.isdir(moduleList.env['DEFS']['TMP_XILINX_DIR']): os.mkdir(moduleList.env['DEFS']['TMP_XILINX_DIR']) # Gather Tcl files for handling constraints. self.tcl_headers = [] if(len(moduleList.getAllDependenciesWithPaths('GIVEN_VIVADO_TCL_HEADERS')) > 0): self.tcl_headers = map(model.modify_path_hw, moduleList.getAllDependenciesWithPaths('GIVEN_VIVADO_TCL_HEADERS')) self.tcl_defs = [] if(len(moduleList.getAllDependenciesWithPaths('GIVEN_VIVADO_TCL_DEFINITIONS')) > 0): self.tcl_defs = map(model.modify_path_hw, moduleList.getAllDependenciesWithPaths('GIVEN_VIVADO_TCL_DEFINITIONS')) self.tcl_funcs = [] if(len(moduleList.getAllDependenciesWithPaths('GIVEN_VIVADO_TCL_FUNCTIONS')) > 0): self.tcl_funcs = map(model.modify_path_hw, moduleList.getAllDependenciesWithPaths('GIVEN_VIVADO_TCL_FUNCTIONS')) self.tcl_algs = [] if(len(moduleList.getAllDependenciesWithPaths('GIVEN_VIVADO_TCL_ALGEBRAS')) > 0): self.tcl_algs = map(model.modify_path_hw, moduleList.getAllDependenciesWithPaths('GIVEN_VIVADO_TCL_ALGEBRAS')) self.tcl_bmms = [] if(len(moduleList.getAllDependencies('GIVEN_XILINX_BMMS')) > 0): self.tcl_bmms = moduleList.getAllDependencies('GIVEN_XILINX_BMMS') self.tcl_elfs = [] if(len(moduleList.getAllDependencies('GIVEN_XILINX_ELFS')) > 0): self.tcl_elfs = moduleList.getAllDependencies('GIVEN_XILINX_ELFS') self.tcl_ag = [] #Emit area group definitions # If we got an area group placement data structure, now is the # time to convert it into a new constraint tcl. self.area_group_file = moduleList.compileDirectory + '/areagroups.xdc' if ('AREA_GROUPS' in moduleList.topModule.moduleDependency): self.area_constraints = area_group_tool.AreaConstraints(moduleList) self.routeAG = (moduleList.getAWBParam('area_group_tool', 'AREA_GROUPS_ROUTE_AG') != 0) # user ucf may be overridden by our area group ucf. Put our # generated ucf first. #tcl_defs.insert(0,self.area_group_file) def area_group_ucf_closure(moduleList): def area_group_ucf(target, source, env): self.area_constraints.loadAreaConstraints() self.area_constraints.emitConstraintsVivado(self.area_group_file) return area_group_ucf moduleList.env.Command( [self.area_group_file], self.area_constraints.areaConstraintsFile(), area_group_ucf_closure(moduleList) ) synthDepsBase = moduleList.getAllDependencies('GEN_VIVADO_DCPS') # We got a stack of synthesis results for the LI modules. We need # to convert these to design checkpoints for the fast place and # route flow. ngcModules = [module for module in moduleList.synthBoundaries() if not module.liIgnore] for module in ngcModules + [moduleList.topModule]: # did we get a dcp from the first pass? If so, did the lim # graph give code for this module? If both are true, then we # will link the old ngc in, rather than regenerate it. if ((not self.firstPassLIGraph is None) and (module.name in self.firstPassLIGraph.modules) and (self.firstPassLIGraph.modules[module.name].getAttribute('RESYNTHESIZE') is None)): if (li_module.linkFirstPassObject(moduleList, module, self.firstPassLIGraph, 'GEN_VIVADO_DCPS', 'GEN_VIVADO_DCPS') is None): module.moduleDependency['GEN_VIVADO_DCPS'] = [self.edf_to_dcp(moduleList, module)] # it's possible that we got dcp from this compilation # pass. This will happen for the platform modules. elif (len(module.getDependencies('GEN_VIVADO_DCPS')) > 0): continue # we got neither. therefore, we must create a dcp out of the ngc. else: module.moduleDependency['GEN_VIVADO_DCPS'] = [self.edf_to_dcp(moduleList, module)] synthDeps = moduleList.getAllDependencies('GEN_VIVADO_DCPS') postSynthTcl = apm_name + '.physical.tcl' topWrapper = moduleList.topModule.wrapperName() newTclFile = open(postSynthTcl, 'w') newTclFile.write('create_project -force ' + moduleList.apmName + ' ' + moduleList.compileDirectory + ' -part ' + self.part + ' \n') # To resolve black boxes, we need to load checkpoints in the # following order: # 1) topModule # 2) platformModule # 3) user program, in any order userModules = [module for module in moduleList.synthBoundaries() if not module.liIgnore and not module.platformModule] platformModules = [module for module in moduleList.synthBoundaries() if not module.liIgnore and module.platformModule] checkpointCommands = [] if(not moduleList.getAWBParamSafe('area_group_tool', 'AREA_GROUPS_ENABLE')): for module in [moduleList.topModule] + platformModules + userModules: dcps.append(module.getDependencies('GEN_VIVADO_DCPS')) checkpoint = model.convertDependencies(module.getDependencies('GEN_VIVADO_DCPS')) # There should only be one checkpoint here. if(len(checkpoint) > 1): print "Error too many checkpoints for " + str(module.name) + ": " + str(checkpoint) continue if(len(checkpoint) == 0): print "No checkpoints for " + str(module.name) + ": " + str(checkpoint) continue newTclFile.write('read_checkpoint ' + checkpoint[0] + '\n') # We're attempting the new, parallel flow. else: # we need to issue seperate place commands. Therefore, we attempt to place each design # There may be some special area groups in platforms -- handle them elabAreaConstraints = area_group_tool.AreaConstraints(moduleList) elabAreaConstraints.loadAreaConstraintsElaborated() #self.area_constraints = area_group_tool.AreaConstraints(moduleList) for module in userModules: # Did we get a placed module already? if((module.name in elabAreaConstraints.constraints) and ('LIBRARY_DCP' in elabAreaConstraints.constraints[module.name].attributes)): # we need to locate the dcp corresponding to this area group. candidates = moduleList.getAllDependencies('GIVEN_VIVADO_DCPS') for dcpCandidate in moduleList.getAllDependencies('GIVEN_VIVADO_DCPS'): if dcpCandidate.attributes['module'] == module.name: dcp = str(model.modify_path_hw(dcpCandidate)) model.dictionary_list_create_append(module.moduleDependency, 'GEN_VIVADO_PLACEMENT_DCPS', dcp) dcps.append(dcp) else: dcp = self.place_dcp(moduleList, module) model.dictionary_list_create_append(module.moduleDependency, 'GEN_VIVADO_PLACEMENT_DCPS', dcp) dcps.append(dcp) for module in [moduleList.topModule] + platformModules: checkpoint = model.convertDependencies(module.getDependencies('GEN_VIVADO_DCPS')) dcps.append(checkpoint) # There should only be one checkpoint here. if(len(checkpoint) > 1): print "Error too many checkpoints for " + str(module.name) + ": " + str(checkpoint) continue if(len(checkpoint) == 0): print "No checkpoints for " + str(module.name) + ": " + str(checkpoint) continue newTclFile.write('read_checkpoint ' + checkpoint[0] + '\n') # We can have parent/child relationships in the user modules. # Vivado requires that checkpoints be read in topological # order. def isBlackBox(module): if(self.firstPassLIGraph.modules[module.name].getAttribute('BLACK_BOX_AREA_GROUP')): return 1 return 0 for module in sorted(userModules, key=isBlackBox): checkpoint = model.convertDependencies(module.getDependencies('GEN_VIVADO_PLACEMENT_DCPS')) # There should only be one checkpoint here. if(len(checkpoint) > 1): print "Error too many checkpoints for " + str(module.name) + ": " + str(checkpoint) continue if(len(checkpoint) == 0): print "No checkpoints for " + str(module.name) + ": " + str(checkpoint) continue #read in new checkoutpoint newTclFile.write('read_checkpoint ' + checkpoint[0] + '\n') emitPlatformAreaGroups = (moduleList.getAWBParam('area_group_tool', 'AREA_GROUPS_GROUP_PLATFORM_CODE') != 0) # platformModule refers to the main platform module, not # the subordinate device area groups. platformModule = (self.firstPassLIGraph.modules[module.name].getAttribute('BLACK_BOX_AREA_GROUP') is None) and (not self.firstPassLIGraph.modules[module.name].getAttribute('PLATFORM_MODULE') is None) allowAGPlatform = (not platformModule) or emitPlatformAreaGroups emitDeviceGroups = (moduleList.getAWBParam('area_group_tool', 'AREA_GROUPS_PAR_DEVICE_AG') != 0) allowAGDevice = (self.firstPassLIGraph.modules[module.name].getAttribute('BLACK_BOX_AREA_GROUP') is None) or emitDeviceGroups if (allowAGPlatform and allowAGDevice): refName = module.wrapperName() lockPlacement = True lockRoute = self.routeAG # If this is an platform/user-defined area group, the wrapper name may be different. if (not self.firstPassLIGraph.modules[module.name].getAttribute('BLACK_BOX_AREA_GROUP') is None): refName = elabAreaConstraints.constraints[module.name].attributes['MODULE_NAME'] lockPlacement = not ('NO_PLACE' in elabAreaConstraints.constraints[module.name].attributes) and lockPlacement lockRoute = not ('NO_ROUTE' in elabAreaConstraints.constraints[module.name].attributes) and lockRoute checkpointCommands.append('if { [llength [get_cells -hier -filter {REF_NAME =~ "' + refName + '"}]] } {\n') checkpointCommands.append(' puts "Locking ' + refName + '"\n') if (lockRoute): # locking routing requires us to emit an area group. boo. ag_tcl = self.ag_constraints(moduleList, module) self.tcl_ag.append(ag_tcl) checkpointCommands.append(' source ' + str(ag_tcl) + '\n') checkpointCommands.append(' lock_design -level routing [get_cells -hier -filter {REF_NAME =~ "' + refName + '"}]\n') elif (lockPlacement): checkpointCommands.append(' lock_design -level placement [get_cells -hier -filter {REF_NAME =~ "' + refName + '"}]\n') checkpointCommands.append('}\n') given_netlists = [ moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + netlist for netlist in moduleList.getAllDependenciesWithPaths('GIVEN_NGCS') + moduleList.getAllDependenciesWithPaths('GIVEN_EDFS') ] for netlist in given_netlists: newTclFile.write('read_edif ' + netlist + '\n') # We have lots of dangling wires (Thanks, Bluespec). Set the # following properties to silence the warnings. newTclFile.write("set_property SEVERITY {Warning} [get_drc_checks NSTD-1]\n") newTclFile.write("set_property SEVERITY {Warning} [get_drc_checks UCIO-1]\n") newTclFile.write("link_design -top " + topWrapper + " -part " + self.part + "\n") newTclFile.write("report_utilization -file " + apm_name + ".link.util\n") newTclFile.write("write_checkpoint -force " + apm_name + ".link.dcp\n") # lock down the area group routing. newTclFile.write("\n".join(checkpointCommands) + "\n") for elf in self.tcl_elfs: newTclFile.write("add_file " + model.modify_path_hw(elf) + "\n") newTclFile.write("set_property MEMDATA.ADDR_MAP_CELLS {" + str(elf.attributes['ref']) + "} [get_files " + model.modify_path_hw(elf) + "]\n") # We will now attempt to link in any bmm that we might have. for bmm in self.tcl_bmms: newTclFile.write("add_file " + model.modify_path_hw(bmm) + "\n") newTclFile.write("set_property SCOPED_TO_REF " + str(bmm.attributes['ref']) + " [get_files " + model.modify_path_hw(bmm) + "]\n") newTclFile.write('set IS_TOP_BUILD 1\n ') newTclFile.write('set IS_AREA_GROUP_BUILD 0\n ') newTclFile.write('set SYNTH_OBJECT ""\n') newTclFile.write('source ' + self.paramTclFile + '\n') for tcl_header in self.tcl_headers: newTclFile.write('source ' + tcl_header + '\n') for tcl_def in self.tcl_defs: newTclFile.write('source ' + tcl_def + '\n') for tcl_func in self.tcl_funcs: newTclFile.write('source ' + tcl_func + '\n') for tcl_alg in self.tcl_algs: newTclFile.write('source ' + tcl_alg + '\n') def dumpPBlockCmd(tgt): return 'dumpPBlockUtilization "' + moduleList.compileDirectory + '/' + tgt + '.util"\n' newTclFile.write(dumpPBlockCmd('link')) newTclFile.write("report_timing_summary -file " + apm_name + ".map.twr\n\n") newTclFile.write("opt_design -directive AddRemap\n") newTclFile.write("report_utilization -file " + apm_name + ".opt.util\n") newTclFile.write(dumpPBlockCmd('opt')) newTclFile.write("write_checkpoint -force " + apm_name + ".opt.dcp\n\n") newTclFile.write("place_design -no_drc -directive WLDrivenBlockPlacement\n") newTclFile.write(dumpPBlockCmd('place')) newTclFile.write("phys_opt_design -directive AggressiveFanoutOpt\n") newTclFile.write("write_checkpoint -force " + apm_name + ".map.dcp\n") newTclFile.write(dumpPBlockCmd('phyopt')) newTclFile.write("report_utilization -file " + apm_name + ".map.util\n\n") newTclFile.write("route_design\n") newTclFile.write("write_checkpoint -force " + apm_name + ".par.dcp\n") newTclFile.write(dumpPBlockCmd('par')) newTclFile.write("report_timing_summary -file " + apm_name + ".par.twr\n\n") newTclFile.write("report_utilization -hierarchical -file " + apm_name + ".par.util\n") newTclFile.write("report_drc -file " + topWrapper + ".drc\n\n") newTclFile.write("write_bitstream -force " + apm_name + "_par.bit\n") newTclFile.close() # generate bitfile xilinx_bit = moduleList.env.Command( apm_name + '_par.bit', synthDeps + self.tcl_algs + self.tcl_defs + self.tcl_funcs + self.tcl_ag + [self.paramTclFile] + dcps + [postSynthTcl], ['touch start.txt; vivado -verbose -mode batch -source ' + postSynthTcl + ' -log ' + moduleList.compileDirectory + '/postsynth.log']) moduleList.topModule.moduleDependency['BIT'] = [apm_name + '_par.bit'] # We still need to generate a download script. xilinx_loader.LOADER(moduleList)
def __init__(self, moduleList, isPrimaryBuildTarget): # if we have a deps build, don't do anything... if (moduleList.isDependsBuild): return APM_NAME = moduleList.env['DEFS']['APM_NAME'] BSC = moduleList.env['DEFS']['BSC'] inc_paths = moduleList.swIncDir # we need to depend on libasim self.firstPassLIGraph = wrapper_gen_tool.getFirstPassLIGraph() # This is not correct for LIM builds and needs to be fixed. TMP_BSC_DIR = moduleList.env['DEFS']['TMP_BSC_DIR'] ALL_DIRS_FROM_ROOT = moduleList.env['DEFS']['ALL_HW_DIRS'] ALL_BUILD_DIRS_FROM_ROOT = model.transform_string_list( ALL_DIRS_FROM_ROOT, ':', '', '/' + TMP_BSC_DIR) ALL_LIB_DIRS_FROM_ROOT = ALL_DIRS_FROM_ROOT + ':' + ALL_BUILD_DIRS_FROM_ROOT # Due to the bluespec linker, for LI second pass builds, the final # verilog link step must occur in a different directory than the # bsc object code wrapper compilation step. However, non-LIM # linker builds need to build in the original .bsc directory to # pick up VPI. vexe_vdir = moduleList.env['DEFS'][ 'ROOT_DIR_HW'] + '/' + moduleList.env['DEFS'][ 'ROOT_DIR_MODEL'] + '/' + moduleList.env['DEFS']['TMP_BSC_DIR'] if (not self.firstPassLIGraph is None): vexe_vdir = vexe_vdir + '_vlog' if not os.path.isdir(vexe_vdir): os.mkdir(vexe_vdir) LI_LINK_DIR = "" if (not self.firstPassLIGraph is None): LI_LINK_DIR = model.get_build_path(moduleList, moduleList.topModule) + "/.li/" inc_paths += [LI_LINK_DIR] ALL_LIB_DIRS_FROM_ROOT = LI_LINK_DIR + ':' + ALL_LIB_DIRS_FROM_ROOT liCodeType = [ 'VERILOG', 'GIVEN_VERILOG_HS', 'GEN_VPI_CS', 'GEN_VPI_HS' ] # This can be refactored as a function. if (not self.firstPassLIGraph is None): for moduleName in self.firstPassLIGraph.modules: moduleObject = self.firstPassLIGraph.modules[moduleName] # we also need the module list object moduleListObject = moduleList.modules[moduleName] for codeType in liCodeType: # If we're linking, clean out any previous code dependencies. These are guaranteed not to be used. moduleListObject.moduleDependency[codeType] = [] li_module.linkFirstPassObject(moduleList, moduleListObject, self.firstPassLIGraph, codeType, codeType, linkDirectory=vexe_vdir) bsc_version = bsv_tool.getBluespecVersion() ldflags = '' for ld_file in moduleList.getAllDependenciesWithPaths( 'GIVEN_BLUESIM_LDFLAGSS'): ldHandle = open( moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + ld_file, 'r') ldflags += ldHandle.read() + ' ' BSC_FLAGS_VERILOG = '-steps 10000000 +RTS -K1000M -RTS -keep-fires -aggressive-conditions -wait-for-license -no-show-method-conf -no-opt-bool -licenseWarning 7 -elab -show-schedule ' + ldflags + ' -verilog -v -vsim iverilog ' # Build in parallel. n_jobs = moduleList.env.GetOption('num_jobs') if (bsc_version >= 30006): BSC_FLAGS_VERILOG += '-parallel-sim-link ' + str(n_jobs) + ' ' for path in inc_paths: BSC_FLAGS_VERILOG += ' -I ' + path + ' ' #+ '-Xv -I' + path + ' ' LDFLAGS = moduleList.env['DEFS']['LDFLAGS'] TMP_BSC_DIR = moduleList.env['DEFS']['TMP_BSC_DIR'] ROOT_WRAPPER_SYNTH_ID = 'mk_' + moduleList.env['DEFS'][ 'ROOT_DIR_MODEL'] + '_Wrapper' vexe_gen_command = \ BSC + ' ' + BSC_FLAGS_VERILOG + ' -vdir ' + vexe_vdir + ' -simdir ' + vexe_vdir + ' -bdir ' + vexe_vdir +' -p +:' + ALL_LIB_DIRS_FROM_ROOT + ' -vsearch +:' + ALL_LIB_DIRS_FROM_ROOT + ' ' + \ ' -o $TARGET' if (bsc_version >= 13013): # 2008.01.A compiler allows us to pass C++ arguments. if (model.getDebug(moduleList)): vexe_gen_command += ' -Xc++ -O0' else: vexe_gen_command += ' -Xc++ -O1' # g++ 4.5.2 is complaining about overflowing the var tracking table if (model.getGccVersion() >= 40501): vexe_gen_command += ' -Xc++ -fno-var-tracking-assignments' defs = (software_tool.host_defs()).split(" ") for definition in defs: vexe_gen_command += ' -Xc++ ' + definition + ' -Xc ' + definition # Hack to link against pthreads. Really we should have a better solution. vexe_gen_command += ' -Xl -lpthread ' # construct full path to BAs def modify_path(str): array = str.split('/') file = array.pop() return moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + '/'.join( array) + '/' + TMP_BSC_DIR + '/' + file # Use systemverilog 2005 if (moduleList.getAWBParam('verilog_tool', 'ENABLE_SYSTEM_VERILOG')): vexe_gen_command += ' -Xv -g2005-sv ' # Allow .vh/.sv file extensions etc. # vexe_gen_command += ' -Xv -Y.vh -Xv -Y.sv ' # Bluespec requires that source files terminate the command line. vexe_gen_command += '-verilog -e ' + ROOT_WRAPPER_SYNTH_ID + ' ' +\ moduleList.env['DEFS']['BDPI_CS'] if (model.getBuildPipelineDebug(moduleList) != 0): for m in moduleList.getAllDependencies('BA'): print 'BA dep: ' + str(m) for m in moduleList.getAllDependencies('VERILOG'): print 'VL dep: ' + str(m) for m in moduleList.getAllDependencies('VHDL'): print 'BA dep: ' + str(m) # Generate a thin wrapper around the verilog executable. This # wrapper is used to address a problem in iverilog in which the # simulator does not support shared library search paths. The # current wrapper only works for iverilog. Due to brokeness in # the iverilog argument parser, we must construct a correct # iverilog command line by analyzing its compiled script. Also, # this script is not passing through the arguments that it should # be passing through. def generate_vexe_wrapper(target, source, env): wrapper_handle = open(str(target[0]), 'w') wrapper_handle.write('#!/usr/bin/perl\n') wrapper_handle.write('# generated by verilog.py\n') wrapper_handle.write('$platform = $ENV{"PLATFORM_DIRECTORY"};\n') wrapper_handle.write('@script = `cat $platform/' + TMP_BSC_DIR + '/' + APM_NAME + '_hw.exe' + '`;\n') wrapper_handle.write('$script[0] =~ s/#!/ /g;\n') wrapper_handle.write('$vvp = $script[0];\n') wrapper_handle.write('chomp($vvp);\n') wrapper_handle.write( 'exec("$vvp -m$platform/directc_mk_model_Wrapper.so $platform/' + TMP_BSC_DIR + '/' + APM_NAME + '_hw.exe' + ' +bscvcd \$* ");\n') wrapper_handle.close() def modify_path_ba_local(path): return bsv_tool.modify_path_ba(moduleList, path) # Bluesim builds apparently touch this code. This control block # preserves their behavior, but it is unclear why the verilog build is # involved. if (isPrimaryBuildTarget): vbinDeps = [] # If we got a lim graph, we'll pick up many of our dependencies from it. # These were annotated in the top module above. Really, this seems unclean. # we should build a graph during the second pass and just use it. if (not self.firstPassLIGraph is None): # Collect linked dependencies for every module for moduleName in self.firstPassLIGraph.modules: moduleListObject = moduleList.modules[moduleName] vbinDeps += moduleList.getDependencies( moduleListObject, 'VERILOG') + moduleList.getDependencies( moduleListObject, 'GIVEN_VERILOG_HS') + moduleList.getDependencies( moduleListObject, 'GEN_VPI_HS') + moduleList.getDependencies( moduleListObject, 'GEN_VPI_CS') + moduleList.getDependencies( moduleListObject, 'VHDL') + moduleList.getDependencies( moduleListObject, 'BA') + moduleList.getDependencies( moduleListObject, 'GEN_BAS') vbinDeps += moduleList.getDependencies( moduleList.topModule, 'VERILOG') + moduleList.getDependencies( moduleList.topModule, 'GIVEN_VERILOG_HS') + moduleList.getDependencies( moduleList.topModule, 'GEN_VPI_HS') + moduleList.getDependencies( moduleList.topModule, 'GEN_VPI_CS' ) + moduleList.getDependencies( moduleList.topModule, 'VHDL' ) + moduleList.getDependencies( moduleList.topModule, 'BA') + map( modify_path_ba_local, moduleList.getModuleDependenciesWithPaths( moduleList.topModule, 'GEN_BAS')) # collect dependencies from all awb modules else: vbinDeps += moduleList.getAllDependencies( 'VERILOG') + moduleList.getAllDependencies( 'VHDL') + moduleList.getAllDependencies('BA') + map( modify_path_ba_local, moduleList.getAllDependenciesWithPaths('GEN_BAS')) vbin = moduleList.env.Command( TMP_BSC_DIR + '/' + APM_NAME + '_hw.exe', vbinDeps, [vexe_gen_command, SCons.Script.Delete('directc.sft')]) vexe = moduleList.env.Command(APM_NAME + '_hw.exe', vbin, [ generate_vexe_wrapper, '@chmod a+x $TARGET', SCons.Script.Delete(APM_NAME + '_hw.errinfo') ]) moduleList.topDependency = moduleList.topDependency + [vexe] else: vbinDeps = moduleList.getAllDependencies( 'VERILOG') + moduleList.getAllDependencies( 'VHDL') + moduleList.getAllDependencies('BA') + map( modify_path_ba_local, moduleList.getAllDependenciesWithPaths('GEN_BAS')) vbin = moduleList.env.Command( TMP_BSC_DIR + '/' + APM_NAME + '_hw.vexe', vbinDeps, [vexe_gen_command, SCons.Script.Delete('directc.sft')]) vexe = moduleList.env.Command(APM_NAME + '_hw.vexe', vbin, [ generate_vexe_wrapper, '@chmod a+x $TARGET', SCons.Script.Delete(APM_NAME + '_hw.exe'), SCons.Script.Delete(APM_NAME + '_hw.errinfo') ]) moduleList.env.Alias('vexe', vexe)
def __init__(self, moduleList): # if we have a deps build, don't do anything... if (moduleList.isDependsBuild): return self.firstPassLIGraph = wrapper_gen_tool.getFirstPassLIGraph() # A collector for all of the checkpoint objects we will gather/build in the following code. dcps = [] # Construct the tcl file self.part = moduleList.getAWBParam('physical_platform_config', 'FPGA_PART_XILINX') apm_name = moduleList.compileDirectory + '/' + moduleList.apmName self.paramTclFile = moduleList.topModule.moduleDependency['PARAM_TCL'][ 0] # If the TMP_FPGA_DIR doesn't exist, create it. if not os.path.isdir(moduleList.env['DEFS']['TMP_FPGA_DIR']): os.mkdir(moduleList.env['DEFS']['TMP_FPGA_DIR']) # Gather Tcl files for handling constraints. self.tcl_headers = [] if (len( moduleList.getAllDependenciesWithPaths( 'GIVEN_VIVADO_TCL_HEADERS')) > 0): self.tcl_headers = map( model.modify_path_hw, moduleList.getAllDependenciesWithPaths( 'GIVEN_VIVADO_TCL_HEADERS')) self.tcl_defs = [] if (len( moduleList.getAllDependenciesWithPaths( 'GIVEN_VIVADO_TCL_DEFINITIONS')) > 0): self.tcl_defs = map( model.modify_path_hw, moduleList.getAllDependenciesWithPaths( 'GIVEN_VIVADO_TCL_DEFINITIONS')) self.tcl_funcs = [] if (len( moduleList.getAllDependenciesWithPaths( 'GIVEN_VIVADO_TCL_FUNCTIONS')) > 0): self.tcl_funcs = map( model.modify_path_hw, moduleList.getAllDependenciesWithPaths( 'GIVEN_VIVADO_TCL_FUNCTIONS')) self.tcl_algs = [] if (len( moduleList.getAllDependenciesWithPaths( 'GIVEN_VIVADO_TCL_ALGEBRAS')) > 0): self.tcl_algs = map( model.modify_path_hw, moduleList.getAllDependenciesWithPaths( 'GIVEN_VIVADO_TCL_ALGEBRAS')) self.tcl_bmms = [] if (len(moduleList.getAllDependencies('GIVEN_XILINX_BMMS')) > 0): self.tcl_bmms = moduleList.getAllDependencies('GIVEN_XILINX_BMMS') self.tcl_elfs = [] if (len(moduleList.getAllDependencies('GIVEN_XILINX_ELFS')) > 0): self.tcl_elfs = moduleList.getAllDependencies('GIVEN_XILINX_ELFS') self.tcl_ag = [] #Emit area group definitions # If we got an area group placement data structure, now is the # time to convert it into a new constraint tcl. self.area_group_file = moduleList.compileDirectory + '/areagroups.xdc' if ('AREA_GROUPS' in moduleList.topModule.moduleDependency): self.area_constraints = area_group_tool.AreaConstraints(moduleList) self.routeAG = (moduleList.getAWBParam( 'area_group_tool', 'AREA_GROUPS_ROUTE_AG') != 0) # user ucf may be overridden by our area group ucf. Put our # generated ucf first. #tcl_defs.insert(0,self.area_group_file) def area_group_ucf_closure(moduleList): def area_group_ucf(target, source, env): self.area_constraints.loadAreaConstraints() self.area_constraints.emitConstraintsVivado( self.area_group_file) return area_group_ucf moduleList.env.Command([self.area_group_file], self.area_constraints.areaConstraintsFile(), area_group_ucf_closure(moduleList)) synthDepsBase = moduleList.getAllDependencies('GEN_VIVADO_DCPS') # We got a stack of synthesis results for the LI modules. We need # to convert these to design checkpoints for the fast place and # route flow. ngcModules = [ module for module in moduleList.synthBoundaries() if not module.liIgnore ] for module in ngcModules + [moduleList.topModule]: # did we get a dcp from the first pass? If so, did the lim # graph give code for this module? If both are true, then we # will link the old ngc in, rather than regenerate it. if ((not self.firstPassLIGraph is None) and (module.name in self.firstPassLIGraph.modules) and (self.firstPassLIGraph.modules[ module.name].getAttribute('RESYNTHESIZE') is None)): if (li_module.linkFirstPassObject( moduleList, module, self.firstPassLIGraph, 'GEN_VIVADO_DCPS', 'GEN_VIVADO_DCPS') is None): module.moduleDependency['GEN_VIVADO_DCPS'] = [ self.edf_to_dcp(moduleList, module) ] # it's possible that we got dcp from this compilation # pass. This will happen for the platform modules. elif (len(module.getDependencies('GEN_VIVADO_DCPS')) > 0): continue # we got neither. therefore, we must create a dcp out of the ngc. else: module.moduleDependency['GEN_VIVADO_DCPS'] = [ self.edf_to_dcp(moduleList, module) ] synthDeps = moduleList.getAllDependencies('GEN_VIVADO_DCPS') postSynthTcl = apm_name + '.physical.tcl' topWrapper = moduleList.topModule.wrapperName() newTclFile = open(postSynthTcl, 'w') newTclFile.write('create_project -force ' + moduleList.apmName + ' ' + moduleList.compileDirectory + ' -part ' + self.part + ' \n') # To resolve black boxes, we need to load checkpoints in the # following order: # 1) topModule # 2) platformModule # 3) user program, in any order userModules = [ module for module in moduleList.synthBoundaries() if not module.liIgnore and not module.platformModule ] platformModules = [ module for module in moduleList.synthBoundaries() if not module.liIgnore and module.platformModule ] checkpointCommands = [] if (not moduleList.getAWBParamSafe('area_group_tool', 'AREA_GROUPS_ENABLE')): for module in [moduleList.topModule ] + platformModules + userModules: dcps.append(module.getDependencies('GEN_VIVADO_DCPS')) checkpoint = model.convertDependencies( module.getDependencies('GEN_VIVADO_DCPS')) # There should only be one checkpoint here. if (len(checkpoint) > 1): print "Error too many checkpoints for " + str( module.name) + ": " + str(checkpoint) continue if (len(checkpoint) == 0): print "No checkpoints for " + str( module.name) + ": " + str(checkpoint) continue newTclFile.write('read_checkpoint ' + checkpoint[0] + '\n') # We're attempting the new, parallel flow. else: # we need to issue seperate place commands. Therefore, we attempt to place each design # There may be some special area groups in platforms -- handle them elabAreaConstraints = area_group_tool.AreaConstraints(moduleList) elabAreaConstraints.loadAreaConstraintsElaborated() #self.area_constraints = area_group_tool.AreaConstraints(moduleList) for module in userModules: # Did we get a placed module already? if ((module.name in elabAreaConstraints.constraints) and ('LIBRARY_DCP' in elabAreaConstraints.constraints[ module.name].attributes)): # we need to locate the dcp corresponding to this area group. candidates = moduleList.getAllDependencies( 'GIVEN_VIVADO_DCPS') for dcpCandidate in moduleList.getAllDependencies( 'GIVEN_VIVADO_DCPS'): if dcpCandidate.attributes['module'] == module.name: dcp = str(model.modify_path_hw(dcpCandidate)) model.dictionary_list_create_append( module.moduleDependency, 'GEN_VIVADO_PLACEMENT_DCPS', dcp) dcps.append(dcp) else: dcp = self.place_dcp(moduleList, module) model.dictionary_list_create_append( module.moduleDependency, 'GEN_VIVADO_PLACEMENT_DCPS', dcp) dcps.append(dcp) for module in [moduleList.topModule] + platformModules: checkpoint = model.convertDependencies( module.getDependencies('GEN_VIVADO_DCPS')) dcps.append(checkpoint) # There should only be one checkpoint here. if (len(checkpoint) > 1): print "Error too many checkpoints for " + str( module.name) + ": " + str(checkpoint) continue if (len(checkpoint) == 0): print "No checkpoints for " + str( module.name) + ": " + str(checkpoint) continue newTclFile.write('read_checkpoint ' + checkpoint[0] + '\n') # We can have parent/child relationships in the user modules. # Vivado requires that checkpoints be read in topological # order. def isBlackBox(module): if (self.firstPassLIGraph.modules[module.name].getAttribute( 'BLACK_BOX_AREA_GROUP')): return 1 return 0 for module in sorted(userModules, key=isBlackBox): checkpoint = model.convertDependencies( module.getDependencies('GEN_VIVADO_PLACEMENT_DCPS')) # There should only be one checkpoint here. if (len(checkpoint) > 1): print "Error too many checkpoints for " + str( module.name) + ": " + str(checkpoint) continue if (len(checkpoint) == 0): print "No checkpoints for " + str( module.name) + ": " + str(checkpoint) continue #read in new checkoutpoint newTclFile.write('read_checkpoint ' + checkpoint[0] + '\n') emitPlatformAreaGroups = (moduleList.getAWBParam( 'area_group_tool', 'AREA_GROUPS_GROUP_PLATFORM_CODE') != 0) # platformModule refers to the main platform module, not # the subordinate device area groups. platformModule = ( self.firstPassLIGraph.modules[module.name].getAttribute( 'BLACK_BOX_AREA_GROUP') is None) and (not self.firstPassLIGraph.modules[ module.name].getAttribute('PLATFORM_MODULE') is None) allowAGPlatform = ( not platformModule) or emitPlatformAreaGroups emitDeviceGroups = (moduleList.getAWBParam( 'area_group_tool', 'AREA_GROUPS_PAR_DEVICE_AG') != 0) allowAGDevice = (self.firstPassLIGraph.modules[ module.name].getAttribute('BLACK_BOX_AREA_GROUP') is None) or emitDeviceGroups if (allowAGPlatform and allowAGDevice): refName = module.wrapperName() lockPlacement = True lockRoute = self.routeAG # If this is an platform/user-defined area group, the wrapper name may be different. if (not self.firstPassLIGraph.modules[module.name]. getAttribute('BLACK_BOX_AREA_GROUP') is None): refName = elabAreaConstraints.constraints[ module.name].attributes['MODULE_NAME'] lockPlacement = not ( 'NO_PLACE' in elabAreaConstraints.constraints[ module.name].attributes) and lockPlacement lockRoute = not ( 'NO_ROUTE' in elabAreaConstraints.constraints[ module.name].attributes) and lockRoute checkpointCommands.append( 'if { [llength [get_cells -hier -filter {REF_NAME =~ "' + refName + '"}]] } {\n') checkpointCommands.append(' puts "Locking ' + refName + '"\n') if (lockRoute): # locking routing requires us to emit an area group. boo. ag_tcl = self.ag_constraints(moduleList, module) self.tcl_ag.append(ag_tcl) checkpointCommands.append(' source ' + str(ag_tcl) + '\n') checkpointCommands.append( ' lock_design -level routing [get_cells -hier -filter {REF_NAME =~ "' + refName + '"}]\n') elif (lockPlacement): checkpointCommands.append( ' lock_design -level placement [get_cells -hier -filter {REF_NAME =~ "' + refName + '"}]\n') checkpointCommands.append('}\n') given_netlists = [ moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + netlist for netlist in moduleList.getAllDependenciesWithPaths('GIVEN_NGCS') + moduleList.getAllDependenciesWithPaths('GIVEN_EDFS') ] for netlist in given_netlists: newTclFile.write('read_edif ' + netlist + '\n') # We have lots of dangling wires (Thanks, Bluespec). Set the # following properties to silence the warnings. newTclFile.write( "set_property SEVERITY {Warning} [get_drc_checks NSTD-1]\n") newTclFile.write( "set_property SEVERITY {Warning} [get_drc_checks UCIO-1]\n") newTclFile.write("link_design -top " + topWrapper + " -part " + self.part + "\n") newTclFile.write("report_utilization -file " + apm_name + ".link.util\n") newTclFile.write("write_checkpoint -force " + apm_name + ".link.dcp\n") # lock down the area group routing. newTclFile.write("\n".join(checkpointCommands) + "\n") for elf in self.tcl_elfs: newTclFile.write("add_file " + model.modify_path_hw(elf) + "\n") newTclFile.write("set_property MEMDATA.ADDR_MAP_CELLS {" + str(elf.attributes['ref']) + "} [get_files " + model.modify_path_hw(elf) + "]\n") # We will now attempt to link in any bmm that we might have. for bmm in self.tcl_bmms: newTclFile.write("add_file " + model.modify_path_hw(bmm) + "\n") newTclFile.write("set_property SCOPED_TO_REF " + str(bmm.attributes['ref']) + " [get_files " + model.modify_path_hw(bmm) + "]\n") newTclFile.write('set IS_TOP_BUILD 1\n ') newTclFile.write('set IS_AREA_GROUP_BUILD 0\n ') newTclFile.write('set SYNTH_OBJECT ""\n') newTclFile.write('source ' + self.paramTclFile + '\n') for tcl_header in self.tcl_headers: newTclFile.write('source ' + tcl_header + '\n') for tcl_def in self.tcl_defs: newTclFile.write('source ' + tcl_def + '\n') for tcl_func in self.tcl_funcs: newTclFile.write('source ' + tcl_func + '\n') for tcl_alg in self.tcl_algs: newTclFile.write('source ' + tcl_alg + '\n') def dumpPBlockCmd(tgt): return 'dumpPBlockUtilization "' + moduleList.compileDirectory + '/' + tgt + '.util"\n' newTclFile.write(dumpPBlockCmd('link')) newTclFile.write("report_timing_summary -file " + apm_name + ".map.twr\n\n") newTclFile.write("opt_design -directive AddRemap\n") newTclFile.write("report_utilization -file " + apm_name + ".opt.util\n") newTclFile.write(dumpPBlockCmd('opt')) newTclFile.write("write_checkpoint -force " + apm_name + ".opt.dcp\n\n") newTclFile.write( "place_design -no_drc -directive WLDrivenBlockPlacement\n") newTclFile.write(dumpPBlockCmd('place')) newTclFile.write("phys_opt_design -directive AggressiveFanoutOpt\n") newTclFile.write("write_checkpoint -force " + apm_name + ".map.dcp\n") newTclFile.write(dumpPBlockCmd('phyopt')) newTclFile.write("report_utilization -file " + apm_name + ".map.util\n\n") newTclFile.write("route_design\n") newTclFile.write("write_checkpoint -force " + apm_name + ".par.dcp\n") newTclFile.write(dumpPBlockCmd('par')) newTclFile.write("report_timing_summary -file " + apm_name + ".par.twr\n\n") newTclFile.write("report_utilization -hierarchical -file " + apm_name + ".par.util\n") newTclFile.write("report_drc -file " + topWrapper + ".drc\n\n") newTclFile.write("write_bitstream -force " + apm_name + "_par.bit\n") newTclFile.close() # generate bitfile xilinx_bit = moduleList.env.Command( apm_name + '_par.bit', synthDeps + self.tcl_algs + self.tcl_defs + self.tcl_funcs + self.tcl_ag + [self.paramTclFile] + dcps + [postSynthTcl], [ 'touch start.txt; vivado -verbose -mode batch -source ' + postSynthTcl + ' -log ' + moduleList.compileDirectory + '/postsynth.log' ]) moduleList.topModule.moduleDependency['BIT'] = [apm_name + '_par.bit'] # We still need to generate a download script. xilinx_loader.LOADER(moduleList)