Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix hash #355

Merged
merged 9 commits into from
Feb 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 0 additions & 3 deletions magma/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,6 @@ def __repr__(cls):

return s

def __hash__(cls):
return hash(repr(cls))

def _repr_html_(cls):
return circuit_to_html(cls)

Expand Down
7 changes: 4 additions & 3 deletions magma/passes/passes.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ def _run(self, definition):
self._run( instancedefinition )

# call each definition only once
name = definition.__name__
if name not in self.definitions:
self.definitions[name] = definition
id_ = id(definition)
if id_ not in self.definitions:
self.definitions[id_] = definition
if callable(self):
self(definition)

Expand Down Expand Up @@ -82,6 +82,7 @@ def done(self):
graph.append((vert, edges))
self.tsortedgraph = tsort(graph)


class InstanceGraphPass(Pass):
def __init__(self, main):
super(InstanceGraphPass, self).__init__(main)
Expand Down
34 changes: 17 additions & 17 deletions magma/uniquification.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,28 @@ class UniquificationMode(Enum):
class UniquificationPass(DefinitionPass):
def __init__(self, main, mode):
super(UniquificationPass, self).__init__(main)
self.definitions = {}
self.mode = mode
self.seen = {}
self.original_names = {}

def __call__(self, definition):
name = definition.name
key = hash(definition)
insert = False
key = hash(repr(definition))

if name not in self.seen:
self.seen[name] = {}
insert = True
elif self.mode is UniquificationMode.UNIQUIFY:
seen = self.seen[name]
if key in seen:
new_name = seen[key].name
insert = False
else:
idx = len(seen)
new_name = name + "_unq" + str(idx)
insert = True
self.original_names[definition] = name
type(definition).rename(definition, new_name)
if key not in self.seen[name]:
if self.mode is UniquificationMode.UNIQUIFY and len(self.seen[name]) > 0:
new_name = name + "_unq" + str(len(self.seen[name]))
type(definition).rename(definition, new_name)
self.seen[name][key] = [definition]
else:
insert = True
if insert:
self.seen[name][key] = definition
if self.mode is not UniquificationMode.UNIQUIFY:
assert self.seen[name][key][0].name == definition.name
else:
type(definition).rename(definition, self.seen[name][key][0].name)
self.seen[name][key].append(definition)

def _run(self, definition):
if not isdefinition(definition):
Expand All @@ -53,6 +49,10 @@ def _run(self, definition):
if isdefinition(instancedefinition):
self._run( instancedefinition )

id_ = id(definition)
if id_ in self.definitions:
return
self.definitions[id_] = definition
self(definition)

def run(self):
Expand Down
68 changes: 68 additions & 0 deletions tests/gold/uniquification_key_error_mux.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{"top":"global.MuxWithDefaultWrapper_2_6_19_0",
"namespaces":{
"global":{
"modules":{
"Mux2x6":{
"type":["Record",[
["I0",["Array",6,"BitIn"]],
["I1",["Array",6,"BitIn"]],
["S","BitIn"],
["O",["Array",6,"Bit"]]
]],
"instances":{
"coreir_commonlib_mux2x6_inst0":{
"genref":"commonlib.muxn",
"genargs":{"N":["Int",2], "width":["Int",6]}
}
},
"connections":[
["self.I0","coreir_commonlib_mux2x6_inst0.in.data.0"],
["self.I1","coreir_commonlib_mux2x6_inst0.in.data.1"],
["self.S","coreir_commonlib_mux2x6_inst0.in.sel.0"],
["self.O","coreir_commonlib_mux2x6_inst0.out"]
]
},
"MuxWithDefaultWrapper_2_6_19_0":{
"type":["Record",[
["I",["Array",2,["Array",6,"BitIn"]]],
["S",["Array",19,"BitIn"]],
["O",["Array",6,"Bit"]]
]],
"instances":{
"MuxWrapper_2_6_inst0":{
"modref":"global.MuxWrapper_2_6"
},
"MuxWrapper_2_6_inst1":{
"modref":"global.MuxWrapper_2_6"
}
},
"connections":[
["self.I","MuxWrapper_2_6_inst0.I"],
["self.S.0","MuxWrapper_2_6_inst0.S.0"],
["self.I","MuxWrapper_2_6_inst1.I"],
["self.O","MuxWrapper_2_6_inst1.O"],
["self.S.0","MuxWrapper_2_6_inst1.S.0"]
]
},
"MuxWrapper_2_6":{
"type":["Record",[
["I",["Array",2,["Array",6,"BitIn"]]],
["S",["Array",1,"BitIn"]],
["O",["Array",6,"Bit"]]
]],
"instances":{
"Mux2x6_inst0":{
"modref":"global.Mux2x6"
}
},
"connections":[
["self.I.0","Mux2x6_inst0.I0"],
["self.I.1","Mux2x6_inst0.I1"],
["self.O","Mux2x6_inst0.O"],
["self.S.0","Mux2x6_inst0.S"]
]
}
}
}
}
}
64 changes: 62 additions & 2 deletions tests/test_uniquify.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test_uniquify_equal():
m.wire(curr, top.O)
m.EndCircuit()

assert hash(foo) == hash(bar)
assert hash(repr(foo)) == hash(repr(bar))

m.compile("build/uniquify_equal", top, output="coreir")
assert check_files_equal(__file__,
Expand All @@ -57,9 +57,69 @@ def test_uniquify_unequal():
m.wire(bar_inst.O[0], top.O)
m.EndCircuit()

assert hash(foo) != hash(bar)
assert hash(repr(foo)) != hash(repr(bar))

m.compile("build/uniquify_unequal", top, output="coreir")
assert check_files_equal(__file__,
"build/uniquify_unequal.json",
"gold/uniquify_unequal.json")


def test_key_error():
default_port_mapping = {
"I": "in",
"I0": "in0",
"I1": "in1",
"O": "out",
"S": "sel",
}

def DeclareCoreirCircuit(*args, **kwargs):
return m.DeclareCircuit(*args, **kwargs,
renamed_ports=default_port_mapping)

Mux2x6 = m.DefineCircuit("Mux2x6", "I0", m.In(m.Bits(6)), "I1", m.In(m.Bits(6)), "S", m.In(m.Bit), "O", m.Out(m.Bits(6)))
mux = DeclareCoreirCircuit(f"coreir_commonlib_mux{2}x{6}",
*["I", m.In(m.Tuple(data=m.Array(2, m.Bits(6)),
sel=m.Bits(m.bitutils.clog2(2)))),
"O", m.Out(m.Bits(6))],
coreir_name="muxn",
coreir_lib="commonlib",
coreir_genargs={"width": 6, "N": 2})()
m.wire(Mux2x6.I0, mux.I.data[0])
m.wire(Mux2x6.I1, mux.I.data[1])
m.wire(Mux2x6.S, mux.I.sel[0])
m.wire(mux.O, Mux2x6.O)
m.EndDefine()

MuxWrapper_2_6 = m.DefineCircuit("MuxWrapper_2_6", "I", m.Array(2,m.In(m.Bits(6))), "S", m.In(m.Bits(1)), "O", m.Out(m.Bits(6)))
Mux2x6_inst0 = Mux2x6()
m.wire(MuxWrapper_2_6.I[0], Mux2x6_inst0.I0)
m.wire(MuxWrapper_2_6.I[1], Mux2x6_inst0.I1)
m.wire(MuxWrapper_2_6.S[0], Mux2x6_inst0.S)
m.wire(Mux2x6_inst0.O, MuxWrapper_2_6.O)
m.EndCircuit()

MuxWrapper_2_6_copy = m.DefineCircuit("MuxWrapper_2_6", "I", m.Array(2,m.In(m.Bits(6))), "S", m.In(m.Bits(1)), "O", m.Out(m.Bits(6)))
Mux2x6_inst0 = Mux2x6()
m.wire(MuxWrapper_2_6_copy.I[0], Mux2x6_inst0.I0)
m.wire(MuxWrapper_2_6_copy.I[1], Mux2x6_inst0.I1)
m.wire(MuxWrapper_2_6_copy.S[0], Mux2x6_inst0.S)
m.wire(Mux2x6_inst0.O, MuxWrapper_2_6_copy.O)
m.EndCircuit()

MuxWithDefaultWrapper_2_6_19_0 = m.DefineCircuit("MuxWithDefaultWrapper_2_6_19_0", "I", m.Array(2,m.In(m.Bits(6))), "S", m.In(m.Bits(19)), "O", m.Out(m.Bits(6)))
MuxWrapper_2_6_inst0 = MuxWrapper_2_6()
MuxWrapper_2_6_inst1 = MuxWrapper_2_6_copy()
m.wire(MuxWithDefaultWrapper_2_6_19_0.I, MuxWrapper_2_6_inst0.I)
m.wire(MuxWithDefaultWrapper_2_6_19_0.I, MuxWrapper_2_6_inst1.I)
m.wire(MuxWithDefaultWrapper_2_6_19_0.S[0], MuxWrapper_2_6_inst0.S[0])
m.wire(MuxWithDefaultWrapper_2_6_19_0.S[0], MuxWrapper_2_6_inst1.S[0])
m.wire(MuxWrapper_2_6_inst1.O, MuxWithDefaultWrapper_2_6_19_0.O)
m.EndCircuit()

top = MuxWithDefaultWrapper_2_6_19_0
m.compile(f"build/{top.name}", top, output="coreir")
assert check_files_equal(__file__,
f"build/{top.name}.json",
"gold/uniquification_key_error_mux.json")