Design Pattern Examples
Overview of object-oriented design patterns
adapter_frontendclass.py
Go to the documentation of this file.
5
6from ctypes import sizeof, c_uint32
7from io import StringIO
8from enum import Enum
9from math import trunc
10
11from .adapter_backendfunctions import *
12
13
16 pass
17
18
19
22 pass
23
24
25
27class MemoryBlock(Enum):
28
29 MEMORY_BLOCK_0 = 0,
30
31 MEMORY_BLOCK_1 = 1,
32
33 MEMORY_BLOCK_2 = 2
34
35
36
44
45
50 def __init__(self, blockNumber: MemoryBlock):
51 self._initialized = False
52 self._blockNumber = blockNumber
55
56
66
67
69 def __enter__(self):
70 block_name = self._GetBlockNameForBlockNumber(self._blockNumber)
71 errorCode = ddr_openmemoryblock(block_name, self._dataHandle)
72 if errorCode == DDR_ErrorCode.DDR_ErrorCode_Success:
73 value = ValueHandle()
74 errorCode = ddr_getmemorysize(self._dataHandle, value)
75 if errorCode == DDR_ErrorCode.DDR_ErrorCode_Success:
76 self._memoryBlockByteSize = value.value * sizeof(c_uint32)
77 self._initialized = True
78 else:
79 msg = self._ConstructErrorMessage(errorCode, "Getting size of memory block")
81 else:
82 msg = self._ConstructErrorMessage(errorCode, "Initializing data reader/writer")
84 return self
85
86
87
88 def __exit__(self, *args):
89 if self._initialized:
91 self._initialized = False
92
93
94
99 @property
101 if not self._initialized:
102 msg = self._ConstructErrorMessage(DDR_ErrorCode.DDR_ErrorCode_Block_Not_Opened,
103 "Memory block not opened so cannot retrieve memory block size")
105 return self._memoryBlockByteSize
106
107
108
112 def _GetBlockNameForBlockNumber(self, block_number: MemoryBlock):
113 block_name = "unknown"
114
115 if block_number == MemoryBlock.MEMORY_BLOCK_0:
116 block_name = BLOCK_NAME_0
117 elif block_number == MemoryBlock.MEMORY_BLOCK_1:
118 block_name = BLOCK_NAME_1
119 elif block_number == MemoryBlock.MEMORY_BLOCK_2:
120 block_name = BLOCK_NAME_2
121 return block_name
122
123
124
132 def _GetErrorMessage(self, errorCode: DDR_ErrorCode) -> str:
133 message = "";
134
135 match errorCode:
136 case DDR_ErrorCode.DDR_ErrorCode_Success:
137 message = "Operation succeeded";
138
139 case DDR_ErrorCode.DDR_ErrorCode_Block_Already_Opened:
140 message = "Memory block is already open and cannot be opened again";
141
142 case DDR_ErrorCode.DDR_ErrorCode_Block_Not_Opened:
143 message = "Memory block is closed and cannot be accessed";
144
145 case DDR_ErrorCode.DDR_ErrorCode_Invalid_Block_Name:
146 message = "The given name is not a recognized memory block name";
147
148 case DDR_ErrorCode.DDR_ErrorCode_Invalid_Handle:
149 message = "The handle argument does not correspond to a valid open memory block";
150
151 case DDR_ErrorCode.DDR_ErrorCode_Invalid_Offset:
152 message = "The given offset is out of bounds";
153
154 case DDR_ErrorCode.DDR_ErrorCode_Null_Argument:
155 message = "The block name pointer or return handle pointer argument is NULL";
156
157 case _ :
158 message = f"Unrecognized error code: {errorCode}"
159
160 return message
161
162
175 def _ConstructErrorMessage(self, errorCode: int, operation : str) -> str:
176 msg = self._GetErrorMessage(errorCode)
177 return "{0}: {1}".format(operation, msg)
178
179
180
192 def Read(self, byteOffset: int, maxBytes : int) -> bytearray:
193 if not self._initialized:
194 raise DataReaderWriterInitException("Data reader/writer is not initialized. Unable to read.");
195
196 return_data = bytearray()
197 if maxBytes > 0:
198 chunkOffset = byteOffset // sizeof(c_uint32)
199 value = ValueHandle()
200 bufferIndex = 0
201 errorCode = ddr_getdatachunk(self._dataHandle, chunkOffset, value)
202 if errorCode == DDR_ErrorCode.DDR_ErrorCode_Success:
203 byteOffsetInChunk = byteOffset % sizeof(c_uint32)
204 while bufferIndex < maxBytes:
205 return_data.append(value.value & 0xff)
206 bufferIndex += 1
207 value.value >>= 8
208 byteOffsetInChunk += 1
209 if byteOffsetInChunk == sizeof(c_uint32):
210 chunkOffset += 1
211 if chunkOffset >= DDR_MAX_OFFSET:
212 break
213 byteOffsetInChunk = 0
214 errorCode = ddr_getdatachunk(self._dataHandle, chunkOffset, value)
215 if errorCode != DDR_ErrorCode.DDR_ErrorCode_Success:
216 msg = self._ConstructErrorMessage(errorCode, "Reading memory")
218 else:
219 msg = self._ConstructErrorMessage(errorCode, "Reading memory")
221
222 return return_data
223
224
225
236 def Write(self, byteOffset: int, data : bytearray, maxBytes: int) -> None:
237 if not self._initialized:
238 raise DataReaderWriterInitException("Data reader/writer is not initialized. Unable to write.");
239 if maxBytes > 0:
240 errorCode = DDR_ErrorCode.DDR_ErrorCode_Success
241 chunkOffset = byteOffset // sizeof(c_uint32)
242 value = ValueHandle()
243 byteOffsetInChunk = int(byteOffset % sizeof(c_uint32))
244 bufferIndex = 0
245 byteMask = 0xff << (byteOffsetInChunk * 8)
246 if byteOffsetInChunk != 0:
247 errorCode = ddr_getdatachunk(self._dataHandle, chunkOffset, value)
248 if errorCode == DDR_ErrorCode.DDR_ErrorCode_Success:
249 while bufferIndex < maxBytes:
250 value.value = value.value & (byteMask ^ 0xffffffff)
251 value.value = value.value | (data[bufferIndex] << (byteOffsetInChunk * 8))
252 bufferIndex += 1
253 byteMask <<= 8
254 byteOffsetInChunk += 1
255 if byteOffsetInChunk == sizeof(c_uint32):
256 errorCode = ddr_setdatachunk(self._dataHandle, chunkOffset, value.value)
257 if errorCode == DDR_ErrorCode.DDR_ErrorCode_Success:
258 byteMask = 0xff
259 byteOffsetInChunk = 0
260 chunkOffset += 1
261 if chunkOffset >= DDR_MAX_OFFSET:
262 break
263 errorCode = ddr_getdatachunk(self._dataHandle, chunkOffset, value)
264 if errorCode != DDR_ErrorCode.DDR_ErrorCode_Success:
265 msg = self._ConstructErrorMessage(errorCode, "Reading memory")
267 else:
268 msg = self._ConstructErrorMessage(errorCode, "Writing memory")
270 if errorCode == DDR_ErrorCode.DDR_ErrorCode_Success:
271 if byteOffsetInChunk != 0:
272 errorCode = ddr_setdatachunk(self._dataHandle, chunkOffset, value.value)
273
274 if errorCode != DDR_ErrorCode.DDR_ErrorCode_Success:
275 msg = self._ConstructErrorMessage(errorCode, "Writing memory")
277 else:
278 msg = self._ConstructErrorMessage(errorCode, "Reading memory in preparation to writing memory")
280
281
282
295 def BufferToString(self, data: bytearray, maxBytes : int, indent: int) -> str:
296 output = StringIO()
297 indent_spaces = ' ' * indent
298
299 if maxBytes != 0:
300 byteCount = maxBytes
301 if byteCount > len(data):
302 byteCount = len(data)
303 bytesPerRow = 32
304 for row in range(0, maxBytes, bytesPerRow):
305 output.write("{}{:04x} --".format(indent_spaces, row))
306 for col in range(0, bytesPerRow):
307 if (col + row) >= maxBytes:
308 break
309 if col > 0:
310 output.write(" ")
311 dataIndex = row + col
312 output.write("{:02x}".format(data[dataIndex]))
313 output.write("\n")
314
315 return output.getvalue()
316
Represents a value that can be passed into or out of a function.
Represents an error that occurred when reading or writing data in the Data reader/writer.
_memoryBlockByteSize
Holds the number of bytes in the opened memory block.
str _GetErrorMessage(self, DDR_ErrorCode errorCode)
Convert the given error code to a string message.
bytearray Read(self, int byteOffset, int maxBytes)
Read a specified number of bytes.
str BufferToString(self, bytearray data, int maxBytes, int indent)
Convert the specified data up to the specified number of bytes into a string by performing a "hex dum...
def __enter__(self)
Entry function used in the with statement to initialize an instance of the reader/writer.
str _ConstructErrorMessage(self, int errorCode, str operation)
Creates a formatted error message from the given operation, using the given error code returned from ...
None Write(self, int byteOffset, bytearray data, int maxBytes)
Write a specified number of bytes.
def MemoryBlockByteSize(self)
Retrieve the size of the memory block in bytes.
def _GetBlockNameForBlockNumber(self, MemoryBlock block_number)
Given a value from the MemoryBlock enumeration that specifies the number of the block,...
_initialized
True if this instance has been initialized to use the specified memory block (by a call to enter())
def __exit__(self, *args)
Exit function automatically called when used in the with statement.
_dataHandle
Contains the handle to the memory block after enter() has returned.
Represents an error that occurred during initialization or shut down of the Data reader/writer.
DDR_ErrorCode ddr_getdatachunk(Handle dataHandle, int chunkOffset, ValueHandle value)
Read a single 32-bit value at the given offset in the memory block indicated by the specified handle.
DDR_ErrorCode ddr_closememoryblock(Handle dataHandle)
Close access to a memory block previously opened by ddr_openmemoryblock(), thus releasing it for othe...
DDR_ErrorCode ddr_getmemorysize(Handle dataHandle, ValueHandle memorySizeInChunks)
Retrieve the number of chunks in the memory block indicated by the handle to the successfully opened ...
DDR_ErrorCode ddr_setdatachunk(Handle dataHandle, int chunkOffset, int value)
Writes a single 32-bit value to the given offset in the memory block indicated by the specified handl...
DDR_ErrorCode ddr_openmemoryblock(blockName, Handle dataHandle)
Open access to a memory block for exclusive use, given the name of the memory block.