summaryrefslogtreecommitdiffstats
path: root/awlstruct.py
blob: 9c98d4452ba561bb1541a9563f7053177a28a203 (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
# -*- coding: utf-8 -*-
#
# AWL simulator - data structs
# Copyright 2013 Michael Buesch <m@bues.ch>
#
# Licensed under the terms of the GNU General Public License version 2.
#

from util import *
from awldatatypes import *


class AwlStructField(object):
	"Data structure field"

	def __init__(self, name, offset, size, initialValue=0):
		self.name = name
		self.offset = offset
		self.size = size # Size, in bits
		self.initialValue = initialValue

	# Return size, in bytes
	@property
	def byteSize(self):
		return intDivRoundUp(self.size, 8)

class AwlStruct(object):
	"Data structure"

	def __init__(self):
		self.fields = []
		self.name2field = {}

	# Return size, in bytes.
	def getSize(self):
		if not self.fields:
			return 0
		lastField = self.fields[-1]
		return lastField.byteOffset + lastField.byteSize

	def addField(self, name, size):
		if not size:
			return
		offset = self.getSize()
		field = AwlStructField(name, offset, size)
		self.fields.append(field)
		if name:
			self.name2field[name] = field

	def addFieldAligned(self, name, size, alignment):
		padding = alignment - self.getSize() % alignment
		if padding == alignment:
			padding = 0
		self.addField(None, padding)
		self.addField(name, size)

	def getField(self, name):
		try:
			return self.name2field[name]
		except KeyError:
			raise AwlSimError("Data structure field '%s' not found" % name)

class AwlStructInstanceByte(GenericByte):
	"Data structure byte"

	def __init__(self, value=0):
		GenericByte.__init__(self, value)

class AwlStructInstance(object):
	"Data structure instance"

	def __init__(self, struct):
		self.struct = struct
		self.__allocate()

	def __allocate(self):
		self.dataBytes = []
		for field in self.struct.fields:
			bsize = field.byteSize
			value = field.initialValue
			for i in range(field.byteSize):
				b = (value >> ((bsize - i - 1) * 8)) & 0xFF
				self.dataBytes.append(AwlStructInstanceByte(b))

	def getData(self, offset, size):
		if size % 8 == 0:
			nrBytes, value = size // 8, 0
			off = offset.byteOffset
			assert(offset.bitOffset == 0)
			while nrBytes:
				value = (value << 8) | self.dataBytes[off].get()
				nrBytes -= 1
				off += 1
			return value
		if size == 1:
			return self.dataBytes[offset.byteOffset].getBit(offset.bitOffset)
		raise AwlSimError("Invalid struct fetch size of %d" % size)

	def setData(self, offset, size, value):
		if size % 8 == 0:
			nrBytes = size // 8
			off = offset.byteOffset + nrBytes - 1
			assert(offset.bitOffset == 0)
			while nrBytes:
				self.dataBytes[off].set(value)
				value >>= 8
				nrBytes -= 1
				off -= 1
			return
		if size == 1:
			self.dataBytes[offset.byteOffset].setBitValue(
				offset.bitOffset, value)
			return
		raise AwlSimError("Invalid struct write size of %d" % size)

	def getFieldData(self, name):
		field = self.struct.getField(name)
		return self.getData(field.offset, field.size)

	def setFieldData(self, name, value):
		field = self.struct.getField(name)
		self.setData(field.offset, field.size, value)
bues.ch cgit interface