import os import subprocess import win32com.client ProjectName = "CP11U" XilinxPath = os.environ["XILINX"] XilinxBin = os.path.join(XilinxPath,'bin\\nt') ProjectDirectory = os.getcwd() WorkbookPath = os.path.join(ProjectDirectory,WorkbookFilename) WorkbookFilename = "%s.xlsx" % ProjectName Excel = win32com.client.Dispatch("Excel.Application") try: ProjectWorkbook = Excel.Workbooks(WorkbookFilename) #check if it's already open except Exception,e: try: ProjectWorkbook = Excel.Workbooks.Open(WorkbookPath) #open it except Exception,ex: print ex run, runXST, runNGDBuild, runMAP, runPAR, runBitgen = False, True, False, False, False, False getXDL = True class XilinxProject: ''' XilinxProject class accepts a Workbook specifying a Xilinx compilation project ''' def __init__(self,ProjectWorkbook,ProjectPath): self.ProjectWorkbook = ProjectWorkbook self.ProjectSheet = ProjectWorkbook.Sheets("Project") self.SynthesisSheet = ProjectWorkbook.Sheets("Synthesis") self.TranslationSheet = ProjectWorkbook.Sheets("Translation") self.ConstraintsSheet = ProjectWorkbook.Sheets("Constraints") self.BitstreamSheet = ProjectWorkbook.Sheets("Bitstream") self.ProjectPath = self.ProjectSheet.Range("ProjectPath").Value self.top = self.ProjectSheet.Range("top").Value self.tmpdir = self.ProjectSheet.Range("tmpdir").Value self.xsthdpdir = self.ProjectSheet.Range("xsthdpdir").Value self.part = self.ProjectSheet.Range("part").Value #Make tmp_dir and hdp_dir if necessary if (not os.path.exists(tmpdir)): os.mkdir(os.path.join(self.ProjectPath,self.tmpdir)) if (not os.path.exists(xsthdpdir)): os.mkdir(os.path.join(self.ProjectPath,self.xsthdpdir)) def SetUCF(self,ucf_file_path): self.ucf_file = ucf_file_path self.ConstraintsSheet.Range("ucffile").Formula = ucf_file_path def GetUCF(self): self.ucf_file = self.ConstraintsSheet.Range("ucffile").Formula #------------------------------------------------------------------------ #UCF Generation #------------------------------------------------------------------------ def GenerateUCF(self): ConstraintsRange = self.ConstraintsSheet.Range("ConstraintsRange") Constraints = self.ConstraintsSheet.Range(ConstraintsRange).Formula self.ucf_file = "%s.ucf"%self.top ucf_fo = open(self.ucf_file, mode='w') for net,loc,iostandard,slew in Constraints: line = "NET \"%s\" LOC = \"%s\" | IOSTANDARD = %s" % (net,loc,iostandard) if (slew == None): line += ";\n" else: line += " | SLEW = %s;\n" % slew ucf_fo.write(line) ucf_fo.close() self.SetUCF(ucf_file) #------------------------------------------------------------------------ #End UCF Generation #------------------------------------------------------------------------ #------------------------------------------------------------------------ #XST file Generation #------------------------------------------------------------------------ def GenerateXST(self): SynthesisParametersRange = self.SynthesisSheet.Range("SynthParams").Value #There is a problem with integer values turning into Floats when accessed using Range("xx:xx").Value, use Formula instead #SynthesisParameters = SynthesisSheet.Range(SynthesisParametersRange).Value #this xst writer used to have the style "for param,default,setting in SynthesisParameters:" SynthesisParametersRows = self.SynthesisSheet.Range(SynthesisParametersRange).Rows self.xst_file = "%s.xst"%top xst_fo = open(self.xst_file, mode='w') xst_fo.write("set -tmpdir %s\n" % self.tmpdir) xst_fo.write("set -xsthdpdir %s\n" % self.xsthdpdir) xst_fo.write("run\n") for row in SynthesisParametersRows: Parameter=row.Columns(1).Value if row.Columns(3).HasFormula: Setting = row.Columns(3).Value else: Setting = row.Columns(3).Formula if row.Columns(2).HasFormula: Default = row.Columns(2).Value else: Default = row.Columns(2).Formula if (Setting != None) and (Setting != ""): xst_fo.write("-%s %s\n"%(Parameter,Setting)) elif (Default != None) and (Default != ""): xst_fo.write("-%s %s\n"%(Parameter,Default)) xst_fo.close() #------------------------------------------------------------------------ #End of XST file Generation #------------------------------------------------------------------------ #------------------------------------------------------------------------ #PRJ file Generation #------------------------------------------------------------------------ def GeneratePRJ(self): SrcFilesAddress = ProjectSheet.Range("SrcFiles").Value SrcFileArray = ProjectSheet.Range(SrcFilesAddress).Value SrcFileList = [] for line in SrcFileArray: for element in line: SrcFileList.append(element) prj_file = open("%s.prj"%top,mode='w') #todo: verilog and vhdl segregation for file in SrcFileList: line = "vhdl work %s\n" % file #previous version had a path appended... prj_file.write(line) prj_file.close() #------------------------------------------------------------------------ #End of PRJ file Generation #------------------------------------------------------------------------ def GenerateLSO(self): #Generate LSO file lso_file = open ("%s.lso"%top,mode='w') lso_file.write('work') lso_file.close() def GenerateBitgenOptions(self): BitgenParametersRange = self.ConstraintsSheet.Range("ConstraintsRange") BitgenParameters = self.ConstraintsSheet.Range(BitgenParametersRange).Formula self.bitgen_g_options = [] for option,setting in BitgenParameters: self.bitgen_g_options.append("%s:%s"%(option,setting)) ##bit_gen_g_options.append('DebugBitstream:No') ##bit_gen_g_options.append('Binary:no') ##bit_gen_g_options.append('CRC:Enable') ##bit_gen_g_options.append('ConfigRate:6') ##bit_gen_g_options.append('CclkPin:PullUp') ##bit_gen_g_options.append('M0Pin:PullUp') ##bit_gen_g_options.append('M1Pin:PullUp') ##bit_gen_g_options.append('M2Pin:PullUp') ##bit_gen_g_options.append('ProgPin:PullUp') ##bit_gen_g_options.append('DonePin:PullUp') ##bit_gen_g_options.append('TckPin:PullUp') ##bit_gen_g_options.append('TdiPin:PullUp') ##bit_gen_g_options.append('TdoPin:PullUp') ##bit_gen_g_options.append('TmsPin:PullUp') ##bit_gen_g_options.append('UnusedPin:PullDown') ##bit_gen_g_options.append('UserID:0xFFFFFFFF') ###bit_gen_g_options.append('DCMShutDown:Disable') #not available ##bit_gen_g_options.append('StartUpClk:CClk') ##bit_gen_g_options.append('DONE_cycle:4') ##bit_gen_g_options.append('GTS_cycle:5') ##bit_gen_g_options.append('GWE_cycle:6') ##bit_gen_g_options.append('LCK_cycle:NoWait') ##bit_gen_g_options.append('Match_cycle:Auto') ##bit_gen_g_options.append('Security:None') ##bit_gen_g_options.append('DonePipe:No') ##bit_gen_g_options.append('DriveDone:Yes') def RunSynthesis(self): xst_path = os.path.join(XilinxBin,"xst") self.SynthesisProcess = subprocess.Popen([xst_path,"-ifn", self.xst_file, "-ofn", "%s_xst_log.syr"%self.top],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE) # xst -ifn CPU_TOP.xst -ofn CPU_TOP_xst_log.syr def RunTranslate(self): ngdbuild_path = os.path.join(XilinxBin,"ngdbuild") TranslationSheet self.TranslateProcess = subprocess.Popen([ngdbuild_path,"-dd", self.tmpdir, "-aul", "-uc", self.ucf_file, "-p", self.part, '%s.ngc'%self.top, '%s.ngd'%self.top]) # ngdbuild -dd tmp -aul -uc CP11-CPU.ucf -p xc5vlx85-ff676-1 CPU_TOP.ngc CPU_TOP.ngd # map -p xc5vlx85-ff676-1 -cm area -pr b -k 4 -c 100 -tx off -o CPU_TOP_map.ncd CPU_TOP.ngd CPU_TOP.pcf # par -w -ol std -t 1 CPU_TOP_map.ncd CPU_TOP_par.ncd CPU_TOP.pcf class XSTFile: def __init__(self,name): if os.path.exists(name): self.File = open(name) class Synthesizer: def __init__(self): self.xst_path = os.path.join(XilinxBin,"xst") self.XST_Attr_Map = {} self.InputFileName self.XST_Attr self.InputFormat def Run(self): RunReq = [self.xst_path,"-ifn", "%s.xst"%top, "-ofn", "%s_xst_log.syr"%top] print "Invoking Synthesis Tool: " + RunReq self.retcode = subprocess.call(RunReq) def LogPrint(Port,File): ln = Port.readline() print ln File.write(ln) def HyperlinkSelection(Excel): for cell in Excel.Selection: cell.Hyperlinks.Add(cell,cell.Value) #todo: define classes for each of the synthesis and placement files #create XML-RPC interface to marshal and demarshal components and invoke toolchain if __name__ == "__main__": if run: if runXST: #Invoke XST xst_path = os.path.join(XilinxBin,"xst") retcode = subprocess.call([xst_path,"-ifn", "%s.xst"%top, "-ofn", "%s_xst_log.syr"%top]) if runNGDBuild: #Invoke NGDBuild part = '%(device)s-%(package)s-%(speed)s'%globals() ngdbuild_path = os.path.join(XilinxBin,"ngdbuild") retcode = subprocess.call([ngdbuild_path,"-dd", tmpdir, "-aul", "-uc", ucf_file, "-p", part, '%s.ngc'%top, '%s.ngd'%top]) if runMAP: #Invoke MAP map_path = os.path.join(XilinxBin,"map") retcode = subprocess.call([map_path, '-p', part, '-cm', 'area', '-pr', 'b', '-k', '4', '-c', '100', '-tx', 'off', '-o', '%s_map.ncd'%top, '%s.ngd'%top, '%s.pcf'%top]) if genXDL: xdl_path = os.path.join(XilinxBin,"xdl") retcode = subprocess.call([xdl_path,'-ncd2xdl','%s_map.ncd'%top]) if runPAR: #Invoke PAR par_path = os.path.join(XilinxBin,"par") retcode = subprocess.call([par_path, '-w', '-ol', 'std', '-t', '1', '%s_map.ncd'%top, '%s_par.ncd'%top, '%s.pcf'%top]) if genXDL: xdl_path = os.path.join(XilinxBin,"xdl") retcode = subprocess.call([xdl_path,'-ncd2xdl','%s_par.ncd'%top]) if runBitgen: #Invoke Bitgen bitgen_path = os.path.join(XilinxBin,"bitgen") bitgen_arglist = [bitgen_path, '%s_par.ncd'%top,'%s.bit'%top, '-w'] for opt in bit_gen_g_options: bitgen_arglist.append('-g') bitgen_arglist.append('%s'%opt) retcode = subprocess.call(bitgen_arglist)