Skip to content

Commit

Permalink
[Sim][#50] Support saving nodes to and restoring them from images.
Browse files Browse the repository at this point in the history
  • Loading branch information
kosarev committed Jun 21, 2022
1 parent 1c7228e commit 03fe38f
Showing 1 changed file with 33 additions and 18 deletions.
51 changes: 33 additions & 18 deletions tests/z80sim/z80sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import ast
import hashlib
import os
import pathlib
import pprint
import sys
Expand Down Expand Up @@ -46,6 +47,17 @@ def __repr__(self):
return (repr(self.__e) if isinstance(self.__e, bool)
else self.__e.sexpr())

@property
def image(self):
return (self.__e if isinstance(self.__e, bool)
else self.__e.serialize())

@staticmethod
def from_image(image):
if isinstance(image, bool):
return TRUE if image else FALSE
return Bool(z3.deserialize(image))

@staticmethod
def boolify(x):
if isinstance(x, bool):
Expand Down Expand Up @@ -159,11 +171,11 @@ def reduced(self):


class Node(object):
def __init__(self, index, pull, custom_id=None):
def __init__(self, index, pull, custom_id=None, state=None):
self.custom_id = custom_id
assert pull is None or isinstance(pull, Bool)
self.index, self.pull = index, pull
self.state = None
self.state = state

# These are not sets as we want reproducible behaviour.
self.gate_of = []
Expand All @@ -176,15 +188,17 @@ def __lt__(self, other):
return self.index < other.index

@property
def fields(self):
return self.index, self.custom_id, self.pull
def image(self):
pull = None if self.pull is None else self.pull.image
state = None if self.state is None else self.state.image
return self.index, self.custom_id, pull, state

@staticmethod
def by_fields(fields):
index, custom_id, pull = fields
if pull is not None:
pull = Bool(pull)
return Node(index, pull, custom_id)
def from_image(image):
index, custom_id, pull, state = image
pull = None if pull is None else Bool.from_image(pull)
state = None if state is None else Bool.from_image(state)
return Node(index, pull, custom_id, state)

@property
def id(self):
Expand Down Expand Up @@ -340,14 +354,11 @@ def __load_nodes(self):
assert ((n.pull is None and pull is None) or
n.pull.is_equiv(pull))

def __get_nodes_cache(self):
return (n.fields for n in sorted(self.__nodes.values()))

def __restore_nodes_from_cache(self, cache):
def __restore_nodes_from_image(self, image):
self.__nodes_by_name = {}
self.__nodes = {}
for fields in cache:
n = Node.by_fields(fields)
for i in image:
n = Node.from_image(i)
if n.custom_id is not None:
self.__nodes_by_name[n.custom_id] = n
self.__nodes[n.index] = n
Expand Down Expand Up @@ -447,7 +458,7 @@ def __load_defs(self):
with open(CACHE_FILENAME) as f:
Z80Simulator.__cache = ast.literal_eval(f.read())
nodes, trans = Z80Simulator.__cache
self.__restore_nodes_from_cache(nodes)
self.__restore_nodes_from_image(nodes)
self.__restore_transistors_from_cache(trans)
except FileNotFoundError:
self.__load_nodes()
Expand All @@ -459,11 +470,15 @@ def __load_defs(self):
i: n for i, n in self.__nodes.items()
if len(n.conn_of) > 0 or len(n.gate_of) > 0}

with open(CACHE_FILENAME, 'w') as f:
Z80Simulator.__cache = (tuple(self.__get_nodes_cache()),
TEMP_FILENAME = CACHE_FILENAME + '.tmp'
nodes_image = tuple(n.image for n in sorted(self.__nodes.values()))
with open(TEMP_FILENAME, 'w') as f:
Z80Simulator.__cache = (nodes_image,
tuple(self.__get_transistors_cache()))
pprint.pp(Z80Simulator.__cache, compact=True, stream=f)

os.rename(TEMP_FILENAME, CACHE_FILENAME)

self.__gnd = self.__nodes_by_name[_GND_ID]
self.__pwr = self.__nodes_by_name[_PWR_ID]
self.__gnd_pwr = self.__gnd, self.__pwr
Expand Down

0 comments on commit 03fe38f

Please sign in to comment.