BDD Synth::get_bdd_for_sign_lit(uint lit) { /* lit is an AIGER variable index with a 'sign' */ if (bdd_by_aiger_unlit.find(STRIP_LIT(lit)) != bdd_by_aiger_unlit.end()) { BDD res = bdd_by_aiger_unlit[STRIP_LIT(lit)]; if (IS_NEGATED(lit)) return ~res; } uint stripped_lit = STRIP_LIT(lit); BDD res; if (stripped_lit == 0) { res = cudd.bddZero(); } else if (aiger_is_input(aiger_spec, stripped_lit) || aiger_is_latch(aiger_spec, stripped_lit)) { res = cudd.ReadVars(cudd_by_aiger[stripped_lit]); // MASSERT(res.NodeReadIndex() == stripped_lit/2, "that bug again: impossible: " << res.NodeReadIndex() << " vs " << stripped_lit/2 ); } else { // aiger_and aiger_and *and_ = aiger_is_and(aiger_spec, stripped_lit); res = get_bdd_for_sign_lit(and_->rhs0) & get_bdd_for_sign_lit(and_->rhs1); } bdd_by_aiger_unlit[stripped_lit] = res; return IS_NEGATED(lit) ? (~res):res; }
void Synth::model_to_aiger(const BDD &c_signal, const BDD &func) { /// Update AIGER spec with a definition of `c_signal` uint c_lit = aiger_by_cudd[c_signal.NodeReadIndex()]; string output_name = string(aiger_is_input(aiger_spec, c_lit)->name); // save the name before it is freed uint func_as_aiger_lit = walk(func.getNode()); aiger_redefine_input_as_and(aiger_spec, c_lit, func_as_aiger_lit, func_as_aiger_lit); if (print_full_model) aiger_add_output(aiger_spec, c_lit, output_name.c_str()); }
static const char * next_symbol (unsigned idx, int slice) { aiger_symbol *input_symbol; const char *unsliced_name; unsigned len, pos; assert (!strip); assert (1 <= idx); assert (idx <= model->maxvar); assert (slice >= 0); input_symbol = aiger_is_input (model, 2 * idx); assert (input_symbol); unsliced_name = input_symbol->name; len = unsliced_name ? strlen (unsliced_name) : 20; len += 30; if (size_buffer < len) { if (size_buffer) { while (size_buffer < len) size_buffer *= 2; buffer = realloc (buffer, size_buffer); } else buffer = malloc (size_buffer = len); } pos = input_symbol - model->inputs; assert (pos < model->num_inputs); if (unsliced_name) sprintf (buffer, "%d %s %u", slice, unsliced_name, pos); else sprintf (buffer, "%d %u %u", slice, 2 * idx, pos); return buffer; }
hmap<uint,BDD> Synth::extract_output_funcs() { /** The result vector respects the order of the controllable variables **/ L_INF("extract_output_funcs.."); cudd.FreeTree(); // ordering that worked for win region computation might not work here hmap<uint,BDD> model_by_cuddidx; vector<BDD> controls = get_controllable_vars_bdds(); while (!controls.empty()) { BDD c = controls.back(); controls.pop_back(); aiger_symbol *aiger_input = aiger_is_input(aiger_spec, aiger_by_cudd[c.NodeReadIndex()]); L_INF("getting output function for " << aiger_input->name); BDD c_arena; if (controls.size() > 0) { BDD cube = cudd.bddComputeCube(controls.data(), NULL, (int)controls.size()); c_arena = non_det_strategy.ExistAbstract(cube); } else { //no other signals left c_arena = non_det_strategy; } // Now we have: c_arena(t,u,c) = ∃c_others: nondet(t,u,c) // (i.e., c_arena talks about this particular c, about t and u) BDD c_can_be_true = c_arena.Cofactor(c); BDD c_can_be_false = c_arena.Cofactor(~c); BDD c_must_be_true = ~c_can_be_false & c_can_be_true; BDD c_must_be_false = c_can_be_false & ~c_can_be_true; // Note that we cannot use `c_must_be_true = ~c_can_be_false`, // since the negation can cause including tuples (t,i,o) that violate non_det_strategy. auto support_indices = cudd.SupportIndices(vector<BDD>({c_must_be_false, c_must_be_true})); for (auto const var_cudd_idx : support_indices) { auto v = cudd.ReadVars(var_cudd_idx); auto new_c_must_be_false = c_must_be_false.ExistAbstract(v); auto new_c_must_be_true = c_must_be_true.ExistAbstract(v); if ((new_c_must_be_false & new_c_must_be_true) == cudd.bddZero()) { c_must_be_false = new_c_must_be_false; c_must_be_true = new_c_must_be_true; } } // We use 'restrict' operation, but we could also just do: // c_model = care_set -> must_be_true // but this is (presumably) less efficient (in time? in size?). // (intuitively, because we always set c_model to 1 if !care_set, but we could set it to 0) // // The result of restrict operation satisfies: // on c_care_set: c_must_be_true <-> must_be_true.Restrict(c_care_set) BDD c_model = c_must_be_true.Restrict(c_must_be_true | c_must_be_false); model_by_cuddidx[c.NodeReadIndex()] = c_model; //killing node refs c_must_be_false = c_must_be_true = c_can_be_false = c_can_be_true = c_arena = cudd.bddZero(); //TODO: ak: strange -- the python version for the example amba_02_9n produces a smaller circuit (~5-10 times)! non_det_strategy = non_det_strategy.Compose(c_model, c.NodeReadIndex()); //non_det_strategy = non_det_strategy & ((c & c_model) | (~c & ~c_model)); } return model_by_cuddidx; }