Java tutorial
/* * 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(); } } }