import enum
from cached_property import cached_property
import mmap
+import struct
from pickle import PicklingError
import ctypes
from nmutil import plain_data
raise NotImplementedError
yield 0
+ def make_sim_state_dict(self):
+ """ returns a dict equivalent to:
+ retval = {}
+ for k in list(self.word_idxs()):
+ data = self.ld(k*8, 8, False)
+ retval[k*8] = data
+ """
+ retval = {}
+ for k in list(self.word_idxs()):
+ data = self.ld(k*8, 8, False, reason=_ReadReason.Dump)
+ retval[k*8] = data
+ return retval
+
def _get_shifter_mask(self, wid, remainder, do_log=True):
shifter = ((self.bytes_per_word - wid) - remainder) * \
8 # bits per byte
if bytes_ != zeros:
yield word_idx
+ def make_sim_state_dict(self):
+ """ returns a dict equivalent to:
+ retval = {}
+ for k in list(self.word_idxs()):
+ data = self.ld(k*8, 8, False)
+ retval[k*8] = data
+ """
+ if self.bytes_per_word != 8:
+ return super().make_sim_state_dict()
+ retval = {}
+ page_struct = struct.Struct("<%dQ" % (MMAP_PAGE_SIZE // 8,))
+ assert page_struct.size == MMAP_PAGE_SIZE, "got wrong format"
+ for page_idx in self.modified_pages:
+ start = self.mmap_page_idx_to_addr(page_idx)
+ block, block_addr = self.__access_addr_range(
+ start, MMAP_PAGE_SIZE, MMapPageFlags.R)
+ # written this way to avoid unnecessary allocations
+ words = page_struct.unpack_from(block, block_addr)
+ for i, v in zip(range(start, start + MMAP_PAGE_SIZE, 8), words):
+ if v != 0:
+ retval[i] = v
+ return retval
+
@plain_data.plain_data()
class LoadedELF:
0x7FFFFEDCBA90: 00 00 00 00 00 00 00 00 89 67 45 23 01 EF CD AB |.........gE#....|
""")
+ def test_make_sim_state_dict(self):
+ m = self.MemCls(row_bytes=8, initial_mem=(0x58, [
+ 0x5DE6DA2A1137745E, 0x6054D17B4C773D2D,
+ 0x5B66920D9540B825, 0x7753D053D9854A8F,
+ 0x9F2A58E2B5B79829, 0x974AC142D081CE83,
+ 0xAA963F95FC566F57, 0xE63A95A3F654A57E,
+ 0x103709510CBE0EEF, 0,
+ 0x5053575776376ACD, 0xCFDFF67B7C5096C2,
+ 0x9F8FC1B06E7868A0, 0x6E7B1D27CCBAF8E7,
+ 0xEB91B92FAF546BA1, 0x21FB683F34641876,
+ ]))
+
+ a = m.make_sim_state_dict()
+ b = m.make_sim_state_dict()
+ self.assertIsNot(a, b) # must always return a new dict
+ self.assertEqual(a, b) # should return the same result
+ expected = {
+ 0x58: 0x5DE6DA2A1137745E, 0x60: 0x6054D17B4C773D2D,
+ 0x68: 0x5B66920D9540B825, 0x70: 0x7753D053D9854A8F,
+ 0x78: 0x9F2A58E2B5B79829, 0x80: 0x974AC142D081CE83,
+ 0x88: 0xAA963F95FC566F57, 0x90: 0xE63A95A3F654A57E,
+ 0x98: 0x103709510CBE0EEF, 0xA0: 0,
+ 0xA8: 0x5053575776376ACD, 0xB0: 0xCFDFF67B7C5096C2,
+ 0xB8: 0x9F8FC1B06E7868A0, 0xC0: 0x6E7B1D27CCBAF8E7,
+ 0xC8: 0xEB91B92FAF546BA1, 0xD0: 0x21FB683F34641876,
+ }
+ if isinstance(m, MemMMap):
+ del expected[0xA0] # MemMMap doesn't list zero entries
+ self.assertEqual(a, expected)
+
class TestMemMMap(TestMemCommon):
MemCls = MemMMap
mem = self.sim.mem
if isinstance(mem, RADIX):
mem = mem.mem
- keys = list(mem.word_idxs())
- self.mem = {}
- # from each address in the underlying mem-simulated dictionary
- # issue a 64-bit LD (with no byte-swapping)
- for k in keys:
- data = mem.ld(k*8, 8, False)
- self.mem[k*8] = data
+ self.mem = mem.make_sim_state_dict()
class ExpectedState(State):