-
Daniela Genius authoredDaniela Genius authored
TasksAndMainGenerator.java 44.24 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.
*
* /**
* Class AVATAR2CSOCLIB
* Creation: 01/07/2014
* @version 1.0 01/07/2014
* @version 2.0 07/07/2015
* @author Ludovic APVRILLE, Raja GATGOUT, Julien HENON, Daniela GENIUS
* @see
*/
package ddtranslatorSoclib.toSoclib;
import java.awt.*;
import java.util.*;
import java.io.*;
import myutil.*;
import avatartranslator.*;
import ddtranslatorSoclib.*;
public class TasksAndMainGenerator {
private final static int USEC = 0;
private final static int MSEC = 1;
private final static int SEC = 2;
private final static String UNUSED_ATTR = "__attribute__((unused))";
//private final static String GENERATED_PATH = "generated_src_soclib" + File.separator;
private final static String GENERATED_PATH = "generated_src" + File.separator;
private final static String UNKNOWN = "UNKNOWN";
private final static String CR = "\n";
private final static String CR2 = "\n\n";
public static AvatarSpecification avspec;
public static AvatarddSpecification avddspec;
private Vector warnings;
private MainFileSoclib mainFile;
private Vector<TaskFileSoclib> taskFiles;
private String makefile_src;
private String makefile_SocLib;
private int timeUnit;
private boolean debug;
private boolean tracing;
private boolean includeUserCode = true;
int channel_counter=0;
public TasksAndMainGenerator(AvatarddSpecification _avddspec,AvatarSpecification _avspec) {
avspec = _avspec;
avddspec = _avddspec;
taskFiles = new Vector<TaskFileSoclib>();
}
public void setTimeUnit(int _timeUnit) {
timeUnit = _timeUnit;
}
public void includeUserCode(boolean _inc) {
includeUserCode = _inc;
}
public static String getGeneratedPath() {
return GENERATED_PATH;
}
public void saveInFiles(String path) throws FileException {
System.err.println("ok");
TraceManager.addDev("Generating files");
if (mainFile != null) {
TraceManager.addDev("Generating main files in " + path + mainFile.getName() + ".h");
FileUtils.saveFile(path + GENERATED_PATH + mainFile.getName() + ".h", Conversion.indentString(mainFile.getHeaderCode(), 2));
FileUtils.saveFile(path + GENERATED_PATH + mainFile.getName() + ".c", Conversion.indentString(mainFile.getMainCode(), 2));
}
for(TaskFileSoclib taskFile: taskFiles) {
FileUtils.saveFile(path + GENERATED_PATH + taskFile.getName() + ".h", Conversion.indentString(taskFile.getFullHeaderCode/*Soclib*/(), 2));
FileUtils.saveFile(path + GENERATED_PATH + taskFile.getName() + ".c", Conversion.indentString(taskFile.getMainCode(), 2));
}
// Standard Makefile
makeMakefileSrc(GENERATED_PATH);
FileUtils.saveFile(path + "Makefile.src", makefile_src);
// Makefile for SocLib
makeMakefileSocLib();
FileUtils.saveFile(path + "Makefile.soclib", makefile_SocLib);
}
public Vector getWarnings() {
return warnings;
}
public void generateSoclib(boolean _debug, boolean _tracing) {
debug = _debug;
tracing = _tracing;
mainFile = new MainFileSoclib("main");
avspec.removeCompositeStates();
avspec.removeTimers();
if (avspec.hasApplicationCode() && includeUserCode) {
//mainFile.appendToBeforeMainCode("/* User code */\n");
mainFile.appendToBeforeMainCode(avspec.getApplicationCode());
//mainFile.appendToBeforeMainCode("\n/* End of User code */\n\n");
}
makeTasks();
makeMainHeader();
makeMainMutex();
makeSynchronousChannels();
makeAsynchronousChannels();
makeThreadsInMain(debug);
}
public void makeMainMutex() {
// Create a main mutex
//mainFile.appendToHCode("/* Main mutex */" + CR);
mainFile.appendToBeforeMainCode("/* Main mutex */" + CR);
mainFile.appendToHCode("extern pthread_mutex_t __mainMutex;" + CR + CR);
// mainFile.appendToBeforeMainCode("pthread_mutex_t __mainMutex;" + CR + CR);
mainFile.appendToBeforeMainCode("pthread_barrier_t barrier ;" + CR );
mainFile.appendToBeforeMainCode("pthread_attr_t *attr_t;" + CR );
mainFile.appendToBeforeMainCode("pthread_mutex_t __mainMutex;" + CR2 );
//the address of mwmr segments is currently hard coded for powerPC; will be changed later
mainFile.appendToBeforeMainCode("#define MWMRADDR 0xB0200000" + CR );
mainFile.appendToBeforeMainCode("#define LOCKSADDR 0xC0200000" + CR );
mainFile.appendToBeforeMainCode("#define base(arg) arg" + CR2 );
mainFile.appendToBeforeMainCode("typedef struct mwmr_s mwmr_t;" + CR2);
mainFile.appendToMainCode("void *ptr;" + CR);
mainFile.appendToMainCode("pthread_barrier_init(&barrier,NULL, NB_PROC);" +CR);
mainFile.appendToMainCode("pthread_attr_t *attr_t = malloc(sizeof(pthread_attr_t));" +CR);
mainFile.appendToMainCode("pthread_attr_init(attr_t);" + CR );
mainFile.appendToMainCode("pthread_mutex_init(&__mainMutex, NULL);" +CR2);
}
public void makeSynchronousChannels() {
int i=0;
// Create a synchronous channel per relation/signal
mainFile.appendToHCode("/* Synchronous channels */" + CR);
mainFile.appendToBeforeMainCode("/* Synchronous channels */" + CR);
mainFile.appendToMainCode("/* Synchronous channels */" + CR);
for(AvatarRelation ar: avspec.getRelations()) {
if (!ar.isAsynchronous()) {
for(i=0; i<ar.nbOfSignals() ; i++) {
mainFile.appendToHCode("extern syncchannel __" + getChannelName(ar, i) + ";" + CR);
mainFile.appendToBeforeMainCode("syncchannel __" +getChannelName(ar, i) + ";" + CR);
mainFile.appendToMainCode("__" + getChannelName(ar, i) + ".inname =\"" + ar.getInSignal(i).getName() + "\";" + CR);
mainFile.appendToMainCode("__" +getChannelName(ar, i) + ".outname =\"" + ar.getOutSignal(i).getName() + "\";" + CR);
mainFile.appendToMainCode("__" + getChannelName(ar, i) + ".mwmr_fifo = &" + getChannelName(ar, i) + ";" + CR);
mainFile.appendToBeforeMainCode("uint32_t *const "+ getChannelName(ar, i)+"_lock= LOCKSADDR+0x"+(i*20) +";" + CR);
mainFile.appendToBeforeMainCode("struct mwmr_status_s "+ getChannelName(ar, i) +"_status = MWMR_STATUS_INITIALIZER(1, 1);" + CR);
// mainFile.appendToBeforeMainCode("uint8_t "+getChannelName(ar, i) +"_data[32*2];" + CR);
//synchronous channels are depth 1
mainFile.appendToBeforeMainCode("uint8_t "+getChannelName(ar, i) +"_data[32];" + CR);
mainFile.appendToBeforeMainCode("struct mwmr_s "+getChannelName(ar, i) + "= MWMR_INITIALIZER(1, 1, "+getChannelName(ar, i)+"_data,&"+getChannelName(ar, i)+"_status,\""+getChannelName(ar, i)+"\","+getChannelName(ar, i)+"_lock);" + CR2);
}
}
}
}
/* if (!ar.isAsynchronous()) {
for(i=0; i<ar.nbOfSignals(); i++) {
mainFile.appendToHCode("extern syncchannel __" + getChannelName(ar, i) + ";" + CR);
mainFile.appendToBeforeMainCode("syncchannel __" + getChannelName(ar, i) + ";" + CR);
mainFile.appendToMainCode("__" + getChannelName(ar, i) + ".inname =\"" + ar.getInSignal(i).getName() + "\";" + CR);
mainFile.appendToMainCode("__" + getChannelName(ar, i) + ".outname =\"" + ar.getOutSignal(i).getName() + "\";" + CR);
if (ar.isBroadcast()) {
mainFile.appendToMainCode("setBroadcast(&__" + getChannelName(ar, i) + ", true);" + CR);
}
}
}
}
channel_counter = i/
//mainFile.appendToHCode("pthread_mutex_t mainMutex;" + CR);
}*/
public void makeAsynchronousChannels() {
if (avspec.ASynchronousExist()){
// Create a synchronous channel per relation/signal
mainFile.appendToHCode("/* Asynchronous channels */" + CR);
mainFile.appendToBeforeMainCode("/* Asynchronous channels */" + CR);
mainFile.appendToMainCode("/* Asynchronous channels */" + CR);
for(AvatarRelation ar: avspec.getRelations()) {
if (ar.isAsynchronous()) {
for(int i=0; i<ar.nbOfSignals() ; i++) {
mainFile.appendToHCode("extern asyncchannel __" + getChannelName(ar, i) + ";" + CR);
mainFile.appendToBeforeMainCode("asyncchannel __" +getChannelName(ar, i) + ";" + CR);
mainFile.appendToMainCode("__" + getChannelName(ar, i) + ".inname =\"" + ar.getInSignal(i).getName() + "\";" + CR);
mainFile.appendToMainCode("__" +getChannelName(ar, i) + ".outname =\"" + ar.getOutSignal(i).getName() + "\";" + CR);
if (ar.isBlocking()) {
mainFile.appendToMainCode("__" +getChannelName(ar, i) + ".isBlocking = 1;" + CR);
} else {
mainFile.appendToMainCode("__" + getChannelName(ar, i) + ".isBlocking = 0;" + CR);
}
mainFile.appendToMainCode("__" + getChannelName(ar, i) + ".maxNbOfMessages = " + ar.getSizeOfFIFO() + ";" + CR);
mainFile.appendToMainCode("__" + getChannelName(ar, i) + ".mwmr_fifo = &" + getChannelName(ar, i) + ";" + CR);
mainFile.appendToBeforeMainCode("uint32_t *const "+ getChannelName(ar, i)+"_lock= LOCKSADDR+0x"+(i*20) +";" + CR);
//DG parameter <depth> should ultimately be generated; width is fixed as long as data is not explicitly modeled
mainFile.appendToBeforeMainCode("struct mwmr_status_s "+ getChannelName(ar, i) +"_status = MWMR_STATUS_INITIALIZER(1, 1);" + CR);
mainFile.appendToBeforeMainCode("uint8_t "+getChannelName(ar, i) +"_data[32*2];" + CR);
mainFile.appendToBeforeMainCode("struct mwmr_s "+getChannelName(ar, i) + "= MWMR_INITIALIZER(1, 1, "+getChannelName(ar, i)+"_data,&"+getChannelName(ar, i)+"_status,\""+getChannelName(ar, i)+"\","+getChannelName(ar, i)+"_lock);" + CR2);
}
}
}
}
//mainFile.appendToHCode("pthread_mutex_t mainMutex;" + CR);
}
public int FindCPUidFromTask(AvatarBlock block){
LinkedList<AvatarTask> tasks = avddspec.getAllMappedTask();
for (AvatarTask task : tasks){
if (task.getTaskName().equals(block.getName())){
return task.getCPUNo();
}
}
return 0;
}
public void makeTasks() {
for(AvatarBlock block: avspec.getListOfBlocks()) {
makeTask(block,FindCPUidFromTask(block));
}
}
public void makeTask(AvatarBlock block , int cpuId) {
TaskFileSoclib taskFile = new TaskFileSoclib(block.getName(),cpuId);
//taskFile.addToHeaderCode("#include \"main.h\"" + CR);
//taskFile.addToMainCode("#include \"" + block.getName() + ".h\"");
if (includeUserCode) {
String tmp = block.getGlobalCode();
if (tmp != null) {
taskFile.addToMainCode(CR + "// Header code defined in the model" + CR + tmp + CR + "// End of header code defined in the model" + CR + CR);
}
}
defineAllSignal(block,taskFile);
defineAllStates(block, taskFile);
defineAllMethods(block, taskFile);
makeMainFunction(block, taskFile);
taskFiles.add(taskFile);
}
// ---------------------------------------------------------
public void defineAllStates(AvatarBlock _block, TaskFileSoclib _taskFile) {
int id = 1;
_taskFile.addToMainCode("#define STATE__START__STATE 0" + CR);
for (AvatarStateMachineElement asme: _block.getStateMachine().getListOfElements()) {
if (asme instanceof AvatarState) {
_taskFile.addToMainCode("#define STATE__" + asme.getName() + " " + id + CR);
id ++;
}
}
_taskFile.addToMainCode("#define STATE__STOP__STATE " + id + CR);
_taskFile.addToMainCode(CR);
}
public void defineAllSignal(AvatarBlock _block, TaskFileSoclib _taskFile) {
for (AvatarSignal as: _block.getSignals()) {
//DG 22.09. avoid name clashes cf "open" as a signal name
_taskFile.addToMainCode( "static uint32_t _" + as.getName() + ";" + CR);
}
_taskFile.addToMainCode(CR);
}
public void defineAllMethods(AvatarBlock _block, TaskFileSoclib _taskFile) {
Vector<String> allNames = new Vector<String>();
for (AvatarMethod am: _block.getMethods()) {
makeMethod(_block, am, allNames, _taskFile);
}
// Make method of father
makeFatherMethod(_block, _block, allNames, _taskFile);
}
private void makeFatherMethod(AvatarBlock _originBlock, AvatarBlock _currentBlock, Vector<String> _allNames, TaskFileSoclib _taskFile) {
if (_currentBlock.getFather() == null) {
return;
}
for (AvatarMethod am: _currentBlock.getFather().getMethods()) {
makeMethod(_originBlock, am, _allNames, _taskFile);
}
makeFatherMethod(_originBlock, _currentBlock.getFather(), _allNames, _taskFile);
}
private void makeMethod(AvatarBlock _block, AvatarMethod _am, Vector<String> _allNames, TaskFileSoclib _taskFile) {
String ret = "";
LinkedList<AvatarAttribute> list;
LinkedList<AvatarAttribute> listA;
String nameMethod = _block.getName() + "__" +_am.getName();
for(String s: _allNames) {
if (s.compareTo(nameMethod) == 0) {
return;
}
}
list = _am.getListOfReturnAttributes();
if (list.size() == 0) {
ret += "void";
} else {
ret += getCTypeOf(list.get(0));
}
ret += " " + nameMethod + "(";
list = _am.getListOfAttributes();
int cpt = 0;
for(AvatarAttribute aa: list) {
if (cpt != 0) {
ret += ", ";
}
ret += getCTypeOf(aa) + " " + aa.getName();
cpt ++;
}
ret += ") {" + CR;
if (tracing) {
String tr = "";
cpt = 0;
if (list.size() > 0) {
ret += "char my__attr[CHAR_ALLOC_SIZE];" + CR;
ret += "sprintf(my__attr, \"";
for(AvatarAttribute aa: list) {
if (cpt != 0) {
tr += ",";
ret += ",";
}
tr += aa.getName();
ret += "%d";
cpt ++;
}
ret += "\"," + tr + ");" + CR;
ret += traceFunctionCall(_block.getName(), _am.getName(), "my__attr");
} else {
ret += traceFunctionCall(_block.getName(), _am.getName(), null);
}
}
if (debug) {
ret += "debugMsg(\"-> ....() Executing method " + _am.getName() + "\");" + CR;
list = _am.getListOfAttributes();
cpt = 0;
for(AvatarAttribute aa: list) {
ret += "debugInt(\"Attribute " + aa.getName() + " = \"," + aa.getName() + ");" + CR;
}
}
listA = list;
list = _am.getListOfReturnAttributes();
if (list.size() != 0) {
// Returns the first attribute. If not possible, return 0;
// Implementation is provided by the user?
// In that case, no need to generate the code!
if (_am.isImplementationProvided()) {
ret += "return _userImplemented_" + nameMethod + "(";
cpt = 0;
for(AvatarAttribute aaa: listA) {
if (cpt != 0) {
ret += ", ";
}
ret += aaa.getName();
cpt ++;
}
ret+= ");" + CR;
} else {
if (listA.size() >0) {
ret += "return " + listA.get(0).getName() + ";" + CR;
} else {
ret += "return 0;" + CR;
}
}
} else {
if (_am.isImplementationProvided()) {
ret += "_userImplemented_" + nameMethod + "(";
cpt = 0;
for(AvatarAttribute aaa: listA) {
if (cpt != 0) {
ret += ", ";
}
ret += aaa.getName();
cpt ++;
}
ret+= ");" + CR;
}
}
ret += "}" + CR + CR;
_taskFile.addToMainCode(ret + CR);
}
public void makeMainHeader() {
mainFile.appendToBeforeMainCode(CR);
for(TaskFileSoclib taskFile: taskFiles) {
mainFile.appendToBeforeMainCode("#include \"" + taskFile.getName() + ".h\"" + CR);
}
mainFile.appendToBeforeMainCode(CR);
}
private String makeChannelAction(AvatarBlock _block,AvatarStateMachineElement asme) {
String ret2 = "";
int i;
if (asme instanceof AvatarActionOnSignal) {
AvatarActionOnSignal aaos = (AvatarActionOnSignal)asme;
AvatarSignal as = aaos.getSignal();
AvatarRelation ar = avspec.getAvatarRelationWithSignal(as);
//DG 2.5.
//if(ar.isAsynchronous()){
ret2+= CR + "struct mwmr_s *" + getChannelName(ar, as);
//}
}
return ret2;
}
public static String[] enleveDoublons(String[] table) {
String[] copy = new String[table.length];
System.arraycopy(table, 0, copy, 0, table.length);
table = copy;
for (int i = 0; i < table.length; i++) {
for (int j = i + 1; j < table.length; j++) {
//Si table[j] n'est jamais null, simplifier la ligne suivante
if (table[j] != null && table[j].equals(table[i])) {
table[j] = table[table.length - 1];
table[table.length - 1] = null;
String[] newTable = new String[table.length - 1];
System.arraycopy(table, 0, newTable, 0, table.length - 1);
table = newTable;
j--;
}
}
}
return table;
}
/************************************************************************
public int AccountAllSignal(AvatarBlock _block) {
int cpt=0;
for (AvatarSignal as: _block.getSignals()) {
cpt ++; }
return cpt;
}
************************************************************************/
public String makeCanalDec(AvatarBlock _block) {
AvatarStateMachine asm = _block.getStateMachine();
String ret="";
int m=0;
int i =0;
//int cpt = AccountAllSignal (_block);
String []canal= new String[100];
//String []canalNonDouble= new String[100];
String block_Name = _block.getName() ;
for(AvatarStateMachineElement asme: asm.getListOfElements()) {
canal[i]= makeChannelAction(_block, asme); //"[" + i + "];";
i ++;
}
String [] canalNonDouble= enleveDoublons(canal);
//************************************************************************RG
for(int k = 0; k<canalNonDouble.length ; k++) {
if ((canalNonDouble[k] != null) && (canalNonDouble[k] !="")){
String vari = "= channels_" + block_Name + "[" + m + "];";
ret += (canalNonDouble[k] + vari);
m++;}
}
return ret;
}
//************************************************************************RG
public void makeMainFunction(AvatarBlock _block, TaskFileSoclib _taskFile) {
int i;
String s;
AvatarStateMachine asm = _block.getStateMachine();
//DG 21.09. if block contains no asynchronous channels
// temporarily desactivated
//if(_block.getSignals().isEmpty()){
// s = "void *mainFunc__" + _block.getName() + "(void *arg)";
//}
//else{
s = "void *mainFunc__" + _block.getName() + "(struct mwmr_s *channels_"+ _block.getName() +"[])";
// }
String sh = "extern " + s + ";" + CR;
s+= "{" + CR;
s+= makeCanalDec( _block) + CR;
s += makeAttributesDeclaration(_block, _taskFile);
s+= CR + "int __currentState = STATE__START__STATE;" + CR;
int nbOfMaxParams = _block.getMaxNbOfParams();
//DG retabli
for(i=0; i<_block.getMaxNbOfMultipleBranches(); i++) {
s+= UNUSED_ATTR + " request __req" + i + ";" + CR;
s+= UNUSED_ATTR + "int *__params" + i + "[" + nbOfMaxParams + "];" + CR;
}
s+= UNUSED_ATTR + "setOfRequests __list;" + CR;
s+= UNUSED_ATTR + "pthread_cond_t __myCond;" + CR;
s+= UNUSED_ATTR + "request *__returnRequest;" + CR;
//s+= CR + "char * __myname = (char *)arg;" + CR;
s+= CR + "char * __myname = \"" + _block.getName() + "\";"+ CR;//DG 7.7.
// s+= CR + "char * __myname;"+ CR;
s+= CR + "pthread_cond_init(&__myCond, NULL);" + CR;
s+= CR + "fillListOfRequests(&__list, __myname, &__myCond, &__mainMutex);" + CR;
s+= "//printf(\"my name = %s\\n\", __myname);" + CR;
s+= CR + "/* Main loop on states */" + CR;
s+= "while(__currentState != STATE__STOP__STATE) {" + CR;
s += "switch(__currentState) {" + CR;
s += "case STATE__START__STATE: " + CR;
s += traceStateEntering("__myname", "__StartState");
s += makeBehaviourFromElement(_block, asm.getStartState(), true);
s += "break;" + CR + CR;
String tmp;
// Making other states
for(AvatarStateMachineElement asme: asm.getListOfElements()) {
if (asme instanceof AvatarState) {
s += "case STATE__" + asme.getName() + ": " + CR;
//s += traceStateEntering("__myname", asme.getName());
if (includeUserCode) {
tmp = ((AvatarState)asme).getEntryCode();
if (tmp != null) {
if (tmp.trim().length() > 0) {
s += "/* Entry code */\n" + tmp + "\n/* End of entry code */\n\n";
}
}
}
s += makeBehaviourFromElement(_block, asme, true);
s += "break;" + CR + CR;
}
}
s += "}" + CR;
s += "}" + CR;
s+= "//printf(\"Exiting = %s\\n\", __myname);" + CR;
s+= "return NULL;" + CR;
s += "}" + CR;
_taskFile.addToMainCode(s + CR);
_taskFile.addToHeaderCode(sh + CR);
}
public String makeBehaviourFromElement(AvatarBlock _block, AvatarStateMachineElement _asme, boolean firstCall) {
AvatarStateMachineElement asme0;
if (_asme == null) {
return "";
}
String ret = "";
int i;
if (_asme instanceof AvatarStartState) {
return makeBehaviourFromElement(_block, _asme.getNext(0), false);
}
if (_asme instanceof AvatarTransition) {
AvatarTransition at = (AvatarTransition)_asme;
if (at.isGuarded()) {
String g = modifyGuard(at.getGuard().toString());
ret += "if (!" + g + ") {" + CR;
if (debug) {
ret += "debug2Msg(__myname, \"Guard failed: " + g + "\");" + CR;
}
ret += "__currentState = STATE__STOP__STATE;" + CR;
ret += "break;" + CR;
ret += "}" + CR;
}
if (at.hasDelay()) {
ret+= "waitFor(" + reworkDelay(at.getMinDelay()) + ", " + reworkDelay(at.getMaxDelay()) + ");" + CR;
}
String act;
ret += makeActionsOfTransaction(_block, at);
/*for(i=0; i<at.getNbOfAction(); i++) {
// Must know whether this is an action or a method call
act = at.getAction(i);
if (at.isAMethodCall(act)) {
ret += modifyMethodName(_block, act) + ";" + CR;
} else {
ret += act + ";" + CR;
}
}*/
return ret + makeBehaviourFromElement(_block, _asme.getNext(0), false);
}
if (_asme instanceof AvatarState) {
//DG 29.03.
int cpuid = FindCPUidFromTask(_block);
// ret += "printf(\"tracing cycles --- block: "+_block.getName()+" cpu: %d cycle count: %d \\n\","+ cpuid+", cpu_cycle_count());"+CR;
if (!firstCall) {
if (debug) {
ret += "debug2Msg(__myname, \"-> (=====) Entering state + " + _asme.getName() + "\");" + CR;
}
return ret + "__currentState = STATE__" + _asme.getName() + ";" + CR;
} else {
if (_asme.nbOfNexts() == 0) {
return ret + "__currentState = STATE__STOP__STATE;" + CR;
}
if (_asme.nbOfNexts() == 1) {
return ret + makeBehaviourFromElement(_block, _asme.getNext(0), false);
}
// Complex case of states -> several nexts
// Put in list all
// 1) Only immediatly executable transitions
for(i=0; i<_asme.nbOfNexts(); i++) {
if (_asme.getNext(i) instanceof AvatarTransition) {
AvatarTransition at = (AvatarTransition)(_asme.getNext(i));
if (at.hasActions()) {
ret += makeImmediateAction(at, i);
} else {
if (at.getNext(0) instanceof AvatarActionOnSignal) {
ret += makeSignalAction(at, i);
} else {
// nothing special to do : immediate choice
ret += makeImmediateAction(at, i);
}
}
}
}
// Make all requests
// Test if at least one request in the list!
ret += "if (nbOfRequests(&__list) == 0) {" + CR;
ret += "debug2Msg(__myname, \"No possible request\");" + CR;
ret += "__currentState = STATE__STOP__STATE;" + CR;
ret += "break;" + CR;
ret += "}" + CR;
ret += "__returnRequest = executeListOfRequests(&__list);" + CR;
ret += "clearListOfRequests(&__list);" + CR ;
ret += traceRequest();
// Resulting requests
for(i=0; i<_asme.nbOfNexts(); i++) {
if (i != 0) {
ret += "else ";
}
AvatarTransition at = (AvatarTransition)(_asme.getNext(i));
if (at.hasActions()) {
ret += " if (__returnRequest == &__req" + i + ") {" + CR;
ret += makeActionsOfTransaction(_block, at);
/*for(int j=0; j<at.getNbOfAction(); j++) {
if (at.isAMethodCall(at.getAction(j))) {
ret += modifyMethodName(_block, at.getAction(j)) + ";" + CR;
} else {
ret += at.getAction(j) + ";" + CR;
}
}*/
ret += makeBehaviourFromElement(_block, at.getNext(0), false) + CR + "}";
} else {
if (at.getNext(0) instanceof AvatarActionOnSignal) {
ret += " if (__returnRequest == &__req" + i + ") {" + CR + makeBehaviourFromElement(_block, at.getNext(0).getNext(0), false) + CR + "}";
} else {
// nothing special to do : immediate choice
ret += " if (__returnRequest == &__req" + i + ") {" + CR + makeBehaviourFromElement(_block, at.getNext(0), false) + CR + "}";
}
}
ret += CR;
}
return ret;
}
}
if (_asme instanceof AvatarStopState) {
return ret + "__currentState = STATE__STOP__STATE;" + CR;
}
if (_asme instanceof AvatarRandom) {
AvatarRandom ar = (AvatarRandom)_asme;
ret += ar.getVariable() + " = computeRandom(" + ar.getMinValue() + ", " + ar.getMaxValue() + ");" + CR;
return ret + makeBehaviourFromElement(_block, _asme.getNext(0), false);
}
if (_asme instanceof AvatarActionOnSignal) {
AvatarActionOnSignal aaos = (AvatarActionOnSignal)_asme;
ret += makeSignalAction(aaos, 0, false, "", "");
AvatarSignal as = aaos.getSignal();
AvatarRelation ar = avspec.getAvatarRelationWithSignal(as);
ret += executeOneRequest("__req0");
ret += traceRequest();
}
// Default
return ret + makeBehaviourFromElement(_block, _asme.getNext(0), false);
}
private String makeSignalAction(AvatarTransition _at, int _index) {
String ret = "";
AvatarActionOnSignal aaos;
if (!(_at.getNext(0) instanceof AvatarActionOnSignal)) {
return "";
}
aaos = (AvatarActionOnSignal)(_at.getNext(0));
if (_at.isGuarded()) {
String g = modifyGuard(_at.getGuard().toString());
ret += "if (" + g + ") {" + CR;
}
if (_at.hasDelay()) {
ret += makeSignalAction(aaos, _index, true, _at.getMinDelay(), _at.getMaxDelay());
} else {
ret += makeSignalAction(aaos, _index, false, "", "");
}
ret += "addRequestToList(&__list, &__req" + _index + ");" + CR;
if (_at.isGuarded()) {
ret += "}" + CR;
}
return ret;
}
private String makeSignalAction(AvatarActionOnSignal _aaos, int _index, boolean hasDelay, String minDelay, String maxDelay) {
String ret = "";
int i;
AvatarSignal as = _aaos.getSignal();
AvatarRelation ar = avspec.getAvatarRelationWithSignal(as);
String delay;
if (hasDelay) {
delay = "1, " + reworkDelay(minDelay) + ", " + reworkDelay(maxDelay);
} else {
delay = "0, 0, 0";
}
if (ar != null) {
// Sending
if (_aaos.isSending()) {
// Putting params
for(i=0; i<_aaos.getNbOfValues() ;i++) {
ret += "__params" + _index + "[" + i + "] = &" + _aaos.getValue(i) + ";" + CR;
}
if (ar.isAsynchronous()) {
//DG 3.12. inserted debug messages
ret += "debug2Msg(__myname, \"-> (=====)before MakeNewRequest\");" + CR;
ret+="debugInt(\"channel address\", &__req"+_index+");" + CR;
ret += "makeNewRequest(&__req" + _index + ", " + _aaos.getID() + ", SEND_ASYNC_REQUEST, " + delay + ", " + _aaos.getNbOfValues() + ", __params" + _index + ");" + CR;
ret += "debug2Msg(__myname, \"-> (=====)after MakeNewRequest\");" + CR;
ret += "__req" + _index + ".asyncChannel = &__" + getChannelName(ar, as) + ";" + CR;
} else {
if (ar.isBroadcast()) {
ret += "makeNewRequest(&__req" + _index + ", " + _aaos.getID()+ ", SEND_BROADCAST_REQUEST, " + delay + ", " + _aaos.getNbOfValues() + ", __params" + _index + ");" + CR;
ret += "__req" + _index + ".syncChannel = &__" + getChannelName(ar, as) + ";" + CR;
} else {
ret += "makeNewRequest(&__req" + _index + ", " + _aaos.getID()+ ", SEND_SYNC_REQUEST, " + delay + ", " + _aaos.getNbOfValues() + ", __params" + _index + ");" + CR;
ret += "__req" + _index + ".syncChannel = &__" + getChannelName(ar, as) + ";" + CR;
}
}
// Receiving
}
else {
for(i=0; i<_aaos.getNbOfValues() ;i++) {
ret += "__params" + _index + "[" + i + "] = &" + _aaos.getValue(i) + ";" + CR;
}
if (ar.isAsynchronous()) {
//ret += "debug2Msg(__myname, \"-> (=====)before MakeNewRequest\");" + CR;
//ret+="debugInt(\"channel address\", &__req"+_index+");" + CR;
ret += "makeNewRequest(&__req" + _index + ", " + _aaos.getID() + ", RECEIVE_ASYNC_REQUEST, " + delay + ", " + _aaos.getNbOfValues() + ", __params" + _index + ");" + CR;
ret += "__req" + _index + ".asyncChannel = &__" + getChannelName(ar, as) + ";" + CR;
} else {
if (ar.isBroadcast()) {
ret += "makeNewRequest(&__req" + _index + ", " + _aaos.getID() + ", RECEIVE_BROADCAST_REQUEST, " + delay + ", " + _aaos.getNbOfValues() + ", __params" + _index + ");" + CR;
ret += "__req" + _index + ".syncChannel = &__" + getChannelName(ar, as) + ";" + CR;
} else {
ret += "makeNewRequest(&__req" + _index + ", " + _aaos.getID() + ", RECEIVE_SYNC_REQUEST, " + delay + ", " + _aaos.getNbOfValues() + ", __params" + _index + ");" + CR;
ret += "__req" + _index + ".syncChannel = &__" + getChannelName(ar, as) + ";" + CR;
}
}
}
}
return ret;
}
private String makeImmediateAction(AvatarTransition _at, int _index) {
String ret = "";
if (_at.isGuarded()) {
String g = modifyGuard(_at.getGuard().toString());
ret += "if (" + g + ") {" + CR;
}
if (_at.hasDelay()) { // if (( remainingTime>0 ))
ret += "makeNewRequest(&__req" + _index + ", " + _at.getID() + ", IMMEDIATE, 1, " + reworkDelay(_at.getMinDelay()) + ", " + reworkDelay(_at.getMaxDelay()) + ", 0, __params" + _index + ");" + CR;
} else {
ret += "makeNewRequest(&__req" + _index + ", " + _at.getID() + ", IMMEDIATE, 0, 0, 0, 0, __params" + _index + ");" + CR;
}
ret += "addRequestToList(&__list, &__req" + _index + ");" + CR;
if (_at.isGuarded()) {
ret += "}" + CR;
}
return ret;
}
private String executeOneRequest(String var) {
String ret = "debug2Msg(__myname, \"-> (=====)before executeOneRequest\");" + CR;
ret += "__returnRequest = executeOneRequest(&__list, &" + var + ");" + CR;
ret += "debug2Msg(__myname, \"-> (=====)after executeOneRequest\");" + CR;
ret += "clearListOfRequests(&__list);" + CR;
return ret;
}
public String makeAttributesDeclaration(AvatarBlock _block, TaskFileSoclib _taskFile) {
String ret = "";
for(AvatarAttribute aa: _block.getAttributes()) {
ret += getCTypeOf(aa) + " " + aa.getName() + " = " + aa.getInitialValue() + ";" + CR;
}
return ret;
}
public void makeThreadsInMain(boolean _debug) {
mainFile.appendToMainCode(CR + "/* Threads of tasks */" + CR);
for(TaskFileSoclib taskFile: taskFiles) {
mainFile.appendToMainCode("pthread_t thread__" + taskFile.getName() + ";" + CR);
}
makeArgumentsInMain(_debug);
if (_debug) {
mainFile.appendToMainCode("/* Activating debug messages */" + CR);
mainFile.appendToMainCode("activeDebug();" + CR);
}
mainFile.appendToMainCode("/* Activating randomness */" + CR);
mainFile.appendToMainCode("initRandom();" + CR);
mainFile.appendToMainCode("/* Initializing the main mutex */" + CR);
mainFile.appendToMainCode("if (pthread_mutex_init(&__mainMutex, NULL) < 0) { exit(-1);}" + CR + CR);
if (avspec.hasApplicationCode()) {
mainFile.appendToMainCode("/* User initialization */" + CR);
mainFile.appendToMainCode("__user_init();" + CR);
}
mainFile.appendToMainCode(CR + CR + mainDebugMsg("Starting tasks"));
/* one relation specified in the AVATAR block diagram can contain
several signals which translate into several soclib channels
for all channels they are transmitted in one array*/
for(TaskFileSoclib taskFile: taskFiles) {
int cptchannels_array = 0;
String channelString= "";
int j=0;
for(AvatarRelation ar: avspec.getRelations()) {
int i;
if(ar.nbOfSignals()!=0){
for(i=0; i<ar.nbOfSignals() ; i++) {
// if(((ar.block1.getName()==taskFile.getName())||(ar.block2.getName()==taskFile.getName()))&&(ar.isAsynchronous())){ //DG 2.5.
if(((ar.block1.getName()==taskFile.getName())||(ar.block2.getName()==taskFile.getName()))){
channelString+="channels_array_"+ taskFile.getName() +"["+j+"]=&"+getChannelName(ar, i)+";" + CR;
cptchannels_array ++;
j++;
}
}
}
}
//skip this line if there are no channels associated
if(!(cptchannels_array==0)){
mainFile.appendToMainCode("struct mwmr_s *channels_array_"+ taskFile.getName() +"["+cptchannels_array+"];"+CR);
mainFile.appendToMainCode(channelString+CR);
}
else{
mainFile.appendToMainCode("struct mwmr_s *channels_array_"+ taskFile.getName()+";"+CR);
}
mainFile.appendToMainCode("ptr =malloc(sizeof(pthread_t));" + CR);
mainFile.appendToMainCode("thread__"+taskFile.getName() + "= (pthread_t)ptr;" + CR);
mainFile.appendToMainCode("attr_t = malloc(sizeof(pthread_attr_t));" + CR);
mainFile.appendToMainCode("attr_t->cpucount = "+ taskFile.getCPUId() +"; " +CR);
mainFile.appendToMainCode(CR + CR + mainDebugMsg("Starting tasks"));
//if(cptchannels_array==0){
// mainFile.appendToMainCode("pthread_create(&thread__" +taskFile.getName()+", NULL, mainFunc__" + taskFile.getName()+", NULL);" + CR2);
// }else{
mainFile.appendToMainCode("pthread_create(&thread__" +taskFile.getName()+", NULL, mainFunc__" + taskFile.getName() +", (void *)channels_array_"+taskFile.getName()+");" + CR2);
//}
}
mainFile.appendToMainCode(CR + CR + mainDebugMsg("Joining tasks"));
for(TaskFileSoclib taskFile: taskFiles) {
mainFile.appendToMainCode("pthread_join(thread__" + taskFile.getName() + ", NULL);" + CR);
}
mainFile.appendToMainCode(CR + CR + mainDebugMsg("Application terminated"));
mainFile.appendToMainCode("return 0;" + CR);
}
public void makeArgumentsInMain(boolean _debug) {
mainFile.appendToMainCode("/* Activating tracing */" + CR);
if (tracing) {
mainFile.appendToMainCode("if (argc>1){" + CR);
mainFile.appendToMainCode("activeTracingInFile(argv[1]);" + CR + "} else {" + CR);
mainFile.appendToMainCode("activeTracingInConsole();" + CR + "}" + CR);
}
}
public void makeMakefileSrc(String _path) {
makefile_src = "SRCS = ";
makefile_src += _path + "main.c ";
for(TaskFileSoclib taskFile: taskFiles) {
makefile_src += _path + taskFile.getName() + ".c ";
}
}
public void makeMakefileSocLib() {
makefile_SocLib = "objs = ";
makefile_SocLib += "main.o ";
for(TaskFileSoclib taskFile: taskFiles) {
makefile_SocLib += taskFile.getName() + ".o ";
}
}
public String getCTypeOf(AvatarAttribute _aa) {
String ret = "int";
if (_aa.getType() == AvatarType.BOOLEAN) {
ret = "bool";
}
return ret;
}
public String getChannelName(AvatarRelation _ar, int _index) {
return _ar.block1.getName() + "_" + _ar.getSignal1(_index).getName() + "__" + _ar.block2.getName() + "_" + _ar.getSignal2(_index).getName();
}
public String getSigName(AvatarRelation _ar, int _index) {
return _ar.getSignal2(_index).getName();
}
public String getChannelName(AvatarRelation _ar, AvatarSignal _as) {
int index = _ar.getIndexOfSignal(_as);
return getChannelName(_ar, index);
}
public String getSigName(AvatarRelation _ar, AvatarSignal _as) {
int index = _ar.getIndexOfSignal(_as);
return getSigName(_ar, index);
}
public String modifyGuard(String _g) {
String g = Conversion.replaceAllString(_g, "[", "(").trim();
g = Conversion.replaceAllString(g, "]", ")").trim();
g = Conversion.replaceOp(g, "and", "&&");
g = Conversion.replaceOp(g, "or", "||");
g = Conversion.replaceOp(g, "not", "!");
return g;
}
public String reworkDelay(String _delay) {
switch(timeUnit) {
case USEC:
return _delay;
case MSEC:
return "(" + _delay + ")*1000";
case SEC:
return "(" + _delay + ")*1000000";
}
return _delay;
}
private String modifyMethodName(AvatarBlock _ab, String _call) {
int index;
String ret0 = "";
index = _call.indexOf("=");
if (index > -1) {
ret0 = _call.substring(0, index+1);
_call = _call.substring(index+2, _call.length());
}
return ret0 + _ab.getName() + "__" + _call.trim();
}
private String traceRequest() {
if (!tracing) {
return "";
}
return "traceRequest(__myname, __returnRequest);" + CR;
}
private String traceVariableModification(String blockName, String varName, String type) {
if (!tracing) {
return "";
}
return "traceVariableModification(\"" + blockName + "\", \"" + varName + "\", " + varName + "," + type + ");" + CR;
}
private String traceFunctionCall(String blockName, String functionName, String params) {
if (!tracing) {
return "";
}
if (params == null) {
params = "\"-\"";
}
return "traceFunctionCall(\"" + blockName + "\", \"" + functionName + "\", " + params + ");" + CR;
}
private String traceStateEntering(String name, String stateName) {
if (!tracing) {
return "";
}
return "traceStateEntering(" + name + ", \"" + stateName + "\");" + CR;
}
private String mainDebugMsg(String s) {
if (!debug) {
return "";
}
return "debugMsg(\"" + s + "\");" + CR;
}
private String taskDebugMsg(String s) {
if (!debug) {
return "";
}
return "debug2Msg(__myname, \"" + s + "\");" + CR;
}
public String makeActionsOfTransaction(AvatarBlock _block, AvatarTransition _at) {
String ret = "";
String act;
String var;
String type;
for(int i=0; i<_at.getNbOfAction(); i++) {
// Must know whether this is an action or a method call
AvatarAction actObj = _at.getAction(i);
act = actObj.getName();
if (actObj.isAMethodCall()) {
ret += modifyMethodName(_block, act) + ";" + CR;
} else {
ret += act + ";" + CR;
AvatarAttribute aa;
aa = (AvatarAttribute) ((AvatarActionAssignment) actObj).getLeftHand();
var = aa.getName ();
if (aa != null) {
if (aa.isInt()) {
type = "0";
} else {
type = "1";
}
//ret += "sprintf(__value, \"%d\", " + var + ");" + CR;
ret += traceVariableModification(_block.getName(), var, type);
}
}
}
return ret;
}
}