co.turnus.analysis.buffers.util.AbstractTraceCutScheduler.java Source code

Java tutorial

Introduction

Here is the source code for co.turnus.analysis.buffers.util.AbstractTraceCutScheduler.java

Source

/* 
 * TURNUS, the co-exploration framework
 * 
 * Copyright (C) 2014 EPFL SCI STI MM
 *
 * This file is part of TURNUS.
 *
 * TURNUS 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.
 *
 * TURNUS 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 TURNUS.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Additional permission under GNU GPL version 3 section 7
 * 
 * If you modify this Program, or any covered work, by linking or combining it
 * with Eclipse (or a modified version of Eclipse or an Eclipse plugin or 
 * an Eclipse library), containing parts covered by the terms of the 
 * Eclipse Public License (EPL), the licensors of this Program grant you 
 * additional permission to convey the resulting work.  Corresponding Source 
 * for a non-source form of such a combination shall include the source code 
 * for the parts of Eclipse libraries used as well as that of the  covered work.
 * 
 */
package co.turnus.analysis.buffers.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Set;

import org.apache.commons.math3.stat.descriptive.SummaryStatistics;

import co.turnus.TurnusRuntimeException;
import co.turnus.analysis.data.buffers.BuffersData;
import co.turnus.analysis.data.buffers.BuffersFactory;
import co.turnus.analysis.trace.NearestNeighbor;
import co.turnus.dataflow.Fifo;
import co.turnus.mapping.FifosSize;
import co.turnus.mapping.MappingFactory;
import co.turnus.trace.Dependency;
import co.turnus.trace.Step;
import co.turnus.trace.TraceProject;
import co.turnus.trace.scheduler.simple.AbstractTraceScheduler;
import co.turnus.util.ProgressTheadPrinter;
import co.turnus.util.TurnusLogger;

import com.google.common.collect.Sets;

public abstract class AbstractTraceCutScheduler extends AbstractTraceScheduler<BuffersData> {

    protected final int maxDegree;
    protected final int maxSteps;
    protected final boolean bitAccurate;

    protected final boolean useQuickCut;

    private SummaryStatistics traceCutStat;

    public AbstractTraceCutScheduler(TraceProject traceProject, boolean useQuickCut, int maxDegree, int maxSteps,
            boolean bitAccurate, Map<Fifo, Integer> initialFifosSize, String heuristic, int iteration) {
        super(traceProject, initialFifosSize, heuristic, iteration);

        this.maxDegree = maxDegree;
        this.maxSteps = maxSteps;
        this.bitAccurate = bitAccurate;
        this.useQuickCut = useQuickCut;

        traceCutStat = new SummaryStatistics();
    }

    protected void appendResultsAttributes(BuffersData data) {
    }

    private final BuffersData collectResults(boolean deadlockFree) {
        BuffersData data = BuffersFactory.eINSTANCE.createBuffersData();

        // set parameters
        data.setBitAccurate(bitAccurate);
        data.setDeadlockFree(deadlockFree);
        data.setAttribute("max trace cut degree", maxDegree);
        data.setAttribute("max trace cut steps", maxSteps);
        data.setAttribute("total firings", firings);
        data.setAttribute("quick cut mode", useQuickCut);

        if (!useQuickCut) {
            data.setAttribute("trace cut (mean)", traceCutStat.getMean());
            data.setAttribute("trace cut (min)", traceCutStat.getMin());
            data.setAttribute("trace cut (max)", traceCutStat.getMax());
            data.setAttribute("trace cut (var)", traceCutStat.getVariance());
        }

        // store the maximum token occupancy of each fifo (bits)
        FifosSize sizes = MappingFactory.eINSTANCE.createFifosSize();
        sizes.setNetwork(network);
        data.setFifosSize(sizes);

        int totalBits = 0;
        int maxTokens = 0;

        for (Fifo fifo : network.getFifos()) {
            int size = fifo.getAttribute(FIFO_TOKENS_MAX);
            sizes.getFifosSizeMap().put(fifo, size);
            TurnusLogger.debug(fifo.toString() + ": " + size);

            totalBits += (size * fifo.getType().getBits());
            maxTokens = Math.max(maxTokens, size);

            // store the starting point
            int initialSize = fifo.getAttribute(FIFO_TOKENS_MAX_INIT);
            data.getStartingPoint().put(fifo, initialSize);
        }

        // set the default size as 0
        sizes.setDefaultSize(0);

        TurnusLogger.debug("Buffer configuration size (bit): " + totalBits);

        appendResultsAttributes(data);

        return data;
    }

    protected abstract Set<Step> getNextSteps(Collection<Step> traceCut);

    private BuffersData nearestNeighborSchedule() {
        // start the progress monitor
        ProgressTheadPrinter pPrinter = new ProgressTheadPrinter(
                "Trace Graph post-processing, heuristic " + heuristic + ", iteration " + iteration, traceLength);
        pPrinter.start();

        // get the initial steps and fire them
        Set<Step> ancestors = Sets.newHashSet(trace.getInitialSteps());
        Set<Step> fireables = Sets.newHashSet(ancestors);

        do {

            for (Step s : fireables) {

                fire(s);
                pPrinter.increment();
            }

            if (firings == traceLength) {
                break;
            }

            ancestors.addAll(fireables);
            removeFiredUnconnectedSteps(ancestors);

            Set<Step> ngh = NearestNeighbor.find(ancestors, maxSteps, maxDegree, STEP_FIRED);

            traceCutStat.addValue(ngh.size());

            fireables = getNextSteps(ngh);

        } while (!fireables.isEmpty());

        TurnusLogger.debug("fired steps: " + firings + " of " + traceLength);

        // stop the progress monitor
        try {
            pPrinter.finish();
            pPrinter.join();
        } catch (InterruptedException e) {
            TurnusLogger.warning("Progress monitor stopping error: " + e.getMessage());
        }

        if (firings > traceLength) {
            throw new TurnusRuntimeException("The number of firings is bigger then the trace size!");
        }

        boolean deadlockFree = firings == traceLength;
        if (!deadlockFree) {
            TurnusLogger.warning("Infeasible configuration:" + "deadlock free not guaranteed!!");
        }

        return collectResults(deadlockFree);
    }

    private BuffersData quickCutSchedule() {
        // start the progress monitor
        ProgressTheadPrinter pPrinter = new ProgressTheadPrinter(
                "Trace Graph post-processing, heuristic " + heuristic + ", iteration " + iteration, traceLength);
        pPrinter.start();

        ArrayList<Step> predictionWindow = new ArrayList<Step>();

        // start the algorithm
        for (long id = 0; id < traceLength; id++) {
            Step step = trace.getStep(id);
            predictionWindow.add(step);
            if (predictionWindow.size() == maxSteps) {
                for (Step s : getNextSteps(predictionWindow)) {
                    fire(s);
                    predictionWindow.remove(s);
                    pPrinter.increment();
                }
            }
        }

        // fire the remaining steps
        while (firings < traceLength) {
            for (Step s : getNextSteps(predictionWindow)) {
                fire(s);
                predictionWindow.remove(s);
                pPrinter.increment();
            }
        }

        TurnusLogger.debug("fired steps: " + firings + " of " + traceLength);

        // stop the progress monitor
        try {
            pPrinter.finish();
            pPrinter.join();
        } catch (InterruptedException e) {
            TurnusLogger.warning("Progress monitor stopping error: " + e.getMessage());
        }

        if (firings > traceLength) {
            throw new TurnusRuntimeException("The number of firings is bigger then the trace size!");
        }

        boolean deadlockFree = firings == traceLength;
        if (!deadlockFree) {
            TurnusLogger.warning("Infeasible configuration:" + "deadlock free not guaranteed!!");
        }

        return collectResults(deadlockFree);
    }

    private final void removeFiredUnconnectedSteps(Collection<Step> ancestors) {
        Set<Step> removables = Sets.newHashSet();
        for (Step step : ancestors) {
            if (step.getAttribute(STEP_FIRED, false)) {
                boolean alive = false;
                for (Dependency outgoing : step.getOutgoings()) {
                    Step target = outgoing.getTarget();
                    if (!target.getAttribute(STEP_FIRED, false)) {
                        alive = true;
                        break;
                    }
                }
                if (!alive) {
                    removables.add(step);
                }
            }
        }

        ancestors.removeAll(removables);
    }

    @Override
    public final BuffersData schedule() {

        if (useQuickCut)
            return quickCutSchedule();
        else {
            return nearestNeighborSchedule();
        }

    }

}