Beispiel #1
0
    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
Beispiel #2
0
	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
Beispiel #3
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
Beispiel #4
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
Beispiel #5
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
Beispiel #6
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
Beispiel #7
0
	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)
Beispiel #9
0
	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
Beispiel #10
0
	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)
Beispiel #11
0
	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)
Beispiel #12
0
    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)
Beispiel #13
0
 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
Beispiel #14
0
	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)
Beispiel #15
0
	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)
Beispiel #16
0
    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)
Beispiel #17
0
	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))
Beispiel #18
0
	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
Beispiel #19
0
	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
Beispiel #20
0
    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
Beispiel #21
0
	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
Beispiel #22
0
    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
Beispiel #23
0
    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
Beispiel #24
0
    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))
Beispiel #25
0
	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)