def assure_biased(self, vars_id): if vars_id in self.biased_cache: self.biased_cache.remove(vars_id) return vars_id biased_vars = PropVarSet(biased=self.prop_var_sets[vars_id], solver=self.solver) self.solver.add_comment("defined %d as biased %d (%s)" % (biased_vars.id, vars_id, biased_vars)) self.prop_var_sets[biased_vars.id] = biased_vars return biased_vars.id
def __init_propvarset(self, var_idx, var): gate_vars = PropVarSet(num=self.num_vars) gate_vars.ones.add(var_idx) self.formula.prop_var_sets[gate_vars.id] = gate_vars self.formula.nonlin_gate_set[gate_vars.id] = (gate_vars.id, ) self.formula.linear_gate_set[gate_vars.id] = (gate_vars.id, ) self.formula.nonlin_set_cache[(gate_vars.id, )] = gate_vars.id self.formula.linear_set_cache[(gate_vars.id, )] = gate_vars.id assert (self.circuit.cells[var].type in REGPORT_TYPES) self.formula.node_vars_stable[-1][var] = gate_vars.id self.formula.node_vars_trans[-1][var] = gate_vars.id
def make_choice(self, arg1, arg2): if arg1 == arg2: return arg1 arg_pvs = tuple(self.prop_var_sets[x] for x in (arg1, arg2)) res = PropVarSet(choice=arg_pvs, solver=self.solver) self.prop_var_sets[res.id] = res self.nonlin_gate_set[res.id] = (res.id, ) self.linear_gate_set[res.id] = (res.id, ) self.nonlin_set_cache[(res.id, )] = res.id self.linear_set_cache[(res.id, )] = res.id self.add_cover(res.id, arg1) self.add_cover(res.id, arg2) return res.id
def assure_biased(self, vars_id): if vars_id in self.biased_cache: self.biased_cache.remove(vars_id) return vars_id biased_vars = PropVarSet(biased=self.prop_var_sets[vars_id], solver=self.solver) self.solver.add_comment("defined %d as biased %d (%s)" % (biased_vars.id, vars_id, biased_vars)) self.prop_var_sets[biased_vars.id] = biased_vars self.nonlin_gate_set[biased_vars.id] = self.nonlin_gate_set[vars_id] self.linear_gate_set[biased_vars.id] = (biased_vars.id, ) self.nonlin_set_cache[(biased_vars.id, )] = biased_vars.id self.linear_set_cache[(biased_vars.id, )] = biased_vars.id self.add_cover(biased_vars.id, vars_id) return biased_vars.id
def __init_labeled_vars(self): assert(len(self.formula.node_vars_stable) == 0) assert(len(self.formula.node_vars_trans) == 0) self.formula.node_vars_stable.append({}) self.formula.node_vars_trans.append({}) for var, var_idx in zip(self.variables, range(self.num_vars)): gate_vars = PropVarSet(num=self.num_vars) gate_vars.ones.add(var_idx) self.formula.prop_var_sets[gate_vars.id] = gate_vars self.formula.nonlin_gate_set[gate_vars.id] = (gate_vars.id,) self.formula.linear_gate_set[gate_vars.id] = (gate_vars.id,) self.formula.nonlin_set_cache[(gate_vars.id,)] = gate_vars.id self.formula.linear_set_cache[(gate_vars.id,)] = gate_vars.id cell = self.circuit.cells[var] assert (cell.type in REGPORT_TYPES) dst = var if cell.type == PORT_TYPE else self.circuit.predecessors(var).__next__() self.formula.node_vars_stable[0][dst] = gate_vars.id self.formula.node_vars_trans[0][dst] = gate_vars.id
def make_simple(self, gate_type, vars_id1, vars_id2): assert (gate_type in GATE_TYPES) # simple application of (a ^ a) == 0 and (a & a) == a if vars_id1 == vars_id2: return None if (gate_type in LINEAR_TYPES) else vars_id1 l1 = self.linear_gate_set[vars_id1] l2 = self.linear_gate_set[vars_id2] n1 = self.nonlin_gate_set[vars_id1] n2 = self.nonlin_gate_set[vars_id2] if gate_type in LINEAR_TYPES: sd = tuple(sorted(set(l1).symmetric_difference(l2))) assert (len(sd) != 0) cached = self.linear_set_cache.get(sd) if cached is not None: self.solver.add_comment("found duplicate xor %s for %s" % (sd, cached)) return cached xor_args = tuple(self.prop_var_sets[x] for x in (vars_id1, vars_id2)) gate_vars = PropVarSet(xor=xor_args, solver=self.solver) self.solver.add_comment("defined %d == %d xor %d" % (gate_vars.id, vars_id1, vars_id2)) if len(gate_vars.ones) == 0 and len(gate_vars.vars) == 0: return None self.prop_var_sets[gate_vars.id] = gate_vars self.symdiff_gate_set(gate_vars.id, vars_id1, vars_id2, symdiff=sd) self.nonlin_gate_set[gate_vars.id] = (gate_vars.id, ) self.nonlin_set_cache[(gate_vars.id, )] = gate_vars.id self.biased_cache.discard(vars_id1) self.biased_cache.discard(vars_id2) else: # gate_type in NONLINEAR_TYPES un = tuple(sorted(set(n1).union(n2))) if n1 == un: self.add_cover(vars_id1, vars_id2) self.solver.add_comment("%s is super of %s" % (vars_id1, vars_id2)) return vars_id1 if n2 == un: self.add_cover(vars_id2, vars_id1) self.solver.add_comment("%s is super of %s" % (vars_id2, vars_id1)) return vars_id2 cached = self.nonlin_set_cache.get(un) if cached is not None: self.add_cover(cached, vars_id1) self.add_cover(cached, vars_id2) self.solver.add_comment("found duplicate and %s for %s" % (un, cached)) return cached biased_id1 = self.assure_biased(vars_id1) biased_id2 = self.assure_biased(vars_id2) xor_args = tuple(self.prop_var_sets[x] for x in (biased_id1, biased_id2)) gate_vars = PropVarSet(xor=xor_args, solver=self.solver) self.solver.add_comment( "defined %d == %d and %d (%d xor %d)" % (gate_vars.id, vars_id1, vars_id2, biased_id1, biased_id2)) if len(gate_vars.ones) == 0 and len(gate_vars.vars) == 0: return None self.prop_var_sets[gate_vars.id] = gate_vars self.union_gate_set(gate_vars.id, vars_id1, vars_id2, union=un) self.add_cover(gate_vars.id, vars_id1) self.add_cover(gate_vars.id, vars_id2) self.linear_gate_set[gate_vars.id] = (gate_vars.id, ) self.linear_set_cache[(gate_vars.id, )] = gate_vars.id self.biased_cache.add(gate_vars.id) self.biased_vars.add(gate_vars.id) return gate_vars.id