de.uni_potsdam.hpi.asg.logictool.helper.BDDHelper.java Source code

Java tutorial

Introduction

Here is the source code for de.uni_potsdam.hpi.asg.logictool.helper.BDDHelper.java

Source

package de.uni_potsdam.hpi.asg.logictool.helper;

/*
 * Copyright (C) 2015 Norman Kluge
 * 
 * This file is part of ASGlogic.
 * 
 * ASGlogic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * ASGlogic is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with ASGlogic.  If not, see <http://www.gnu.org/licenses/>.
 */

import java.util.BitSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Map.Entry;

import org.apache.commons.lang3.mutable.MutableBoolean;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import de.uni_potsdam.hpi.asg.common.stg.model.Signal;
import de.uni_potsdam.hpi.asg.common.stggraph.AbstractState.Value;
import de.uni_potsdam.hpi.asg.logictool.netlist.Netlist;
import de.uni_potsdam.hpi.asg.logictool.netlist.NetlistVariable;
import de.uni_potsdam.hpi.asg.logictool.srgraph.State;

import net.sf.javabdd.BDD;

public class BDDHelper {
    private static final Logger logger = LogManager.getLogger();

    public static String getFunctionString(BDD bdd, Netlist netlist) {
        if (bdd.isZero()) {
            return "0";
        } else if (bdd.isOne()) {
            return "1";
        } else if (isOrGate(bdd)) {
            return formatOrGate(bdd, netlist);
        } else if (isAndGate(bdd)) {
            return formatArbitraryFunction(bdd, netlist); // And Gate looks normal in this format
        } else {
            return formatArbitraryFunction(bdd, netlist);
        }
    }

    private static String formatOrGate(BDD bdd, Netlist netlist) {
        StringBuilder str = new StringBuilder();
        str.append("(");
        for (NetlistVariable var : getVars(bdd, netlist)) {
            if (!isPos(bdd, var)) {
                str.append("!");
            }
            str.append(var.getName() + "+");
        }
        str.replace(str.length() - 1, str.length(), ")");
        return str.toString();
    }

    @SuppressWarnings("unchecked")
    private static String formatArbitraryFunction(BDD bdd, Netlist netlist) {
        StringBuilder str = new StringBuilder();
        Object x = bdd.allsat();
        if (x instanceof LinkedList<?>) {
            for (Object o : (LinkedList<Object>) x) {
                int id = 0;
                byte[] a = (byte[]) o;
                str.append("(");
                for (byte b : a) {
                    switch (b) {
                    case -1:
                        break;
                    case 0:
                        str.append("!" + netlist.getNetlistVariableByBddId(id).getName() + "*");
                        break;
                    case 1:
                        str.append(netlist.getNetlistVariableByBddId(id).getName() + "*");
                        break;
                    default:
                        logger.error("BBD allsat entry unknown");
                    }
                    id++;
                }
                str.replace(str.length() - 1, str.length(), ")+");
            }
            str.replace(str.length() - 1, str.length(), "");
        }
        return str.toString();
    }

    public static boolean isNotGate(BDD bdd) {
        if (isAndGateInternal(bdd) && isOrGateInternal(bdd)) {
            int var = getVars(bdd).iterator().next();
            if (!isPosAnd(bdd, var)) {
                return true;
            }
        }
        return false;
    }

    public static boolean isBuffer(BDD bdd) {
        if (isAndGateInternal(bdd) && isOrGateInternal(bdd)) {
            int var = getVars(bdd).iterator().next();
            if (isPosAnd(bdd, var)) {
                return true;
            }
        }
        return false;
    }

    public static boolean isAndGate(BDD bdd) {
        //      if(isNotGate(bdd) || isBuffer(bdd)) {
        //         return false;
        //      }
        return isAndGateInternal(bdd);
    }

    private static boolean isAndGateInternal(BDD bdd) {
        // only one "1" in table
        double sats = bdd.satCount();
        int irr = numberOfIrrelevantVars(bdd);
        double onetableentries = sats / Math.pow(2, irr);
        if (onetableentries == 1) {
            return true;
        }
        return false;
    }

    public static boolean isOrGate(BDD bdd) {
        //      if(isNotGate(bdd) || isBuffer(bdd)) {
        //         return false;
        //      }
        return isOrGateInternal(bdd);
    }

    private static boolean isOrGateInternal(BDD bdd) {
        // only one "0" in table
        double sats = bdd.satCount();
        int irr = numberOfIrrelevantVars(bdd);
        double onetableentries = sats / Math.pow(2, irr);
        if (onetableentries == (Math.pow(2, BDDHelper.numberOfVars(bdd)) - 1)) {
            return true;
        }
        return false;
    }

    private static int numberOfIrrelevantVars(BDD bdd) {
        return bdd.getFactory().varNum() - numberOfVars(bdd);
    }

    public static int numberOfVars(BDD bdd) {
        int num = 0;
        for (int x : bdd.varProfile()) {
            if (x > 0) {
                num++;
            }
        }
        return num;
    }

    public static Set<NetlistVariable> getVars(BDD bdd, Netlist netlist) {
        Set<NetlistVariable> retVal = new LinkedHashSet<>();
        for (int id : getVars(bdd)) {
            retVal.add(netlist.getNetlistVariableByBddId(id));
        }
        return retVal;
    }

    private static Set<Integer> getVars(BDD bdd) {
        Set<Integer> retVal = new LinkedHashSet<>();
        int id = 0;
        for (int x : bdd.varProfile()) {
            if (x > 0) {
                retVal.add(id);
            }
            id++;
        }
        return retVal;
    }

    public static Boolean isPos(BDD bdd, NetlistVariable var) {
        return isPos(bdd, var.getId());
    }

    private static Boolean isPos(BDD bdd, int id) {
        if (isAndGate(bdd)) {
            return isPosAnd(bdd, id);
        } else if (isOrGate(bdd)) {
            return isPosOr(bdd, id);
        } else {
            logger.warn("ispos only for 'and' and 'or' gates");
            return null;
        }
    }

    private static Boolean isPosOr(BDD bdd, int id) {
        Boolean retVal = isPosAnd(bdd.not(), id);
        if (retVal == null) {
            return null;
        }
        return !retVal;
    }

    @SuppressWarnings("unchecked")
    private static Boolean isPosAnd(BDD bdd, int id) {
        LinkedList<Object> list = (LinkedList<Object>) bdd.allsat();
        for (Object o : list) {
            byte[] a = (byte[]) o;
            switch (a[id]) {
            case -1:
                return null;
            case 0:
                return false;
            case 1:
                return true;
            default:
                logger.error("BBD allsat entry unknown");
            }
        }
        return null;
    }

    public static BDD mergeBDDs(BDD bdd, NetlistVariable replaceVar, BDD replaceBdd, Netlist netlist) {

        Set<NetlistVariable> bddvars = BDDHelper.getVars(bdd, netlist);
        if (!bddvars.contains(replaceVar)) {
            logger.error("ReplaceVar not in Vars");
            return null;
        }

        if (bddvars.size() == 1) {
            //         logger.debug("Shortcut");
            //         logger.debug("BDD: " + getFunctionString(bdd, netlist));
            //         logger.debug("ReplBDD: " + getFunctionString(replaceBdd, netlist));
            //         logger.debug("ReplVar: " + replaceVar.getName());
            if (isPos(bdd, replaceVar)) {
                return replaceBdd;
            } else {
                return replaceBdd.not();
            }
            //         return replaceBdd;//.and(netlist.getFac().one());
        }

        SortedSet<NetlistVariable> newinputs = new TreeSet<>();
        newinputs.addAll(bddvars);
        newinputs.addAll(BDDHelper.getVars(replaceBdd, netlist));
        newinputs.remove(replaceVar);
        //      System.out.println("New Inp: " + newinputs.toString());

        BDD retVal = netlist.getFac().zero();
        BitSet b = new BitSet(newinputs.size());
        for (int i = 0; i < Math.pow(2, newinputs.size()); i++) {
            //         System.out.println(i + ": " + BitSetHelper.formatBitset(b, newinputs.size()));
            int index = 0;
            BDD bdd_new = bdd;
            BDD replacBdd_new = replaceBdd;
            BDD minterm = netlist.getFac().one();
            //TODO: xWITH
            for (NetlistVariable var : newinputs) {
                if (b.get(index)) {
                    bdd_new = bdd_new.restrict(var.toBDD());
                    replacBdd_new = replacBdd_new.restrict(var.toBDD());
                    minterm = minterm.and(var.toBDD());
                } else {
                    bdd_new = bdd_new.restrict(var.toNotBDD());
                    replacBdd_new = replacBdd_new.restrict(var.toNotBDD());
                    minterm = minterm.and(var.toNotBDD());
                }
                index++;
            }
            if (replacBdd_new.isZero()) {
                bdd_new = bdd_new.restrict(replaceVar.toNotBDD());
            } else if (replacBdd_new.isOne()) {
                bdd_new = bdd_new.restrict(replaceVar.toBDD());
            } else {
                logger.error("Repl BDD should be one or zero");
            }

            if (bdd_new.isZero()) {

            } else if (bdd_new.isOne()) {
                retVal.orWith(minterm);
            } else {
                logger.error("BDD should be one or zero");
            }

            BitSetHelper.dualNext(b);
        }

        //      if(bddvars.size() == 1) {
        //         logger.debug("RetVal: " + getFunctionString(retVal, netlist));
        //      }

        return retVal;
    }

    public static boolean evaluateBDD(MutableBoolean result, BDD bdd, State state, Netlist netlist) {
        if (bdd == null) {
            return false;
        }
        BDD bdd2 = bdd.and(bdd.getFactory().one());
        for (Entry<Signal, Value> entry : state.getStateValues().entrySet()) {
            BDD sigbdd = null;
            switch (entry.getValue()) {
            case falling:
            case high:
                sigbdd = netlist.getNetlistVariableBySignal(entry.getKey()).toBDD();
                break;
            case low:
            case rising:
                sigbdd = netlist.getNetlistVariableBySignal(entry.getKey()).toNotBDD();
                break;
            }
            bdd2 = bdd2.restrictWith(sigbdd);
        }
        for (Entry<NetlistVariable, Boolean> entry : netlist.getQuasiSignals().entrySet()) {
            BDD sigbdd = null;
            if (entry.getValue()) {
                //true => Normally 1
                sigbdd = entry.getKey().toBDD();
            } else {
                sigbdd = entry.getKey().toNotBDD();
            }
            bdd2 = bdd2.restrictWith(sigbdd);
        }

        if (bdd2.isOne()) {
            result.setTrue();
        } else if (bdd2.isZero()) {
            result.setFalse();
        } else {
            System.out.println(BDDHelper.getFunctionString(bdd2, netlist));
            logger.error("BDD not restricted enough?!");

            return false;
        }
        return true;
    }
}