de.uni_potsdam.hpi.asg.logictool.synthesis.CElementSynthesis.java Source code

Java tutorial

Introduction

Here is the source code for de.uni_potsdam.hpi.asg.logictool.synthesis.CElementSynthesis.java

Source

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

/*
 * 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.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

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.logictool.helper.BDDHelper;
import de.uni_potsdam.hpi.asg.logictool.mapping.TechnologyMapper;
import de.uni_potsdam.hpi.asg.logictool.mapping.model.GateMapping;
import de.uni_potsdam.hpi.asg.logictool.mapping.model.Mapping;
import de.uni_potsdam.hpi.asg.logictool.mapping.model.NoMapping;
import de.uni_potsdam.hpi.asg.logictool.mapping.model.WireMapping;
import de.uni_potsdam.hpi.asg.logictool.netlist.Netlist;
import de.uni_potsdam.hpi.asg.logictool.netlist.NetlistCelem;
import de.uni_potsdam.hpi.asg.logictool.netlist.NetlistCelem.Arch;
import de.uni_potsdam.hpi.asg.logictool.netlist.NetlistCelem.InternalArch;
import de.uni_potsdam.hpi.asg.logictool.netlist.NetlistTerm;
import de.uni_potsdam.hpi.asg.logictool.netlist.NetlistVariable;
import de.uni_potsdam.hpi.asg.logictool.reset.Reset;
import de.uni_potsdam.hpi.asg.logictool.reset.decision.ResetDecider.ResetDecision;
import de.uni_potsdam.hpi.asg.logictool.srgraph.State;
import de.uni_potsdam.hpi.asg.logictool.srgraph.StateGraph;
import de.uni_potsdam.hpi.asg.logictool.synthesis.function.CElementFunctionSynthesis;
import de.uni_potsdam.hpi.asg.logictool.synthesis.function.CElementFunctionSynthesis.ComplementaryDecision;
import de.uni_potsdam.hpi.asg.logictool.synthesis.helper.MonotonicCoverChecker;
import de.uni_potsdam.hpi.asg.logictool.synthesis.helper.RegionCalculator;
import de.uni_potsdam.hpi.asg.logictool.synthesis.model.EspressoTable;
import de.uni_potsdam.hpi.asg.logictool.synthesis.table.CElementTableSynthesis;
import de.uni_potsdam.hpi.asg.logictool.synthesis.table.TableSynthesis;
import net.sf.javabdd.BDD;

public class CElementSynthesis extends Synthesis {
    private static final Logger logger = LogManager.getLogger();
    public static final String separator = "__";
    public static final String setEnding = separator + "set";
    public static final String resetEnding = separator + "reset";

    private StateGraph stateGraph;
    private CElementFunctionSynthesis syn2;
    private EspressoOptimiser optimiser;
    private SortedSet<Signal> outsignals;
    private RegionCalculator regCalc;
    private Map<Signal, ComplementaryDecision> networksComplementaryMap;
    private Arch arch;

    public CElementSynthesis(StateGraph stateGraph, Netlist netlist, String resetname, Arch arch) {
        super(netlist, resetname);
        this.stateGraph = stateGraph;
        this.optimiser = new EspressoOptimiser();
        this.regCalc = new RegionCalculator(stateGraph);
        this.outsignals = new TreeSet<>();
        this.arch = arch;
        this.networksComplementaryMap = new HashMap<>();
    }

    @Override
    public boolean doTableSynthesis() {
        for (Signal sig : stateGraph.getAllSignals()) {
            if (sig.isInternalOrOutput()) {
                outsignals.add(sig);
            }
        }
        TableSynthesis syn = new CElementTableSynthesis(stateGraph, outsignals, regCalc.getRegions(), resetname);
        table = syn.synthesise();
        return true;
    }

    @Override
    public boolean doTableCheck(EspressoTable table) {
        this.table = table;
        SortedSet<Signal> signals = new TreeSet<>(outsignals);
        TableSynthesis syn = null;
        EspressoTable tmptable = table;
        while (true) {
            MonotonicCoverChecker mchecker = new MonotonicCoverChecker(stateGraph, signals, regCalc.getRegions(),
                    tmptable, resetname);
            if (mchecker.check()) {
                break;
            } else {
                if (mchecker.getMonotonicityViolatingStates() != null) {
                    regCalc.apply(mchecker.getMonotonicityViolatingStates());
                    signals = mchecker.getNonMonotonSignals();
                } else {
                    logger.error("Cannot ensure monotonic cover for " + mchecker.getNonMonotonSignals());
                    return false;
                }
            }
            syn = new CElementTableSynthesis(stateGraph, signals, regCalc.getRegions(), resetname);
            tmptable = syn.synthesise();
            tmptable = optimiser.espressoMinimization(tmptable);
            if (tmptable == null) {
                return false;
            }
            if (table == null) {
                table = tmptable;
            } else {
                table.mergeIn(tmptable, signals);
            }

        }
        return true;
    }

    @Override
    public boolean doFunctionSynthesis() {
        syn2 = new CElementFunctionSynthesis(resetname, table, stateGraph,
                netlist/*, explicitInverterInResetNetwork*/, arch);
        if (!syn2.fillNetlist()) {
            logger.error("Could not fill netlist");
            return false;
        }

        return true;
    }

    @Override
    public boolean doComplementaryCheck(Reset reset) {
        for (Signal sig : stateGraph.getAllSignals()) {
            if (sig.isInternalOrOutput()) {
                Set<NetlistVariable> ands_set = syn2.getSetnetworkMap().get(sig);
                Set<NetlistVariable> ands_reset = syn2.getResetnetworkMap().get(sig);
                BDD setbdd = null;
                if (!ands_set.isEmpty()) {
                    setbdd = netlist.getFac().zero();
                    for (NetlistVariable var : ands_set) {
                        setbdd = setbdd.or(var.getDriver().getBdd());
                    }
                }
                BDD resetbdd = null;
                if (!ands_reset.isEmpty()) {
                    resetbdd = netlist.getFac().zero();
                    for (NetlistVariable var : ands_reset) {
                        resetbdd = resetbdd.or(var.getDriver().getBdd());
                    }
                }

                if (setbdd == null && resetbdd == null) {
                    logger.error("Both networks are empty");
                    return false;
                } else if (setbdd == null) {
                    networksComplementaryMap.put(sig, ComplementaryDecision.RESETANDC);
                } else if (resetbdd == null) {
                    networksComplementaryMap.put(sig, ComplementaryDecision.SETANDC);
                } else {
                    MutableBoolean setresult = new MutableBoolean();
                    MutableBoolean resetresult = new MutableBoolean();
                    boolean complementary = true;
                    boolean onsetfull = true;
                    boolean offsetfull = true;
                    for (State s : stateGraph.getStates()) {
                        if (!BDDHelper.evaluateBDD(setresult, setbdd, s, netlist)) {
                            logger.error("Coult not eval set network for " + sig.getName());
                        }
                        if (!BDDHelper.evaluateBDD(resetresult, resetbdd, s, netlist)) {
                            logger.error("Coult not eval reset network for " + sig.getName());
                        }

                        switch (s.getStateValues().get(sig)) {
                        case rising:
                        case high:
                            if (!setresult.booleanValue()) {
                                onsetfull = false;
                            }
                            break;
                        case low:
                        case falling:
                            if (!resetresult.booleanValue()) {
                                offsetfull = false;
                            }
                            break;
                        }
                        if (!setresult.booleanValue() && !resetresult.booleanValue()) {
                            //set=0, reset=0
                            // => no complementary mapping
                            complementary = false;
                        }

                        if (!complementary && !onsetfull && !offsetfull) {
                            break;
                        }
                    }

                    Map<Signal, ResetDecision> resetDecision = reset.getDecision();
                    NetlistVariable var = netlist.getNetlistVariableBySignal(sig);
                    NetlistTerm celemterm = var.getDriver();
                    if (!(celemterm instanceof NetlistCelem)) {
                        logger.error("Signal " + sig.getName() + " is not driven by an Celem");
                        return false;
                    }
                    NetlistCelem celem = (NetlistCelem) celemterm;
                    InternalArch arch = celem.getArch();

                    if (complementary) {
                        networksComplementaryMap.put(sig, ComplementaryDecision.BOTH);
                    } else if (onsetfull) {
                        networksComplementaryMap.put(sig, ComplementaryDecision.SETONLY);
                    } else if (offsetfull) {
                        networksComplementaryMap.put(sig, ComplementaryDecision.RESETONLY);
                    } else {
                        networksComplementaryMap.put(sig, ComplementaryDecision.NONE);
                        switch (resetDecision.get(sig)) {
                        case NORST:
                            break;
                        case RESETRST:
                            switch (arch) {
                            case standardC:
                            case generalisedCreset:
                                break;
                            case generalisedCset:
                                resetDecision.put(sig, ResetDecision.NORST);
                                break;
                            }
                            break;
                        case SETRST:
                            switch (arch) {
                            case standardC:
                            case generalisedCset:
                                break;
                            case generalisedCreset:
                                resetDecision.put(sig, ResetDecision.NORST);
                                break;
                            }
                            break;
                        case BOTHRST:
                            switch (arch) {
                            case generalisedCreset:
                                resetDecision.put(sig, ResetDecision.RESETRST);
                                break;
                            case generalisedCset:
                                resetDecision.put(sig, ResetDecision.SETRST);
                                break;
                            case standardC:
                                break;
                            }
                            break;
                        }
                    }
                }
            }
        }
        return true;
    }

    @Override
    public boolean doPostMappingSynthesis(TechnologyMapper mapper) {
        //      new NetlistGraph(netlist, null, true);
        for (Signal sig : stateGraph.getAllSignals()) {
            if (sig.isInternalOrOutput()) {
                //            System.out.println(sig.getName() + ": " + networksComplementaryMap.get(sig));
                ComplementaryDecision decision = networksComplementaryMap.get(sig);
                if (decision != ComplementaryDecision.NONE) {
                    //               new NetlistGraph(netlist, null, false);
                    // optimised
                    NetlistVariable var = netlist.getNetlistVariableBySignal(sig);
                    NetlistTerm celemterm = var.getDriver();
                    if (!(celemterm instanceof NetlistCelem)) {
                        logger.error("Signal " + sig.getName() + " is not driven by an Celem");
                        return false;
                    }
                    NetlistCelem celem = (NetlistCelem) celemterm;
                    boolean forceset = false, forcereset = false;
                    // get data for choosing network
                    Set<NetlistTerm> setnetwork = new HashSet<>();
                    Set<NetlistTerm> resetnetwork = new HashSet<>();
                    float setsize = getSizeOfDriverNetwork(celem.getSetInput(), setnetwork);
                    float resetsize = getSizeOfDriverNetwork(celem.getResetInput(), resetnetwork);
                    if (setsize == -1 || resetsize == -1) {
                        return false;
                    }
                    if (setsize == -2) {
                        forcereset = true;
                    }
                    if (resetsize == -2) {
                        forceset = true;
                    }

                    // choose
                    Boolean chooseset = null;
                    Boolean keepcelem = null;
                    if (!forceset && !forcereset) {
                        //no unmapped networks
                        switch (decision) {
                        case BOTH:
                            chooseset = setsize <= resetsize;
                            keepcelem = false;
                            break;
                        case RESETONLY:
                            chooseset = false;
                            keepcelem = false;
                            break;
                        case RESETANDC:
                            chooseset = false;
                            keepcelem = true;
                            break;
                        case SETONLY:
                            chooseset = true;
                            keepcelem = false;
                            break;
                        case SETANDC:
                            chooseset = true;
                            keepcelem = true;
                            break;
                        case NONE:
                            //should not happen
                            return false;
                        }
                    } else if (forceset && forcereset) {
                        //both unmapped?!
                        logger.error("Both networks of signal " + sig.getName() + " are unmapped");
                        return false;
                    } else if (forceset) {
                        //set network partly unmapped
                        switch (decision) {
                        case SETONLY:
                        case BOTH:
                            chooseset = true;
                            keepcelem = false;
                            break;
                        case SETANDC:
                            chooseset = true;
                            keepcelem = true;
                            break;
                        case RESETANDC:
                        case RESETONLY:
                            logger.error(
                                    "Complementary Mapping: Only Resetnetwork can be chosen, but it is unmapped");
                            return false;
                        case NONE:
                            //should not happen
                            return false;
                        }
                    } else { //forcereset
                        //set network partly unmapped
                        switch (decision) {
                        case RESETONLY:
                        case BOTH:
                            chooseset = false;
                            keepcelem = false;
                            break;
                        case RESETANDC:
                            chooseset = false;
                            keepcelem = true;
                            break;
                        case SETANDC:
                        case SETONLY:
                            logger.error(
                                    "Complementary Mapping: Only Setnetwork can be chosen, but it is unmapped");
                            return false;
                        case NONE:
                            //should not happen
                            return false;
                        }
                    }

                    if (chooseset == null || keepcelem == null) {
                        logger.error("Decision not found");
                        return false;
                    }

                    if (keepcelem) {
                        //actually SETANDC and RESETANDC is the same as NONE
                        continue;
                    }

                    // apply
                    // remove celem
                    celem.remove();
                    if (chooseset) {
                        // take set network
                        Signal inpSig = netlist.getSignalByNetlistVariable(celem.getSetInput());
                        if (inpSig != null) {
                            netlist.replaceMapping(new WireMapping(celem.getSetInput(), var, netlist));
                        } else {
                            netlist.changeConnection(var, celem.getSetInput().getDriver());
                        }
                        if (!celem.getResetInput().removeReaderTransitive(celem)) {
                            return false;
                        }
                    } else {
                        // take reset network
                        Signal inpSig = netlist.getSignalByNetlistVariable(celem.getResetInput());
                        if (inpSig != null) {
                            netlist.replaceMapping(new WireMapping(celem.getResetInput(), var, netlist));
                        } else {
                            netlist.changeConnection(var, celem.getResetInput().getDriver());
                        }
                        if (!celem.getSetInput().removeReaderTransitive(celem)) {
                            return false;
                        }
                    }
                }
            }
        }
        if (!netlist.checkNotResetNeeded()) {
            return false;
        }

        //      for(Mapping map : netlist.getMappings()) {
        //         System.out.println(map.toString());
        //      }

        //      new NetlistGraph(netlist, null, true);
        return true;
    }

    /**
     * 
     * @param var
     * @param vars
     * @return size of driver network; -1 if error happend; -2 if network was
     *         partly not mapped
     */
    private float getSizeOfDriverNetwork(NetlistVariable var, Set<NetlistTerm> terms) {
        float size = 0;
        Set<NetlistTerm> network = netlist.getDrivingNetworkTransitive(var);
        terms.addAll(network);
        for (NetlistTerm t : network) {
            Mapping mapping = t.getMapping();
            if (mapping == null) {
                logger.error("No mapping for term " + t.toString());
                return -1;
            }
            if (mapping instanceof GateMapping) {
                size += ((GateMapping) mapping).getGate().getSize();
            } else if (mapping instanceof NoMapping) {
                return -2;
            }
        }
        return size;
    }

    public Map<Signal, ComplementaryDecision> getNetworksComplementaryMap() {
        return networksComplementaryMap;
    }
}