def __init__(self, pathstr): self.htype = CfgPathHierType.UNKNOWN # resolved path type is unknown by default self.call = None # default to no call basepathstr = '' if '(' in pathstr: # detect a call and remove from path pat = re.compile('(.*)\\.(\\w+)') mat = pat.match(pathstr) if mat: basepathstr = mat.group(1) self.call = mat.group(2) #print(f'found call match path={self.val}, call={self.call}') else: basepathstr = pathstr # TODO - store as path elem tuples? also TODO allow range wildcards # create a list of path elements self.val = [] newlist = basepathstr.split('.') for elemstr in newlist: elem = CfgPathDataElement(elemstr) self.val.append(elem) # check for valid path var extract if not self.val: MsgUtils.errorExit(f'unable create path from string={pathstr}') firstPathElement = self.getBasePathElem() # check for valid path base variable baseVar = CfgVariable.resolveLhsExpression( firstPathElement.name, CfgPathDataType, False, False) # check for existing base path variable if not baseVar: MsgUtils.errorExit(f'unable to resolve root of path {pathstr}') firstPathElement.baseVar = baseVar # save the referenced path variable in first element
def checkAllowedVersions(allowedTags): ''' issue an error if allowed version Tags specified by config model are not a subset of those in the register model ''' inhibitCheck = __class__._config.inhibitAllowedVersionCheck unsupportedTags = allowedTags - __class__.getAllRegModelTags() if bool(unsupportedTags) and not inhibitCheck: MsgUtils.errorExit( f'version tags specified {unsupportedTags} are not found in register model list {RegModelWrapper._regModTags}' ) return
def getOutBuilder(outFormStr, outFileName, headerInfo): ''' return an OutBuilder instance given a format string and file name ''' try: outputType = ConfigFileOutputFormat[outFormStr] except: MsgUtils.errorExit(f'unsupported output format: {outFormStr}') if outputType == ConfigFileOutputFormat.PYTHON_FORMAT_1: return PyF1OutBuilder(outFileName, headerInfo) elif outputType == ConfigFileOutputFormat.UVM_FORMAT_1: return UvmF1OutBuilder(outFileName, headerInfo)
def getInExtractor(inFormStr, inFileName): ''' return an Extractor instance given a type string ''' try: inputType = ConfigFileInputFormat[inFormStr] except: MsgUtils.errorExit(f'unsupported input format: {inFormStr}') if inputType == ConfigFileInputFormat.PYTHON_FORMAT_1: return PyF1Extractor(inFileName) elif inputType == ConfigFileInputFormat.CFGTOOL_FORMAT: return CfgExtractor(inFileName)
def importRegModel(pyModelFile): ''' read the py register model, store extracted model root instance and version tags ''' regmodSpec = importlib.util.spec_from_file_location( 'regmod', pyModelFile) regmod = importlib.util.module_from_spec(regmodSpec) regmodSpec.loader.exec_module(regmod) __class__._regRoot = regmod.ordt_drv_root() __class__._regModTags = __class__._regRoot.get_tags() if not bool(__class__._regModTags): MsgUtils.errorExit( f'No version tags found in extraction of register model from {pyModelFile}' )
def __init__(self, name, vartype=CfgNumDataType): self.name = name self.vartype = vartype self.val = None # add var in current scope parent = BaseCfgNode._nodeStack[-1] if parent.findVar(self.name): MsgUtils.errorExit('variable ' + self.name + ' is already defined.') if not name.isalnum(): MsgUtils.errorExit('variable name ' + self.name + ' is not valid.') parent.vars[self.name] = self
def findVar(self, varName, allowInputs=True): ''' find a variable by name traversing from current node thru ancestors ''' if self.vars.__contains__(varName): retVar = self.vars[varName] if allowInputs or (type(retVar) is not CfgInputVariable): return retVar MsgUtils.errorExit('input variable ' + varName + ' can not be assigned a value.') return None elif self.parent is None: return None else: return self.parent.findVar(varName)
def getRegModelTags(): ''' return version tags to be used in the register model after applying any overrides ''' overrides = __class__._config.versionTagOverrideSet modeltags = __class__.getAllRegModelTags() if not bool(overrides ): # if no overrides just return the full regmodel tag set return modeltags # check that the override set is a subset of model unsupportedTags = overrides - modeltags if bool(unsupportedTags): MsgUtils.errorExit( f'versionTagOverrideSet specified includes tags {unsupportedTags} not found in register model list {modeltags}' ) return overrides
def annotatePath(self, tag, regModelPath): # extract the full path by expanding lead path vars expandedPath = self.getExpandedPathList() #print(f' -> CfgPathDataType annotatePath: this path len={len(self.getPathList())}, expanded path len={len(expandedPath)}, regmod path len={len(regModelPath)}, path={regModelPath}') if len(expandedPath) != len(regModelPath): MsgUtils.errorExit( f'Path {self.genRawPathStr()} does not match form of returned register model path.' ) # now loop and append regmodel info to local (non expanded) path elements localIndex = len(expandedPath) - len(self.getPathList()) for pathElem, regModElem in zip(self.getPathList( ), regModelPath[localIndex:]): # only annotate local path elements print( f' -> CfgPathDataType annotatePath: element annotation, tag={tag}, elem={pathElem.name}, mod elem type={type(regModElem)}' ) annotation = RegModelWrapper.createAnnotation(regModElem) pathElem.annotations[tag] = annotation # annotate pathElem by tag
def resolveLhsExpression( inVar, targetVarType, allowVarCreate=True, exitOnFail=True): # targetVarType is valid CfgDataType ''' given an unknown lhs expression, return an existing variable or create a new variable of specified target data type from str ''' if (type(inVar) is CfgVariable) and ( inVar.vartype is targetVarType): # already a variable so done return inVar if type(inVar) is str: # try to find an existing (non-input) variable foundVar = HierCfgNode.peekNode().findVar( inVar, False) # input variables are not allowed on lhs if (foundVar is not None) and (foundVar.vartype is targetVarType): return foundVar # else create a new var of target type if allowVarCreate: return CfgVariable(inVar, targetVarType) if exitOnFail: MsgUtils.errorExit('unable to resolve lhs expression ' + str(inVar) + ' to a variable.')
def __init__(self, className, methodName, parmList, sourceAstNode=None): BaseCfgNode.__init__(self, sourceAstNode) # if className specified in call path resolve class as a variable, else use current class if className: cfgClassVar = CfgVariable.resolveRhsExpression( className, CfgClassNode, False, True) # find the class variable #self.cfgClass = CfgClassNode.getCurrent() # TODO add findVar option for non-none className self.cfgClass = CfgClassNode.findClass( cfgClassVar.val[0].name ) # TODO - saved call name structure shoul be fixed else: self.cfgClass = CfgClassNode.getCurrent() #if not cfgClass: # MsgUtils.errorExit('unable to resolve cfgClass ' + str(className) + ' in call of method ' + methodName) self.cfgMethod = self.cfgClass.findMethod(methodName) if not self.cfgMethod: MsgUtils.errorExit( f'unable to resolve method {methodName} in cfgClass {self.cfgClass.name}' ) self.parmList = self.cfgMethod.verifyInputParms(parmList, self.parent)
def resolvePath(self, allowedTags, targetType=CfgPathHierType.UNKNOWN ): # TODO also pass in allowedTags ''' resolve path type and any path index wildcards by referencing the regmodel ''' print( f' -> resolvePath CfgPathDataType raw path: {self} full path: {self.genFullPathStr()} sample path: {self.genSamplePathStr()}' ) # TODO regModel = RegModelWrapper.getRegModelRoot() if not regModel: if self.needsResolution(): MsgUtils.errorExit( f'Path {self} has unresolved info, but no register model is defined.' ) return # if no model and resolved we're done # extract valid version tags and annotate path elements for each validTags = RegModelWrapper.getValidTags(allowedTags) print( f' -> resolvePath CfgPathDataType: allowedTags={allowedTags}, regmod tags: {RegModelWrapper.getRegModelTags()} valid tags: {validTags}' ) # TODO for tag in validTags: plist = regModel.get_path_instance_list(tag, self.genSamplePathStr()) if 'error' in plist: MsgUtils.errorExit( f'Path {self.genRawPathStr()} was not found in register model using tag="{tag}".' ) if not targetType.matchesRegModelType( plist['type'] ): # check that path type returned from model matches target MsgUtils.errorExit( f'Expected type of path {self.genRawPathStr()} ({targetType}) does not match returned register model type ({plist["type"]}).' ) # TODO - check that MultPath elems are allowed self.annotatePath(tag, plist['instances'])
def verifyInputParms(self, inputListStr, callingNode): ''' check that a list of call parameter strings matches inputs for this hier and return the list of resolved inputs ''' if type(inputListStr) is not str: MsgUtils.errorExit( f'misformed input list found when in call of {self.whatami()} {self.name}' ) inputList = [] if not inputListStr else inputListStr.split(',') inputCount = len(inputList) inputParms = self.getInputList() inputParmCount = len(inputParms) #print(f"HierCfgNode verifyInputParms: inputList={inputList}, in len={inputCount}, vars=({', '.join(str(e) for e in inputParms.values())}), parm len={inputParmCount}, callNode type={type(callingNode)}") if inputCount != inputParmCount: MsgUtils.errorExit( f'incorrect number of input parameters (found {inputCount}, expected {inputParmCount}) in call of {self.whatami()} {self.name}' ) # loop and resolve inputs CfgVariable.resolveRhsExpression(className, CfgClassNode, False, True) resolvedInputList = [] for inVal, inParm in zip(inputList, inputParms.values()): resolvedInputList.append( CfgVariable.resolveRhsExpression(inVal, inParm.vartype, True, True)) return resolvedInputList
def resolveRhsExpression( inVal, targetVarType, allowInstCreate=True, exitOnFail=True): # targetVarType is valid CfgDataType ''' given an unknown rhs expression, return an existing variable or instance (new from str or existing) of specified target data type ''' if type(inVal) is targetVarType: # already target type so done return inVal if (type(inVal) is CfgVariable) and ( inVal.vartype is targetVarType): # already a variable so done return inVal if type(inVal) is str: # try to find an existing variable foundVar = HierCfgNode.peekNode().findVar(inVal) if (foundVar is not None) and (foundVar.vartype is targetVarType): return foundVar # else try creating new target instance if allowInstCreate: newVal = targetVarType(inVal) if newVal.isValid(): return newVal if exitOnFail: MsgUtils.errorExit('unable to resolve rhs expression ' + str(inVal) + ' to a value or variable.')
def __init__(self, fileName, headerInfo): self.setConfig() # --- open/create the file for output self.outfile = open(fileName, "w") MsgUtils.infoMsg(f'writing to file={fileName}\n') self.writeComment(0, headerInfo)