Example #1
0
def generateWrapperStub(moduleList, module):
    suffixes=['_Wrapper.bsv','_Log.bsv']
    compileWrapperPath = get_build_path(moduleList, module)
    for suffix in suffixes:
        # check for file's existance before overwriting. 
        wrapperPath = compileWrapperPath + '/' + module.name + suffix
        if(os.path.exists(wrapperPath)):
            # No need to dump a spurious wrapper.
            continue

        wrapper = open(wrapperPath, 'w')

        wrapper.write('//   Wrapper Stub. This file was created by wrapper-gen\n')  

        wrapper.write('import Vector::*;\n')
        generateWellKnownIncludes(wrapper)
        wrapper.write('// import non-synthesis public files\n')
        wrapper.write('`include "' + module.name + '_compile.bsv"\n')

        ## Import all other modules used in the build.  On the first pass this
        ## is simply all modules.  After that import only the modules used
        ## on the platform.
        first_pass_LI_graph = getFirstPassLIGraph()
        import_modules = []
        if (first_pass_LI_graph is None):
            import_modules = [m for m in moduleList.synthBoundaries() if not m.platformModule]
        else:
            import_modules = bsv_tool.getUserModules(first_pass_LI_graph)

        for m in sorted(import_modules, key=lambda m: m.name):
            wrapper.write('import ' + m.name + '_Wrapper::*;\n')

        wrapper.close()
Example #2
0
File: BSV.py Project: chenm001/leap
        def compile_bo_closure(source, target, env, for_signature):
            cmd = ''

            if (str(source[0]) !=
                    get_build_path(self.moduleList, self.moduleList.topModule)
                    + '/' + self.moduleList.topModule.name + '.bsv'):
                cmd = self.compile_bo_bsc_base(
                    target, module_path) + ' -D CONNECTION_SIZES_KNOWN ' + str(
                        source[0])
            return cmd
Example #3
0
def generateAWBCompileWrapper(moduleList, module):
    compileWrapperPath = get_build_path(moduleList, module)
    wrapper = open( compileWrapperPath + '/' + module.name + '_compile.bsv', 'w')

    wrapper.write('//   AWB Compile Wrapper. This file was created by wrapper-gen\n')  
    wrapper.write('`define BUILDING_MODULE_' + module.name + '\n')

    for includeClass in ['GIVEN_BSVS', 'WRAPPER_BSHS']:
        if (includeClass in module.moduleDependency):
            for file in module.moduleDependency[includeClass]:
                wrapper.write('`include "' + file +'"\n')

    wrapper.close()
Example #4
0
def getModuleRTLs(moduleList, module):
    moduleVerilogs = []
    moduleVHDs = []
    MODULE_PATH =  model.get_build_path(moduleList, module) 
    for v in moduleList.getDependencies(module, 'GEN_VERILOGS'):              
        moduleVerilogs += [MODULE_PATH + '/' + moduleList.env['DEFS']['TMP_BSC_DIR'] + '/' + v]
    for v in moduleList.getDependencies(module, 'GIVEN_VERILOGS'): 
        moduleVerilogs += [MODULE_PATH + '/' + v]
    for v in moduleList.getDependencies(module, 'GIVEN_VHDS'): 
        moduleVHDs += [MODULE_PATH + '/' + v]
    for v in moduleList.getDependencies(module, 'GIVEN_VHDLS'):
        lib = ""
        if('lib' in v.attributes):
            lib = v.attributes['lib'] + '/'
        moduleVHDs += [model.Source.Source(MODULE_PATH + '/' + lib + v.file, v.attributes)]


    return [moduleVerilogs, moduleVHDs] 
Example #5
0
def getModuleRTLs(moduleList, module):
    moduleVerilogs = []
    moduleVHDs = []
    MODULE_PATH =  model.get_build_path(moduleList, module) 
    for v in moduleList.getDependencies(module, 'GEN_VERILOGS'):              
        moduleVerilogs += [MODULE_PATH + '/' + moduleList.env['DEFS']['TMP_BSC_DIR'] + '/' + v]
    for v in moduleList.getDependencies(module, 'GIVEN_VERILOGS'): 
        moduleVerilogs += [MODULE_PATH + '/' + v]
    for v in moduleList.getDependencies(module, 'GIVEN_VHDS'): 
        moduleVHDs += [MODULE_PATH + '/' + v]
    for v in moduleList.getDependencies(module, 'GIVEN_VHDLS'):
        lib = ""
        if('lib' in v.attributes):
            lib = v.attributes['lib'] + '/'
        moduleVHDs += [model.Source.Source(MODULE_PATH + '/' + lib + v.file, v.attributes)]


    return [moduleVerilogs, moduleVHDs] 
Example #6
0
def getSynthHandle(moduleList, module):
    compileWrapperPath = get_build_path(moduleList, module)
    path = compileWrapperPath + '/' + module.name + '_synth.bsv'
    print "Generating synthesis stub: " + path
    return open(path, 'w')
    def setupTreeBuild(self, moduleList, topo):
        useBVI = self.parent.USE_BVI
        env = moduleList.env

        root_directory = model.rootDir

        ##
        ## Load intra-Bluespec dependence already computed.  This
        ## information will ultimately drive the building of Bluespec
        ## modules. Build tree has a few dependencies which must be
        ## captured.
        ##

        ## If we aren't building the build tree, don't bother with its dependencies
        env.ParseDepends(get_build_path(moduleList, moduleList.topModule) + '/.depends-build-tree',
                         must_exist = not moduleList.env.GetOption('clean'))
        tree_base_path = env.Dir(get_build_path(moduleList, moduleList.topModule))

        tree_file_synth = tree_base_path.File('build_tree_synth.bsv')
        tree_file_synth_bo_path = tree_base_path.File(self.parent.TMP_BSC_DIR + '/build_tree_synth.bo')

        tree_file_wrapper = tree_base_path.File('build_tree_Wrapper.bsv')
        tree_file_wrapper_bo_path = tree_base_path.File(self.parent.TMP_BSC_DIR + '/build_tree_Wrapper.bo')

        # Area constraints
        area_constraints = None
        try:
            if (moduleList.getAWBParam('area_group_tool', 'AREA_GROUPS_ENABLE')):
                area_constraints = area_group_tool.AreaConstraints(moduleList)
        except:
            # The area constraints code is not present.
            pass

        boundary_logs = []
        for module in topo:
            # Remove any platform modules.. These are special in that
            # they can have wired interfaces.
            if (not module.platformModule):
                for log in module.moduleDependency['BSV_LOG']:
                    boundary_logs += [root_directory.File(log)]
        ##
        ## Back to SCons configuration (first) pass...
        ##

        top_module_path = get_build_path(moduleList, moduleList.topModule)

        # Inform object code build of the LI Graph retrieved from the
        # first pass.  Probe firstPassGraph for relevant object codes
        # (BA/NGC/BSV_SYNTH/BSV_SYNTH_BSH) accessed:
        # module.objectCache['NGC'] (these already have absolute
        # paths) I feel like the GEN_BAS/GEN_VERILOGS of the first
        # pass may be missing.  We insert these modules as objects in
        # the ModuleList.

        def makeAWBLink(doLink, source, buildPath, uniquifier=''):
            base_file = os.path.basename(str(source))
            link_dir = buildPath + '/.li'
            link_path =  link_dir + '/' + uniquifier + base_file
            if (doLink):
                if (os.path.lexists(link_path)):
                    os.remove(link_path)
                rel = os.path.relpath(str(source), link_dir)
                print 'Linking: ' + link_path + ' -> ' + rel
                os.symlink(rel, link_path)

            return link_path


        limLinkUserSources = []
        limLinkUserTargets = []
        limLinkPlatformSources = []
        limLinkPlatformTargets = []
        importStubs = []


        if (not self.getFirstPassLIGraph is None):
            # Now that we have demanded bluespec builds (for
            # dependencies), we should now should downgrade synthesis boundaries for the backend.
            oldStubs = []
            for module in topo:
                if(not module.platformModule):
                    if((not module.name in self.getFirstPassLIGraph.modules) or (self.getFirstPassLIGraph.modules[module.name].getAttribute('RESYNTHESIZE') is None)): 
                        module.liIgnore = True
                    # this may not be needed.
                    else:
                        oldStubs += module.moduleDependency['GEN_VERILOG_STUB']

            # let's pick up the platform dependencies, since they are also special.
            env.ParseDepends(get_build_path(moduleList, moduleList.topModule) + '/.depends-platform',
                             must_exist = not moduleList.env.GetOption('clean'))

            # Due to the way that string files are
            # generated, they are difficult to rename in
            # the front-end compilation. This leads to
            # collisions amoung similarly-typed LI
            # Modules.  We fix it by uniquifying the links.

            def getModuleName(module):
                return module.name

            def getEmpty(module):
                return ''

            linkthroughMap = {'BA': getEmpty, 'GEN_BAS': getEmpty, 'GEN_VERILOGS': getEmpty, 'GEN_VERILOG_STUB': getEmpty, 'STR': getModuleName}

            buildPath = get_build_path(moduleList, moduleList.topModule)
            for module in self.getFirstPassLIGraph.modules.values():
            
                # do not link through those modules marked for resynthesis. 
                if(not module.getAttribute('RESYNTHESIZE') is None):  
                    continue

                moduleDeps = {}

                for objType in linkthroughMap:
                    if(objType in module.objectCache):
                        localNames =  map(lambda fileName: makeAWBLink(False,
                                                                       fileName.from_bld(),
                                                                       buildPath, 
                                                                       uniquifier=linkthroughMap[objType](module)),
                                          module.objectCache[objType])

                        # The previous passes GEN_VERILOGS are not
                        # really generated here, so we can't call them
                        # as such. Tuck them in to 'VERILOG'
                        if(objType == 'GEN_VERILOG_STUB'):
                            oldStubs += localNames                        
                        moduleDeps[objType] = localNames

                        if (module.getAttribute('PLATFORM_MODULE') is None):
                            limLinkUserTargets += localNames
                            limLinkUserSources += module.objectCache[objType]
                        else:
                            limLinkPlatformTargets += localNames
                            limLinkPlatformSources += module.objectCache[objType]

                m = Module(module.name, ["mk_" + module.name + "_Wrapper"],\
                           moduleList.topModule.buildPath, moduleList.topModule.name,\
                           [], moduleList.topModule.name, [], moduleDeps)

                moduleList.insertModule(m)
        else:
            # The top module/build pipeline only depend on non-platformModules
            oldStubs = [module.moduleDependency['GEN_VERILOG_STUB'] for module in moduleList.synthBoundaries() if not module.platformModule]




        ## Enumerate the dependencies created by the build tree.
        buildTreeDeps = {}

        ## We have now generated a completely new module. Let's throw it
        ## into the list.  Although we are building it seperately, this
        ## module is an extension to the build tree.
        expected_wrapper_count = len(boundary_logs) - 2
        importBOs = []

        if (not self.getFirstPassLIGraph is None):
            # we now have platform modules in here.
            expected_wrapper_count = len(self.getFirstPassLIGraph.modules) - 2

            # If we have an LI graph, we need to construct and compile
            # LI import wrappers for the modules we received from the
            # first pass.  Do that here.  include all the dependencies
            # in the graph in the wrapper.
            liGraph = LIGraph([])
            firstPassGraph = self.getFirstPassLIGraph
            # We should ignore the 'PLATFORM_MODULE'
            liGraph.mergeModules([ module for module in bsv_tool.getUserModules(firstPassGraph) if module.getAttribute('RESYNTHESIZE') is None])
            for module in sorted(liGraph.graph.nodes(), key=lambda module: module.name):
                # pull in the dependecies generate by the dependency pass.
                env.ParseDepends(str(tree_base_path) + '/.depends-' + module.name,
                                 must_exist = not moduleList.env.GetOption('clean'))
                wrapper_path = tree_base_path.File(module.name + '_Wrapper.bsv')
                wrapper_bo_path = tree_base_path.File(self.parent.TMP_BSC_DIR + '/' + module.name + '_Wrapper.bo')

                # include commands to build the wrapper .bo/.ba
                # Here, we won't be using the generated .v (it's garbage), so we intentionally  get rid of it.
                importVDir = env.Dir('.lim_import_verilog')
                if not os.path.isdir(str(importVDir)):
                   os.mkdir(str(importVDir))

                wrapper_command = self.parent.compile_bo_bsc_base([wrapper_bo_path], get_build_path(moduleList, moduleList.topModule), vdir=importVDir) + ' $SOURCES'
                wrapper_bo = env.Command([wrapper_bo_path],
                                         [wrapper_path],
                                         wrapper_command)
                # create BO.
                importBOs += [wrapper_bo]

        verilog_deps = [ "__TREE_MODULE__" + str(id) for id in range(expected_wrapper_count)]

        if(self.parent.BUILD_LOGS_ONLY == 0):
            buildTreeDeps['GEN_VERILOGS'] = ["mk_" + vlog + '_Wrapper' + ".v"  for vlog in verilog_deps]
        else:
            buildTreeDeps['GEN_VERILOGS'] = []

        buildTreeDeps['GEN_BAS'] = [  "mk_" + vlog + '_Wrapper' + ".ba" for vlog in verilog_deps]
        buildTreeDeps['BA'] = []
        buildTreeDeps['STR'] = []
        buildTreeDeps['VERILOG'] = [top_module_path + '/' + self.parent.TMP_BSC_DIR + '/mk_build_tree_Wrapper.v']
        buildTreeDeps['GIVEN_BSVS'] = []
        buildTreeDeps['VERILOG_STUB'] = model.convertDependencies(oldStubs)

        tree_module = Module( 'build_tree', ["mkBuildTree"], moduleList.topModule.buildPath,\
                             moduleList.topModule.name,\
                             [], moduleList.topModule.name, [], buildTreeDeps, platformModule=True)

        tree_module.putAttribute('LI_GRAPH_IGNORE', True)

        moduleList.insertModule(tree_module)    
        wrapper_gen_tool.generateAWBCompileWrapper(moduleList, tree_module)

        ## This produces the treeNode BSV. It must wait for the
        ## compilation of the log files, which it will read to form the
        ## LIM graph
        ##
        ## We do two operations during this phase.  First, we dump a
        ## representation of the user program. This representation is
        ## used by the LIM compiler to create heterogeneous
        ## executables.  We then do a local modification to the build
        ## tree to reduce Bluespec compilation time.

        # If I got an LI graph, I don't care about the boundary logs.
        # In this case, everything comes from the first pass graph.

        # Usually, we only need logs and BOs to build the build tree.
        # However, during the second pass build we also need to fill
        # in information about area group paths (changed by tree build)
        tree_build_deps = boundary_logs + importBOs
        tree_build_results = [tree_file_wrapper, tree_file_synth]

        if (self.getFirstPassLIGraph and area_constraints):
            tree_build_deps += [area_constraints.areaConstraintsFilePlaced()]
            tree_build_results += [area_constraints.areaConstraintsFile()]

        ##
        ## The cutTreeBuild builder function needs some of the local state
        ## in the current function.  Build a dictionary with the required
        ## state and partial instance of cutTreeBuild with the state applied.
        ##
        cut_tree_state = dict()
        cut_tree_state['area_constraints'] = area_constraints
        cut_tree_state['boundary_logs'] = boundary_logs
        cut_tree_state['moduleList'] = moduleList
        cut_tree_state['tree_file_synth'] = tree_file_synth
        cut_tree_state['tree_file_wrapper'] = tree_file_wrapper

        cut_tree_build = functools.partial(self.cutTreeBuild, cut_tree_state)
        cut_tree_build.__name__ = 'cutTreeBuild'

        tree_components = env.Command(tree_build_results,
                                      tree_build_deps,
                                      cut_tree_build)

        ## Compiling the build tree wrapper produces several .ba
        ## files, some that are useful, the TREE_MODULES, and some
        ## which are not, the _Wrapper.ba.  As a result, we dump the
        ## tree build output to a different directory, so as not to
        ## pollute the existing build.  Here, we link to the relevant
        ## files in that directory.

        def linkLIMObjClosure(liModules, buildPath):
            def linkLIMObj(target, source, env):
                if (not self.getFirstPassLIGraph is None):
                    # The LIM build has passed us some source and we need
                    # to patch it through.
                    for module in liModules:
                        for objType in linkthroughMap:
                            if(objType in module.objectCache):                
                                map(lambda fileName: makeAWBLink(True, fileName.from_bld(), buildPath, uniquifier=linkthroughMap[objType](module)),
                                    module.objectCache[objType])

            return linkLIMObj


        ## The top level build depends on the compilation of the tree components
        ## into bo/ba/v files.

        # the GEN_BAS attached to the build tree need to be massaged
        # to reflect their actual path.  Perhaps we should be using
        # some kind of object that makes these sorts of conversions
        # simpler.

        producedBAs = map(lambda path: bsv_tool.modify_path_ba(moduleList, path), moduleList.getModuleDependenciesWithPaths(tree_module, 'GEN_BAS'))
        producedVs = map(lambda path: bsv_tool.modify_path_ba(moduleList, path), moduleList.getModuleDependenciesWithPaths(tree_module, 'GEN_VERILOGS')) + \
                     buildTreeDeps['VERILOG']

        tree_command = self.parent.compile_bo_bsc_base([tree_file_wrapper_bo_path], get_build_path(moduleList, moduleList.topModule)) + ' ' + tree_file_wrapper.path
        tree_file_wrapper_bo = env.Command([tree_file_wrapper_bo_path] + producedBAs + producedVs,
                                           tree_components,
                                           tree_command)

        # If we got a first pass LI graph, we need to link its object codes.
        if (not self.getFirstPassLIGraph is None):
            srcs = [s.from_bld() for s in limLinkUserSources]
            link_lim_user_objs = env.Command(limLinkUserTargets,
                                             srcs,
                                             linkLIMObjClosure([ module for module in bsv_tool.getUserModules(firstPassGraph) if module.getAttribute('RESYNTHESIZE') is None],
                                                               tree_base_path.path))
            env.Depends(link_lim_user_objs, tree_file_wrapper_bo)


        # the tree_file_wrapper build needs all the wrapper bo from the user program,
        # but not the top level build.
        top_bo = moduleList.topModule.moduleDependency['BSV_BO']
        all_bo = moduleList.getAllDependencies('BO')

        env.Depends(tree_file_wrapper_bo, all_bo)

        tree_synth_command = self.parent.compile_bo_bsc_base([tree_file_synth_bo_path], get_build_path(moduleList, moduleList.topModule)) + ' ' + tree_file_synth.path
        tree_file_synth_bo = env.Command([tree_file_synth_bo_path],
                                         [tree_file_synth, tree_file_wrapper_bo],
                                         tree_synth_command)

        env.Depends(top_bo, tree_file_synth_bo)
        env.Depends(moduleList.topModule.moduleDependency['BSV_LOG'],
                    tree_file_synth_bo)


        #Handle the platform_synth build, which is special cased.
        platform_synth = get_build_path(moduleList, moduleList.topModule) + "/" +  moduleList.localPlatformName + "_platform_synth.bsv"
        platform_synth_bo_path = get_build_path(moduleList, moduleList.topModule) + "/" + self.parent.TMP_BSC_DIR +"/" + moduleList.localPlatformName + "_platform_synth"
        # if we are in the lim linking phase, we need to change the
        # vdir directory to hide the spurious verilog generated by
        # bluespec.
        importVDir = None
        if(not self.getFirstPassLIGraph is None):
            importVDir = env.Dir('.lim_import_verilog')
            if not os.path.isdir(str(importVDir)):
                os.mkdir(str(importVDir))

        platform_synth_command = self.parent.compile_bo_bsc_base([platform_synth_bo_path + '.bo'], get_build_path(moduleList, moduleList.topModule), vdir=importVDir) + ' $SOURCE'
        platform_wrapper_bo = get_build_path(moduleList, moduleList.topModule) + "/" + self.parent.TMP_BSC_DIR + "/" +moduleList.localPlatformName + '_platform_Wrapper.bo'

        platform_synth_deps = [platform_synth]
        #if we have a module graph, we don't require the compilation of the platform_wrapper_bo.
        if (self.getFirstPassLIGraph is None):
            platform_synth_deps.append(platform_wrapper_bo)
        platform_synth_bo = env.Command([platform_synth_bo_path + '.bo'],
                                         platform_synth_deps,
                                         platform_synth_command)
        # this produces a ba also?
        env.Depends(moduleList.topModule.moduleDependency['BSV_LOG'],
                        platform_synth_bo)

        # Platform synth does the same object-bypass dance as tree_module.
        if(not self.getFirstPassLIGraph is None):
            srcs = [s.from_bld() for s in limLinkPlatformSources]
            link_lim_platform_objs = env.Command(limLinkPlatformTargets,
                                                 srcs,
                                                 linkLIMObjClosure([ module for module in bsv_tool.getPlatformModules(firstPassGraph) if module.getAttribute('RESYNTHESIZE') is None],
                                                                   tree_base_path.path))
            env.Depends(link_lim_platform_objs, platform_synth_bo)

        # need to generate a stub file for the build tree module.
        # note that in some cases, there will be only one module in
        # the graph, usually in a multifpga build.  In this case,
        # the build_tree module will be vestigal, but since we can't
        # predict this statically we'll have to build it anyway.

        tree_module.moduleDependency['GEN_VERILOG_STUB'] = [self.parent.stubGenCommand(top_module_path,
                                                                                       "build_tree",
                                                                                       top_module_path + '/' + self.parent.TMP_BSC_DIR + "/mk_build_tree_Wrapper.v")]

        # top level only depends on platform modules
        moduleList.topModule.moduleDependency['VERILOG_STUB'] = model.convertDependencies([module.moduleDependency['GEN_VERILOG_STUB'] for module in moduleList.synthBoundaries() if module.platformModule])
        if(not self.getFirstPassLIGraph is None):
            #Second pass build picks up stub files from the first pass build.
            moduleList.topModule.moduleDependency['VERILOG_STUB'] += model.convertDependencies(oldStubs)
Example #8
0
File: BSV.py Project: chenm001/leap
        def compile_bo_closure(source, target, env, for_signature):
            cmd = ''

            if (str(source[0]) != get_build_path(self.moduleList, self.moduleList.topModule) + '/' + self.moduleList.topModule.name + '.bsv'):
                cmd = self.compile_bo_bsc_base(target, module_path) + ' -D CONNECTION_SIZES_KNOWN ' + str(source[0])
            return cmd
Example #9
0
File: BSV.py Project: chenm001/leap
    def build_synth_boundary(self, moduleList, module):
        if (self.pipeline_debug != 0):
            print "Working on " + module.name

        env = moduleList.env
        BSVS = moduleList.getSynthBoundaryDependencies(module, 'GIVEN_BSVS')
        # each submodel will have a generated BSV
        GEN_BSVS = moduleList.getSynthBoundaryDependencies(module, 'GEN_BSVS')
        APM_FILE = moduleList.env['DEFS']['APM_FILE']
        BSC = moduleList.env['DEFS']['BSC']

        MODULE_PATH = get_build_path(moduleList, module)

        ##
        ## Load intra-Bluespec dependence already computed.  This information will
        ## ultimately drive the building of Bluespec modules.
        ##
        env.ParseDepends(MODULE_PATH + '/' + module.dependsFile,
                         must_exist=not moduleList.env.GetOption('clean'))

        # This function is responsible for creating build rules for
        # subdirectories.  It must be called or no subdirectory builds
        # will happen since scons won't have the recipe.
        self.setup_module_build(moduleList, MODULE_PATH)

        if not os.path.isdir(self.TMP_BSC_DIR):
            os.mkdir(self.TMP_BSC_DIR)

        moduleList.env.VariantDir(MODULE_PATH + '/' + self.TMP_BSC_DIR,
                                  '.',
                                  duplicate=0)

        # set up builds for the various bsv of this synthesis
        # boundary.  One wonders if we could handle this as a single
        # global operation.
        bsc_builds = []
        for bsv in BSVS + GEN_BSVS:
            bsc_builds += env.BSC(
                MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' +
                bsv.replace('.bsv', ''), MODULE_PATH + '/' + bsv)

        firstPassLIGraph = wrapper_gen_tool.getFirstPassLIGraph()
        # In the second pass of the LIM build, we don't need to build
        # any modules, except in some cases where we turn on
        # module-specific optimizations, as in the case of central
        # cache.  If we do need to rebuild, we'll see a tag.
        if ((module.name != moduleList.topModule.name)
                and (not firstPassLIGraph is None)
                and (module.name in firstPassLIGraph.modules) and
            (firstPassLIGraph.modules[module.name].getAttribute('RESYNTHESIZE')
             is None)):
            return

        # This should not be a for loop.
        for bsv in [model.get_wrapper(module)]:
            if env.GetOption('clean'):
                os.system('rm -f ' + MODULE_PATH + '/' +
                          bsv.replace('Wrapper.bsv', 'Log.bsv'))
                os.system('rm -f ' + MODULE_PATH + '/' +
                          bsv.replace('.bsv', '_con_size.bsh'))

            ##
            ## First pass just generates a log file to figure out cross synthesis
            ## boundary soft connection array sizes.
            ##
            ## All but the top level build need the log build pass to compute
            ## the size of the external soft connection vector.  The top level has
            ## no exposed connections and can generate the log file, needed
            ## for global strings, during the final build.
            ##
            logfile = model.get_logfile(moduleList, module)
            module.moduleDependency['BSV_LOG'] += [logfile]
            module.moduleDependency['GEN_LOGS'] = [logfile]
            if (module.name != moduleList.topModule.name):
                log = env.BSC_LOG_ONLY(
                    logfile,
                    MODULE_PATH + '/' + bsv.replace('Wrapper.bsv', 'Log'))

                ##
                ## Parse the log, generate a stub file
                ##

                stub_name = bsv.replace('.bsv', '_con_size.bsh')

                def build_con_size_bsh_closure(target, source, env):
                    liGraph = LIGraph(li_module.parseLogfiles(source))
                    # Should have only one module...
                    if (len(liGraph.modules) == 0):
                        bshModule = LIModule(module.name, module.name)
                    else:
                        bshModule = liGraph.modules.values()[0]
                    bsh_handle = open(str(target[0]), 'w')
                    wrapper_gen_tool.generateConnectionBSH(
                        bshModule, bsh_handle)
                    bsh_handle.close()

                stub = env.Command(MODULE_PATH + '/' + stub_name, log,
                                   build_con_size_bsh_closure)

            ##
            ## Now we are ready for the real build
            ##
            if (module.name != moduleList.topModule.name):
                wrapper_bo = env.BSC(
                    MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' +
                    bsv.replace('.bsv', ''), MODULE_PATH + '/' + bsv)
                moduleList.env.Depends(wrapper_bo, stub)
                module.moduleDependency['BO'] = [wrapper_bo]
                if (self.BUILD_LOGS_ONLY):
                    model_dir = self.hw_dir.Dir(
                        moduleList.env['DEFS']['ROOT_DIR_MODEL'])

                    module.moduleDependency['BSV_SCHED'] = \
                        [moduleList.env.Command(MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + module.wrapperName() + '.ba.sched',
                                                wrapper_bo,
                                                'bluetcl ' + model_dir.File('sched.tcl').path + ' -p ' + self.ALL_BUILD_DIR_PATHS + ' --m ' + module.wrapperName() + ' > $TARGET')]

                    module.moduleDependency['BSV_PATH'] = \
                        [moduleList.env.Command(MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + module.wrapperName() + '.ba.path',
                                                wrapper_bo,
                                                'bluetcl ' + model_dir.File('path.tcl').path + ' -p ' + self.ALL_BUILD_DIR_PATHS + ' --m ' + module.wrapperName() + ' > $TARGET')]

                    moduleList.topDependency += \
                        module.moduleDependency['BSV_SCHED'] + module.moduleDependency['BSV_PATH']

                    module.moduleDependency['BSV_IFC'] = \
                        [moduleList.env.Command(MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + module.wrapperName() + '.ba.ifc',
                                                wrapper_bo,
                                                'bluetcl ' + model_dir.File('interfaceType.tcl').path + ' -p ' + self.ALL_BUILD_DIR_PATHS + ' --m ' + module.wrapperName() + ' | python site_scons/model/PythonTidy.py > $TARGET')]

                    moduleList.topDependency += module.moduleDependency[
                        'BSV_IFC']

            else:
                ## Top level build can generate the log in a single pass since no
                ## connections are exposed
                wrapper_bo = env.BSC_LOG(
                    MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' +
                    bsv.replace('.bsv', ''), MODULE_PATH + '/' + bsv)

                ## SCons doesn't deal well with logfile as a 2nd target to BSC_LOG rule,
                ## failing to derive dependence correctly.
                module.moduleDependency['BSV_BO'] = [wrapper_bo]
                log = env.Command(logfile, wrapper_bo, '')
                env.Precious(logfile)

                ## In case Bluespec build is the end of the build pipeline.
                if (not self.BUILD_LOGS_ONLY):
                    moduleList.topDependency += [log]

                ## The toplevel bo also depends on the on the synthesis of the build tree from log files.

            ##
            ## Meta-data written during compilation to separate files.
            ##
            glob_str = env.Command(
                MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' +
                bsv.replace('.bsv', '.str'), wrapper_bo, '')

            env.Precious(glob_str)
            module.moduleDependency['STR'] = [glob_str]

            ## All but the top level build need the log build pass to compute
            ## the size of the external soft connection vector.  The top level has
            ## no exposed connections and needs no log build pass.
            ##
            if (module.name != moduleList.topModule.name):
                if (self.pipeline_debug != 0):
                    print 'wrapper_bo: ' + str(wrapper_bo)
                    print 'stub: ' + str(stub)

                synth_stub_path = moduleList.env['DEFS'][
                    'ROOT_DIR_HW'] + '/' + module.buildPath + '/'
                synth_stub = synth_stub_path + module.name + '_synth.bsv'
                # This stub may be needed in certain compilation flows.  Note its presence here.
                module.moduleDependency['BSV_SYNTH'] = [
                    module.name + '_synth.bsv'
                ]
                module.moduleDependency['BSV_SYNTH_BSH'] = [
                    module.name + '_Wrapper_con_size.bsh'
                ]

                def build_synth_stub(target, source, env):
                    liGraph = LIGraph(li_module.parseLogfiles(source))
                    # Should have only one module...
                    if (len(liGraph.modules) == 0):
                        synthModule = LIModule(module.name, module.name)
                    else:
                        synthModule = liGraph.modules.values()[0]

                    synth_handle = open(target[0].path, 'w')
                    wrapper_gen_tool.generateSynthWrapper(
                        synthModule,
                        synth_handle,
                        moduleList.localPlatformName,
                        moduleType=module.interfaceType,
                        extraImports=module.extraImports,
                        synthBoundaryModule=module)
                    synth_handle.close()

                env.Command(
                    synth_stub,  # target
                    logfile,
                    build_synth_stub)

            ##
            ## The mk_<wrapper>.v file is really built by the Wrapper() builder
            ## above.  We use NULL commands to convince SCons the file is generated.
            ## This seems easier than SCons SideEffect() calls, which don't clean
            ## targets.
            ##
            ## We also generate all this synth boundary's GEN_VS
            ##
            ext_gen_v = []
            for v in moduleList.getSynthBoundaryDependencies(module, 'GEN_VS'):
                ext_gen_v += [MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + v]

            # Add the dependence for all Verilog noted above
            bld_v = env.Command([
                MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' +
                module.wrapperName() + '.v'
            ] + ext_gen_v, MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' +
                                bsv.replace('.bsv', '.bo'), '')
            env.Precious(bld_v)

            if (moduleList.getAWBParam('bsv_tool', 'BUILD_VERILOG') == 1):

                module.moduleDependency['VERILOG'] += [bld_v] + [ext_gen_v]

                module.moduleDependency['GEN_WRAPPER_VERILOGS'] = [
                    os.path.basename(module.wrapperName() + '.v')
                ]

            if (self.pipeline_debug != 0):
                print "Name: " + module.name

            # each synth boundary will produce a ba
            bld_ba = [
                env.Command([
                    MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' +
                    module.wrapperName() + '.ba'
                ], MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' +
                            bsv.replace('.bsv', '.bo'), '')
            ]

            module.moduleDependency['BA'] += bld_ba
            env.Precious(bld_ba)

            ##
            ## Build the Verilog black-box stub.
            ##
            bb = self.stubGenCommand(MODULE_PATH, module.boundaryName, bld_v)

            # Only the subordinate modules have stubs.
            # The platform module should not be enumerated here. This is a false dependency.
            if (module.name != moduleList.topModule.name):
                moduleList.topModule.moduleDependency['VERILOG_STUB'] += [bb]
                module.moduleDependency['GEN_VERILOG_STUB'] = [bb]

            return [bb]  #This doesn't seem to do anything.
Example #10
0
  def __init__(self, moduleList, isPrimaryBuildTarget):
    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_INC_DIRS_FROM_ROOT   = '-Xv +incdir+' + ALL_DIRS_FROM_ROOT.replace(':','+') 
    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]
            for codeType in liCodeType:
                if(codeType in moduleObject.objectCache):
                    for verilog in moduleObject.objectCache[codeType]:
                        linkPath = vexe_vdir + '/' + os.path.basename(verilog)
                        def linkVerilog(target, source, env):
                            # It might be more useful if the Module contained a pointer to the LIModules...                        
                            if(os.path.lexists(str(target[0]))):
                                os.remove(str(target[0]))
                            print "Linking: " + str(source[0]) + " to " + str(target[0])
                            os.symlink(str(source[0]), str(target[0]))
                        moduleList.env.Command(linkPath, verilog, linkVerilog)
                        if(codeType in moduleList.topModule.moduleDependency):
                            moduleList.topModule.moduleDependency[codeType] += [linkPath]
                        else:
                            moduleList.topModule.moduleDependency[codeType] = [linkPath]
                    else:
                        # Warn that we did not find the ngc we expected to find..
                        print "Warning: We did not find verilog for module " + moduleName 
                
    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 vcs '

    # 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 + ' '

    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
 
    # cflags to be passed into vcs compiler
    for definition in defs:
        vexe_gen_command += ' -Xv -CFLAGS -Xv ' + definition
    for path in inc_paths:
        vexe_gen_command += ' -Xv -CFLAGS -Xv -I' + path

    for lib in moduleList.swLinkLibs:
        vexe_gen_command += ' -Xl -l' + lib + ' '
        vexe_gen_command += ' -Xv -LDFLAGS -Xv -l' + lib + ' '

    # 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 

    vexe_gen_command += ' -Xv -full64 '
    vexe_gen_command += ' -Xv -sverilog '
    vexe_gen_command += ' -Xv +librescan '
    vexe_gen_command += ' -Xv +libext+.sv '
    if(moduleList.getAWBParam('verilog_tool', 'VCS_ARGUMENTS')):
        vexe_gen_command += moduleList.getAWBParam('verilog_tool', 'VCS_ARGUMENTS')
    vexe_gen_command += ' ' + ALL_INC_DIRS_FROM_ROOT + ' '

    # VCS must be informed of all BDPI.  Really we need some kind of
    # file object here.  All this massaging of path is ridiculous.
    vexe_gen_command += ' -Xv ' +  moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + (' -Xv ' +  moduleList.env['DEFS']['ROOT_DIR_HW'] + '/').join(moduleList.getAllDependenciesWithPaths('GIVEN_BDPI_CS')) + ' ' 

    # 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)
        for m in moduleList.getAllDependencies('GIVEN_BDPI_CS'):
            print 'GIVEN_BDPI_CS: ' + 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('$ENV{LD_LIBRARY_PATH} = $platform . ":" . $ENV{LD_LIBRARY_PATH};\n')
        wrapper_handle.write('`ln -sf $platform/directc_mk_model_Wrapper.so .`;\n')
        wrapper_handle.write('exec("$platform/' + TMP_BSC_DIR + '/' + APM_NAME + '_hw.exe  -licqueue \$* ");\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):
            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 ])

        moduleList.env.AlwaysBuild(vbin)

        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:
        vbin = moduleList.env.Command(
            TMP_BSC_DIR + '/' + APM_NAME + '_hw.vexe',
            moduleList.getAllDependencies('VERILOG') +
            moduleList.getAllDependencies('VHDL') +
            moduleList.getAllDependencies('BA') +
            map(modify_path_ba_local, moduleList.getAllDependenciesWithPaths('GEN_BAS')),
            [ vexe_gen_command ])
 

        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)
Example #11
0
    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)
Example #12
0
    def __init__(self, moduleList):
        env = moduleList.env

        tree_base_path = env.Dir(
            model.get_build_path(moduleList, moduleList.topModule))

        # get rid of this at some point - since we know we're in
        # bluesim, we should be able to do the right thing.
        APM_NAME = moduleList.env['DEFS']['APM_NAME']
        BSC = moduleList.env['DEFS']['BSC']
        inc_paths = moduleList.swIncDir  # we need to depend on libasim

        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_SIM = '-steps 10000000 +RTS -K1000M -RTS -keep-fires -aggressive-conditions -wait-for-license -no-show-method-conf -no-opt-bool -licenseWarning 7 -elab -show-schedule -l pthread ' + ldflags + ' '

        # Build in parallel.
        n_jobs = moduleList.env.GetOption('num_jobs')
        if (bsc_version >= 30006):
            BSC_FLAGS_SIM += '-parallel-sim-link ' + str(n_jobs) + ' '

        for path in inc_paths:
            BSC_FLAGS_SIM += '-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'

        all_hw_dirs = [
            env.Dir(d)
            for d in moduleList.env['DEFS']['ALL_HW_DIRS'].split(':')
        ]
        all_build_dirs = [d.Dir(TMP_BSC_DIR) for d in all_hw_dirs]

        ALL_DIRS_FROM_ROOT = ':'.join([d.path for d in all_hw_dirs])
        ALL_BUILD_DIRS_FROM_ROOT = ':'.join([d.path for d in all_build_dirs])
        ALL_LIB_DIRS_FROM_ROOT = ALL_DIRS_FROM_ROOT + ':' + ALL_BUILD_DIRS_FROM_ROOT

        bsc_sim_command = BSC + ' ' + BSC_FLAGS_SIM + ' ' + LDFLAGS + ' ' + ldflags + ' -o $TARGET'

        # Set MAKEFLAGS because Bluespec is going to invoke make on its own and
        # we don't want to pass on the current build's recursive flags.
        bsc_sim_command = 'env MAKEFLAGS="-j ' + str(
            n_jobs) + '" ' + bsc_sim_command

        if (bsc_version >= 13013):
            # 2008.01.A compiler allows us to pass C++ arguments.
            if (model.getDebug(moduleList)):
                bsc_sim_command += ' -Xc++ -O0'
            else:
                bsc_sim_command += ' -Xc++ -O1'

            # g++ 4.5.2 is complaining about overflowing the var tracking table

            if (model.getGccVersion() >= 40501):
                bsc_sim_command += ' -Xc++ -fno-var-tracking-assignments'

        defs = (software_tool.host_defs()).split(" ")
        for definition in defs:
            bsc_sim_command += ' -Xc++ ' + definition + ' -Xc ' + definition

        def modify_path_bdpi(path):
            return moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + path

        def modify_path_ba_local(path):
            return bsv_tool.modify_path_ba(moduleList, path)

        LI_LINK_DIR = ""
        if (not (wrapper_gen_tool.getFirstPassLIGraph()) is None):
            LI_LINK_DIR = tree_base_path.Dir('.li').path

        bdpi_cs = [
            env.File(c) for c in moduleList.env['DEFS']['BDPI_CS'].split(' ')
        ]
        BDPI_CS = ' '.join([c.path for c in bdpi_cs])

        bsc_sim_command += \
            ' -sim -e ' + ROOT_WRAPPER_SYNTH_ID + ' -p +:' + LI_LINK_DIR + ':' + ALL_LIB_DIRS_FROM_ROOT +' -simdir ' + \
            TMP_BSC_DIR + ' ' +\
            ' ' + BDPI_CS

        if (model.getBuildPipelineDebug(moduleList) != 0):
            print "BLUESIM DEPS: \n"
            for ba in moduleList.getAllDependencies('BA'):
                print 'Bluesim BA dep: ' + str(ba) + '\n'

            for ba in map(modify_path_ba_local,
                          moduleList.getAllDependenciesWithPaths('GIVEN_BAS')):
                print 'Bluesim GIVEN_BA dep: ' + str(ba) + '\n'

            for ba in map(modify_path_ba_local,
                          moduleList.getAllDependenciesWithPaths('GEN_BAS')):
                print 'Bluesim GEN_BA dep: ' + str(ba) + '\n'

        sbin_name = TMP_BSC_DIR + '/' + APM_NAME
        sbin = moduleList.env.Command(
            sbin_name + '_hw.exe',
            moduleList.getAllDependencies('BA') +
            map(modify_path_ba_local,
                moduleList.getAllDependenciesWithPaths('GIVEN_BAS')) +
            map(modify_path_ba_local,
                moduleList.getAllDependenciesWithPaths('GEN_BAS')) +
            map(modify_path_bdpi,
                moduleList.getAllDependenciesWithPaths('GIVEN_BDPI_CS')) +
            map(modify_path_bdpi,
                moduleList.getAllDependenciesWithPaths('GIVEN_BDPI_HS')),
            bsc_sim_command)

        if moduleList.env.GetOption('clean'):
            os.system('rm -rf .bsc')

        # If we have bsc data files, copy them over to the .bsc directory
        if len(moduleList.getAllDependencies('GEN_VS')) > 0:
            Copy(TMP_BSC_DIR, moduleList.getAllDependencies('GIVEN_DATAS'))

        #
        # The final step must leave a few well known names:
        #   APM_NAME must be the software side, if there is one.  If there isn't, then
        #   it must be the Bluesim image.
        #
        if (model.getBuildPipelineDebug(moduleList) != 0):
            print "ModuleList desp : " + str(moduleList.swExe)

        exe = moduleList.env.Command(APM_NAME, sbin, [
            '@ln -fs ' + sbin_name + '_hw.exe ${TARGET}_hw.exe',
            '@ln -fs ' + sbin_name + '_hw.exe.so ${TARGET}_hw.exe.so',
            '@ln -fs ' + moduleList.swExeOrTarget + ' ${TARGET}',
            SCons.Script.Delete('${TARGET}_hw.vexe'),
            SCons.Script.Delete('${TARGET}_hw.errinfo')
        ])

        moduleList.topDependency = moduleList.topDependency + [exe]
Example #13
0
    def __init__(self, moduleList):
        env = moduleList.env

        tree_base_path = env.Dir(model.get_build_path(moduleList, moduleList.topModule))

        # get rid of this at some point - since we know we're in 
        # bluesim, we should be able to do the right thing.
        APM_NAME = moduleList.env['DEFS']['APM_NAME']
        BSC = moduleList.env['DEFS']['BSC']
        inc_paths = moduleList.swIncDir # we need to depend on libasim

        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_SIM = '-steps 10000000 +RTS -K1000M -RTS -keep-fires -aggressive-conditions -wait-for-license -no-show-method-conf -no-opt-bool -licenseWarning 7 -elab -show-schedule -l pthread ' + ldflags + ' '

        # Build in parallel.
        n_jobs = moduleList.env.GetOption('num_jobs')
        if (bsc_version >= 30006):
            BSC_FLAGS_SIM += '-parallel-sim-link ' + str(n_jobs) + ' '

        for path in inc_paths:
            BSC_FLAGS_SIM += '-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'

        all_hw_dirs = [env.Dir(d) for d in moduleList.env['DEFS']['ALL_HW_DIRS'].split(':')]
        all_build_dirs = [d.Dir(TMP_BSC_DIR) for d in all_hw_dirs]

        ALL_DIRS_FROM_ROOT = ':'.join([d.path for d in all_hw_dirs])
        ALL_BUILD_DIRS_FROM_ROOT = ':'.join([d.path for d in all_build_dirs])
        ALL_LIB_DIRS_FROM_ROOT = ALL_DIRS_FROM_ROOT + ':' + ALL_BUILD_DIRS_FROM_ROOT
        
        bsc_sim_command = BSC + ' ' + BSC_FLAGS_SIM + ' ' + LDFLAGS + ' ' + ldflags + ' -o $TARGET'

        # Set MAKEFLAGS because Bluespec is going to invoke make on its own and
        # we don't want to pass on the current build's recursive flags.
        bsc_sim_command = 'env MAKEFLAGS="-j ' + str(n_jobs) + '" ' + bsc_sim_command


        if (bsc_version >= 13013):
            # 2008.01.A compiler allows us to pass C++ arguments.
            if (model.getDebug(moduleList)):
                bsc_sim_command += ' -Xc++ -O0'
            else:
                bsc_sim_command += ' -Xc++ -O1'

            # g++ 4.5.2 is complaining about overflowing the var tracking table

            if (model.getGccVersion() >= 40501):
                 bsc_sim_command += ' -Xc++ -fno-var-tracking-assignments'

        defs = (software_tool.host_defs()).split(" ")
        for definition in defs:
            bsc_sim_command += ' -Xc++ ' + definition + ' -Xc ' + definition


        def modify_path_bdpi(path):
            return  moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + path

        def modify_path_ba_local(path):
            return bsv_tool.modify_path_ba(moduleList, path)

        LI_LINK_DIR = ""
        if (not (wrapper_gen_tool.getFirstPassLIGraph()) is None):
            LI_LINK_DIR = tree_base_path.Dir('.li').path

        bdpi_cs = [env.File(c) for c in moduleList.env['DEFS']['BDPI_CS'].split(' ')]
        BDPI_CS = ' '.join([c.path for c in bdpi_cs])

        bsc_sim_command += \
            ' -sim -e ' + ROOT_WRAPPER_SYNTH_ID + ' -p +:' + LI_LINK_DIR + ':' + ALL_LIB_DIRS_FROM_ROOT +' -simdir ' + \
            TMP_BSC_DIR + ' ' +\
            ' ' + BDPI_CS


        if (model.getBuildPipelineDebug(moduleList) != 0):
            print "BLUESIM DEPS: \n" 
            for ba in moduleList.getAllDependencies('BA'):
                print 'Bluesim BA dep: ' + str(ba) + '\n'

            for ba in map(modify_path_ba_local, moduleList.getAllDependenciesWithPaths('GIVEN_BAS')):
                print 'Bluesim GIVEN_BA dep: ' + str(ba) + '\n'

            for ba in map(modify_path_ba_local, moduleList.getAllDependenciesWithPaths('GEN_BAS')):
                print 'Bluesim GEN_BA dep: ' + str(ba) + '\n'

        sbin_name = TMP_BSC_DIR + '/' + APM_NAME
        sbin = moduleList.env.Command(
            sbin_name + '_hw.exe',
            moduleList.getAllDependencies('BA') + 
            map(modify_path_ba_local, moduleList.getAllDependenciesWithPaths('GIVEN_BAS')) +
            map(modify_path_ba_local, moduleList.getAllDependenciesWithPaths('GEN_BAS')) +
            map(modify_path_bdpi, moduleList.getAllDependenciesWithPaths('GIVEN_BDPI_CS')) + 
            map(modify_path_bdpi, moduleList.getAllDependenciesWithPaths('GIVEN_BDPI_HS')),
            bsc_sim_command)

        if moduleList.env.GetOption('clean'):
            os.system('rm -rf .bsc')

        # If we have bsc data files, copy them over to the .bsc directory 
        if len(moduleList.getAllDependencies('GEN_VS'))> 0:
           Copy(TMP_BSC_DIR,  moduleList.getAllDependencies('GIVEN_DATAS')) 

        #
        # The final step must leave a few well known names:
        #   APM_NAME must be the software side, if there is one.  If there isn't, then
        #   it must be the Bluesim image.
        #
        if (model.getBuildPipelineDebug(moduleList) != 0):
            print "ModuleList desp : " + str(moduleList.swExe)

        exe = moduleList.env.Command(
            APM_NAME,
            sbin,
            [ '@ln -fs ' + sbin_name + '_hw.exe ${TARGET}_hw.exe',
              '@ln -fs ' + sbin_name + '_hw.exe.so ${TARGET}_hw.exe.so',
              '@ln -fs ' + moduleList.swExeOrTarget + ' ${TARGET}',
              SCons.Script.Delete('${TARGET}_hw.vexe'),
              SCons.Script.Delete('${TARGET}_hw.errinfo') ])

        moduleList.topDependency = moduleList.topDependency + [exe] 
Example #14
0
  def __init__(self, moduleList, isPrimaryBuildTarget):
    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_INC_DIRS_FROM_ROOT   = '-Xv +incdir+' + ALL_DIRS_FROM_ROOT.replace(':','+') 

    #insert any supplied include paths
    for incdir in moduleList.getAllDependencies('VERILOG_INC_DIRS'):
        ALL_INC_DIRS_FROM_ROOT += "+" + incdir

    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_PKG', '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]
            for codeType in liCodeType:
                if(codeType in moduleObject.objectCache):
                    for verilog in moduleObject.objectCache[codeType]:
                        linkPath = vexe_vdir + '/' + os.path.basename(verilog)
                        moduleList.env.Command(linkPath, verilog, model.link_file)
                        if(codeType in moduleList.topModule.moduleDependency):
                            moduleList.topModule.moduleDependency[codeType] += [linkPath]
                        else:
                            moduleList.topModule.moduleDependency[codeType] = [linkPath]
                    else:
                        # Warn that we did not find the ngc we expected to find..
                        print "Warning: We did not find verilog for module " + moduleName 
                
    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 vcs '

    # 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 + ' '

    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
 
    # cflags to be passed into vcs compiler
    for definition in defs:
        vexe_gen_command += ' -Xv -CFLAGS -Xv ' + definition
    for path in inc_paths:
        vexe_gen_command += ' -Xv -CFLAGS -Xv -I' + path

    for lib in moduleList.swLinkLibs:
        vexe_gen_command += ' -Xl -l' + lib + ' '
        vexe_gen_command += ' -Xv -LDFLAGS -Xv -l' + lib + ' '

    # 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 

    if (moduleList.getAWBParam('verilog_tool', 'VCS_ENABLE_LINT') != 0):
        vexe_gen_command += ' -Xv +lint=all,noVCDE'

    vexe_gen_command += ' -Xv -full64 '
    vexe_gen_command += ' -Xv -sverilog '
    vexe_gen_command += ' -Xv +librescan '
    vexe_gen_command += ' -Xv +libext+.sv '
    if (moduleList.getAWBParam('verilog_tool', 'VCS_ARGUMENTS')):
        vexe_gen_command += moduleList.getAWBParam('verilog_tool', 'VCS_ARGUMENTS')
    vexe_gen_command += ' ' + ALL_INC_DIRS_FROM_ROOT + ' '

    # VCS must be informed of all BDPI.  Really we need some kind of
    # file object here.  All this massaging of path is ridiculous.
    vexe_gen_command += ' -Xv ' +  moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + (' -Xv ' +  moduleList.env['DEFS']['ROOT_DIR_HW'] + '/').join(moduleList.getAllDependenciesWithPaths('GIVEN_BDPI_CS')) + ' ' 

    # Bluespec requires that source files terminate the command line.
    vexe_gen_command += ' -verilog -e ' + ROOT_WRAPPER_SYNTH_ID + ' ' +\
                        moduleList.env['DEFS']['BDPI_CS']

    vexe_gen_command += ' ' + ' '.join(moduleList.getAllDependencies('VERILOG_PKG'))
    vexe_gen_command += ' ' + ' '.join(moduleList.getAllDependencies('VERILOG'))
    vexe_gen_command += ' ' + ' '.join(moduleList.getAllDependencies('VHDL'))

    if (model.getBuildPipelineDebug(moduleList) != 0):
        for m in moduleList.getAllDependencies('BA'):
            print 'BA dep: ' + str(m)
        for m in moduleList.getAllDependencies('VERILOG_PKG'):
            print 'VPKG 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)
        for m in moduleList.getAllDependencies('GIVEN_BDPI_CS'):
            print 'GIVEN_BDPI_CS: ' + 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('$ENV{LD_LIBRARY_PATH} = $platform . ":" . $ENV{LD_LIBRARY_PATH};\n')
        wrapper_handle.write('`ln -sf $platform/directc_mk_model_Wrapper.so .`;\n')
        wrapper_handle.write('exec("$platform/' + TMP_BSC_DIR + '/' + APM_NAME + '_hw.exe  -licqueue \$* ");\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):
            vbinDeps += moduleList.getDependencies(moduleList.topModule, 'VERILOG_PKG') + \
                        moduleList.getDependencies(moduleList.topModule, 'VERILOG') + \
                        moduleList.getDependencies(moduleList.topModule, 'VERILOG_LIB') + \
                        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_PKG') + \
                        moduleList.getAllDependencies('VERILOG') + \
                        moduleList.getAllDependencies('VERILOG_LIB') + \
                        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 ])

        moduleList.env.AlwaysBuild(vbin)

        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:
        vbin = moduleList.env.Command(
            TMP_BSC_DIR + '/' + APM_NAME + '_hw.vexe',
            moduleList.getAllDependencies('VERILOG_PKG') +
            moduleList.getAllDependencies('VERILOG') +
            moduleList.getAllDependencies('VHDL') +
            moduleList.getAllDependencies('BA') +
            map(modify_path_ba_local, moduleList.getAllDependenciesWithPaths('GEN_BAS')),
            [ vexe_gen_command ])
 

        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)
Example #15
0
File: BSV.py Project: chenm001/leap
    def __init__(self, moduleList):
        # some definitions used during the bsv compilation process
        env = moduleList.env
        self.moduleList = moduleList

        self.hw_dir = env.Dir(moduleList.env['DEFS']['ROOT_DIR_HW'])

        self.TMP_BSC_DIR = env['DEFS']['TMP_BSC_DIR']
        synth_modules = moduleList.synthBoundaries()

        self.USE_TREE_BUILD = moduleList.getAWBParam('wrapper_gen_tool',
                                                     'USE_BUILD_TREE')

        # all_module_dirs: a list of all module directories in the build tree
        self.all_module_dirs = [
            self.hw_dir.Dir(moduleList.topModule.buildPath)
        ]
        for module in synth_modules:
            if (module.buildPath != moduleList.topModule.buildPath):
                self.all_module_dirs += [self.hw_dir.Dir(module.buildPath)]

        # all_build_dirs: the build (.bsc) sub-directory of all module directories
        self.all_build_dirs = [
            d.Dir(self.TMP_BSC_DIR) for d in self.all_module_dirs
        ]

        # Include iface directories
        self.all_module_dirs += iface_tool.getIfaceIncludeDirs(moduleList)
        self.all_build_dirs += iface_tool.getIfaceLibDirs(moduleList)

        # Add the top level build directory
        self.all_build_dirs += [env.Dir(self.TMP_BSC_DIR)]

        self.all_module_dirs += [
            self.hw_dir.Dir('include'),
            self.hw_dir.Dir('include/awb/provides')
        ]

        # Full search path: all module and build directories
        self.all_lib_dirs = self.all_module_dirs + self.all_build_dirs

        all_build_dir_paths = [d.path for d in self.all_build_dirs]
        self.ALL_BUILD_DIR_PATHS = ':'.join(all_build_dir_paths)

        all_lib_dir_paths = [d.path for d in self.all_lib_dirs]
        self.ALL_LIB_DIR_PATHS = ':'.join(all_lib_dir_paths)

        # we need to annotate the module list with the
        # bluespec-provided library files. Do so here.
        bsv_tool.decorateBluespecLibraryCode(moduleList)

        self.TMP_BSC_DIR = moduleList.env['DEFS']['TMP_BSC_DIR']
        self.BUILD_LOGS_ONLY = moduleList.getAWBParam('bsv_tool',
                                                      'BUILD_LOGS_ONLY')
        self.USE_BVI = moduleList.getAWBParam('bsv_tool', 'USE_BVI')

        self.pipeline_debug = model.getBuildPipelineDebug(moduleList)

        # Should we be building in events?
        if (model.getEvents(moduleList) == 0):
            bsc_events_flag = ' -D HASIM_EVENTS_ENABLED=False '
        else:
            bsc_events_flag = ' -D HASIM_EVENTS_ENABLED=True '

        self.BSC_FLAGS = moduleList.getAWBParam('bsv_tool',
                                                'BSC_FLAGS') + bsc_events_flag

        moduleList.env.VariantDir(self.TMP_BSC_DIR, '.', duplicate=0)
        moduleList.env['ENV']['BUILD_DIR'] = moduleList.env['DEFS'][
            'BUILD_DIR']  # need to set the builddir for synplify

        topo = moduleList.topologicalOrderSynth()
        topo.reverse()

        # Cleaning? Wipe out module temporary state. Do this before
        # the topo pop to ensure that we don't leave garbage around at
        # the top level.
        if moduleList.env.GetOption('clean'):
            for module in topo:
                MODULE_PATH = get_build_path(moduleList, module)
                os.system('cd ' + MODULE_PATH + '/' + self.TMP_BSC_DIR +
                          '; rm -f *.ba *.c *.h *.sched *.log *.v *.bo *.str')

        topo.pop()  # get rid of top module.

        ## Python module that generates a wrapper to connect the exposed
        ## wires of all synthesis boundaries.
        tree_builder = bsv_tool.BSVSynthTreeBuilder(self)

        ##
        ## Is this a normal build or a build in which only Bluespec dependence
        ## is computed?
        ##

        if not moduleList.isDependsBuild:
            ##
            ## Normal build.
            ##

            ##
            ## Now that the "depends-init" build is complete we can
            ## continue with accurate inter-Bluespec file dependence.
            ## This build only takes place for the first pass object
            ## code generation.  If the first pass li graph exists, it
            ## subsumes awb-style synthesis boundary generation.
            ##
            for module in topo:
                self.build_synth_boundary(moduleList, module)

            ## We are going to have a whole bunch of BA and V files coming.
            ## We don't yet know what they contain, but we do know that there
            ## will be |synth_modules| - 2 of them

            if (not 'GEN_VERILOGS' in moduleList.topModule.moduleDependency):
                moduleList.topModule.moduleDependency['GEN_VERILOGS'] = []
            if (not 'GEN_BAS' in moduleList.topModule.moduleDependency):
                moduleList.topModule.moduleDependency['GEN_BAS'] = []

            ## Having described the new build tree dependencies we can build
            ## the top module.
            self.build_synth_boundary(moduleList, moduleList.topModule)

            ## Merge all synthesis boundaries using a tree?  The tree reduces
            ## the number of connections merged in a single compilation, allowing
            ## us to support larger systems.
            if self.USE_TREE_BUILD:
                tree_builder.setupTreeBuild(moduleList, topo)

            ##
            ## Generate the global string table.  Bluespec-generated global
            ## strings are stored in files by the compiler.
            ##
            ## The global string file will be generated in the top-level
            ## .bsc directory and a link to it will be added to the
            ## top-level directory.
            ##
            all_str_src = []
            #for module in topo + [moduleList.topModule]:
            for module in moduleList.moduleList + topo + [
                    moduleList.topModule
            ]:
                if ('STR' in module.moduleDependency):
                    all_str_src.extend(module.moduleDependency['STR'])

            if (self.BUILD_LOGS_ONLY == 0):
                bsc_str = moduleList.env.Command(
                    self.TMP_BSC_DIR + '/' +
                    moduleList.env['DEFS']['APM_NAME'] + '.str', all_str_src,
                    ['cat $SOURCES > $TARGET'])
                strDep = moduleList.env.Command(
                    moduleList.env['DEFS']['APM_NAME'] + '.str', bsc_str, [
                        'ln -fs ' + self.TMP_BSC_DIR +
                        '/`basename $TARGET` $TARGET'
                    ])
                moduleList.topDependency += [strDep]

            if moduleList.env.GetOption('clean'):
                print 'Cleaning depends-init...'
                s = os.system('scons --clean depends-init')
        else:

            ##
            ## Dependence build.  The target of this build is "depens-init".  No
            ## Bluespec modules will be compiled in this invocation of SCons.
            ## Only .depends-bsv files will be produced.
            ##

            # We need to calculate some dependencies for the build
            # tree.  We could be clever and put this code somewhere
            # rather than replicate it.
            if self.USE_TREE_BUILD:

                buildTreeDeps = {}
                buildTreeDeps['GEN_VERILOGS'] = []
                buildTreeDeps['GEN_BAS'] = []
                #This is sort of a hack.
                buildTreeDeps['WRAPPER_BSHS'] = [
                    'awb/provides/soft_services.bsh'
                ]
                buildTreeDeps['GIVEN_BSVS'] = []
                buildTreeDeps['BA'] = []
                buildTreeDeps['STR'] = []
                buildTreeDeps['VERILOG'] = []
                buildTreeDeps['BSV_LOG'] = []
                buildTreeDeps['VERILOG_STUB'] = []

                tree_module = Module( 'build_tree', ["mkBuildTree"], moduleList.topModule.buildPath,\
                             moduleList.topModule.name,\
                             [], moduleList.topModule.name, [], buildTreeDeps, platformModule=True)

                tree_module.dependsFile = '.depends-build-tree'

                moduleList.insertModule(tree_module)
                tree_file_bo = get_build_path(
                    moduleList, moduleList.topModule) + "/build_tree.bsv"
                # sprinkle files to get dependencies right
                bo_handle = open(tree_file_bo, 'w')

                # mimic AWB/leap-configure

                bo_handle.write('//\n')
                bo_handle.write(
                    '// Synthesized compilation file for module: build_tree\n')
                bo_handle.write('//\n')
                bo_handle.write('//   This file was created by BSV.py\n')
                bo_handle.write('//\n')

                bo_handle.write('`define BUILDING_MODULE_build_tree\n')
                bo_handle.write('`include "build_tree_Wrapper.bsv"\n')

                bo_handle.close()

                # Calling generateWrapperStub will write out default _Wrapper.bsv
                # and _Log.bsv files for build tree. However, these files
                # may already exists, and, in the case of build_tree_Wrapper.bsv,
                # have meaningful content.  Fortunately, generateWrapperStub
                # will not over write existing files.
                wrapper_gen_tool.generateWrapperStub(moduleList, tree_module)
                wrapper_gen_tool.generateAWBCompileWrapper(
                    moduleList, tree_module)
                topo.append(tree_module)

            deps = []

            useDerived = True
            first_pass_LI_graph = wrapper_gen_tool.getFirstPassLIGraph()
            if (not first_pass_LI_graph is None):
                useDerived = False
                # we also need to parse the platform_synth file in th
                platform_synth = get_build_path(
                    moduleList, moduleList.topModule
                ) + "/" + moduleList.localPlatformName + "_platform_synth.bsv"
                platform_deps = ".depends-platform"
                deps += self.compute_dependence(moduleList,
                                                moduleList.topModule,
                                                useDerived,
                                                fileName=platform_deps,
                                                targetFiles=[platform_synth])

                # If we have an LI graph, we need to construct and compile
                # several LI wrappers.  do that here.
                # include all the dependencies in the graph in the wrapper.
                li_wrappers = []
                tree_base_path = get_build_path(moduleList,
                                                moduleList.topModule)
                liGraph = LIGraph([])
                firstPassGraph = first_pass_LI_graph
                # We should ignore the 'PLATFORM_MODULE'
                liGraph.mergeModules([
                    module for module in getUserModules(firstPassGraph)
                    if module.getAttribute('RESYNTHESIZE') is None
                ])
                for module in sorted(liGraph.graph.nodes(),
                                     key=lambda module: module.name):
                    wrapper_import_path = tree_base_path + '/' + module.name + '_Wrapper.bsv'
                    li_wrappers.append(module.name + '_Wrapper.bsv')
                    wrapper_import_handle = open(wrapper_import_path, 'w')
                    wrapper_import_handle.write('import Vector::*;\n')
                    wrapper_gen_tool.generateWellKnownIncludes(
                        wrapper_import_handle)
                    wrapper_gen_tool.generateBAImport(module,
                                                      wrapper_import_handle)
                    wrapper_import_handle.close()
                    platform_deps = ".depends-" + module.name
                    deps += self.compute_dependence(
                        moduleList,
                        moduleList.topModule,
                        useDerived,
                        fileName=platform_deps,
                        targetFiles=[wrapper_import_path])

            for module in topo + [moduleList.topModule]:
                # for object import builds no Wrapper code will be included. remove it.
                deps += self.compute_dependence(moduleList,
                                                module,
                                                useDerived,
                                                fileName=module.dependsFile)

            moduleList.topDependsInit += deps
Example #16
0
  def __init__(self, moduleList):
    TMP_BSC_DIR = moduleList.env['DEFS']['TMP_BSC_DIR']
    topModulePath = get_build_path(moduleList, moduleList.topModule)
    # The LIM compiler uniquifies synthesis boundary names  
    uidOffset = int(moduleList.getAWBParam('wrapper_gen_tool', 'MODULE_UID_OFFSET'))

    # We only inject the platform wrapper in first pass builds.  In
    # the second pass, we import the first pass object code.  It may
    # be that we need this code?

    # Inject a synth boundary for platform build code.  we need to
    # pick up some dependencies from the top level code.  this is a
    # pretty major hack, in my opinion. Better would be to actually
    # inspect the eventual .ba files for their dependencies. 
    platformName = moduleList.localPlatformName + '_platform'
    platformDeps = {}
    platformDeps['GEN_VERILOGS'] = []
    platformDeps['GEN_BAS'] = [] #moduleList.getSynthBoundaryDependencies(moduleList.topModule, 'GEN_BAS')                               
    platformDeps['GEN_VPI_HS'] = moduleList.getSynthBoundaryDependencies(moduleList.topModule, 'GEN_VPI_HS')                               
    platformDeps['GEN_VPI_CS'] = moduleList.getSynthBoundaryDependencies(moduleList.topModule, 'GEN_VPI_CS')                          
     
    #This is sort of a hack.

    platformDeps['GIVEN_BSVS'] = []
    platformDeps['WRAPPER_BSHS'] = ['awb/provides/virtual_platform.bsh', 'awb/provides/physical_platform.bsh']
    platformDeps['BA'] = []
    platformDeps['STR'] = []
    platformDeps['VERILOG'] = [topModulePath + '/' + TMP_BSC_DIR + '/mk_' + platformName + '_Wrapper.v']
    platformDeps['BSV_LOG'] = []
    platformDeps['VERILOG_STUB'] = []
       
    platform_module = Module( platformName, ["mkVirtualPlatform"], moduleList.topModule.buildPath,\
                          moduleList.topModule.name,\
                          [], moduleList.topModule.name, [], platformDeps, platformModule=True)

    platform_module.dependsFile = '.depends-platform'
    platform_module.interfaceType = 'VIRTUAL_PLATFORM'
    platform_module.extraImports = ['virtual_platform']

    first_pass_LI_graph = getFirstPassLIGraph()
    if(first_pass_LI_graph is None):
        moduleList.insertModule(platform_module)
        moduleList.graphize()
        moduleList.graphizeSynth()

        # Sprinkle more files expected by the two-pass build.  
        generateWrapperStub(moduleList, platform_module)
        generateAWBCompileWrapper(moduleList, platform_module)

    else:
        platform_module_li = first_pass_LI_graph.modules[moduleList.localPlatformName + '_platform']

        # This gives us the right path. 
        synthHandle = getSynthHandle(moduleList, platform_module)

        # throw in some includes...
        synthHandle.write('import HList::*;\n')
        synthHandle.write('import Vector::*;\n')
        synthHandle.write('import ModuleContext::*;\n')
        synthHandle.write('import GetPut::*;\n')
        synthHandle.write('import Clocks::*;\n')
        synthHandle.write('`include "awb/provides/virtual_platform.bsh"\n')
        synthHandle.write('`include "awb/provides/physical_platform.bsh"\n')
        generateWellKnownIncludes(synthHandle)
        # May need an extra import here?
        # get the platform module from the LIGraph            
        generateBAImport(platform_module_li, synthHandle)
        # include synth stub here....
        _emitSynthModule(platform_module_li, synthHandle, platform_module.interfaceType,
                         localPlatformName = moduleList.localPlatformName)

    ## Here we use a module list sorted alphabetically in order to guarantee
    ## the generated wrapper files are consistent.  The topological sort
    ## guarantees only a depth first traversal -- not the same traversal
    ## each time.
    synth_modules = [moduleList.topModule] + moduleList.synthBoundaries()

    ## Models have the option of declaring top-level clocks that will
    ## be exposed as arguments.  When top-level clocks exist a single
    ## top-level reset is also defined.  To request no top-level clocks
    ## the variable N_TOP_LEVEL_CLOCKS should be removed from a platform's
    ## AWB configuration file, since Bluespec can't test the value of
    ## a preprocessor variable.
    try:
      n_top_clocks = int(moduleList.getAWBParam('physical_platform', 'N_TOP_LEVEL_CLOCKS'))
      if (n_top_clocks == 0):
        sys.stderr.write("Error: N_TOP_LEVEL_CLOCKS may not be 0 due to Bluespec preprocessor\n")
        sys.stderr.write("       limitations.  To eliminate top-level clocks, remove the AWB\n")
        sys.stderr.write("       parameter from the platform configuration.\n")
        sys.exit(1)
    except:
      n_top_clocks = 0

    for module in synth_modules:
      modPath = moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + module.buildPath + '/' + module.name
      wrapperPath =  modPath + "_Wrapper.bsv"
      logPath = modPath + "_Log.bsv"

      conSizePath =  modPath + "_Wrapper_con_size.bsh"
      ignorePath = moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + module.buildPath + '/.ignore'

      # clear out code on clean.
      if moduleList.env.GetOption('clean'):
          os.system('rm -f ' + wrapperPath)
          os.system('rm -f ' + logPath)
          os.system('rm -f ' + conSizePath)
          os.system('rm -f ' + ignorePath)
          if (module.name != moduleList.topModule.name):
              os.system('rm -f ' + modPath + '.bsv') 
          continue

      if (model.getBuildPipelineDebug(moduleList) != 0):
        print "Wrapper path is " + wrapperPath
      wrapper_bsv = open(wrapperPath, 'w')

      ignore_bsv = open(ignorePath, 'w')
      ignore_bsv.write("// Generated by wrapper_gen.py\n\n")

      # Connection size doesn't appear on the first dependence pass, since it
      # doesn't exist until after the first build.  Finding it later results in
      # build dependence changes and rebuilding.  Ignore it, since the file will
      # change only when some other file changes.
      ignore_bsv.write(conSizePath)
      ignore_bsv.close()

      # Generate a dummy connection size file to avoid errors during dependence
      # analysis.
      if not os.path.exists(conSizePath):
          dummyModule = LIModule(module.name, module.name)
          bsh_handle = open(conSizePath, 'w')
          generateConnectionBSH(dummyModule, bsh_handle)
          bsh_handle.close()

      wrapper_bsv.write('import HList::*;\n')
      wrapper_bsv.write('import Vector::*;\n')
      wrapper_bsv.write('import ModuleContext::*;\n')
      # the top module is handled specially
      if (module.name == moduleList.topModule.name):
        generateWellKnownIncludes(wrapper_bsv)
        wrapper_bsv.write('// These are well-known/required leap modules\n')
        wrapper_bsv.write('// import non-synthesis public files\n')

        # Include all subordinate synthesis boundaries for use by
        # instantiateAllSynthBoundaries() below.
        # If we're doing a LIM build, there are no *_synth.bsv for use codes.
        # Probably if we're doing a build tree they aren't necessary either, but
        # removing those dependencies would take a little work. 
        if(first_pass_LI_graph is None):
            for synth in synth_modules:
                if synth != module:
                    wrapper_bsv.write('`include "' + synth.name + '_synth.bsv"\n')

        # Provide a method that imports all subordinate synthesis
        # boundaries.  It will be invoked inside the top level model
        # in order to build all soft connections
        use_build_tree = moduleList.getAWBParam('wrapper_gen_tool', 'USE_BUILD_TREE')
        expose_all_connections = 0
        try:
            expose_all_connections = moduleList.getAWBParam('model', 'EXPOSE_ALL_CONNECTIONS')
        except:
            pass

        if (use_build_tree == 1):
            wrapper_bsv.write('\n\n`ifdef  CONNECTION_SIZES_KNOWN\n');
            # build_tree.bsv will get generated later, during the
            # leap-connect phase.
            wrapper_bsv.write('    import build_tree_synth::*;\n'); 
            wrapper_bsv.write('    module [Connected_Module] instantiateAllSynthBoundaries#(Reset baseReset) ();\n')
            wrapper_bsv.write('        Reset rst <- mkResetFanout(baseReset);\n')
            wrapper_bsv.write('        let m <- build_tree(baseReset, reset_by rst);\n')
            wrapper_bsv.write('    endmodule\n')
            wrapper_bsv.write('`else\n');

        wrapper_bsv.write('\n    module ')
        if len(synth_modules) != 1:
            wrapper_bsv.write('[Connected_Module]')
        wrapper_bsv.write(' instantiateAllSynthBoundaries#(Reset baseReset) ();\n')

        for synth in synth_modules:
          if synth != module and not synth.platformModule:
              wrapper_bsv.write('        ' + synth.synthBoundaryModule + '();\n')

        wrapper_bsv.write('    endmodule\n')
        if (use_build_tree == 1):
            wrapper_bsv.write('`endif\n'); 


        # Import platform wrapper.
        wrapper_bsv.write('    import ' + moduleList.localPlatformName +'_platform_synth::*;\n'); 

        wrapper_bsv.write('    module [Connected_Module] instantiatePlatform ('+ platform_module.interfaceType +');\n')
        wrapper_bsv.write('        let m <- ' + moduleList.localPlatformName + '_platform(noReset);\n')
        wrapper_bsv.write('        return m;\n')
        wrapper_bsv.write('    endmodule\n')

        wrapper_bsv.write('`include "' + module.name + '.bsv"\n')

        wrapper_bsv.write('\n// import non-synthesis private files\n')
        wrapper_bsv.write('// Get defintion of TOP_LEVEL_WIRES\n')
        wrapper_bsv.write('import physical_platform::*;\n')
        wrapper_bsv.write('(* synthesize *)\n')

        wrapper_bsv.write('module [Module] mk_model_Wrapper\n')
        wrapper_bsv.write('    (TOP_LEVEL_WIRES);\n\n')
        wrapper_bsv.write('    // Instantiate main module\n')
        
        wrapper_bsv.write('    let m <- mkModel(clocked_by noClock, reset_by noReset);\n')

        wrapper_bsv.write('    return m;\n')
        wrapper_bsv.write('endmodule\n')

      else:
        log_bsv = open(logPath, 'w')
        log_bsv.write('import HList::*;\n')
        log_bsv.write('import ModuleContext::*;\n')

        # Parents of a synthesis boundary likely import the top level module of
        # the boundary.  This way, the synthesis boundary could be removed and
        # the code within the boundary would be imported correctly by the parent.
        # The code within the synthesis boundary will actually be imported at the
        # top level instead, so we need a dummy module for use by the parent of
        # a boundary that looks like it imports the code but actually does nothing.
        # Importing at the top level allows us to build all synthesis regions
        # in parallel.
        dummy_import_bsv = open(modPath + '.bsv', 'w')
        dummy_import_bsv.write('// Generated by wrapper_gen.py\n\n')
        dummy_import_bsv.write('module ' + module.synthBoundaryModule + ' ();\n');
        dummy_import_bsv.write('endmodule\n');
        dummy_import_bsv.close()

        if not os.path.exists(modPath + '_synth.bsv'):            
            dummy_module = LIModule(module.name, module.name)
            handle = getSynthHandle(moduleList, module)
            generateSynthWrapper(dummy_module, handle, moduleList.localPlatformName,
                                 moduleType = module.interfaceType,
                                 extraImports = module.extraImports)

        for wrapper in [wrapper_bsv, log_bsv]:      
            wrapper.write('// These are well-known/required leap modules\n')
            generateWellKnownIncludes(wrapper)
            wrapper.write('`include "awb/provides/librl_bsv_base.bsh"\n')
            wrapper.write('// import non-synthesis public files\n')
            wrapper.write('`include "' + module.name + '_compile.bsv"\n')
            wrapper.write('\n\n')
            
        log_bsv.write('// First pass to see how large the vectors should be\n')
        log_bsv.write('`define CON_RECV_' + module.boundaryName + ' 100\n')
        log_bsv.write('`define CON_SEND_' + module.boundaryName + ' 100\n')
        log_bsv.write('`define CON_RECV_MULTI_' + module.boundaryName + ' 50\n')
        log_bsv.write('`define CON_SEND_MULTI_' + module.boundaryName + ' 50\n')
        log_bsv.write('`define CHAINS_' + module.boundaryName + ' 50\n')
        wrapper_bsv.write('// Real build pass.  Include file built dynamically.\n')
        wrapper_bsv.write('`include "' + module.name + '_Wrapper_con_size.bsh"\n')

        for wrapper in [wrapper_bsv, log_bsv]:      
            wrapper.write('(* synthesize *)\n')
            wrapper.write('module [Module] ' + module.wrapperName() + '#(Reset baseReset) (SOFT_SERVICES_SYNTHESIS_BOUNDARY#(`CON_RECV_' + module.boundaryName + ', `CON_SEND_' + module.boundaryName + ', `CON_RECV_MULTI_' + module.boundaryName + ', `CON_SEND_MULTI_' + module.boundaryName +', `CHAINS_' + module.boundaryName +', ' + module.interfaceType + '));\n')
            wrapper.write('  \n')
            # we need to insert the fpga platform here
            # get my parameters 

            wrapper.write('    // instantiate own module\n')
            wrapper.write('    let int_ctx0 <- initializeServiceContext();\n')
            wrapper.write('    match {.int_ctx1, .int_name1} <- runWithContext(int_ctx0, putSynthesisBoundaryID(fpgaNumPlatforms() + ' + str(module.synthBoundaryUID + uidOffset)  + '));\n');
            wrapper.write('    match {.int_ctx2, .int_name2} <- runWithContext(int_ctx1, putSynthesisBoundaryPlatform("' + moduleList.localPlatformName + '"));\n')
            wrapper.write('    match {.int_ctx3, .int_name3} <- runWithContext(int_ctx2, putSynthesisBoundaryPlatformID(' + str(moduleList.localPlatformUID) + '));\n')
            wrapper.write('    match {.int_ctx4, .int_name4} <- runWithContext(int_ctx3, putSynthesisBoundaryName("' + str(module.boundaryName) + '"));\n')
            wrapper.write('    // By convention, global string ID 0 (the first string) is the module name\n');
            wrapper.write('    match {.int_ctx5, .int_name5} <- runWithContext(int_ctx4, getGlobalStringUID("' + moduleList.localPlatformName + ':' + module.name + '"));\n');
            wrapper.write('    match {.int_ctx6, .module_ifc} <- runWithContext(int_ctx5, ' + module.synthBoundaryModule + ');\n')
            
            # Need to expose clocks of the platform Module
            if(module.platformModule):
                wrapper.write('    match {.clk, .rst} = extractClocks(module_ifc);\n')
                wrapper.write('    match {.int_ctx7, .int_name7} <- runWithContext(int_ctx6, mkSoftConnectionDebugInfo(clocked_by clk, reset_by rst));\n')
                wrapper.write('    match {.final_ctx, .m_final}  <- runWithContext(int_ctx7, mkSoftConnectionLatencyInfo(clocked_by clk, reset_by rst));\n')                
            else:
                wrapper.write('    match {.int_ctx7, .int_name7} <- runWithContext(int_ctx6, mkSoftConnectionDebugInfo);\n')
                wrapper.write('    match {.final_ctx, .m_final}  <- runWithContext(int_ctx7, mkSoftConnectionLatencyInfo);\n')
            wrapper.write('    let service_ifc <- exposeServiceContext(final_ctx);\n')
            wrapper.write('    interface services = service_ifc;\n')
            wrapper.write('    interface device = module_ifc;\n')
            wrapper.write('endmodule\n')
    
        log_bsv.close()

      wrapper_bsv.close()
Example #17
0
File: BSV.py Project: chenm001/leap
    def compute_dependence(self, moduleList, module, useDerived, fileName='.depends-bsv', targetFiles=[]):
        MODULE_PATH =  get_build_path(moduleList, module)

        #allow caller to override dependencies.  If the caller does
        #not, then we should use the baseline
        if (len(targetFiles) == 0):
            targetFiles = [ moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + module.buildPath + '/' + model.get_wrapper(module) ]
            if (module.name != moduleList.topModule.name):
                targetFiles.append(moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + module.buildPath + '/'+ model.get_log(module))

        # We must depend on all sythesis boundaries. They can be instantiated anywhere.
        surrogate_children = moduleList.synthBoundaries()
        SURROGATE_BSVS = ''
        for child in surrogate_children:
            # Make sure module doesn't self-depend
            if (child.name != module.name):
                SURROGATE_BSVS += moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + child.buildPath +'/' + child.name + '.bsv '

        if (useDerived and SURROGATE_BSVS != ''):
            DERIVED = ' -derived "' + SURROGATE_BSVS + '"'
        else:
            DERIVED = ''

        depends_bsv = MODULE_PATH + '/' + fileName
        moduleList.env.NoCache(depends_bsv)
        compile_deps = 'leap-bsc-mkdepend -ignore ' + MODULE_PATH + '/.ignore' + ' -bdir ' + self.TMP_BSC_DIR + DERIVED + ' -p +:' + self.ALL_LIB_DIR_PATHS + ' ' + ' '.join(targetFiles) + ' > ' + depends_bsv

        # Delete depends_bsv if it is empty under the assumption that something
        # went wrong when creating it.  An empty dependence file would never be
        # rebuilt without this.
        try:
            if (os.path.getsize(depends_bsv) == 0):
                os.unlink(depends_bsv)
        except:
            None

        dep = moduleList.env.Command(depends_bsv,
                                     targetFiles +
                                     moduleList.topModule.moduleDependency['IFACE_HEADERS'],
                                     compile_deps)

        # Load an old .depends-bsv file if it exists.  The file describes
        # the previous dependence among Bluespec files, giving a clue of whether
        # anything changed.  The file describes dependence between derived objects
        # and sources.  Here, we need to know about all possible source changes.
        # Scan the file looking for source file names.
        if os.path.isfile(depends_bsv):
            df = open(depends_bsv, 'r')
            dep_lines = df.readlines()

            # Match .bsv and .bsh files
            bsv_file_pattern = re.compile('\S+.[bB][sS][vVhH]$')

            all_bsc_files = []
            for ln in dep_lines:
                all_bsc_files += [f for f in re.split('[:\s]+', ln) if (bsv_file_pattern.match(f))]

            # Sort dependence in case SCons cares
            for f in sorted(all_bsc_files):
                if os.path.exists(f):
                    moduleList.env.Depends(dep, f)

            df.close()

        return dep
Example #18
0
  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)
Example #19
0
File: BSV.py Project: chenm001/leap
    def build_synth_boundary(self, moduleList, module):
        if (self.pipeline_debug != 0):
            print "Working on " + module.name

        env = moduleList.env
        BSVS = moduleList.getSynthBoundaryDependencies(module, 'GIVEN_BSVS')
        # each submodel will have a generated BSV
        GEN_BSVS = moduleList.getSynthBoundaryDependencies(module, 'GEN_BSVS')
        APM_FILE = moduleList.env['DEFS']['APM_FILE']
        BSC = moduleList.env['DEFS']['BSC']

        MODULE_PATH =  get_build_path(moduleList, module)

        ##
        ## Load intra-Bluespec dependence already computed.  This information will
        ## ultimately drive the building of Bluespec modules.
        ##
        env.ParseDepends(MODULE_PATH + '/' + module.dependsFile,
                         must_exist = not moduleList.env.GetOption('clean'))


        # This function is responsible for creating build rules for
        # subdirectories.  It must be called or no subdirectory builds
        # will happen since scons won't have the recipe.
        self.setup_module_build(moduleList, MODULE_PATH)

        if not os.path.isdir(self.TMP_BSC_DIR):
            os.mkdir(self.TMP_BSC_DIR)

        moduleList.env.VariantDir(MODULE_PATH + '/' + self.TMP_BSC_DIR, '.', duplicate=0)

        # set up builds for the various bsv of this synthesis
        # boundary.  One wonders if we could handle this as a single
        # global operation.
        bsc_builds = []
        for bsv in BSVS + GEN_BSVS:
            bsc_builds += env.BSC(MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + bsv.replace('.bsv', ''), MODULE_PATH + '/' + bsv)


        firstPassLIGraph = wrapper_gen_tool.getFirstPassLIGraph()
        # In the second pass of the LIM build, we don't need to build
        # any modules, except in some cases where we turn on
        # module-specific optimizations, as in the case of central
        # cache.  If we do need to rebuild, we'll see a tag.
        if ((module.name != moduleList.topModule.name) and (not firstPassLIGraph is None) and (module.name in firstPassLIGraph.modules) and (firstPassLIGraph.modules[module.name].getAttribute('RESYNTHESIZE') is None)):
            return

        # This should not be a for loop.
        for bsv in [model.get_wrapper(module)]:
            if env.GetOption('clean'):
                os.system('rm -f ' + MODULE_PATH + '/' + bsv.replace('Wrapper.bsv', 'Log.bsv'))
                os.system('rm -f ' + MODULE_PATH + '/' + bsv.replace('.bsv', '_con_size.bsh'))

            ##
            ## First pass just generates a log file to figure out cross synthesis
            ## boundary soft connection array sizes.
            ##
            ## All but the top level build need the log build pass to compute
            ## the size of the external soft connection vector.  The top level has
            ## no exposed connections and can generate the log file, needed
            ## for global strings, during the final build.
            ##
            logfile = model.get_logfile(moduleList, module)
            module.moduleDependency['BSV_LOG'] += [logfile]
            module.moduleDependency['GEN_LOGS'] = [logfile]
            if (module.name != moduleList.topModule.name):
                log = env.BSC_LOG_ONLY(logfile, MODULE_PATH + '/' + bsv.replace('Wrapper.bsv', 'Log'))

                ##
                ## Parse the log, generate a stub file
                ##

                stub_name = bsv.replace('.bsv', '_con_size.bsh')

                def build_con_size_bsh_closure(target, source, env):
                    liGraph = LIGraph(li_module.parseLogfiles(source))
                    # Should have only one module...
                    if(len(liGraph.modules) == 0):
                        bshModule = LIModule(module.name, module.name)
                    else:
                        bshModule = liGraph.modules.values()[0]
                    bsh_handle = open(str(target[0]), 'w')
                    wrapper_gen_tool.generateConnectionBSH(bshModule, bsh_handle)
                    bsh_handle.close()

                stub = env.Command(MODULE_PATH + '/' + stub_name, log, build_con_size_bsh_closure)

            ##
            ## Now we are ready for the real build
            ##
            if (module.name != moduleList.topModule.name):
                wrapper_bo = env.BSC(MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + bsv.replace('.bsv', ''), MODULE_PATH + '/' + bsv)
                moduleList.env.Depends(wrapper_bo, stub)
                module.moduleDependency['BO'] = [wrapper_bo]
                if (self.BUILD_LOGS_ONLY):
                    model_dir = self.hw_dir.Dir(moduleList.env['DEFS']['ROOT_DIR_MODEL'])

                    module.moduleDependency['BSV_SCHED'] = \
                        [moduleList.env.Command(MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + module.wrapperName() + '.ba.sched',
                                                wrapper_bo,
                                                'bluetcl ' + model_dir.File('sched.tcl').path + ' -p ' + self.ALL_BUILD_DIR_PATHS + ' --m ' + module.wrapperName() + ' > $TARGET')]

                    module.moduleDependency['BSV_PATH'] = \
                        [moduleList.env.Command(MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + module.wrapperName() + '.ba.path',
                                                wrapper_bo,
                                                'bluetcl ' + model_dir.File('path.tcl').path + ' -p ' + self.ALL_BUILD_DIR_PATHS + ' --m ' + module.wrapperName() + ' > $TARGET')]

                    moduleList.topDependency += \
                        module.moduleDependency['BSV_SCHED'] + module.moduleDependency['BSV_PATH']

                    module.moduleDependency['BSV_IFC'] = \
                        [moduleList.env.Command(MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + module.wrapperName() + '.ba.ifc',
                                                wrapper_bo,
                                                'bluetcl ' + model_dir.File('interfaceType.tcl').path + ' -p ' + self.ALL_BUILD_DIR_PATHS + ' --m ' + module.wrapperName() + ' | python site_scons/model/PythonTidy.py > $TARGET')]

                    moduleList.topDependency += module.moduleDependency['BSV_IFC']




            else:
                ## Top level build can generate the log in a single pass since no
                ## connections are exposed
                wrapper_bo = env.BSC_LOG(MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + bsv.replace('.bsv', ''),
                                         MODULE_PATH + '/' + bsv)

                ## SCons doesn't deal well with logfile as a 2nd target to BSC_LOG rule,
                ## failing to derive dependence correctly.
                module.moduleDependency['BSV_BO'] = [wrapper_bo]
                log = env.Command(logfile, wrapper_bo, '')
                env.Precious(logfile)

                ## In case Bluespec build is the end of the build pipeline.
                if (not self.BUILD_LOGS_ONLY):
                    moduleList.topDependency += [log]

                ## The toplevel bo also depends on the on the synthesis of the build tree from log files.

            ##
            ## Meta-data written during compilation to separate files.
            ##
            glob_str = env.Command(MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + bsv.replace('.bsv', '.str'),
                                   wrapper_bo,
                                   '')

            env.Precious(glob_str)
            module.moduleDependency['STR'] = [glob_str]

            ## All but the top level build need the log build pass to compute
            ## the size of the external soft connection vector.  The top level has
            ## no exposed connections and needs no log build pass.
            ##
            if (module.name != moduleList.topModule.name):
                if (self.pipeline_debug != 0):
                    print 'wrapper_bo: ' + str(wrapper_bo)
                    print 'stub: ' + str(stub)

                synth_stub_path = moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' + module.buildPath + '/'
                synth_stub = synth_stub_path + module.name +'_synth.bsv'
                # This stub may be needed in certain compilation flows.  Note its presence here.
                module.moduleDependency['BSV_SYNTH'] = [module.name +'_synth.bsv']
                module.moduleDependency['BSV_SYNTH_BSH'] = [module.name +'_Wrapper_con_size.bsh']

                def build_synth_stub(target, source, env):
                    liGraph = LIGraph(li_module.parseLogfiles(source))
                    # Should have only one module...
                    if(len(liGraph.modules) == 0):
                        synthModule = LIModule(module.name, module.name)
                    else:
                        synthModule = liGraph.modules.values()[0]

                    synth_handle = open(target[0].path, 'w')
                    wrapper_gen_tool.generateSynthWrapper(synthModule,
                                                          synth_handle,
                                                          moduleList.localPlatformName,
                                                          moduleType=module.interfaceType,
                                                          extraImports=module.extraImports,
                                                          synthBoundaryModule = module)
                    synth_handle.close()

                env.Command(synth_stub, # target
                            logfile,
                            build_synth_stub)

            ##
            ## The mk_<wrapper>.v file is really built by the Wrapper() builder
            ## above.  We use NULL commands to convince SCons the file is generated.
            ## This seems easier than SCons SideEffect() calls, which don't clean
            ## targets.
            ##
            ## We also generate all this synth boundary's GEN_VS
            ##
            ext_gen_v = []
            for v in moduleList.getSynthBoundaryDependencies(module, 'GEN_VS'):
                ext_gen_v += [MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + v]


            # Add the dependence for all Verilog noted above
            bld_v = env.Command([MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + module.wrapperName() + '.v'] + ext_gen_v,
                                MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + bsv.replace('.bsv', '.bo'),
                                '')
            env.Precious(bld_v)

            if (moduleList.getAWBParam('bsv_tool', 'BUILD_VERILOG') == 1):

                module.moduleDependency['VERILOG'] += [bld_v] + [ext_gen_v]

                module.moduleDependency['GEN_WRAPPER_VERILOGS'] = [os.path.basename(module.wrapperName() + '.v')]

            if (self.pipeline_debug != 0):
                print "Name: " + module.name

            # each synth boundary will produce a ba
            bld_ba = [env.Command([MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' +  module.wrapperName() + '.ba'],
                                  MODULE_PATH + '/' + self.TMP_BSC_DIR + '/' + bsv.replace('.bsv', '.bo'),
                                  '')]

            module.moduleDependency['BA'] += bld_ba
            env.Precious(bld_ba)

            ##
            ## Build the Verilog black-box stub.
            ##
            bb = self.stubGenCommand(MODULE_PATH, module.boundaryName, bld_v)

            # Only the subordinate modules have stubs.
            # The platform module should not be enumerated here. This is a false dependency.
            if (module.name != moduleList.topModule.name):
                moduleList.topModule.moduleDependency['VERILOG_STUB'] += [bb]
                module.moduleDependency['GEN_VERILOG_STUB'] = [bb]

            return [bb] #This doesn't seem to do anything.
Example #20
0
File: BSV.py Project: chenm001/leap
    def __init__(self, moduleList):
        # some definitions used during the bsv compilation process
        env = moduleList.env
        self.moduleList = moduleList

        self.hw_dir = env.Dir(moduleList.env['DEFS']['ROOT_DIR_HW'])

        self.TMP_BSC_DIR = env['DEFS']['TMP_BSC_DIR']
        synth_modules = moduleList.synthBoundaries()

        self.USE_TREE_BUILD = moduleList.getAWBParam('wrapper_gen_tool', 'USE_BUILD_TREE')

        # all_module_dirs: a list of all module directories in the build tree
        self.all_module_dirs = [self.hw_dir.Dir(moduleList.topModule.buildPath)]
        for module in synth_modules:
            if (module.buildPath != moduleList.topModule.buildPath):
                self.all_module_dirs += [self.hw_dir.Dir(module.buildPath)]

        # all_build_dirs: the build (.bsc) sub-directory of all module directories
        self.all_build_dirs = [d.Dir(self.TMP_BSC_DIR) for d in self.all_module_dirs]

        # Include iface directories
        self.all_module_dirs += iface_tool.getIfaceIncludeDirs(moduleList)
        self.all_build_dirs += iface_tool.getIfaceLibDirs(moduleList)

        # Add the top level build directory
        self.all_build_dirs += [env.Dir(self.TMP_BSC_DIR)]

        self.all_module_dirs += [self.hw_dir.Dir('include'),
                                 self.hw_dir.Dir('include/awb/provides')]

        # Full search path: all module and build directories
        self.all_lib_dirs = self.all_module_dirs + self.all_build_dirs

        all_build_dir_paths = [d.path for d in self.all_build_dirs]
        self.ALL_BUILD_DIR_PATHS = ':'.join(all_build_dir_paths)

        all_lib_dir_paths = [d.path for d in self.all_lib_dirs]
        self.ALL_LIB_DIR_PATHS = ':'.join(all_lib_dir_paths)

        # we need to annotate the module list with the
        # bluespec-provided library files. Do so here.
        bsv_tool.decorateBluespecLibraryCode(moduleList)

        self.TMP_BSC_DIR = moduleList.env['DEFS']['TMP_BSC_DIR']
        self.BUILD_LOGS_ONLY = moduleList.getAWBParam('bsv_tool', 'BUILD_LOGS_ONLY')
        self.USE_BVI = moduleList.getAWBParam('bsv_tool', 'USE_BVI')

        self.pipeline_debug = model.getBuildPipelineDebug(moduleList)

        # Should we be building in events?
        if (model.getEvents(moduleList) == 0):
            bsc_events_flag = ' -D HASIM_EVENTS_ENABLED=False '
        else:
            bsc_events_flag = ' -D HASIM_EVENTS_ENABLED=True '

        self.BSC_FLAGS = moduleList.getAWBParam('bsv_tool', 'BSC_FLAGS') + bsc_events_flag

        moduleList.env.VariantDir(self.TMP_BSC_DIR, '.', duplicate=0)
        moduleList.env['ENV']['BUILD_DIR'] = moduleList.env['DEFS']['BUILD_DIR']  # need to set the builddir for synplify


        topo = moduleList.topologicalOrderSynth()
        topo.reverse()

        # Cleaning? Wipe out module temporary state. Do this before
        # the topo pop to ensure that we don't leave garbage around at
        # the top level.
        if moduleList.env.GetOption('clean'):
            for module in topo:
                MODULE_PATH =  get_build_path(moduleList, module)
                os.system('cd '+ MODULE_PATH + '/' + self.TMP_BSC_DIR + '; rm -f *.ba *.c *.h *.sched *.log *.v *.bo *.str')

        topo.pop() # get rid of top module.

        ## Python module that generates a wrapper to connect the exposed
        ## wires of all synthesis boundaries.
        tree_builder = bsv_tool.BSVSynthTreeBuilder(self)

        ##
        ## Is this a normal build or a build in which only Bluespec dependence
        ## is computed?
        ##

        if not moduleList.isDependsBuild:
            ##
            ## Normal build.
            ##

            ##
            ## Now that the "depends-init" build is complete we can
            ## continue with accurate inter-Bluespec file dependence.
            ## This build only takes place for the first pass object
            ## code generation.  If the first pass li graph exists, it
            ## subsumes awb-style synthesis boundary generation.
            ##
            for module in topo:
                self.build_synth_boundary(moduleList, module)


            ## We are going to have a whole bunch of BA and V files coming.
            ## We don't yet know what they contain, but we do know that there
            ## will be |synth_modules| - 2 of them

            if (not 'GEN_VERILOGS' in moduleList.topModule.moduleDependency):
                moduleList.topModule.moduleDependency['GEN_VERILOGS'] = []
            if (not 'GEN_BAS' in moduleList.topModule.moduleDependency):
                moduleList.topModule.moduleDependency['GEN_BAS'] = []

            ## Having described the new build tree dependencies we can build
            ## the top module.
            self.build_synth_boundary(moduleList, moduleList.topModule)

            ## Merge all synthesis boundaries using a tree?  The tree reduces
            ## the number of connections merged in a single compilation, allowing
            ## us to support larger systems.
            if self.USE_TREE_BUILD:
                tree_builder.setupTreeBuild(moduleList, topo)

            ##
            ## Generate the global string table.  Bluespec-generated global
            ## strings are stored in files by the compiler.
            ##
            ## The global string file will be generated in the top-level
            ## .bsc directory and a link to it will be added to the
            ## top-level directory.
            ##
            all_str_src = []
            #for module in topo + [moduleList.topModule]:
            for module in moduleList.moduleList + topo + [moduleList.topModule]:
                if('STR' in module.moduleDependency):
                    all_str_src.extend(module.moduleDependency['STR'])

            if (self.BUILD_LOGS_ONLY == 0):
                bsc_str = moduleList.env.Command(self.TMP_BSC_DIR + '/' + moduleList.env['DEFS']['APM_NAME'] + '.str',
                                                 all_str_src,
                                                 [ 'cat $SOURCES > $TARGET'])
                strDep = moduleList.env.Command(moduleList.env['DEFS']['APM_NAME'] + '.str',
                                                bsc_str,
                                                [ 'ln -fs ' + self.TMP_BSC_DIR + '/`basename $TARGET` $TARGET' ])
                moduleList.topDependency += [strDep]



            if moduleList.env.GetOption('clean'):
                print 'Cleaning depends-init...'
                s = os.system('scons --clean depends-init')
        else:

            ##
            ## Dependence build.  The target of this build is "depens-init".  No
            ## Bluespec modules will be compiled in this invocation of SCons.
            ## Only .depends-bsv files will be produced.
            ##

            # We need to calculate some dependencies for the build
            # tree.  We could be clever and put this code somewhere
            # rather than replicate it.
            if self.USE_TREE_BUILD: 

                buildTreeDeps = {}
                buildTreeDeps['GEN_VERILOGS'] = []
                buildTreeDeps['GEN_BAS'] = []
                #This is sort of a hack.
                buildTreeDeps['WRAPPER_BSHS'] = ['awb/provides/soft_services.bsh']
                buildTreeDeps['GIVEN_BSVS'] = []
                buildTreeDeps['BA'] = []
                buildTreeDeps['STR'] = []
                buildTreeDeps['VERILOG'] = []
                buildTreeDeps['BSV_LOG'] = []
                buildTreeDeps['VERILOG_STUB'] = []

                tree_module = Module( 'build_tree', ["mkBuildTree"], moduleList.topModule.buildPath,\
                             moduleList.topModule.name,\
                             [], moduleList.topModule.name, [], buildTreeDeps, platformModule=True)

                tree_module.dependsFile = '.depends-build-tree'

                moduleList.insertModule(tree_module)
                tree_file_bo = get_build_path(moduleList, moduleList.topModule) + "/build_tree.bsv"
                # sprinkle files to get dependencies right
                bo_handle = open(tree_file_bo,'w')

                # mimic AWB/leap-configure

                bo_handle.write('//\n')
                bo_handle.write('// Synthesized compilation file for module: build_tree\n')
                bo_handle.write('//\n')
                bo_handle.write('//   This file was created by BSV.py\n')
                bo_handle.write('//\n')

                bo_handle.write('`define BUILDING_MODULE_build_tree\n')
                bo_handle.write('`include "build_tree_Wrapper.bsv"\n')

                bo_handle.close()

                # Calling generateWrapperStub will write out default _Wrapper.bsv
                # and _Log.bsv files for build tree. However, these files
                # may already exists, and, in the case of build_tree_Wrapper.bsv,
                # have meaningful content.  Fortunately, generateWrapperStub
                # will not over write existing files.
                wrapper_gen_tool.generateWrapperStub(moduleList, tree_module)
                wrapper_gen_tool.generateAWBCompileWrapper(moduleList, tree_module)
                topo.append(tree_module)


            deps = []

            useDerived = True
            first_pass_LI_graph = wrapper_gen_tool.getFirstPassLIGraph()
            if (not first_pass_LI_graph is None):
                useDerived = False
                # we also need to parse the platform_synth file in th
                platform_synth = get_build_path(moduleList, moduleList.topModule) + "/" +  moduleList.localPlatformName + "_platform_synth.bsv"
                platform_deps = ".depends-platform"
                deps += self.compute_dependence(moduleList, moduleList.topModule, useDerived, fileName=platform_deps, targetFiles=[platform_synth])

                # If we have an LI graph, we need to construct and compile
                # several LI wrappers.  do that here.
                # include all the dependencies in the graph in the wrapper.
                li_wrappers = []
                tree_base_path = get_build_path(moduleList, moduleList.topModule)
                liGraph = LIGraph([])
                firstPassGraph = first_pass_LI_graph
                # We should ignore the 'PLATFORM_MODULE'
                liGraph.mergeModules([ module for module in getUserModules(firstPassGraph) if module.getAttribute('RESYNTHESIZE') is None])
                for module in sorted(liGraph.graph.nodes(), key=lambda module: module.name):
                    wrapper_import_path = tree_base_path + '/' + module.name + '_Wrapper.bsv'
                    li_wrappers.append(module.name + '_Wrapper.bsv')
                    wrapper_import_handle = open(wrapper_import_path, 'w')
                    wrapper_import_handle.write('import Vector::*;\n')
                    wrapper_gen_tool.generateWellKnownIncludes(wrapper_import_handle)
                    wrapper_gen_tool.generateBAImport(module, wrapper_import_handle)
                    wrapper_import_handle.close()
                    platform_deps = ".depends-" + module.name
                    deps += self.compute_dependence(moduleList, moduleList.topModule, useDerived, fileName=platform_deps, targetFiles=[wrapper_import_path])
        
            for module in topo + [moduleList.topModule]:
                # for object import builds no Wrapper code will be included. remove it.
                deps += self.compute_dependence(moduleList, module, useDerived, fileName=module.dependsFile)

            moduleList.topDependsInit += deps
Example #21
0
File: BSV.py Project: chenm001/leap
    def compute_dependence(self,
                           moduleList,
                           module,
                           useDerived,
                           fileName='.depends-bsv',
                           targetFiles=[]):
        MODULE_PATH = get_build_path(moduleList, module)

        #allow caller to override dependencies.  If the caller does
        #not, then we should use the baseline
        if (len(targetFiles) == 0):
            targetFiles = [
                moduleList.env['DEFS']['ROOT_DIR_HW'] + '/' +
                module.buildPath + '/' + model.get_wrapper(module)
            ]
            if (module.name != moduleList.topModule.name):
                targetFiles.append(moduleList.env['DEFS']['ROOT_DIR_HW'] +
                                   '/' + module.buildPath + '/' +
                                   model.get_log(module))

        # We must depend on all sythesis boundaries. They can be instantiated anywhere.
        surrogate_children = moduleList.synthBoundaries()
        SURROGATE_BSVS = ''
        for child in surrogate_children:
            # Make sure module doesn't self-depend
            if (child.name != module.name):
                SURROGATE_BSVS += moduleList.env['DEFS'][
                    'ROOT_DIR_HW'] + '/' + child.buildPath + '/' + child.name + '.bsv '

        if (useDerived and SURROGATE_BSVS != ''):
            DERIVED = ' -derived "' + SURROGATE_BSVS + '"'
        else:
            DERIVED = ''

        depends_bsv = MODULE_PATH + '/' + fileName
        moduleList.env.NoCache(depends_bsv)
        compile_deps = 'leap-bsc-mkdepend -ignore ' + MODULE_PATH + '/.ignore' + ' -bdir ' + self.TMP_BSC_DIR + DERIVED + ' -p +:' + self.ALL_LIB_DIR_PATHS + ' ' + ' '.join(
            targetFiles) + ' > ' + depends_bsv

        # Delete depends_bsv if it is empty under the assumption that something
        # went wrong when creating it.  An empty dependence file would never be
        # rebuilt without this.
        try:
            if (os.path.getsize(depends_bsv) == 0):
                os.unlink(depends_bsv)
        except:
            None

        dep = moduleList.env.Command(
            depends_bsv, targetFiles +
            moduleList.topModule.moduleDependency['IFACE_HEADERS'],
            compile_deps)

        # Load an old .depends-bsv file if it exists.  The file describes
        # the previous dependence among Bluespec files, giving a clue of whether
        # anything changed.  The file describes dependence between derived objects
        # and sources.  Here, we need to know about all possible source changes.
        # Scan the file looking for source file names.
        if os.path.isfile(depends_bsv):
            df = open(depends_bsv, 'r')
            dep_lines = df.readlines()

            # Match .bsv and .bsh files
            bsv_file_pattern = re.compile('\S+.[bB][sS][vVhH]$')

            all_bsc_files = []
            for ln in dep_lines:
                all_bsc_files += [
                    f for f in re.split('[:\s]+', ln)
                    if (bsv_file_pattern.match(f))
                ]

            # Sort dependence in case SCons cares
            for f in sorted(all_bsc_files):
                if os.path.exists(f):
                    moduleList.env.Depends(dep, f)

            df.close()

        return dep