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()
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()
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()
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()
def cutTreeBuild(self, state, target, source, env): pipeline_debug = self.parent.pipeline_debug boundary_logs = state['boundary_logs'] moduleList = state['moduleList'] area_constraints = state['area_constraints'] # If we got a graph from the first pass, merge it in now. if (self.getFirstPassLIGraph is None): liGraph = LIGraph(li_module.parseLogfiles(boundary_logs)) else: #cut_tree_build may modify the first pass graph, so we need #to make a copy liGraph = LIGraph([]) firstPassGraph = self.getFirstPassLIGraph # We should ignore the 'PLATFORM_MODULE' liGraph.mergeModules(bsv_tool.getUserModules(firstPassGraph)) if (area_constraints): area_constraints.loadAreaConstraintsPlaced() synth_handle = open(state['tree_file_synth'].path,'w') wrapper_handle = open(state['tree_file_wrapper'].path,'w') state['wrapper_handle'] = wrapper_handle fileID = 0 for tree_file in [wrapper_handle, synth_handle]: fileID = fileID + 1 tree_file.write("// Generated by BSVSynthTreeBuilder.py\n") tree_file.write("`ifndef BUILD_" + str(fileID) + "\n") # these may not be needed tree_file.write("`define BUILD_" + str(fileID) + "\n") tree_file.write('import Vector::*;\n') wrapper_gen_tool.generateWellKnownIncludes(tree_file) tree_file.write('// import non-synthesis public files\n') tree_file.write('`include "build_tree_compile.bsv"\n') #If we are only building logs, we don't really require the build tree. if(self.parent.BUILD_LOGS_ONLY): wrapper_handle.write("\n\n(*synthesize*)\n") wrapper_handle.write("module mk_build_tree_Wrapper#(Reset baseReset) (Reg#(Bit#(1)));\n") wrapper_handle.write(" let m <- mkRegU();\n") wrapper_handle.write(" return m;\n") wrapper_handle.write("endmodule\n") synth_handle.write("module build_tree#(Reset baseReset) (Reg#(Bit#(1)));\n") synth_handle.write(" let m <- mkRegU();\n") synth_handle.write(" return m;\n") synth_handle.write("endmodule\n") for tree_file in [wrapper_handle, synth_handle]: tree_file.write("// Log build only. This space intentionally left blank.\n") tree_file.write("`endif\n") tree_file.close() return # include all the dependencies in the graph in the wrapper. for module in sorted(liGraph.graph.nodes(), key=lambda module: module.name): wrapper_handle.write('import ' + module.name + '_Wrapper::*;\n') wrapper_handle.write('module mk_empty_Wrapper#(Reset baseReset) (SOFT_SERVICES_SYNTHESIS_BOUNDARY#(0,0,0,0,0, Empty)); return ?; endmodule\n') if (pipeline_debug != 0): print "LIGraph: " + str(liGraph) # Top module has a special, well-known name for stub gen. # unless there is only one module in the graph. expected_wrapper_count = len(boundary_logs) - 2 if(not self.getFirstPassLIGraph is None): expected_wrapper_count = len(self.getFirstPassLIGraph.modules) - 2 module_names = [ "__TREE_MODULE__" + str(id) for id in range(expected_wrapper_count)] + ["build_tree"] # partition the top level LIM graph to produce a tree of # latency insensitive modules. If there is only a # single module, we need to add a vestigial empty module # to the graph. This situation only occurs in a handful # of multifpga modules. # In the first LIM pass, we need to expose all # connections. Doing so through Bluespec results in # object code changes, which are unacceptable. Therefore, # We optionally trim the build tree. # assign top_module some default. top_module = None if(self.parent.BUILD_LOGS_ONLY == 0): if (len(liGraph.graph.nodes()) == 1): # Singleton Modules still need to pass through the # trimming phase to remove references to unmatched # channels. If there's only one module, introduce # a trivial second module. Having no LI modules is # handled correctly. liGraph.mergeModules([LIModule("empty", "empty")]) state['empty_count'] = 0 # Cut the build into a tree of merged wrappers. We could merge # all of them in a single level, but the Bluespec compiler winds # up being too slow. A hierarchy compiles more efficiently. top_module = self.cutRecurse(state, liGraph, 1, module_names) # Generate the code for the cut tree. self.emitWrappersRecurse(state, top_module, 1) # walk the top module to annotate area group paths def annotateAreaGroups(treeModule, verilogPath): if (isinstance(treeModule, TreeModule)): if (not treeModule.children is None): for child in treeModule.children: annotateAreaGroups(child,verilogPath + getInstanceName(treeModule.name) + treeModule.seperator) else: # fill in the area group data structure if (area_constraints and (treeModule.name in area_constraints.constraints)): # We always have synthesis boundaries at the bottom of the tree. area_constraints.constraints[treeModule.name].sourcePath = \ verilogPath + getInstanceName(treeModule.name) # If necessary, dump out the area groups file. if(not self.getFirstPassLIGraph is None): # Also load up areaGroups # top module has a funny recursive base case. Fix it here. # It is possible the the top_module will be a singleton LI module. if(isinstance(top_module,TreeModule)): for child in top_module.children: annotateAreaGroups(child, 'm_sys_sys_syn_m_mod/') else: annotateAreaGroups(top_module, 'm_sys_sys_syn_m_mod/') # Annotate physical platform. This is sort of a hack. if (area_constraints): n = moduleList.localPlatformName + "_platform" if (n in area_constraints.constraints): # Vivado has difficulties in placing platform # code in the presence of device driver area # groups. We optionally disable the # generation of platform area groups here. if (moduleList.getAWBParam('area_group_tool', 'AREA_GROUPS_GROUP_PLATFORM_CODE')): area_constraints.constraints[n].sourcePath = "m_sys_sys_vp_m_mod" else: area_constraints.constraints[n].sourcePath = None area_constraints.storeAreaConstraints() # In multifpga builds, we may have some leftover modules # due to the way that the LIM compiler currently # operates. We emit dummy modules here to make # downstream tools happy. This can be removed once we # reorganize the multifpga compiler. for module in module_names: wrapper_handle.write("\n\n(*synthesize*)\n") wrapper_handle.write("module mk_" + module + '_Wrapper' + " (Reg#(Bit#(1)));\n") wrapper_handle.write(" let m <- mkRegU();\n") wrapper_handle.write(" return m;\n") wrapper_handle.write("endmodule\n") # we need to create a top level wrapper module to # re-monadize the soft connections so that the platform # compiles correctly # however the synth file depends only on the build tree wrapper # if we have a single module, it will be the case that # this module and not a tree build will be returned. Handle both. if(top_module is None): # If we have no top module, then the build tree is empty. synth_handle.write("\n\nmodule [Connected_Module] build_tree();\n") synth_handle.write(" //this space intentionally left blank\n") synth_handle.write("endmodule\n") else: wrapper_gen_tool.generateTopSynthWrapper(top_module, synth_handle, moduleList.localPlatformName, areaConstraints = area_constraints) for tree_file in [synth_handle, wrapper_handle]: tree_file.write("`endif\n") tree_file.close() return None