fhdl: use object creation counter (HUID) as hash. This finally makes the generated code textually the same across runs.
This commit is contained in:
parent
3971600917
commit
9d3e218863
|
@ -42,7 +42,17 @@ class BV:
|
|||
def __eq__(self, other):
|
||||
return self.width == other.width and self.signed == other.signed
|
||||
|
||||
class Value:
|
||||
|
||||
class HUID:
|
||||
__next_uid = 0
|
||||
def __init__(self):
|
||||
self.huid = HUID.__next_uid
|
||||
HUID.__next_uid += 1
|
||||
|
||||
def __hash__(self):
|
||||
return self.huid
|
||||
|
||||
class Value(HUID):
|
||||
def __invert__(self):
|
||||
return _Operator("~", [self])
|
||||
|
||||
|
@ -111,30 +121,35 @@ class Value:
|
|||
return _Assign(self, r)
|
||||
|
||||
def __hash__(self):
|
||||
return id(self)
|
||||
return super().__hash__()
|
||||
|
||||
class _Operator(Value):
|
||||
def __init__(self, op, operands):
|
||||
super().__init__()
|
||||
self.op = op
|
||||
self.operands = list(map(_cst, operands))
|
||||
|
||||
class _Slice(Value):
|
||||
def __init__(self, value, start, stop):
|
||||
super().__init__()
|
||||
self.value = value
|
||||
self.start = start
|
||||
self.stop = stop
|
||||
|
||||
class Cat(Value):
|
||||
def __init__(self, *args):
|
||||
super().__init__()
|
||||
self.l = list(map(_cst, args))
|
||||
|
||||
class Replicate(Value):
|
||||
def __init__(self, v, n):
|
||||
super().__init__()
|
||||
self.v = _cst(v)
|
||||
self.n = n
|
||||
|
||||
class Constant(Value):
|
||||
def __init__(self, n, bv=None):
|
||||
super().__init__()
|
||||
self.bv = bv or BV(bits_for(n), n < 0)
|
||||
self.n = n
|
||||
|
||||
|
@ -148,7 +163,7 @@ class Constant(Value):
|
|||
return self.bv == other.bv and self.n == other.n
|
||||
|
||||
def __hash__(self):
|
||||
return id(self)
|
||||
return super().__hash__()
|
||||
|
||||
|
||||
def binc(x, signed=False):
|
||||
|
@ -161,16 +176,14 @@ def _cst(x):
|
|||
return x
|
||||
|
||||
class Signal(Value):
|
||||
_counter = 0
|
||||
def __init__(self, bv=BV(), name=None, variable=False, reset=0, name_override=None):
|
||||
super().__init__()
|
||||
assert(isinstance(bv, BV))
|
||||
self.bv = bv
|
||||
self.variable = variable
|
||||
self.reset = Constant(reset, bv)
|
||||
self.name_override = name_override
|
||||
self.backtrace = tracer.trace_back(name)
|
||||
self.order = Signal._counter
|
||||
Signal._counter += 1
|
||||
|
||||
def __len__(self):
|
||||
return self.bv.width
|
||||
|
@ -247,8 +260,9 @@ class Array(list):
|
|||
|
||||
# extras
|
||||
|
||||
class Instance:
|
||||
class Instance(HUID):
|
||||
def __init__(self, of, *items, name=""):
|
||||
super().__init__()
|
||||
self.of = of
|
||||
if name:
|
||||
self.name_override = name
|
||||
|
@ -291,9 +305,6 @@ class Instance:
|
|||
for item in self.items:
|
||||
if isinstance(item, Instance._IO) and item.name == name:
|
||||
return item.expr
|
||||
|
||||
def __hash__(self):
|
||||
return id(self)
|
||||
|
||||
(READ_FIRST, WRITE_FIRST, NO_CHANGE) = range(3)
|
||||
|
||||
|
@ -311,8 +322,9 @@ class MemoryPort:
|
|||
self.mode = mode
|
||||
self.clock_domain = clock_domain
|
||||
|
||||
class Memory:
|
||||
class Memory(HUID):
|
||||
def __init__(self, width, depth, *ports, init=None):
|
||||
super().__init__()
|
||||
self.width = width
|
||||
self.depth = depth
|
||||
self.ports = ports
|
||||
|
|
|
@ -134,7 +134,7 @@ def is_variable(node):
|
|||
|
||||
def insert_reset(rst, sl):
|
||||
targets = list_targets(sl)
|
||||
resetcode = [t.eq(t.reset) for t in sorted(targets, key=lambda x: x.order)]
|
||||
resetcode = [t.eq(t.reset) for t in sorted(targets, key=lambda x: x.huid)]
|
||||
return If(rst, *resetcode).Else(*sl)
|
||||
|
||||
def value_bv(v):
|
||||
|
|
|
@ -114,7 +114,7 @@ def _printheader(f, ios, name, ns):
|
|||
wires = _list_comb_wires(f) | inst_mem_outs
|
||||
r = "module " + name + "(\n"
|
||||
firstp = True
|
||||
for sig in sorted(ios, key=lambda x: x.order):
|
||||
for sig in sorted(ios, key=lambda x: x.huid):
|
||||
if not firstp:
|
||||
r += ",\n"
|
||||
firstp = False
|
||||
|
@ -128,7 +128,7 @@ def _printheader(f, ios, name, ns):
|
|||
else:
|
||||
r += "\tinput " + _printsig(ns, sig)
|
||||
r += "\n);\n\n"
|
||||
for sig in sorted(sigs - ios, key=lambda x: x.order):
|
||||
for sig in sorted(sigs - ios, key=lambda x: x.huid):
|
||||
if sig in wires:
|
||||
r += "wire " + _printsig(ns, sig) + ";\n"
|
||||
else:
|
||||
|
@ -244,7 +244,7 @@ def _printinit(f, ios, ns):
|
|||
- list_mem_ios(f, False, True)
|
||||
if signals:
|
||||
r += "initial begin\n"
|
||||
for s in sorted(signals, key=lambda x: x.order):
|
||||
for s in sorted(signals, key=lambda x: x.huid):
|
||||
r += "\t" + ns.get_name(s) + " <= " + _printexpr(ns, s.reset) + ";\n"
|
||||
r += "end\n\n"
|
||||
return r
|
||||
|
|
|
@ -12,8 +12,9 @@ from migen.flow.isd import DFGReporter
|
|||
# instantiated with the parameters from the dictionary.
|
||||
# This form is needed to enable actor duplication or sharing during elaboration.
|
||||
|
||||
class ActorNode:
|
||||
class ActorNode(HUID):
|
||||
def __init__(self, actor_class, parameters=dict()):
|
||||
super().__init__()
|
||||
if isinstance(actor_class, type):
|
||||
self.actor_class = actor_class
|
||||
self.parameters = parameters
|
||||
|
|
Loading…
Reference in New Issue