Beispiel #1
0
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());
}
Beispiel #2
0
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;
}