VCDGenerator.java 10.70 KiB
/* 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) {
}
}
}
}
}
}