summaryrefslogtreecommitdiffstats
path: root/awlsim/core/offset.py
blob: 8cbcc85fdfc2e6353d7d5548016a855f02141938 (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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# -*- coding: utf-8 -*-
#
# AWL data offset
#
# Copyright 2012-2018 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.common.util import *

#cimport cython #@cy


__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 -1.
	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 -1.
	fbNumber = -1 #@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__(AwlOffset self, AwlOffset other):
		return self.add(other)

	def add(self, other): #@nocy
#@cy	cdef AwlOffset add(self, AwlOffset other):
		return self.addInt(other.byteOffset, other.bitOffset)

	def addInt(self, byteOffset, bitOffset): #@nocy
#@cy	@cython.cdivision(True)
#@cy	cdef AwlOffset addInt(self, int64_t byteOffset, int32_t bitOffset):
#@cy		cdef int64_t sumOffset

		sumOffset = ((self.byteOffset + byteOffset) * 8 +	#@nocy
			     self.bitOffset + bitOffset)		#@nocy
#@cy		sumOffset = ((<int64_t>self.byteOffset + <int64_t>byteOffset) * <int64_t>8 +
#@cy			     <int64_t>self.bitOffset + <int64_t>bitOffset)
		return make_AwlOffset(sumOffset // 8, sumOffset % 8)

	def __iadd__(self, other): #@nocy
#@cy	def __iadd__(self, AwlOffset other):
		self.iadd(other)
		return self

	def iadd(self, other): #@nocy
#@cy	cdef void iadd(self, AwlOffset other):
		self.iaddInt(other.byteOffset, other.bitOffset)

	def iaddInt(self, byteOffset, bitOffset): #@nocy
#@cy	@cython.cdivision(True)
#@cy	cdef void iaddInt(self, int64_t byteOffset, int32_t bitOffset):
#@cy		cdef int64_t sumOffset

		sumOffset = ((self.byteOffset + byteOffset) * 8 +	#@nocy
			     self.bitOffset + bitOffset)		#@nocy
#@cy		sumOffset = ((<int64_t>self.byteOffset + <int64_t>byteOffset) * <int64_t>8 +
#@cy			     <int64_t>self.bitOffset + <int64_t>bitOffset)
		self.byteOffset = sumOffset // 8
		self.bitOffset = sumOffset % 8

	# 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 = -1
#@cy	offset.subOffset = None
	offset.byteOffset = byteOffset
	offset.bitOffset = bitOffset

	return offset

#
# make_AwlOffset_fromPointerValue() - Construct an AwlOffset from a S7 pointer value.
# The Cython variant of this function is defined in .pxd.in
#
def make_AwlOffset_fromPointerValue(value, make_AwlOffset=make_AwlOffset):	#@nocy
	return make_AwlOffset((value & 0x0007FFF8) >> 3,			#@nocy
			      (value & 0x7))					#@nocy

#
# make_AwlOffset_fromLongBitOffset() - Construct an AwlOffset from a bit offset.
# The Cython variant of this function is defined in .pxd.in
#
def make_AwlOffset_fromLongBitOffset(bitOffset, make_AwlOffset=make_AwlOffset): #@nocy
	return make_AwlOffset(bitOffset // 8, bitOffset % 8)			#@nocy
bues.ch cgit interface