class HdlParser: reserved = [ 'CHIP', 'IN', 'OUT', 'PARTS', 'BUILTIN', 'CLOCKED' ] tokens = [ 'COMMA', 'NAME', 'COMMENT1', 'COMMENT2', 'SEMICOLON', 'OCURLEYBRACKET', 'CCURLEYBRACKET', 'COLON', 'OBRACKET', 'CBRACKET', 'EQUALS', 'BIT_WIDTH' ] + reserved #literals = ['='] t_ignore = " \t" t_COMMA = r',' t_COLON = r':' t_SEMICOLON = r';' t_OCURLEYBRACKET = r'{' t_CCURLEYBRACKET = r'}' t_OBRACKET = r'\(' t_CBRACKET = r'\)' t_EQUALS = r'=' t_BIT_WIDTH = r'\[(.*?)\]' def __init__(self): self.logger = Logger() self.hdlChip = HdlChip() self.lexer = lex.lex(module=self) self.parser = yacc.yacc(module=self) return def t_NAME(self, t): r'[a-zA-Z_][a-zA-Z_0-9_]*' if t.value in self.reserved: t.type = t.value return t def t_error(self, t): print(f"Illegal character {t.value[0]!r}") t.lexer.skip(1) def t_newline(self, t): r'\n+' t.lexer.lineno += len(t.value) def t_COMMENT1(self, t): r'(/\*(.|\n)*?\*/\n)' t.lexer.lineno += len(t.value.split("\n")) - 1 #return t pass def t_COMMENT2(self, t): r'(//.*?(\n|$))' t.lexer.lineno += 1 #return t pass # statement-list: def p_program(self, p): '''program : chip | empty ''' p[0] = p[1] return # The empty production def p_empty(self, p): 'empty :' p[0] = None #Node("EMPTY", []) return def p_statement(self, p): '''statement : in_list | out_list | clocked_list | parts ''' p[0] = p[1] return def p_partparam(self, p): '''partparam : pin EQUALS pin''' p[0] = HdlConnection(p[1], p[3]) return def p_partparamlist(self, p): '''partparamlist : partparamlist COMMA partparam | partparam''' if len(p) > 2: p[0] = p[1] p[0].append(p[3]) else: p[0] = [p[1]] return def p_part(self, p): '''part : NAME OBRACKET partparamlist CBRACKET SEMICOLON''' hdlChipPart = HdlChipPart(p[1], p.lineno(1)) for part in p[3]: hdlChipPart.AddConnection(part) p[0] = hdlChipPart return def p_partlist(self, p): '''partlist : partlist part | part''' if len(p) > 2: p[0] = p[1] p[0].append(p[2]) else: p[0] = [p[1]] return def p_parts(self, p): '''parts : PARTS COLON partlist''' for part in p[3]: self.hdlChip.AddPart(part) return def p_statement_list(self, p): '''statement_list : statement_list statement | statement''' if len(p) > 2: p[0] = p[1] p[0].append(p[2]) else: p[0] = [p[1]] return def p_chip(self, p): '''chip : CHIP NAME OCURLEYBRACKET statement_list CCURLEYBRACKET''' self.hdlChip.SetChipName(p[2]) return def p_pin(self, p): '''pin : NAME BIT_WIDTH | NAME''' pinName = p[1] pinBitWidth = None if len(p) > 2: pinBitWidth = p[2] if pinBitWidth: p[0] = HdlPin(pinName, bitWidthString=pinBitWidth) else: p[0] = HdlPin(pinName) return def p_pinlist(self, p): '''pinlist : pinlist COMMA pin | pin''' if len(p) > 2: p[0] = p[1] p[0].append(p[3]) else: p[0] = [p[1]] return def p_in_list(self, p): '''in_list : IN pinlist SEMICOLON''' self.hdlChip.AddInputPins(p[2]) return def p_clocked_list(self, p): '''clocked_list : CLOCKED pinlist SEMICOLON''' self.hdlChip.AddClockedPins(p[2]) return def p_out_list(self, p): '''out_list : OUT pinlist SEMICOLON''' self.hdlChip.AddOutputPins(p[2]) return # def p_comment1(self, p): # "comment1 : COMMENT1" # pass # def p_comment2(self, p): # "comment2 : COMMENT2" # pass def p_error(self, p): if p: error_msg = "syntax error '%s' at %d" % (p.value, p.lineno) else: error_msg = "syntax error at end of file" self.logger.Error(error_msg) return ########################################################################## def Parse(self, fileContent): self.lexer.input(fileContent) # for token in self.lexer: # print(token) self.parser.parse(fileContent, tracking=True) self.hdlChip.DumpChipDetails() return self.hdlChip
class HdlToVerilogParamMapper(): def __init__(self, chipName, partName, lineNo, toPort : VerilogPort, fromPort : VerilogPort): self.chipName = chipName self.partName = partName self.lineNo = lineNo self.toPort = toPort self.fromPort = fromPort self.logger = Logger() self.hdlConnections = [] #type: list[HdlConnection] self.mappedParams = H2VMappedParamsList() return ########################################################################## def AddHdlConnection(self, connection : HdlConnection): self.hdlConnections.append(connection) return ########################################################################## def DoMapping(self): pin1, pin2 = self.hdlConnections[0].GetPins() pin1BitWidth = pin1.GetPinBitWidth() self.logger.Info("Start: Chip: %s, part: %s (line %d), pin: %s" % (self.chipName, self.partName, self.lineNo, pin1.pinName)) for connection in self.hdlConnections: pin1, pin2 = connection.GetPins() # type: HdlPin, HdlPin self.logger.Info("Mapping: %s" % (connection.GetPinStr())) # Note: Cases todo.. # all bits <-- input all bits (different bit length) pin1BitIndex, pin1StartBitOfBus, pin1EndBitOfBus, pin1ConnectionWidth, pin1ConnectionType = connection.GetPin1Params() pin2BitIndex, pin2StartBitOfBus, pin2EndBitOfBus, pin2ConnectionWidth, pin2ConnectionType = connection.GetPin2Params() paramFullName = self._MakeParamFullName(pin2.pinName, pin2BitIndex, pin2StartBitOfBus, pin2EndBitOfBus, pin2ConnectionWidth, True if pin1.pinType == HdlPinTypes.Input else False) # Cases: # all bits <-- input all bits (same bit length) # all bits <-- input single bit # all bits <-- input bit range # all bits <-- internal all bits if pin1ConnectionType == HdlConnectionTypes.AllBits: if pin1BitWidth != pin2ConnectionWidth: self.logger.Error("Mapping all input bits of '%s' to '%s' but bit sizes differ. (Pin size: %d, connection size: %d)" % (pin1.pinName, pin2.pinName, pin1BitWidth, pin2ConnectionWidth)) self.mappedParams.AddItem(0, pin1BitWidth - 1, pin1BitWidth, paramFullName) # Cases: # bit range <-- input single bit elif (pin1ConnectionType == HdlConnectionTypes.BitRange and pin2ConnectionType == HdlConnectionTypes.SingleBit): for hdlBitNumber in range(connection.pin1StartBitOfBus, connection.pin1EndBitOfBus): self.mappedParams.AddItem(hdlBitNumber, hdlBitNumber, pin1BitWidth, paramFullName) # Cases: # bit range <-- input all bits # bit range <-- internal all bits elif (pin1ConnectionType == HdlConnectionTypes.BitRange and pin2ConnectionType == HdlConnectionTypes.AllBits): self.mappedParams.AddItem(pin1StartBitOfBus, pin1EndBitOfBus, pin1BitWidth, paramFullName) # Cases: # bit range <-- input bit range elif (pin1ConnectionType == HdlConnectionTypes.BitRange and pin2ConnectionType == HdlConnectionTypes.BitRange): self.mappedParams.AddItem(pin1StartBitOfBus, pin1EndBitOfBus, pin1BitWidth, paramFullName) # Cases: # single bit <-- input all bits # single bit <-- input single bit # single bit <-- internal all bits else: self.mappedParams.AddItem(connection.pin1BitIndex, connection.pin1BitIndex, pin1BitWidth, paramFullName) self.mappedParams.CompleteMapping(pin1, pin2, pin1BitWidth) self.logger.Info("End: Mapping chip: %s, part:%s (line %d), pin: %s" % (self.chipName, self.partName, self.lineNo, pin1.pinName)) return ########################################################################## def GetMappedParams(self): return self.mappedParams ########################################################################## def _MakeParamFullName(self, pinName, pinBitIndex, pinStartBitOfBus, pinEndBitOfBus, pinConnectionWidth, isInputPin): paramName = pinName paramExtra = "" # If the pin is an Input then swap false to 1'b0 if isInputPin and pinName == 'false': paramName = ("%d'b%s" % (pinConnectionWidth, '0'.join(['0' * pinConnectionWidth]))) # If the pin is an Input then swap true to 1'b1 if isInputPin and pinName == 'true': paramName = ("%d'b%s" % (pinConnectionWidth, '1'.join(['1' * pinConnectionWidth]))) if pinBitIndex != commonDefs.NO_BIT_VALUE: paramExtra += "[" + str(pinBitIndex) + "]" elif pinStartBitOfBus != commonDefs.NO_BIT_VALUE: paramExtra += "[" + str(pinEndBitOfBus) + ":" + str(pinStartBitOfBus) + "]" return ("%s%s" % (paramName, paramExtra))
class TstParser: reserved = [ 'set', 'output', 'list', 'eval', 'load', 'compare', 'to', 'file', 'tick', 'tock' ] tokens = [ 'NAME', 'NUMBER', 'COMMA', 'DOT', 'DASH', 'COMMENT1', 'COMMENT2', 'SEMICOLON', 'PERCENT' ] + reserved #literals = ['%'] t_ignore = " \t" t_COMMA = r',' t_DOT = r'\.' t_DASH = r'-' t_SEMICOLON = r';' t_PERCENT = r'%' def __init__(self): self.logger = Logger() self.lexer = lex.lex(module=self) self.parser = yacc.yacc(module=self) self.tstScript = TstScript() return def t_NAME(self, t): r'[a-zA-Z_][a-zA-Z_0-9_]*' if t.value in self.reserved: t.type = t.value return t def t_NUMBER(self, t): r'\d+' t.value = int(t.value) return t def t_error(self, t): print(f"Illegal character {t.value[0]!r}") t.lexer.skip(1) def t_newline(self, t): r'\n+' t.lexer.lineno += len(t.value) def t_COMMENT1(self, t): r'(/\*(.|\n)*?\*/\n)' t.lexer.lineno += len(t.value.split("\n")) - 1 #return t pass def t_COMMENT2(self, t): r'(//.*?(\n|$))' t.lexer.lineno += 1 #return t pass # statement-list: def p_test(self, p): '''test : statement_list | empty ''' p[0] = p[1] return # The empty production def p_empty(self, p): 'empty :' p[0] = None #Node("EMPTY", []) return def p_statement_list(self, p): '''statement_list : statement_list statement | statement''' if len(p) > 2: p[0] = p[1] p[0].append(p[2]) else: p[0] = [p[1]] return def p_statement(self, p): '''statement : set_sequence | output_statement | load_statement | compare_statement ''' p[0] = p[1] #print("Statement: " + str(p[1])) return def p_load_statement(self, p): '''load_statement : load NAME DOT NAME COMMA''' self.tstScript.testHdlModule = p[2] return def p_compare_statement(self, p): '''compare_statement : compare DASH to NAME DOT NAME COMMA | compare DASH to NAME DASH NAME DOT NAME COMMA''' if len(p) > 8: self.tstScript.compareFile = ("%s-%s.%s" % (p[4], p[6], p[8])) else: self.tstScript.compareFile = ("%s.%s" % (p[4], p[6])) return def p_eval_statement(self, p): '''eval_statement : eval COMMA''' p[0] = TstSetSequence(TstSetSequenceTypes.eval, None) return def p_tock_statement(self, p): '''tock_statement : tock COMMA''' p[0] = TstSetSequence(TstSetSequenceTypes.tock, None) return def p_tick_statement(self, p): '''tick_statement : tick COMMA''' p[0] = TstSetSequence(TstSetSequenceTypes.tick, None) return def p_set_sequence(self, p): '''set_sequence : set_statement | tick_statement | tock_statement | eval_statement | output COMMA | output SEMICOLON ''' if type(p[1]) == str: p[1] = TstSetSequence(TstSetSequenceTypes.output, None) #print("set_sequence: %s, len = %d" % (p[1], len(p))) self.tstScript.AddSetSequence(p[1]) return def p_set_statement(self, p): '''set_statement : set NAME NUMBER COMMA | set NAME DASH NUMBER COMMA | set NAME PERCENT NAME COMMA | set NAME PERCENT NAME SEMICOLON | set load NUMBER COMMA | set load DASH NUMBER COMMA | set load PERCENT NAME COMMA | set load PERCENT NAME SEMICOLON ''' pinValue = "" pinName = p[2] if len(p) > 5: pinValue += ("%s%s" % (p[3], p[4])) else: pinValue += str(p[3]) p[0] = TstSetSequence(TstSetSequenceTypes.set, TstSetOperation(pinName, pinValue)) #print("set_statement: %s = %s" % (pinName, pinValue)) return def p_output_statement(self, p): '''output_statement : output_file | output_list ''' p[0] = p[1] #print("set_statement: " + str(p[3])) return def p_output_file(self, p): '''output_file : output DASH file NAME DOT NAME COMMA | output DASH file NAME DASH NAME DOT NAME COMMA''' if len(p) > 8: self.tstScript.outputFile = ("%s-%s.%s" % (p[4], p[6], p[8])) else: self.tstScript.outputFile = ("%s.%s" % (p[4], p[6])) return def p_output_list(self, p): '''output_list : output DASH list output_param_list SEMICOLON''' self.tstScript.SetOutputFormatList(p[4]) #print("output_list: " + str(p[4])) return def p_output_param_list(self, p): '''output_param_list : output_param_list output_param | output_param ''' if len(p) > 2: p[0] = p[1] p[0].append(p[2]) else: p[0] = [p[1]] return def p_output_param(self, p): # a%B1.16.1 '''output_param : NAME PERCENT NAME DOT NUMBER DOT NUMBER | load PERCENT NAME DOT NUMBER DOT NUMBER ''' #p[0] = ("%s%s%s%s%s%s%s" % (p[1], p[2], p[3], p[4], p[5], p[6], p[7])) p[0] = TstOutputParam(p[1], p[3], p[5], p[7]) return def p_error(self, p): if p: error_msg = "syntax error '%s' at %d" % (p.value, p.lineno) else: error_msg = "syntax error at end of file" self.logger.Error(error_msg) return ########################################################################## def GetSequenceType(self, typeName): sequenceType = TstSetSequenceTypes.eval for seqType in TstSetSequenceTypes: if typeName.casefold() == str(seqType).casefold(): sequenceType = seqType return sequenceType ########################################################################## def Parse(self, fileContent, testName): self.lexer.input(fileContent) # for token in self.lexer: # print(token) self.tstScript.testName = testName self.parser.parse(fileContent) self.tstScript.DumpTestDetails() return self.tstScript
class Hdl2verilogMain(): def __init__(self): self.logger = Logger() self.fileActions = FileActions() self.mapper = HdlToVerilogMapper() return ########################################################################## def Run(self, inputFolder, builtInChipFolder, outputFolder): verilogModuleList = VerilogModuleList(builtInChipFolder) # Read in the built-in Verilog modules verilogFilenames = [ join(builtInChipFolder, x) for x in self.fileActions.GetFilesWithExtInFolder( builtInChipFolder, '.v') ] for verilogFilename in verilogFilenames: self.logger.Info("Reading %s .." % (verilogFilename)) verilogFile = VerilogFile(verilogFilename) verilogModule = verilogFile.ParseFile() verilogModuleList.AddBuiltInModule(verilogModule) hdlChipList = HdlChipList() # Read in the built-in HDL chips hdlFilenames = [ join(builtInChipFolder, x) for x in self.fileActions.GetFilesWithExtInFolder( builtInChipFolder, '.hdl') ] for hdlFilename in hdlFilenames: self.logger.Info("Reading %s .." % (hdlFilename)) hdlFile = HdlFile(hdlFilename) hdlChip = hdlFile.ParseFile() hdlChipList.AddBuiltInChip(hdlChip) # Read in the input HDL chips to be converted hdlFilenames = [ join(inputFolder, x) for x in self.fileActions.GetFilesWithExtInFolder( inputFolder, '.hdl') ] for hdlFilename in hdlFilenames: self.logger.Info("Reading %s .." % (hdlFilename)) hdlFile = HdlFile(hdlFilename) hdlChip = hdlFile.ParseFile() hdlChipList.AddChip(hdlChip) result, builtInChipsUsedList = self.CheckChipDependencies( hdlChipList, verilogModuleList) if not result: return hdlChipList.CheckAndAddClockInputs() hdlChipList.UpdateAllPinBitWidths() hdlChipList.UpdateAllPartConnections() # Create the Verilog Modules from input HDL chips for hdlChip in hdlChipList.chipList: self.mapper.CreateVerilogModule(hdlChip, hdlChipList, verilogModuleList) # Read-in the Tst files and create the Verilog Testbench Modules tstsToRun = [] tstFilenames = self.fileActions.GetFilesWithExtInFolder( inputFolder, '.tst') for tstFilename in tstFilenames: testName, ext = self.fileActions.GetFileNameAndExt(tstFilename) self.logger.Info("Reading %s .." % (tstFilename)) tstFile = TstFile(join(inputFolder, tstFilename)) tstScript = tstFile.ParseFile(testName) tstScript.testChip = hdlChipList.GetChip(tstScript.testHdlModule) self.mapper.CreateVerilogModuleTB(tstScript, outputFolder) tstsToRun.append(tstScript) verilogModuleList.WriteModules(outputFolder) verilogModuleList.CopyInternalModules(outputFolder, builtInChipsUsedList) ivlScriptGen = IVerilogScriptGenerator(outputFolder) ivlScriptGen.CreateScript(inputFolder, tstsToRun, hdlChipList, verilogModuleList) return ########################################################################## def CheckChipDependencies(self, hdlChipList, verilogModuleList): passed = True missingChipList, builtInChipsUsedList, noimplementationChipList = hdlChipList.CheckChipDependencies( ) if len(missingChipList) > 0: self.logger.Error( "Missing chips detected! Following dependencies were not found in the input folder or built-in chip folder: %s" % (missingChipList)) passed = False if len(builtInChipsUsedList) > 0: missingBuiltInModuleList = verilogModuleList.CheckModulesInBuiltInList( builtInChipsUsedList) if len(missingBuiltInModuleList) > 0: self.logger.Error( "Missing built-in verilog modules detected! Following expected built-in modules were not found in the built-in chip folder: %s" % (missingBuiltInModuleList)) passed = False if len(noimplementationChipList) > 0: self.logger.Error( "Some HDL chips are missing implementation! Please check the following HDL chips run and pass tests using the nand2tetris HardwareSimulator : %s" % (noimplementationChipList)) passed = False return passed, builtInChipsUsedList
class FileActions: def __init__(self): self.logger = Logger() ########################################################################## # IsFile ########################################################################## def IsFile(self, fileName): my_file = Path(fileName) return my_file.is_file() ########################################################################## # IsExecutable ########################################################################## def IsExecutable(self, fileName): return os.access(fileName, os.X_OK) ########################################################################## # Rename ########################################################################## def Rename(self, srcFolder, dstFolder): os.rename(srcFolder, dstFolder) ########################################################################## # MoveFolder ########################################################################## def MoveFolder(self, srcFolder, dstFolder): shutil.move(srcFolder, dstFolder) # Unlike os calls which are blocking we have to wait until rmtree # completes. We do this by waiting until the folder no longer exists. while os.path.exists(srcFolder): # check if it exists pass @staticmethod ########################################################################## # GetFileNameAndExt ########################################################################## def GetFileNameAndExt(fileName): return os.path.splitext(fileName) ########################################################################## # GetAbsoluteFilename ########################################################################## def GetAbsoluteFilename(self, relativeFilename): return os.path.abspath(relativeFilename) ########################################################################## # CreateFolderIfNeeded ########################################################################## def CreateFolderIfNeeded(self, folder): if not self.DoesFolderExist(folder): os.makedirs(folder) ########################################################################## # DoesFolderExist ########################################################################## def DoesFolderExist(self, folder): return os.path.exists(folder) ########################################################################## # DoesFileExist ########################################################################## def DoesFileExist(self, fileName): my_file = Path(fileName) return my_file.is_file() ########################################################################## # GetNumFilesInFolder ########################################################################## def GetNumFilesInFolder(self, folder, ext=None): if self.DoesFolderExist(folder) == True: files = [f for f in os.scandir(folder) if f.is_file()] if ext != None: files = [k for k in files if ext in k.name] return len(files) else: return 0 ########################################################################## # DeleteFile ########################################################################## def DeleteFile(self, fileName): if self.DoesFileExist(fileName): try: my_file = Path(fileName) my_file.unlink() except Exception as e: self.logger.Error(str(e)) ########################################################################## # DeleteFolder ########################################################################## def DeleteFolder(self, folderName): if self.DoesFolderExist(folderName): try: self.DeleteFilesInFolder(folderName) self.RemoveFolder(folderName) except Exception as e: self.logger.Error(str(e)) ########################################################################## # DeleteFilesInFolder ########################################################################## def DeleteFilesInFolder(self, folderName): if self.DoesFolderExist(folderName) == True: for the_file in os.listdir(folderName): file_path = os.path.join(folderName, the_file) try: if os.path.isfile(file_path): os.unlink(file_path) elif os.path.isdir(file_path): self.RemoveFolder(file_path) except Exception as e: self.logger.Error(str(e)) ########################################################################## # RemoveFolder ########################################################################## def RemoveFolder(self, folderName): if self.DoesFolderExist(folderName) == True: shutil.rmtree(folderName) # Unlike os calls which are blocking we have to wait until rmtree # completes. We do this by waiting until the folder no longer exists. while os.path.exists(folderName): # check if it exists pass ########################################################################## # GetFoldersFromEndPath ########################################################################## def GetFoldersFromEndPath(self, path, numberToRemove): name = "" head = path for i in range(0, numberToRemove): head, tail = os.path.split(head) name = join(tail, name) return name ########################################################################## # GetFoldersFromEndPathUntil ########################################################################## def GetFoldersFromEndPathUntil(self, path, nameToStopAt): name = "" head = path tail = "" found = True while tail != nameToStopAt: newhead, tail = os.path.split(head) name = join(tail, name) if newhead != head: head = newhead else: # This stops an infinite loop if nameToStopAt is not in path found = False break return name[:-1], found ########################################################################## # CopyFile ########################################################################## def CopyFile(self, srcFileName, dstFileName): copyfile(srcFileName, dstFileName) # Unlike os calls which are blocking we have to wait until rmtree # completes. We do this by waiting until the folder no longer exists. while self.DoesFileExist(dstFileName) != True: # check if it exists pass ########################################################################## # GetFileDetailsInFolder ########################################################################## def GetFileDetailsInFolder(self, folder): fileDetails = [] for path, _, files in os.walk(folder): for file in files: fileDetail = FileDetails(file, path, 0, "", None) fileDetail.fileSizeBytes = os.path.getsize( fileDetail.GetAbsoluteFilename()) fileDetail.md5 = self._md5(fileDetail.GetAbsoluteFilename(), fileDetail.fileSizeBytes) fileDetails.append(fileDetail) return fileDetails ########################################################################## # GetFilesWithExtInFolder ########################################################################## def GetFilesWithExtInFolder(self, folder, extension): files = [f for f in listdir(folder) if os.path.isfile(join(folder, f))] files = [k for k in files if extension in k] return files ########################################################################## # GetFileModDate ########################################################################## def GetFileModDate(self, filename): try: mtime = os.path.getmtime(filename) except OSError: # Use 86400 and not 0 so compatible with windows. mtime = 86400 return datetime.fromtimestamp(mtime) ########################################################################## # IsFileNewerThan ########################################################################## def IsFileNewerThan(self, filename1, filename2): file1 = self.GetFileModDate(filename1) file2 = self.GetFileModDate(filename2) #print(filename1 + " = " + str(file1)) #print(filename2 + " = " + str(file2)) return file1 > file2 ########################################################################## # MakeExecutable ########################################################################## def MakeExecutable(self, filename): st = os.stat(filename) os.chmod(filename, st.st_mode | stat.S_IEXEC) return ########################################################################## # Private: _md5 ########################################################################## def _md5(self, fileName, fileSizeBytes): hash_md5 = hashlib.md5() if fileSizeBytes > 20000000: with open(fileName, "rb") as f: for chunk in iter(lambda: f.read(4096), b""): hash_md5.update(chunk) else: with open(fileName, "rb") as f: hash_md5 = hashlib.md5(f.read()) return hash_md5.hexdigest()
class VerilogModuleList(): def __init__(self, builtInChipFolder): self.logger = Logger() self.moduleList = [] # type: list[VerilogModule] self.builtInModuleList = [] # type: list[VerilogModule] self.builtInChipFolder = builtInChipFolder return ########################################################################## def AddModule(self, module): self.moduleList.append(module) return ########################################################################## def AddBuiltInModule(self, module): self.builtInModuleList.append(module) return ########################################################################## def GetFilenamesForModules(self, inputModuleList): filenameList = [] for inputModule in inputModuleList: moduleFromList = [ x for x in self.moduleList if inputModule == x.moduleName ] moduleFromBuiltInList = [ x for x in self.builtInModuleList if inputModule == x.moduleName ] if len(moduleFromList) > 0: # Generated module was found, so let use that filenameList.append(moduleFromList[0].moduleFilename) elif len(moduleFromBuiltInList) > 0: # Module must be taken from the builtin list filenameList.append(moduleFromBuiltInList[0].moduleFilename) else: self.logger.Error( "Couldn't find module %s in the generated or built-in list" % (inputModule)) return filenameList ########################################################################## def CheckModulesInBuiltInList(self, moduleList): missingBuiltInModuleList = [] for module in moduleList: result = [ x for x in self.builtInModuleList if module == x.moduleName ] if len(result) == 0: missingBuiltInModuleList.append(module) return missingBuiltInModuleList ########################################################################## def WriteModules(self, outputFolder): verilogModGen = VerilogModuleGenerator(outputFolder) for module in self.moduleList: verilogModGen.CreateModule(module) return ########################################################################## def CopyInternalModules(self, outputFolder, usedBuiltInModules): fileActions = FileActions() for moduleName in usedBuiltInModules: for verilogModule in self.builtInModuleList: if verilogModule.moduleName == moduleName: fileActions.CopyFile( join(self.builtInChipFolder, verilogModule.moduleFilename), join(outputFolder, verilogModule.moduleFilename)) break return