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.
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.
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
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