示例#1
0
文件: BSVUtils.py 项目: chenm001/leap
def decorateBluespecLibraryCode(moduleList):
    # get the baseline verilog
    bsvBaselineArray = get_bluespec_verilog(moduleList.env)

    # Is there tool specific code?
    if (not moduleList.getAWBParamSafe('synthesis_tool', 'USE_VIVADO_SOURCES') is None):
        bsvVerilog = get_bluespec_verilog(moduleList.env, resultArray = bsvBaselineArray, filePath = 'Verilog.Vivado').values()
    elif (not moduleList.getAWBParamSafe('synthesis_tool', 'USE_QUARTUS_SOURCES') is None):
        bsvVerilog = get_bluespec_verilog(moduleList.env, resultArray = bsvBaselineArray, filePath = 'Verilog.Quartus').values()
    else:
        bsvVerilog = bsvBaselineArray.values()


    for module in moduleList.synthBoundaries():
        model.dictionary_list_create_append(module.moduleDependency, 'VERILOG_LIB', bsvVerilog)

    model.dictionary_list_create_append(moduleList.topModule.moduleDependency, 'VERILOG_LIB', bsvVerilog)
  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)
示例#3
0
    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)