def and_gate(inputs, output=None): output = f'#and_output#{hash(tuple(inputs))}' if output is None else output return aig.AIG( inputs=frozenset(inputs), node_map=frozenset(((output, _map_tree(inputs, f=_and)), )), )
def identity(inputs, outputs=None): if outputs is None: outputs = inputs return aig.AIG( inputs=frozenset(inputs), node_map=frozenset(zip(outputs, map(aig.Input, inputs))), )
def parity_gate(inputs, output=None): # TODO: output = f'#parity#{hash(tuple(inputs))}' if output is None else output return aig.AIG( inputs=frozenset(inputs), node_map=frozenset(((output, _map_tree(inputs, f=_xor)), )), )
def bit_flipper(inputs, outputs=None): if outputs is None: outputs = inputs else: assert len(outputs) == len(inputs) return aig.AIG( inputs=frozenset(inputs), node_map=frozenset(zip(outputs, map(_inverted_input, inputs))), )
def tee(outputs=None): if not outputs: return empty() def tee_output(name, renames): return frozenset((r, aig.Input(name)) for r in renames) return aig.AIG( inputs=frozenset(outputs), node_map=frozenset.union(*starmap(tee_output, outputs.items())), )
def _to_aig(self): gate_order, latch_order = self.eval_order_and_gate_lookup lookup = fn.merge( {0: aig.ConstFalse()}, {_to_idx(l): aig.Input(n) for n, l in self.inputs.items()}, { _to_idx(l): aig.LatchIn(n) for n, (l, _, init) in self.latches.items() }, ) latches = set() and_dependencies = {i: (l, r) for i, l, r in self.gates} for gate in fn.cat(gate_order): if _to_idx(gate) in lookup: continue inputs = and_dependencies[gate] sources = [_polarity(i)(lookup[_to_idx(i)]) for i in inputs] lookup[_to_idx(gate)] = aig.AndGate(*sources) latch_dependencies = { i: (n, dep) for n, (i, dep, _) in self.latches.items() } for gate in fn.cat(latch_order): assert _to_idx(gate) in lookup if not isinstance(lookup[_to_idx(gate)], aig.LatchIn): continue name, dep = latch_dependencies[gate] source = _polarity(dep)(lookup[_to_idx(dep)]) latches.add((name, source)) def get_output(v): idx = _to_idx(v) return _polarity(v)(lookup[idx]) top_level = ((k, get_output(v)) for k, v in self.outputs.items()) return aig.AIG(inputs=frozenset(self.inputs), node_map=frozenset(top_level), latch_map=frozenset(latches), latch2init=frozenset( (n, bool(init)) for n, (_, _, init) in self.latches.items()), comments=self.comments)
def delay(inputs, initials, latches=None, outputs=None): if outputs is None: outputs = inputs if latches is None: latches = inputs assert len(inputs) == len(initials) == len(outputs) == len(latches) _inputs = map(aig.Input, inputs) _latches = map(aig.LatchIn, latches) return aig.AIG( inputs=frozenset(inputs), latch_map=zip(latches, _inputs), latch2init=zip(latches, initials), node_map=zip(outputs, _latches), )
def empty(): return aig.AIG()
def sink(inputs): return aig.AIG(inputs=frozenset(inputs), )
def source(outputs): return aig.AIG(node_map=frozenset( (k, _const(v)) for k, v in outputs.items()), )