def __rawFieldToDataType(self, rawField): AwlDataType = _getAwlDataTypeClass() dtype = AwlDataType.makeByName(nameTokens=rawField.typeTokens, arrayDimensions=rawField.dimensions) if dtype.type == AwlDataType.TYPE_STRUCT: # Make the AwlStruct that represents the STRUCT contents. if not rawField.children: raise AwlSimError( "Data structure does not have " "any containing variables. (STRUCT is empty)") struct = self.__createStructFromRawFields(rawField.children) dtype.setStruct(struct) elif dtype.type == AwlDataType.TYPE_ARRAY and\ dtype.arrayElementType.type == AwlDataType.TYPE_STRUCT: # Make the AwlStruct that represents the # ARRAY-element (of type STRUCT) contents. if not rawField.children: raise AwlSimError( "Data structure does not have " "any containing variables. (STRUCT is empty)") struct = self.__createStructFromRawFields(rawField.children) dtype.arrayElementType.setStruct(struct) else: if rawField.children: raise AwlSimError("Data type '%s' has children '%s', " "but is not a STRUCT." %\ (str(dtype), str(rawField.children))) return dtype
def __rawFieldToDataType(self, rawField): AwlDataType = _getAwlDataTypeClass() dtype = AwlDataType.makeByName(nameTokens = rawField.typeTokens, arrayDimensions = rawField.dimensions) if dtype.type == AwlDataType.TYPE_STRUCT: # Make the AwlStruct that represents the STRUCT contents. if not rawField.children: raise AwlSimError("Data structure does not have " "any containing variables. (STRUCT is empty)") struct = self.__createStructFromRawFields(rawField.children) dtype.setStruct(struct) elif dtype.type == AwlDataType.TYPE_ARRAY and\ dtype.arrayElementType.type == AwlDataType.TYPE_STRUCT: # Make the AwlStruct that represents the # ARRAY-element (of type STRUCT) contents. if not rawField.children: raise AwlSimError("Data structure does not have " "any containing variables. (STRUCT is empty)") struct = self.__createStructFromRawFields(rawField.children) dtype.arrayElementType.setStruct(struct) else: if rawField.children: raise AwlSimError("Data type '%s' has children '%s', " "but is not a STRUCT." %\ (str(dtype), str(rawField.children))) return dtype
def getOperDataWidth(self, oper): """Helper function to get the data type width (in bits) of an operator. This will first attempt to resolve the operator, if it is symbolic. """ from awlsim.core.datatypes import AwlDataType if oper.width > 0: return oper.width if oper.operType == AwlOperatorTypes.NAMED_LOCAL: # Get the type of an interface field # and return its bit width. fieldName = str(oper.offset.identChain) field = self.interf.getFieldByName(fieldName) if not field: raise FupCompilerError("Interface field " "'#%s' could not be found in the " "declared interface." % ( fieldName)) dataType = AwlDataType.makeByName(field.typeStr) if dataType: return dataType.width elif oper.operType == AwlOperatorTypes.SYMBOLIC: # Get the type of a classic symbolic operator # and return its bit width. fieldName = str(oper.offset.identChain) symbol = self.symTab.findByName(fieldName) if not symbol: raise FupCompilerError("The symbolic operator " "\"%s\" not found in symbol tables." % ( fieldName)) dataType = symbol.getType() if dataType: return dataType.width return 0
def getOperDataWidth(self, oper): """Helper function to get the data type width (in bits) of an operator. This will first attempt to resolve the operator, if it is symbolic. """ from awlsim.core.datatypes import AwlDataType if oper.width > 0: return oper.width if oper.operType == AwlOperatorTypes.NAMED_LOCAL: # Get the type of an interface field # and return its bit width. fieldName = str(oper.offset.identChain) field = self.interf.getFieldByName(fieldName) if not field: raise FupCompilerError("Interface field " "'#%s' could not be found in the " "declared interface." % (fieldName)) dataType = AwlDataType.makeByName(field.typeStr) if dataType: return dataType.width elif oper.operType == AwlOperatorTypes.SYMBOLIC: # Get the type of a classic symbolic operator # and return its bit width. fieldName = str(oper.offset.identChain) symbol = self.symTab.findByName(fieldName) if not symbol: raise FupCompilerError("The symbolic operator " "\"%s\" not found in symbol tables." % (fieldName)) dataType = symbol.getType() if dataType: return dataType.width return 0
def translateCodeBlock(self, rawBlock, blockClass): insns = self.__translateInsns(rawBlock.insns) block = blockClass(insns, rawBlock.index) block.setSourceRef(rawBlock.sourceRef, inheritRef = True) # Construct the block interface for rawVar in rawBlock.vars_in: block.interface.addField_IN(self.__translateInterfaceField(rawVar)) for rawVar in rawBlock.vars_out: block.interface.addField_OUT(self.__translateInterfaceField(rawVar)) if rawBlock.retTypeTokens: # ARRAY is not supported for RET_VAL. So make non-array dtype. AwlDataType = _getAwlDataTypeClass() dtype = AwlDataType.makeByName(rawBlock.retTypeTokens) if dtype.type != AwlDataType.TYPE_VOID: # Ok, we have a RET_VAL. field = BlockInterfaceField(name = "RET_VAL", dataType = dtype) block.interface.addField_OUT(field) for rawVar in rawBlock.vars_inout: block.interface.addField_INOUT(self.__translateInterfaceField(rawVar)) for rawVar in rawBlock.vars_static: block.interface.addField_STAT(self.__translateInterfaceField(rawVar)) for rawVar in rawBlock.vars_temp: block.interface.addField_TEMP(self.__translateInterfaceField(rawVar)) return block
def translateCodeBlock(self, rawBlock, blockClass): insns = self.__translateInsns(rawBlock.insns) block = blockClass(insns, rawBlock.index) block.setSourceRef(rawBlock.sourceRef, inheritRef=True) # Construct the block interface for rawVar in rawBlock.vars_in: block.interface.addField_IN(self.__translateInterfaceField(rawVar)) for rawVar in rawBlock.vars_out: block.interface.addField_OUT( self.__translateInterfaceField(rawVar)) if rawBlock.retTypeTokens: # ARRAY is not supported for RET_VAL. So make non-array dtype. AwlDataType = _getAwlDataTypeClass() dtype = AwlDataType.makeByName(rawBlock.retTypeTokens) if dtype.type != AwlDataType.TYPE_VOID: # Ok, we have a RET_VAL. field = BlockInterfaceField(name="RET_VAL", dataType=dtype) block.interface.addField_OUT(field) for rawVar in rawBlock.vars_inout: block.interface.addField_INOUT( self.__translateInterfaceField(rawVar)) for rawVar in rawBlock.vars_static: block.interface.addField_STAT( self.__translateInterfaceField(rawVar)) for rawVar in rawBlock.vars_temp: block.interface.addField_TEMP( self.__translateInterfaceField(rawVar)) return block
def dataType(self): from awlsim.core.datatypes import AwlDataType dataType = self.__dataType if not isinstance(dataType, AwlDataType): dataType = AwlDataType.makeByName(dataType) self.__dataType = dataType return dataType
def addFieldAligned(self, cpu, name, dataType, byteAlignment, initBytes=None): from awlsim.core.datatypes import AwlDataType padding = byteAlignment - self.getUnalignedSize() % byteAlignment if padding == byteAlignment: padding = 0 while padding: self.addField(cpu, None, AwlDataType.makeByName("BYTE"), None) padding -= 1 return self.addField(cpu, name, dataType, initBytes)
def __init__(self, name="", typeStr="", initValueStr="", comment="", uuid=None, enableNameCheck=True): self.name = name self.typeStr = typeStr try: self.dataType = AwlDataType.makeByName(typeStr) except AwlSimError as e: self.dataType = None self.initValueStr = initValueStr self.comment = comment self.uuid = uuid or "00000000-0000-0000-0000-000000000000" self.enableNameCheck = enableNameCheck
def setTypeString(self, newTypeString): if not newTypeString: self.setType(None) return try: from awlsim.core.datatypes import AwlDataType awlType = AwlDataType.makeByName(newTypeString.split()) except AwlSimError as e: raise AwlSimError("Symbol table parser: Can't parse symbol " "type '%s' in line %s" %\ (newTypeString, self.getLineNrString())) self.setType(awlType)
def __init__(self, name, offset, dataType, initBytes=None, override=None): from awlsim.core.datatypes import AwlDataType if isString(dataType): dataType = AwlDataType.makeByName(dataType) self.name = name self.offset = offset self.dataType = dataType self.initBytes = initBytes self.override = override # ** total size of the field in bits self.bitSize = self.dataType.width self.byteSize = intDivRoundUp(self.bitSize, 8) # ** probably refers to whether the data type is complex self.compound = dataType.compound if self.initBytes is not None: assert(len(self.initBytes) == self.byteSize)
def __init__(self, name, offset, dataType, initBytes=None, override=None): from awlsim.core.datatypes import AwlDataType if isString(dataType): dataType = AwlDataType.makeByName(dataType) self.name = name self.offset = offset self.dataType = dataType self.initBytes = initBytes self.override = override self.finalOverride = None # Not known, yet. self.bitSize = self.dataType.width self.byteSize = intDivRoundUp(self.bitSize, 8) self.compound = bool(dataType.compound) from awlsim.core.blockinterface import BlockInterface self.callByRef = bool(dataType.type in AwlDataType.callByRefTypes) if self.initBytes is not None: assert(len(self.initBytes) == self.byteSize)
def __init__(self, name, offset, dataType, initBytes=None, override=None): from awlsim.core.datatypes import AwlDataType if isString(dataType): dataType = AwlDataType.makeByName(dataType) self.name = name self.offset = offset self.dataType = dataType self.initBytes = initBytes self.override = override self.finalOverride = None # Not known, yet. self.bitSize = self.dataType.width self.byteSize = intDivRoundUp(self.bitSize, 8) self.compound = bool(dataType.compound) from awlsim.core.blockinterface import BlockInterface self.callByRef = bool(dataType.type in AwlDataType.callByRefTypes) if self.initBytes is not None: assert (len_u32(self.initBytes) == self.byteSize)
def __doTrans(self, rawInsn, rawOps): assert(len(rawOps) >= 1) token0 = rawOps[0] token0Upper = token0.upper() if rawInsn and rawInsn.block.hasLabel(token0): # Label reference oper = make_AwlOperator(AwlOperatorTypes.LBL_REF, 0, None, None) oper.immediateStr = token0 return OpDescriptor(oper, 1) # Constant operator (from table) operTable = self.__mnemonics2constOperTab[self.mnemonics] opDesc = operTable.get(token0Upper, None) if opDesc is not None: return opDesc.dup() # Bitwise indirect addressing if token0Upper == '[': # This is special case for the "U [AR1,P#0.0]" bitwise addressing. # Create a descriptor for the (yet) unspecified bitwise access. opDesc = OpDescriptor(make_AwlOperator(AwlOperatorTypes.UNSPEC, 1, make_AwlOffset(self.CALC_OFFS, self.CALC_OFFS), None), 1) # And hand over to indirect address parsing. self.__translateIndirectAddressing(opDesc, rawOps[1:]) assert(opDesc.operator.operType != AwlOperatorTypes.UNSPEC) return opDesc # Local variable if token0Upper.startswith('#'): offset, count = self.__transVarIdents(rawOps) if not offset: raise AwlSimError("Failed to parse variable name: %s" %\ "".join(rawOps)) return OpDescriptor(make_AwlOperator(AwlOperatorTypes.NAMED_LOCAL, 0, offset, None), count) # Pointer to local variable if token0Upper.startswith("P##"): offset = make_AwlOffset(self.NO_OFFS, self.NO_OFFS) # Doesn't support struct or array indexing. # Parse it as one identification. offset.identChain = AwlDataIdentChain( [ AwlDataIdent(token0[3:]), ] ) return OpDescriptor(make_AwlOperator(AwlOperatorTypes.NAMED_LOCAL_PTR, 0, offset, None), 1) # Symbolic name if token0Upper.startswith('"') and token0Upper.endswith('"'): offset = make_AwlOffset(self.NO_OFFS, self.NO_OFFS) offset.identChain = AwlDataIdentChain( [ AwlDataIdent(token0[1:-1], doValidateName = False), ] ) return OpDescriptor(make_AwlOperator(AwlOperatorTypes.SYMBOLIC, 0, offset, None), 1) AwlDataType = _getAwlDataTypeClass() # Immediate boolean immediate = AwlDataType.tryParseImmediate_BOOL(token0) if immediate is not None: immediate &= 1 oper = make_AwlOperator(AwlOperatorTypes.IMM, 1, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Immediate integer immediate = AwlDataType.tryParseImmediate_INT(token0) if immediate is not None: immediate &= 0xFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 16, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Immediate float immediate = AwlDataType.tryParseImmediate_REAL(token0) if immediate is not None: immediate &= 0xFFFFFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM_REAL, 32, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # S5Time immediate immediate = AwlDataType.tryParseImmediate_S5T(token0) if immediate is not None: immediate &= 0xFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM_S5T, 16, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Time immediate immediate = AwlDataType.tryParseImmediate_TIME(token0) if immediate is not None: immediate &= 0xFFFFFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM_TIME, 32, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # TIME_OF_DAY immediate immediate = AwlDataType.tryParseImmediate_TOD(token0) if immediate is not None: immediate &= 0xFFFFFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM_TOD, 32, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # DATE immediate immediate = AwlDataType.tryParseImmediate_DATE(token0) if immediate is not None: immediate &= 0xFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM_DATE, 16, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # DATE_AND_TIME immediate immediate = AwlDataType.tryParseImmediate_DT(rawOps) if immediate is not None: oper = make_AwlOperator(AwlOperatorTypes.IMM_DT, len(immediate) * 8, None, None) oper.immediateBytes = immediate return OpDescriptor(oper, 5) # Pointer immediate pointer, fields = AwlDataType.tryParseImmediate_Pointer(rawOps) if pointer is not None: oper = make_AwlOperator(AwlOperatorTypes.IMM_PTR, pointer.width, None, None) oper.pointer = pointer return OpDescriptor(oper, fields) # Binary immediate immediate = AwlDataType.tryParseImmediate_Bin(token0) if immediate is not None: immediate &= 0xFFFFFFFF size = 32 if (immediate > 0xFFFF) else 16 oper = make_AwlOperator(AwlOperatorTypes.IMM, size, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Byte array immediate immediate, fields = AwlDataType.tryParseImmediate_ByteArray(rawOps) if immediate is not None: size = 32 if fields == 10 else 16 oper = make_AwlOperator(AwlOperatorTypes.IMM, size, None, None) oper.immediate = immediate return OpDescriptor(oper, fields) # Hex byte immediate immediate = AwlDataType.tryParseImmediate_HexByte(token0) if immediate is not None: immediate &= 0xFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 8, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Hex word immediate immediate = AwlDataType.tryParseImmediate_HexWord(token0) if immediate is not None: immediate &= 0xFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 16, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Hex dword immediate immediate = AwlDataType.tryParseImmediate_HexDWord(token0) if immediate is not None: immediate &= 0xFFFFFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 32, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Long integer immediate immediate = AwlDataType.tryParseImmediate_DINT(token0) if immediate is not None: immediate &= 0xFFFFFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 32, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # BCD word immediate immediate = AwlDataType.tryParseImmediate_BCD_word(token0) if immediate is not None: immediate &= 0xFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 16, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # String immediate immediate = AwlDataType.tryParseImmediate_STRING(token0) if immediate is not None: oper = make_AwlOperator(AwlOperatorTypes.IMM_STR, len(immediate) * 8, None, None) oper.immediateBytes = immediate return OpDescriptor(oper, 1) # DBx.DBX/B/W/D addressing match = re.match(r'^DB(\d+)\.DB([XBWD])$', token0) if match: dbNumber = int(match.group(1)) width = { "X" : 1, "B" : 8, "W" : 16, "D" : 32, }[match.group(2)] offset = make_AwlOffset(self.CALC_OFFS, self.CALC_OFFS if (width == 1) else 0) offset.dbNumber = dbNumber return OpDescriptor(make_AwlOperator(AwlOperatorTypes.MEM_DB, width, offset, None), 2) # Try to parse DBx.VARIABLE or "DBname".VARIABLE adressing offset, count = self.__transVarIdents(rawOps) if offset: return OpDescriptor(make_AwlOperator(AwlOperatorTypes.NAMED_DBVAR, 0, offset, None), count) # Try convenience operators. # A convenience operator is one that lacks otherwise required white space. # We thus actively support lazy programmers, yay. # For example: # = M0.0 # (Note the missing white space between M and 0.0) for name, opDesc in dictItems(operTable): if opDesc.operator.offset is not None and\ opDesc.operator.offset.byteOffset >= 0 and\ opDesc.operator.offset.bitOffset >= 0: # Only for operators with bit/byte addresses. continue try: # Try convenience operator if token0Upper.startswith(name) and\ token0Upper[len(name)].isdigit(): opDesc = opDesc.dup() opDesc.stripLeadingChars = len(name) opDesc.fieldCount -= 1 return opDesc except IndexError: pass raise AwlSimError("Cannot parse operator: " +\ str(token0))
def __translateIndirectAddressing(self, opDesc, rawOps): #@cy cdef uint64_t area_u64 # rawOps starts _after_ the opening bracket '[' try: if rawOps[0].upper() in ("AR1", "AR2"): AwlDataType = _getAwlDataTypeClass() # Register-indirect access: "L W [AR1, P#0.0]" ar = { "AR1" : AwlIndirectOpConst.AR_1, "AR2" : AwlIndirectOpConst.AR_2, }[rawOps[0].upper()] if rawOps[1] != ',': raise AwlSimError("Missing comma in register-indirect " "addressing operator") offsetPtr, fields = AwlDataType.tryParseImmediate_Pointer(rawOps[2:]) if fields != 1: raise AwlSimError("Invalid offset pointer in " "register indirect addressing operator") if offsetPtr.width != 32: raise AwlSimError("Only plain pointers allowed as " "indirect addressing offset pointer.") if offsetPtr.getArea(): raise AwlSimError("Area internal pointer not " "allowed as indirect addressing offset pointer.") if rawOps[3] != ']': raise AwlSimError("Missing closing brackets in " "register indirect addressing operator") offsetOp = make_AwlOperator(operType=AwlOperatorTypes.IMM_PTR, width=32, offset=None, insn=opDesc.operator.insn) offsetOp.pointer = offsetPtr area = AwlIndirectOpConst.optype2area(opDesc.operator.operType) if area < 0: raise AwlSimError("Invalid memory area type in " "register indirect addressing operator") indirectOp = make_AwlIndirectOp(area=area, width=opDesc.operator.width, addressRegister=ar, offsetOper=offsetOp, insn=opDesc.operator.insn) fieldCount = 4 # ARx + comma + P# + ] else: # Indirect access: "L MW [MD 42]" # Find the end of the brackets. i, lvl = 0, 1 for i, tok in enumerate(rawOps): if tok == ']': lvl -= 1 elif tok == '[': lvl += 1 if lvl == 0: end = i break else: raise AwlSimError("Missing closing brackets in " "indirect addressing operator") # Translate the offset operator offsetOpDesc = self.translateOp(None, rawOps[:end]) if offsetOpDesc.fieldCount != end: raise AwlSimError("Invalid indirect addressing " "operator format. AR1/AR2 missing?") offsetOp = offsetOpDesc.operator if offsetOp.operType == AwlOperatorTypes.INDIRECT: raise AwlSimError("Only direct operators supported " "inside of indirect operator brackets.") area = AwlIndirectOpConst.optype2area(opDesc.operator.operType) if area < 0: raise AwlSimError("Invalid memory area type in " "indirect addressing operator") area_u64 = area if area_u64 == PointerConst.AREA_NONE_S: raise AwlSimError("No memory area code specified in " "indirect addressing operator") if area_u64 in (AwlIndirectOpConst.EXT_AREA_T_S, AwlIndirectOpConst.EXT_AREA_Z_S, AwlIndirectOpConst.EXT_AREA_BLKREF_DB_S, AwlIndirectOpConst.EXT_AREA_BLKREF_DI_S, AwlIndirectOpConst.EXT_AREA_BLKREF_FC_S, AwlIndirectOpConst.EXT_AREA_BLKREF_FB_S): expectedOffsetOpWidth = 16 else: expectedOffsetOpWidth = 32 if offsetOp.operType != AwlOperatorTypes.NAMED_LOCAL and\ offsetOp.width != expectedOffsetOpWidth: #TODO: We should also check for NAMED_LOCAL raise AwlSimError("Offset operator in " "indirect addressing operator has invalid width. " "Got %d bit, but expected %d bit." %\ (offsetOp.width, expectedOffsetOpWidth)) indirectOp = make_AwlIndirectOp(area=area, width=opDesc.operator.width, addressRegister=AwlIndirectOpConst.AR_NONE, offsetOper=offsetOp, insn=opDesc.operator.insn) fieldCount = offsetOpDesc.fieldCount + 1 # offsetOperator + ] except IndexError: raise AwlSimError("Invalid indirect addressing operator") # Adjust the operator descriptor opDesc.operator = indirectOp opDesc.fieldCount += fieldCount
def addField(self, cpu, name, dataType, initBytes=None): #@cy cdef S7CPU _cpu from awlsim.core.datatypes import AwlDataType _cpu = cpu initMem = AwlMemory(initBytes) if dataType.type == dataType.TYPE_UDT_X: # Add an UDT. udt = _cpu.getUDT(dataType.index) if not udt: #@nocov assert(0) # Should never happen assert(not initBytes) # Assign the struct to the UDT data type, if # not already done so. assert(dataType._struct is None or dataType._struct is udt._struct) dataType.setStruct(udt._struct) # Merge the UDT struct with this struct. return self.merge(udt._struct, name, dataType) if dataType.width < 0: raise AwlSimError("Width of data structure field '%s : %s' " "is undefined. This probably means that its data " "type is unsupported." %\ (name, str(dataType))) if dataType.type == dataType.TYPE_STRUCT or\ dataType.type == dataType.TYPE_STRING: # Add a STRUCT (or STRING, which is represented as struct). # The struct is represented by the data types struct. # Merge the data type struct into this struct. assert(dataType._struct) baseField = self.merge(dataType._struct, name, dataType) baseField.override = AwlStructField(baseField.name, baseField.offset, "VOID") baseField.initBytes = initBytes if dataType.type == dataType.TYPE_ARRAY: # Add an ARRAY. # First add a field with the array's name. # It has the data type 'ARRAY' and is informational only. offset = make_AwlOffset(self.getUnalignedSize(), 0) baseField = AwlStructField(name, offset, dataType, override = AwlStructField(name, offset, "VOID")) self.__registerField(baseField) # Add fields for each ARRAY entry. initOffset = make_AwlOffset(0, 0) childIdent = AwlDataIdent(name, [ d[0] for d in dataType.arrayDimensions ], doValidateName = False) childType = dataType.arrayElementType if not childType.allowedInArray: raise AwlSimError("Data type '%s' not allowed in ARRAY" %\ str(childType)) for i in range(dataType.arrayGetNrElements()): try: if not initBytes: raise ValueError fieldInitMem = AwlMemory(intDivRoundUp(childType.width, 8)) fieldInitMem.store(make_AwlOffset(0, 0), initMem.fetch(initOffset, childType.width)) fieldInitData = fieldInitMem.getDataBytes() except (AwlSimError, ValueError) as e: fieldInitData = None self.addField(_cpu, str(childIdent), childType, fieldInitData) initOffset += make_AwlOffset_fromLongBitOffset(childType.width) childIdent.advanceToNextArrayElement(dataType.arrayDimensions) if childType.width > 8 and\ intDivRoundUp(childType.width, 8) % 2 != 0: # Align each element to 2-byte-boundary, if word or bigger. self.addField(_cpu, None, AwlDataType.makeByName("BYTE")) # Add a zero-length array-end guard field, # to enforce alignment of following fields. self.addDummyField() if dataType.type not in {dataType.TYPE_ARRAY, dataType.TYPE_STRUCT, dataType.TYPE_STRING}: # Add a single data type. if dataType.width == 1 and self.fields and\ self.fields[-1].bitSize == 1 and\ self.fields[-1].offset.bitOffset < 7: # Consecutive bitfields are merged into one byte offset = make_AwlOffset(self.fields[-1].offset.byteOffset, self.fields[-1].offset.bitOffset + 1) else: offset = make_AwlOffset(self.getUnalignedSize(), 0) baseField = AwlStructField(name, offset, dataType, initBytes) self.__registerField(baseField) return baseField
def resolveNamedLocal(self, block, insn, oper, pointer=False, allowWholeArrayAccess=False): #@cy cdef S7CPU cpu # Check whether we need to do something. # Otherwise just return the source operator. if pointer: if oper.operType != AwlOperatorTypes.NAMED_LOCAL_PTR: return oper else: if oper.operType != AwlOperatorTypes.NAMED_LOCAL: return oper AwlDataType = _getAwlDataTypeClass() cpu = self.cpu # Walk the ident chain to accumulate the sub-offsets # for the ARRAY accesses. parentStruct = None subOffset = make_AwlOffset(0, 0) for i in range(len(oper.offset.identChain)): isFirstElement = (i == 0) isLastElement = (i == len(oper.offset.identChain) - 1) # Get the sub-chain and the interface field. chain = AwlDataIdentChain(oper.offset.identChain[:i + 1]) dataType = block.interface.getFieldDataType(chain) # Sanity checks if dataType.type in { AwlDataType.TYPE_ARRAY, AwlDataType.TYPE_STRING }: if isLastElement and\ not chain[-1].indices and\ oper.operType != AwlOperatorTypes.NAMED_LOCAL_PTR and\ not allowWholeArrayAccess: raise AwlSimError("Cannot address array #%s " "without subscript list." %\ chain.getString()) else: if chain[-1].indices: raise AwlSimError("Trying to subscript array, " "but #%s is not an array." %\ chain.getString()) # Assign the struct to the UDT data type, if # not already done so. if dataType.type == AwlDataType.TYPE_UDT_X: udt = cpu.getUDT(dataType.index) if not udt: raise AwlSimError("UDT %d not found on CPU" %\ dataType.index) assert (dataType._struct is None or dataType._struct is udt._struct) dataType.setStruct(udt._struct) # Add the struct field offset of this field to the subOffset. # Need to look it up in the parent struct. if not isFirstElement: assert (parentStruct) structFieldName = chain[-1].dup(withIndices=False).getString() structField = parentStruct.getField(structFieldName) subOffset += structField.offset # Add array offset to subOffset, # if this is an ARRAY or STRING element access. if chain[-1].indices: if dataType.type == AwlDataType.TYPE_ARRAY: # Calculate the array offset. arrayIndex = dataType.arrayIndicesCollapse( chain[-1].indices) elemWidth = dataType.arrayElementType.width bitOffset = arrayIndex * elemWidth byteOffset = bitOffset // 8 bitOffset %= 8 elif dataType.type == AwlDataType.TYPE_STRING: # Calculate the string offset. if len(chain[-1].indices) != 1: raise AwlSimError("Only one index is " "allowed in STRING indexing.") index = chain[-1].indices[0] maxIdx = dataType.width // 8 - 2 if index < 1 or index > maxIdx: raise AwlSimError("STRING index %d is " "out of range 1-%d." %\ (index, maxIdx)) byteOffset = 2 + index - 1 bitOffset = 0 else: assert (0) # Add it to the accumulated offset. subOffset += make_AwlOffset(byteOffset, bitOffset) parentStruct = dataType.itemStruct # 'dataType' now is the type of last field in the identChain. # (The field that we eventually address). isWholeArrayAccess = ((dataType.type == AwlDataType.TYPE_ARRAY or\ dataType.type == AwlDataType.TYPE_STRING) and\ not oper.offset.identChain[-1].indices) if dataType.type == AwlDataType.TYPE_ARRAY and\ not isWholeArrayAccess: # This is an array element access. accessDataType = dataType.arrayElementType elif dataType.type == AwlDataType.TYPE_STRING and\ not isWholeArrayAccess: # This is a string single character access. accessDataType = AwlDataType.makeByName("CHAR") else: # Non-array access or whole-array access. accessDataType = dataType # Store the access type and width in the operator. oper.dataType = accessDataType oper.width = accessDataType.width assert (oper.width > 0) # Store the sub-offset (might be zero). if subOffset.byteOffset or subOffset.bitOffset: oper.offset.subOffset = subOffset else: oper.offset.subOffset = None # If interface field is of compound data type access, mark # the operand as such. basicType = block.interface.getFieldDataType(chain, deep=False) oper.compound = basicType.compound fieldType = block.interface.getFieldType(oper.offset.identChain) if block.interface.hasInstanceDB or\ fieldType == BlockInterfaceField.FTYPE_TEMP: # This is an FB or a TEMP access. Translate the operator # to a DI/TEMP access. newOper = block.interface.getOperatorForField( oper.offset.identChain, pointer) assert (newOper.width > 0) newOper.setInsn(oper.insn) newOper.compound = oper.compound newOper.dataType = oper.dataType return newOper else: # This is an FC. Accesses to local symbols # are resolved at runtime. # Just set interface index in the operator. # Pointer access (oper.operType == NAMED_LOCAL_PTR) is resolved # later at runtime. identChain = oper.offset.identChain.dup(withIndices=False) index = block.interface.getFieldByIdentChain(identChain).fieldIndex oper.interfaceIndex = index return oper
def resolveNamedLocal(self, block, insn, oper, pointer=False, allowWholeArrayAccess=False): #@cy cdef S7CPU cpu # Check whether we need to do something. # Otherwise just return the source operator. if pointer: if oper.operType != AwlOperatorTypes.NAMED_LOCAL_PTR: return oper else: if oper.operType != AwlOperatorTypes.NAMED_LOCAL: return oper AwlDataType = _getAwlDataTypeClass() cpu = self.cpu # Walk the ident chain to accumulate the sub-offsets # for the ARRAY accesses. parentStruct = None subOffset = make_AwlOffset(0, 0) for i in range(len(oper.offset.identChain)): isFirstElement = (i == 0) isLastElement = (i == len(oper.offset.identChain) - 1) # Get the sub-chain and the interface field. chain = AwlDataIdentChain(oper.offset.identChain[:i+1]) dataType = block.interface.getFieldDataType(chain) # Sanity checks if dataType.type in {AwlDataType.TYPE_ARRAY, AwlDataType.TYPE_STRING}: if isLastElement and\ not chain[-1].indices and\ oper.operType != AwlOperatorTypes.NAMED_LOCAL_PTR and\ not allowWholeArrayAccess: raise AwlSimError("Cannot address array #%s " "without subscript list." %\ chain.getString()) else: if chain[-1].indices: raise AwlSimError("Trying to subscript array, " "but #%s is not an array." %\ chain.getString()) # Assign the struct to the UDT data type, if # not already done so. if dataType.type == AwlDataType.TYPE_UDT_X: udt = cpu.getUDT(dataType.index) if not udt: raise AwlSimError("UDT %d not found on CPU" %\ dataType.index) assert(dataType._struct is None or dataType._struct is udt._struct) dataType.setStruct(udt._struct) # Add the struct field offset of this field to the subOffset. # Need to look it up in the parent struct. if not isFirstElement: assert(parentStruct) structFieldName = chain[-1].dup(withIndices=False).getString() structField = parentStruct.getField(structFieldName) subOffset += structField.offset # Add array offset to subOffset, # if this is an ARRAY or STRING element access. if chain[-1].indices: if dataType.type == AwlDataType.TYPE_ARRAY: # Calculate the array offset. arrayIndex = dataType.arrayIndicesCollapse(chain[-1].indices) elemWidth = dataType.arrayElementType.width bitOffset = arrayIndex * elemWidth byteOffset = bitOffset // 8 bitOffset %= 8 elif dataType.type == AwlDataType.TYPE_STRING: # Calculate the string offset. if len(chain[-1].indices) != 1: raise AwlSimError("Only one index is " "allowed in STRING indexing.") index = chain[-1].indices[0] maxIdx = dataType.width // 8 - 2 if index < 1 or index > maxIdx: raise AwlSimError("STRING index %d is " "out of range 1-%d." %\ (index, maxIdx)) byteOffset = 2 + index - 1 bitOffset = 0 else: assert(0) # Add it to the accumulated offset. subOffset += make_AwlOffset(byteOffset, bitOffset) parentStruct = dataType.itemStruct # 'dataType' now is the type of last field in the identChain. # (The field that we eventually address). isWholeArrayAccess = ((dataType.type == AwlDataType.TYPE_ARRAY or\ dataType.type == AwlDataType.TYPE_STRING) and\ not oper.offset.identChain[-1].indices) if dataType.type == AwlDataType.TYPE_ARRAY and\ not isWholeArrayAccess: # This is an array element access. accessDataType = dataType.arrayElementType elif dataType.type == AwlDataType.TYPE_STRING and\ not isWholeArrayAccess: # This is a string single character access. accessDataType = AwlDataType.makeByName("CHAR") else: # Non-array access or whole-array access. accessDataType = dataType # Store the access type and width in the operator. oper.dataType = accessDataType oper.width = accessDataType.width assert(oper.width > 0) # Store the sub-offset (might be zero). if subOffset.byteOffset or subOffset.bitOffset: oper.offset.subOffset = subOffset else: oper.offset.subOffset = None # If interface field is of compound data type access, mark # the operand as such. basicType = block.interface.getFieldDataType(chain, deep=False) oper.compound = basicType.compound fieldType = block.interface.getFieldType(oper.offset.identChain) if block.interface.hasInstanceDB or\ fieldType == BlockInterfaceField.FTYPE_TEMP: # This is an FB or a TEMP access. Translate the operator # to a DI/TEMP access. newOper = block.interface.getOperatorForField(oper.offset.identChain, pointer) assert(newOper.width > 0) newOper.setInsn(oper.insn) newOper.compound = oper.compound newOper.dataType = oper.dataType return newOper else: # This is an FC. Accesses to local symbols # are resolved at runtime. # Just set interface index in the operator. # Pointer access (oper.operType == NAMED_LOCAL_PTR) is resolved # later at runtime. identChain = oper.offset.identChain.dup(withIndices = False) index = block.interface.getFieldByIdentChain(identChain).fieldIndex oper.interfaceIndex = index return oper
def addField(self, cpu, name, dataType, initBytes=None): #@cy cdef S7CPU _cpu from awlsim.core.datatypes import AwlDataType _cpu = cpu initMem = AwlMemory(initBytes) if dataType.type == dataType.TYPE_UDT_X: # Add an UDT. udt = _cpu.getUDT(dataType.index) if not udt: #@nocov assert (0) # Should never happen assert (not initBytes) # Assign the struct to the UDT data type, if # not already done so. assert (dataType._struct is None or dataType._struct is udt._struct) dataType.setStruct(udt._struct) # Merge the UDT struct with this struct. return self.merge(udt._struct, name, dataType) if dataType.width < 0: raise AwlSimError("Width of data structure field '%s : %s' " "is undefined. This probably means that its data " "type is unsupported." %\ (name, str(dataType))) if dataType.type == dataType.TYPE_STRUCT or\ dataType.type == dataType.TYPE_STRING: # Add a STRUCT (or STRING, which is represented as struct). # The struct is represented by the data types struct. # Merge the data type struct into this struct. assert (dataType._struct) baseField = self.merge(dataType._struct, name, dataType) baseField.override = AwlStructField(baseField.name, baseField.offset, "VOID") baseField.initBytes = initBytes if dataType.type == dataType.TYPE_ARRAY: # Add an ARRAY. # First add a field with the array's name. # It has the data type 'ARRAY' and is informational only. offset = make_AwlOffset(self.getUnalignedSize(), 0) baseField = AwlStructField(name, offset, dataType, override=AwlStructField( name, offset, "VOID")) self.__registerField(baseField) # Add fields for each ARRAY entry. initOffset = make_AwlOffset(0, 0) childIdent = AwlDataIdent(name, [d[0] for d in dataType.arrayDimensions], doValidateName=False) childType = dataType.arrayElementType if not childType.allowedInArray: raise AwlSimError("Data type '%s' not allowed in ARRAY" %\ str(childType)) for i in range(dataType.arrayGetNrElements()): try: if not initBytes: raise ValueError fieldInitMem = AwlMemory(intDivRoundUp(childType.width, 8)) fieldInitMem.store( make_AwlOffset(0, 0), initMem.fetch(initOffset, childType.width)) fieldInitData = fieldInitMem.getDataBytes() except (AwlSimError, ValueError) as e: fieldInitData = None self.addField(_cpu, str(childIdent), childType, fieldInitData) initOffset += make_AwlOffset_fromLongBitOffset(childType.width) childIdent.advanceToNextArrayElement(dataType.arrayDimensions) if childType.width > 8 and\ intDivRoundUp(childType.width, 8) % 2 != 0: # Align each element to 2-byte-boundary, if word or bigger. self.addField(_cpu, None, AwlDataType.makeByName("BYTE")) # Add a zero-length array-end guard field, # to enforce alignment of following fields. self.addDummyField() if dataType.type not in { dataType.TYPE_ARRAY, dataType.TYPE_STRUCT, dataType.TYPE_STRING }: # Add a single data type. if dataType.width == 1 and self.fields and\ self.fields[-1].bitSize == 1 and\ self.fields[-1].offset.bitOffset < 7: # Consecutive bitfields are merged into one byte offset = make_AwlOffset(self.fields[-1].offset.byteOffset, self.fields[-1].offset.bitOffset + 1) else: offset = make_AwlOffset(self.getUnalignedSize(), 0) baseField = AwlStructField(name, offset, dataType, initBytes) self.__registerField(baseField) return baseField
def __translateIndirectAddressing(self, opDesc, rawOps): #@cy cdef uint64_t area_u64 # rawOps starts _after_ the opening bracket '[' try: if rawOps[0].upper() in ("AR1", "AR2"): AwlDataType = _getAwlDataTypeClass() # Register-indirect access: "L W [AR1, P#0.0]" ar = { "AR1": AwlIndirectOpConst.AR_1, "AR2": AwlIndirectOpConst.AR_2, }[rawOps[0].upper()] if rawOps[1] != ',': raise AwlSimError("Missing comma in register-indirect " "addressing operator") offsetPtr, fields = AwlDataType.tryParseImmediate_Pointer( rawOps[2:]) if fields != 1: raise AwlSimError("Invalid offset pointer in " "register indirect addressing operator") if offsetPtr.width != 32: raise AwlSimError("Only plain pointers allowed as " "indirect addressing offset pointer.") if offsetPtr.getArea(): raise AwlSimError( "Area internal pointer not " "allowed as indirect addressing offset pointer.") if rawOps[3] != ']': raise AwlSimError("Missing closing brackets in " "register indirect addressing operator") offsetOp = make_AwlOperator(operType=AwlOperatorTypes.IMM_PTR, width=32, offset=None, insn=opDesc.operator.insn) offsetOp.pointer = offsetPtr area = AwlIndirectOpConst.optype2area(opDesc.operator.operType) if area < 0: raise AwlSimError("Invalid memory area type in " "register indirect addressing operator") indirectOp = make_AwlIndirectOp(area=area, width=opDesc.operator.width, addressRegister=ar, offsetOper=offsetOp, insn=opDesc.operator.insn) fieldCount = 4 # ARx + comma + P# + ] else: # Indirect access: "L MW [MD 42]" # Find the end of the brackets. i, lvl = 0, 1 for i, tok in enumerate(rawOps): if tok == ']': lvl -= 1 elif tok == '[': lvl += 1 if lvl == 0: end = i break else: raise AwlSimError("Missing closing brackets in " "indirect addressing operator") # Translate the offset operator offsetOpDesc = self.translateOp(None, rawOps[:end]) if offsetOpDesc.fieldCount != end: raise AwlSimError("Invalid indirect addressing " "operator format. AR1/AR2 missing?") offsetOp = offsetOpDesc.operator if offsetOp.operType == AwlOperatorTypes.INDIRECT: raise AwlSimError("Only direct operators supported " "inside of indirect operator brackets.") area = AwlIndirectOpConst.optype2area(opDesc.operator.operType) if area < 0: raise AwlSimError("Invalid memory area type in " "indirect addressing operator") area_u64 = area if area_u64 == PointerConst.AREA_NONE_S: raise AwlSimError("No memory area code specified in " "indirect addressing operator") if area_u64 in (AwlIndirectOpConst.EXT_AREA_T_S, AwlIndirectOpConst.EXT_AREA_Z_S, AwlIndirectOpConst.EXT_AREA_BLKREF_DB_S, AwlIndirectOpConst.EXT_AREA_BLKREF_DI_S, AwlIndirectOpConst.EXT_AREA_BLKREF_FC_S, AwlIndirectOpConst.EXT_AREA_BLKREF_FB_S): expectedOffsetOpWidth = 16 else: expectedOffsetOpWidth = 32 if offsetOp.operType != AwlOperatorTypes.NAMED_LOCAL and\ offsetOp.width != expectedOffsetOpWidth: #TODO: We should also check for NAMED_LOCAL raise AwlSimError("Offset operator in " "indirect addressing operator has invalid width. " "Got %d bit, but expected %d bit." %\ (offsetOp.width, expectedOffsetOpWidth)) indirectOp = make_AwlIndirectOp( area=area, width=opDesc.operator.width, addressRegister=AwlIndirectOpConst.AR_NONE, offsetOper=offsetOp, insn=opDesc.operator.insn) fieldCount = offsetOpDesc.fieldCount + 1 # offsetOperator + ] except IndexError: raise AwlSimError("Invalid indirect addressing operator") # Adjust the operator descriptor opDesc.operator = indirectOp opDesc.fieldCount += fieldCount
def __doTrans(self, rawInsn, rawOps): assert (len(rawOps) >= 1) token0 = rawOps[0] token0Upper = token0.upper() if rawInsn and rawInsn.block.hasLabel(token0): # Label reference oper = make_AwlOperator(AwlOperatorTypes.LBL_REF, 0, None, None) oper.immediateStr = token0 return OpDescriptor(oper, 1) # Constant operator (from table) operTable = self.__mnemonics2constOperTab[self.mnemonics] opDesc = operTable.get(token0Upper, None) if opDesc is not None: return opDesc.dup() # Bitwise indirect addressing if token0Upper == '[': # This is special case for the "U [AR1,P#0.0]" bitwise addressing. # Create a descriptor for the (yet) unspecified bitwise access. opDesc = OpDescriptor( make_AwlOperator( AwlOperatorTypes.UNSPEC, 1, make_AwlOffset(self.CALC_OFFS, self.CALC_OFFS), None), 1) # And hand over to indirect address parsing. self.__translateIndirectAddressing(opDesc, rawOps[1:]) assert (opDesc.operator.operType != AwlOperatorTypes.UNSPEC) return opDesc # Local variable if token0Upper.startswith('#'): offset, count = self.__transVarIdents(rawOps) if not offset: raise AwlSimError("Failed to parse variable name: %s" %\ "".join(rawOps)) return OpDescriptor( make_AwlOperator(AwlOperatorTypes.NAMED_LOCAL, 0, offset, None), count) # Pointer to local variable if token0Upper.startswith("P##"): offset = make_AwlOffset(self.NO_OFFS, self.NO_OFFS) # Doesn't support struct or array indexing. # Parse it as one identification. offset.identChain = AwlDataIdentChain([ AwlDataIdent(token0[3:]), ]) return OpDescriptor( make_AwlOperator(AwlOperatorTypes.NAMED_LOCAL_PTR, 0, offset, None), 1) # Symbolic name if token0Upper.startswith('"') and token0Upper.endswith('"'): offset = make_AwlOffset(self.NO_OFFS, self.NO_OFFS) offset.identChain = AwlDataIdentChain([ AwlDataIdent(token0[1:-1], doValidateName=False), ]) return OpDescriptor( make_AwlOperator(AwlOperatorTypes.SYMBOLIC, 0, offset, None), 1) AwlDataType = _getAwlDataTypeClass() # Immediate boolean immediate = AwlDataType.tryParseImmediate_BOOL(token0) if immediate is not None: immediate &= 1 oper = make_AwlOperator(AwlOperatorTypes.IMM, 1, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Immediate integer immediate = AwlDataType.tryParseImmediate_INT(token0) if immediate is not None: immediate &= 0xFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 16, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Immediate float immediate = AwlDataType.tryParseImmediate_REAL(token0) if immediate is not None: immediate &= 0xFFFFFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM_REAL, 32, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # S5Time immediate immediate = AwlDataType.tryParseImmediate_S5T(token0) if immediate is not None: immediate &= 0xFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM_S5T, 16, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Time immediate immediate = AwlDataType.tryParseImmediate_TIME(token0) if immediate is not None: immediate &= 0xFFFFFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM_TIME, 32, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # TIME_OF_DAY immediate immediate = AwlDataType.tryParseImmediate_TOD(token0) if immediate is not None: immediate &= 0xFFFFFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM_TOD, 32, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # DATE immediate immediate = AwlDataType.tryParseImmediate_DATE(token0) if immediate is not None: immediate &= 0xFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM_DATE, 16, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # DATE_AND_TIME immediate immediate = AwlDataType.tryParseImmediate_DT(rawOps) if immediate is not None: oper = make_AwlOperator(AwlOperatorTypes.IMM_DT, len(immediate) * 8, None, None) oper.immediateBytes = immediate return OpDescriptor(oper, 5) # Pointer immediate pointer, fields = AwlDataType.tryParseImmediate_Pointer(rawOps) if pointer is not None: oper = make_AwlOperator(AwlOperatorTypes.IMM_PTR, pointer.width, None, None) oper.pointer = pointer return OpDescriptor(oper, fields) # Binary immediate immediate = AwlDataType.tryParseImmediate_Bin(token0) if immediate is not None: immediate &= 0xFFFFFFFF size = 32 if (immediate > 0xFFFF) else 16 oper = make_AwlOperator(AwlOperatorTypes.IMM, size, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Byte array immediate immediate, fields = AwlDataType.tryParseImmediate_ByteArray(rawOps) if immediate is not None: size = 32 if fields == 10 else 16 oper = make_AwlOperator(AwlOperatorTypes.IMM, size, None, None) oper.immediate = immediate return OpDescriptor(oper, fields) # Hex byte immediate immediate = AwlDataType.tryParseImmediate_HexByte(token0) if immediate is not None: immediate &= 0xFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 8, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Hex word immediate immediate = AwlDataType.tryParseImmediate_HexWord(token0) if immediate is not None: immediate &= 0xFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 16, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Hex dword immediate immediate = AwlDataType.tryParseImmediate_HexDWord(token0) if immediate is not None: immediate &= 0xFFFFFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 32, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # Long integer immediate immediate = AwlDataType.tryParseImmediate_DINT(token0) if immediate is not None: immediate &= 0xFFFFFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 32, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # BCD word immediate immediate = AwlDataType.tryParseImmediate_BCD_word(token0) if immediate is not None: immediate &= 0xFFFF oper = make_AwlOperator(AwlOperatorTypes.IMM, 16, None, None) oper.immediate = immediate return OpDescriptor(oper, 1) # String immediate immediate = AwlDataType.tryParseImmediate_STRING(token0) if immediate is not None: oper = make_AwlOperator(AwlOperatorTypes.IMM_STR, len(immediate) * 8, None, None) oper.immediateBytes = immediate return OpDescriptor(oper, 1) # DBx.DBX/B/W/D addressing match = re.match(r'^DB(\d+)\.DB([XBWD])$', token0) if match: dbNumber = int(match.group(1)) width = { "X": 1, "B": 8, "W": 16, "D": 32, }[match.group(2)] offset = make_AwlOffset(self.CALC_OFFS, self.CALC_OFFS if (width == 1) else 0) offset.dbNumber = dbNumber return OpDescriptor( make_AwlOperator(AwlOperatorTypes.MEM_DB, width, offset, None), 2) # Try to parse DBx.VARIABLE or "DBname".VARIABLE adressing offset, count = self.__transVarIdents(rawOps) if offset: return OpDescriptor( make_AwlOperator(AwlOperatorTypes.NAMED_DBVAR, 0, offset, None), count) # Try convenience operators. # A convenience operator is one that lacks otherwise required white space. # We thus actively support lazy programmers, yay. # For example: # = M0.0 # (Note the missing white space between M and 0.0) for name, opDesc in dictItems(operTable): if opDesc.operator.offset is not None and\ opDesc.operator.offset.byteOffset >= 0 and\ opDesc.operator.offset.bitOffset >= 0: # Only for operators with bit/byte addresses. continue try: # Try convenience operator if token0Upper.startswith(name) and\ token0Upper[len(name)].isdigit(): opDesc = opDesc.dup() opDesc.stripLeadingChars = len(name) opDesc.fieldCount -= 1 return opDesc except IndexError: pass raise AwlSimError("Cannot parse operator: " +\ str(token0))
def __repr__(self): from awlsim.core.datatypes import AwlDataType from awlsim.common.sources import AwlSource if self.operType == AwlOperatorTypes.IMM: if self.width == 1: return "TRUE" if (self.immediate & 1) else "FALSE" elif self.width == 8: return str(self.immediate) elif self.width == 16: return str(wordToSignedPyInt(self.immediate)) elif self.width == 32: return "L#" + str(dwordToSignedPyInt(self.immediate)) if self.operType == AwlOperatorTypes.IMM_REAL: return str(dwordToPyFloat(self.immediate)) elif self.operType == AwlOperatorTypes.IMM_S5T: seconds = Timer_s5t_to_seconds(self.immediate) return "S5T#" + AwlDataType.formatTime(seconds) elif self.operType == AwlOperatorTypes.IMM_TIME: return "T#" + AwlDataType.formatTime(self.immediate / 1000.0) elif self.operType == AwlOperatorTypes.IMM_DATE: return "D#" #TODO elif self.operType == AwlOperatorTypes.IMM_TOD: return "TOD#" #TODO elif self.operType == AwlOperatorTypes.IMM_PTR: return self.pointer.toPointerString() elif self.operType == AwlOperatorTypes.IMM_STR: strLen = self.immediateBytes[1] return "'" + self.immediateBytes[2:2+strLen].decode( AwlSource.COMPAT_ENCODING) + "'" elif self.operType in {AwlOperatorTypes.MEM_A, AwlOperatorTypes.MEM_E, AwlOperatorTypes.MEM_M, AwlOperatorTypes.MEM_L, AwlOperatorTypes.MEM_VL}: pfx = self.type2str[self.operType] if self.width == 1: return "%s %d.%d" %\ (pfx, self.offset.byteOffset, self.offset.bitOffset) elif self.width == 8: return "%sB %d" % (pfx, self.offset.byteOffset) elif self.width == 16: return "%sW %d" % (pfx, self.offset.byteOffset) elif self.width == 32: return "%sD %d" % (pfx, self.offset.byteOffset) return self.makeANYPointer().toPointerString() elif self.operType == AwlOperatorTypes.MEM_DB: if self.offset.dbNumber < 0: dbPrefix = "" else: dbPrefix = "DB%d." % self.offset.dbNumber if self.width == 1: return "%sDBX %d.%d" % (dbPrefix, self.offset.byteOffset, self.offset.bitOffset) elif self.width == 8: return "%sDBB %d" % (dbPrefix, self.offset.byteOffset) elif self.width == 16: return "%sDBW %d" % (dbPrefix, self.offset.byteOffset) elif self.width == 32: return "%sDBD %d" % (dbPrefix, self.offset.byteOffset) return self.makeANYPointer().toPointerString() elif self.operType == AwlOperatorTypes.MEM_DI: if self.width == 1: return "DIX %d.%d" % (self.offset.byteOffset, self.offset.bitOffset) elif self.width == 8: return "DIB %d" % self.offset.byteOffset elif self.width == 16: return "DIW %d" % self.offset.byteOffset elif self.width == 32: return "DID %d" % self.offset.byteOffset return self.makeANYPointer().toPointerString() elif self.operType == AwlOperatorTypes.MEM_T: return "T %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.MEM_Z: return "Z %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.MEM_PA: if self.width == 8: return "PAB %d" % self.offset.byteOffset elif self.width == 16: return "PAW %d" % self.offset.byteOffset elif self.width == 32: return "PAD %d" % self.offset.byteOffset return self.makeANYPointer().toPointerString() elif self.operType == AwlOperatorTypes.MEM_PE: if self.width == 8: return "PEB %d" % self.offset.byteOffset elif self.width == 16: return "PEW %d" % self.offset.byteOffset elif self.width == 32: return "PED %d" % self.offset.byteOffset return self.makeANYPointer().toPointerString() elif self.operType == AwlOperatorTypes.MEM_STW: if self.width == 1: bitNumber = self.offset.bitOffset bitName = S7StatusWord.nr2name_german[bitNumber] if bitNumber in {4, 5, 8}: return bitName return "__STW " + bitName else: return "STW" elif self.operType == AwlOperatorTypes.LBL_REF: return self.immediateStr elif self.operType == AwlOperatorTypes.BLKREF_FC: return "FC %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.BLKREF_SFC: return "SFC %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.BLKREF_FB: return "FB %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.BLKREF_SFB: return "SFB %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.BLKREF_UDT: return "UDT %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.BLKREF_DB: return "DB %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.BLKREF_DI: return "DI %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.BLKREF_OB: return "OB %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.BLKREF_VAT: return "VAT %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.MULTI_FB: return "#FB<" + self.makeANYPointer(PointerConst.AREA_DI_S).toPointerString() + ">" elif self.operType == AwlOperatorTypes.MULTI_SFB: return "#SFB<" + self.makeANYPointer(PointerConst.AREA_DI_S).toPointerString() + ">" elif self.operType == AwlOperatorTypes.SYMBOLIC: return '"%s"' % self.offset.identChain.getString() elif self.operType == AwlOperatorTypes.NAMED_LOCAL: return "#" + self.offset.identChain.getString() elif self.operType == AwlOperatorTypes.NAMED_LOCAL_PTR: return "P##" + self.offset.identChain.getString() elif self.operType == AwlOperatorTypes.NAMED_DBVAR: return str(self.offset) elif self.operType == AwlOperatorTypes.INDIRECT: assert(0) # Overloaded in AwlIndirectOp elif self.operType == AwlOperatorTypes.VIRT_ACCU: return "__ACCU %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.VIRT_AR: return "__AR %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.VIRT_DBR: return "__DBR %d" % self.offset.byteOffset elif self.operType == AwlOperatorTypes.UNSPEC: return "__UNSPEC" try: return self.type2str[self.operType] except KeyError: #@nocov assert(0)