aboutsummaryrefslogtreecommitdiffstats
path: root/awlsim/core/offset.py
blob: 4acf8e6e9c4afafcb184d9ca74d54a2f3681f1ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# -*- coding: utf-8 -*-
#
# AWL data offset
#
# Copyright 2012-2017 Michael Buesch <m@bues.ch>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

from __future__ import division, absolute_import, print_function, unicode_literals
#from awlsim.common.cython_support cimport * #@cy
from awlsim.common.compat import *

from awlsim.common.datatypehelpers import * #+cimport
from awlsim.common.exceptions import *

from awlsim.core.util import *


__all__ = [ "AwlOffset",
	    "make_AwlOffset",
	    "make_AwlOffset_fromPointerValue",
	    "make_AwlOffset_fromLongBitOffset",
]


class AwlOffset(object): #+cdef
	"""Memory area offset
	"""

	# A DB-number for fully qualified access, or None.
	dbNumber = -1 #@nocy

	# A symbolic DB-name for fully qualified access, or None.
	dbName = None #@nocy

	# An AwlDataIdentChain, or None.
	# Used for fully qualified (DBx.VAR) or named local (#VAR)
	# global symbolic ("VAR") accesses.
	# For global symbols the chain only has one element.
	identChain = None #@nocy

	# A (S)FB-number for multi-instance calls, or None.
	fbNumber = None #@nocy

	# Additional sub-offset that is added to this offset, or None.
	# This is used for arrays and structs.
	subOffset = None #@nocy

	def __eq__(self, other): #@nocy
#@cy	cpdef __eq(self, object other):
		"""Equality operator.
		This does only compare byte and bit offset and
		does _not_ check dynAttrs.
		"""
		return (self is other) or (\
			isinstance(other, AwlOffset) and\
			self.byteOffset == other.byteOffset and\
			self.bitOffset == other.bitOffset\
		)

#@cy	def __richcmp__(self, object other, int op):
#@cy		if op == 2: # __eq__
#@cy			return self.__eq(other)
#@cy		elif op == 3: # __ne__
#@cy			return not self.__eq(other)
#@cy		return False

	def __ne__(self, other):		#@nocy
		return not self.__eq__(other)	#@nocy

	def dup(self): #@nocy
#@cy	cpdef AwlOffset dup(self):
#@cy		cdef AwlOffset offset

		offset = make_AwlOffset(self.byteOffset,
					self.bitOffset)
		offset.dbNumber = self.dbNumber
		return offset

	def toPointerValue(self): #@nocy
#@cy	cpdef uint32_t toPointerValue(self):
		return ((self.byteOffset << 3) & 0x0007FFF8) |\
		       (self.bitOffset & 0x7)

	def toLongBitOffset(self):				#@nocy
#@cy	cpdef uint64_t toLongBitOffset(self):
#@cy		return <int64_t>self.byteOffset * <int64_t>8 + <int64_t>self.bitOffset
		return self.byteOffset * 8 + self.bitOffset	#@nocy

	def __add__(self, other): #@nocy
#@cy	def __add__(self, AwlOffset other):
#@cy		cdef int64_t bitOffset
#@cy		bitOffset = ((<int64_t>self.byteOffset + <int64_t>other.byteOffset) * <int64_t>8 +
#@cy			     <int64_t>self.bitOffset + <int64_t>other.bitOffset)
		bitOffset = ((self.byteOffset + other.byteOffset) * 8 +	#@nocy
			     self.bitOffset + other.bitOffset)		#@nocy
		return make_AwlOffset(bitOffset // 8, bitOffset % 8)

	def __iadd__(self, other): #@nocy
#@cy	def __iadd__(self, AwlOffset other):
#@cy		cdef int64_t bitOffset
#@cy		bitOffset = ((<int64_t>self.byteOffset + <int64_t>other.byteOffset) * <int64_t>8 +
#@cy			     <int64_t>self.bitOffset + <int64_t>other.bitOffset)
		bitOffset = ((self.byteOffset + other.byteOffset) * 8 +	#@nocy
			     self.bitOffset + other.bitOffset)		#@nocy
		self.byteOffset = bitOffset // 8
		self.bitOffset = bitOffset % 8
		return self

	# Round the offset to a multiple of 'byteBase' bytes.
	# Returns an AwlOffset.
	def roundUp(self, byteBase):
#@cy		cdef int64_t byteOffset

		byteOffset = self.byteOffset
		if self.bitOffset:
			byteOffset += 1
		byteOffset = roundUp(byteOffset, byteBase)
		return make_AwlOffset(byteOffset, 0)

	def __repr__(self):
		prefix = ""
		if self.dbNumber >= 0:
			prefix = "DB%d" % self.dbNumber
		if self.dbName is not None:
			prefix = '"%s"' % self.dbName
		if self.identChain is not None:
			if prefix:
				return prefix + "." + self.identChain.getString()
			return "#" + self.identChain.getString()
		else:
			if prefix:
				prefix = prefix + ".DBX "
			return "%s%d.%d" % (prefix,
					    self.byteOffset,
					    self.bitOffset)

#
# make_AwlOffset() - Construct an AwlOffset instance.
# For Cython performance reasons we don't use __init__ with arguments.
#
def make_AwlOffset(byteOffset, bitOffset, AwlOffset=AwlOffset):		#@nocy
#cdef AwlOffset make_AwlOffset(int64_t byteOffset, int32_t bitOffset):	#@cy
#@cy	cdef AwlOffset offset

	offset = AwlOffset()
#@cy	offset.dbNumber = -1
#@cy	offset.dbName = None
#@cy	offset.identChain = None
#@cy	offset.fbNumber = None
#@cy	offset.subOffset = None
	offset.byteOffset, offset.bitOffset = byteOffset, bitOffset

	return offset

#
# make_AwlOffset_fromPointerValue() - Construct an AwlOffset from a S7 pointer value.
#
def make_AwlOffset_fromPointerValue(value, make_AwlOffset=make_AwlOffset): #@nocy
#cdef AwlOffset make_AwlOffset_fromPointerValue(uint32_t value):	#@cy
	return make_AwlOffset((value & 0x0007FFF8) >> 3,
			      (value & 0x7))

#
# make_AwlOffset_fromLongBitOffset() - Construct an AwlOffset from a bit offset.
#
def make_AwlOffset_fromLongBitOffset(bitOffset, make_AwlOffset=make_AwlOffset): #@nocy
#cdef AwlOffset make_AwlOffset_fromLongBitOffset(int64_t bitOffset):	#@cy
	return make_AwlOffset(bitOffset // 8, bitOffset % 8)
bues.ch cgit interface