/* Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Ludovic Apvrille * * ludovic.apvrille AT enst.fr * * This software is a computer program whose purpose is to allow the * edition of TURTLE analysis, design and deployment diagrams, to * allow the generation of RT-LOTOS or Java code from this diagram, * and at last to allow the analysis of formal validation traces * obtained from external tools, e.g. RTL from LAAS-CNRS and CADP * from INRIA Rhone-Alpes. * * This software is governed by the CeCILL license under French law and * abiding by the rules of distribution of free software. You can use, * modify and/ or redistribute the software under the terms of the CeCILL * license as circulated by CEA, CNRS and INRIA at the following URL * "http://www.cecill.info". * * As a counterpart to the access to the source code and rights to copy, * modify and redistribute granted by the license, users are provided only * with a limited warranty and the software's author, the holder of the * economic rights, and the successive licensors have only limited * liability. * * In this respect, the user's attention is drawn to the risks associated * with loading, using, modifying and/or developing or reproducing the * software by the user in light of its specific status of free software, * that may mean that it is complicated to manipulate, and that also * therefore means that it is reserved for developers and experienced * professionals having in-depth computer knowledge. Users are therefore * encouraged to load and test the software's suitability as regards their * requirements in conditions enabling the security of their systems and/or * data to be ensured and, more generally, to use and operate it in the * same conditions as regards security. * * The fact that you are presently reading this means that you have had * knowledge of the CeCILL license and that you accept its terms. */ package graph; import myutil.FileException; import myutil.FileUtils; import myutil.TraceManager; import vcd.VCDContent; import vcd.VCDTimeChange; import vcd.VCDVariable; import java.util.ArrayList; /** * Class VCDGenerator * Creation : 13/07/2009 ** @version 1.0 13/07/2009 * @author Ludovic APVRILLE */ public class VCDGenerator { public final static int LOW = 0; public final static int LOW_TO_HIGH = 1; public final static int HIGH_TO_LOW = 2; public final static int HIGH = 3; public final static int NB_OF_MODES = 4; private AUTGraph graph; private long simulationTicks = 1000000; private String tickInfo = "GOTS"; private String coreInfo = "PRINTCORESTATES"; private String taskInfo = "TASKINFO"; private String info = "SYSTEMINFO"; private int nbOfTasks; private int nbOfCores; private CorePowerConsumption pcs[]; private long pcInMode[]; private long currentTime; private VCDContent vcd; private boolean go; private String activity; public VCDGenerator(AUTGraph _graph) { graph = _graph; pcInMode = new long[NB_OF_MODES]; } public int generateVCD() { go = true; vcd = new VCDContent(); return simulate(); } public void setPowerConsumptionInMode(int _mode, long _value) { if (_mode < NB_OF_MODES) { pcInMode[_mode] = _value; } } public void setSimulationTicks(long _st) { simulationTicks = _st; } public int getPercentage() { return (int)(currentTime*100/simulationTicks); } public void setInfo(String _info) { String s = modify(_info); if (s.length() > 0) { info = s; } } public void setTickInfo(String _info) { String s = modify(_info); if (s.length() > 0) { tickInfo = s; } } public void setCoreInfo(String _info) { String s = modify(_info); if (s.length() > 0) { coreInfo = s; } } public void setTaskInfo(String _info) { String s = modify(_info); if (s.length() > 0) { taskInfo = s; } } private String modify(String _s) { String s = _s.trim().toUpperCase(); return s; } public String getVCDString() { if (vcd != null) { return vcd.toString(); } else { return "No vcd"; } } public void saveInFile(String path, String fileName) throws FileException { FileUtils.saveFile(path + fileName, getVCDString()); } public int simulate() { // Take a random path // Must locate system info first -> nb of tasks, nb of cores boolean deadlock = false; boolean infoFound = false; boolean cycle = false; AUTState currentState; AUTTransition tr; String label; int i; currentTime = 0; ArrayList<AUTState> met = new ArrayList<AUTState>(); TraceManager.addDev("Computing states"); activity = "Computing states"; graph.computeStates(); currentState = graph.findFirstOriginState(); TraceManager.addDev("Searches for info"); activity = "Searches for system info on graph"; while((!cycle) && (!deadlock) && (!infoFound) && (go)) { met.add(currentState); tr = currentState.returnRandomTransition(); if (tr == null) { deadlock = true; } else { label = tr.getLabel(); if (label.toUpperCase().equals(info)) { //TraceManager.addDev("[info search] [state = " + currentState.id + "] currentStateFound label = " + label + " int param=" + tr.getNbOfIntParameters()); if (tr.getNbOfIntParameters() == 2) { nbOfTasks = tr.getIntParameter(0); nbOfCores = tr.getIntParameter(1); initCorePowerConsumption(); infoFound = true; } } currentState = graph.getState(tr.destination); if (met.contains(currentState)) { cycle = true; } } } if (!go) { return -3; } if (deadlock) { TraceManager.addDev("Deadlock"); return -1; } if (cycle) { TraceManager.addDev("Cycle"); return -2; } // Add variables activity = "Creating VCD variables"; VCDVariable var; for(i=0; i<nbOfTasks; i++) { var = new VCDVariable("Task" + i); var.setBitwidth(2); vcd.addVariable(var); var = new VCDVariable("Task" + i + "Running"); var.setBitwidth(1); vcd.addVariable(var); } for(i=0; i<nbOfCores; i++) { var = new VCDVariable("Core" + i); var.setBitwidth(2); vcd.addVariable(var); var = new VCDVariable("Core" + i+ "High"); var.setBitwidth(1); vcd.addVariable(var); } // Now simulate the graph ... TraceManager.addDev("Simulate the graph tasks:" + nbOfTasks + " cores:" + nbOfCores); currentTime = 0; VCDTimeChange currentTC; int time; currentTC = new VCDTimeChange("" + currentTime); vcd.addTimeChange(currentTC); String s; int par, par0; long nbOfStates = 0; long oldCurrentTime; while((!cycle) && (currentTime<simulationTicks) && (go)) { tr = currentState.returnRandomTransition(); if (tr == null) { deadlock = true; } else { // new tick? label = tr.getLabel(); // New tick if (label.toUpperCase().equals(tickInfo)) { time = tr.getIntParameter(0); if (time != 0) { oldCurrentTime = currentTime; currentTime += time; // Verify if all tasks info have been put on previous time /*for(i=0; i<nbOfTasks; i++) { var = vcd.getVariableByName("Task" + i); if (var != null) { if (!currentTC.hasValueChangeOnVariable(var)) { currentTC.addVariable(var, "0"); } } }*/ computePowerConsumption(currentTC, oldCurrentTime, currentTime); currentTC = new VCDTimeChange("" + currentTime); vcd.addTimeChange(currentTC); activity = "Simulation: Current time=" + currentTime + " Nb of analyzed transitions=" + nbOfStates; //TraceManager.addDev("CurrentTime " + currentTime + " nbOfStates: " + nbOfStates); } // Info on cores } else if (label.toUpperCase().equals(coreInfo)) { for(i=0; i<nbOfCores; i++) { par = tr.getIntParameter(i); var = vcd.getVariableByName("Core" + i); if (var != null) { s = "" + par; if (par == 2) { s = "10"; } else if (par == 3) { s = "11"; } currentTC.addVariable(var, s); var = vcd.getVariableByName("Core" + i + "High"); if (var != null) { if (par == 3) { currentTC.addVariable(var, "1"); } else { currentTC.addVariable(var, "0"); } } } } // Info on tasks } else if (label.toUpperCase().equals(taskInfo)) { par0 = tr.getIntParameter(0); var = vcd.getVariableByName("Task" + par0); if (var != null) { par = tr.getIntParameter(1); s = "" + par; if (par == 2) { s = "10"; } currentTC.addVariable(var, s); var = vcd.getVariableByName("Task" + par0 + "Running"); if (var != null) { if (par == 2) { currentTC.addVariable(var, "1"); } else { currentTC.addVariable(var, "0"); } } } } currentState = graph.getState(tr.destination); nbOfStates ++; } } if (!go) { return -3; } activity = "All done"; return 0; } public boolean hasBeenStopped() { return (go == false); } public String getCurrentActivity() { return activity; } public void stop() { go = false; } public int getNbOfCores() { return nbOfCores; } public long getPowerConsumptionOfCore(int _index) { if ((_index < nbOfCores) && (pcs != null)) { return pcs[_index].computePowerConsumption(); } return 0; } public void initCorePowerConsumption() { pcs = new CorePowerConsumption[nbOfCores]; for (int i=0; i<nbOfCores; i++) { pcs[i] = new CorePowerConsumption(NB_OF_MODES); pcs[i].setPowerConsumptionInMode(pcInMode[LOW], LOW); pcs[i].setPowerConsumptionInMode(pcInMode[LOW_TO_HIGH], LOW_TO_HIGH); pcs[i].setPowerConsumptionInMode(pcInMode[HIGH_TO_LOW], HIGH_TO_LOW); pcs[i].setPowerConsumptionInMode(pcInMode[HIGH], HIGH); } } public void computePowerConsumption(VCDTimeChange tc, long oldTime, long newTime) { VCDVariable var; String value; int val, index; String varName; for(int i=0; i<tc.getNbOfVariables(); i++) { var = tc.getVariable(i); varName = var.getName(); if (varName.startsWith("Core")) { if (!varName.endsWith("High")) { value = tc.getValue(i); try { if (value.equals("0")) { val = 0; } else if (value.equals("1")) { val = 1; } else if (value.equals("10")) { val = 2; } else { val = 3; } //val = Integer.parseInt(value); index = Integer.parseInt(varName.substring(4, varName.length())); // Must be from LOW to HIGH if (val < NB_OF_MODES) { pcs[index].addPowerConsumption(val, newTime - oldTime); //TraceManager.addDev("Adding power consumption to core #" + index + " mode = " + val + " value = " + (newTime - oldTime)); } } catch (NumberFormatException nfe) { } } } } } }