diff --git a/src/main/java/avatartranslator/AvatarSignal.java b/src/main/java/avatartranslator/AvatarSignal.java index 0785eae2f9666b17de1c703a7e9a1034f90f1475..f960bec2241f432cc649be1a89ab82bdacd751ef 100644 --- a/src/main/java/avatartranslator/AvatarSignal.java +++ b/src/main/java/avatartranslator/AvatarSignal.java @@ -136,7 +136,9 @@ public class AvatarSignal extends AvatarMethod { } return cumul; }*/ - //fin DG + //fin DG + + public AvatarSignal advancedClone(AvatarStateMachineOwner _block) { AvatarSignal as = new AvatarSignal(getName(), getInOut(), getReferenceObject()); setAdvancedClone(as, _block); diff --git a/src/main/java/avatartranslator/AvatarSpecification.java b/src/main/java/avatartranslator/AvatarSpecification.java index 632f52c641e07ff536999d29e1ea23c8f55c97cd..443d92973d06e9b58f44f76463a429f634e1e89c 100644 --- a/src/main/java/avatartranslator/AvatarSpecification.java +++ b/src/main/java/avatartranslator/AvatarSpecification.java @@ -41,8 +41,8 @@ package avatartranslator; import myutil.NameChecker; import myutil.TraceManager; import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; -import ui.TAttribute; import java.util.*; @@ -59,25 +59,23 @@ public class AvatarSpecification extends AvatarElement { public final static int UPPAAL_MAX_INT = 32767; public static String[] ops = {">", "<", "+", "-", "*", "/", "[", "]", "(", ")", ":", "=", "==", ",", "!", "?", "{", "}", "|", "&"}; - public List<String> checkedIDs; private final List<AvatarBlock> blocks; private final List<AvatarRelation> relations; - private List<AvatarInterfaceRelation> irelations; private final List<AvatarAMSInterface> interfaces; /** * The list of all library functions that can be called. */ private final List<AvatarLibraryFunction> libraryFunctions; - - //private AvatarBroadcast broadcast; - private String applicationCode; private final List<AvatarPragma> pragmas; // Security pragmas private final List<String> safetyPragmas; private final HashMap<String, String> safetyPragmasRefs; private final List<AvatarPragmaLatency> latencyPragmas; private final List<AvatarConstant> constants; private final boolean robustnessMade = false; - + public List<String> checkedIDs; + private List<AvatarInterfaceRelation> irelations; + //private AvatarBroadcast broadcast; + private String applicationCode; private Object informationSource; // Element from which the spec has been built @@ -97,956 +95,19 @@ public class AvatarSpecification extends AvatarElement { this.libraryFunctions = new LinkedList<>(); } - - public List<AvatarLibraryFunction> getListOfLibraryFunctions() { - return this.libraryFunctions; - } - - public void addLibraryFunction(AvatarLibraryFunction libraryFunction) { - this.libraryFunctions.add(libraryFunction); - } - - // For code generation - public void addApplicationCode(String _code) { - if (_code == null) { - return; - } - if (applicationCode == null) { - applicationCode = _code; - return; - } - applicationCode += _code + "\n"; - } - - public String getApplicationCode() { - if (applicationCode == null) { - return ""; - } - return applicationCode; - } - - public boolean hasApplicationCode() { - if (applicationCode == null) { - return false; - } - return (applicationCode.indexOf("__user_init()") != -1); - } - - public Object getInformationSource() { - return informationSource; - } - - public void setInformationSource(Object o) { - informationSource = o; - } - - public List<AvatarBlock> getListOfBlocks() { - return blocks; - } - - public List<AvatarAMSInterface> getListOfInterfaces() { - return interfaces; - } - - public List<AvatarRelation> getRelations() { - return relations; - } - - public List<AvatarPragma> getPragmas() { - return pragmas; - } - - public List<String> getSafetyPragmas() { - return safetyPragmas; - } - - public List<AvatarPragmaLatency> getLatencyPragmas() { - return latencyPragmas; - } - - public List<AvatarConstant> getAvatarConstants() { - return constants; - } - - public HashMap<String, String> getSafetyPragmasRefs() { - return safetyPragmasRefs; - } - - public int getNbOfASMGraphicalElements() { - int cpt = 0; - for (AvatarBlock block : blocks) { - cpt += block.getNbOfASMGraphicalElements(); - } - return cpt; - } - - public boolean isASynchronousSignal(AvatarSignal _as) { - for (AvatarRelation ar : relations) { - if (ar.containsSignal(_as)) { - return !(ar.isAsynchronous()); - } - } - - return false; - } - - public AvatarSignal getCorrespondingSignal(AvatarSignal _as) { - for (AvatarRelation ar : relations) { - if (ar.containsSignal(_as)) { - int index = ar.hasSignal(_as); - return ar.getInSignal(index); - } - } - return null; - } - - //DG - public boolean ASynchronousExist() { - List<AvatarRelation> asynchro = getRelations(); - - for (AvatarRelation ar : asynchro) - if (ar.isAsynchronous()) - return true; - - return false; - } - - public boolean AMSExist() { - List<AvatarRelation> ams = getRelations(); - - for (AvatarRelation ar : ams) - if (ar.isAMS()) - return true; - - return false; - } - - // end DG - public void addBlock(AvatarBlock _block) { - blocks.add(_block); - } - - public void addInterface(AvatarAMSInterface _interface) { - interfaces.add(_interface); - } - - /*public void addBroadcastSignal(AvatarSignal _as) { - if (!broadcast.containsSignal(_as)) { - broadcast.addSignal(_as); - } - } - - public AvatarBroadcast getBroadcast() { - return broadcast; - }*/ - - public void addRelation(AvatarRelation _relation) { - relations.add(_relation); - } - - public void addInterfaceRelation(AvatarInterfaceRelation _irelation) { - irelations.add(_irelation); - } - - public void addPragma(AvatarPragma _pragma) { - pragmas.add(_pragma); - } - - public void addSafetyPragma(String _pragma, String _refPragmas) { - safetyPragmas.add(_pragma); - safetyPragmasRefs.put(_pragma, _refPragmas); - } - - public void addLatencyPragma(AvatarPragmaLatency _pragma) { - latencyPragmas.add(_pragma); - } - - public void addConstant(AvatarConstant _constant) { - //Only add unique constants - if (this.getAvatarConstantWithName(_constant.getName()) == null) { - constants.add(_constant); - } - } - - @Override - public String toString() { - //Thread.currentThread().dumpStack(); - StringBuffer sb = new StringBuffer("Blocks:\n"); - //TraceManager.addDev("TS Block"); - for (AvatarBlock block : blocks) { - sb.append("*** " + block.toString() + "\n"); - } - //TraceManager.addDev("TS Relations"); - sb.append("\nRelations:\n"); - for (AvatarRelation relation : relations) { - sb.append("Relation:" + relation.toString() + "\n"); - } - sb.append("\nPragmas:\n"); - for (AvatarPragma pragma : pragmas) { - sb.append("Pragma:" + pragma.toString() + "\n"); - } - for (AvatarConstant constant : constants) { - sb.append("Constant:" + constant.toString() + "\n"); - } - - //TraceManager.addDev("TS All done"); - - return sb.toString(); - } - - public String toShortString() { - //TraceManager.addDev("To Short String"); - //Thread.currentThread().dumpStack(); - StringBuffer sb = new StringBuffer("Blocks:\n"); - for (AvatarBlock block : blocks) { - sb.append("*** " + block.toShortString() + "\n"); - } - sb.append("\nRelations:\n"); - for (AvatarRelation relation : relations) { - sb.append("Relation:" + relation.toString() + "\n"); - } - /*for (AvatarConstant constant: constants){ - sb.append("Constant:" + constant.toString() + "\n"); - }*/ - - return sb.toString(); - } - - public AvatarBlock getBlockWithName(String _name) { - for (AvatarBlock block : blocks) { - if (block.getName().compareTo(_name) == 0) { - return block; - } - } - - return null; - } - - public int getBlockIndex(AvatarBlock _block) { - int cpt = 0; - for (AvatarBlock block : blocks) { - if (block == _block) { - return cpt; - } - cpt++; - } - - return -1; - } - - public AvatarAMSInterface getAMSInterfaceWithName(String _name) { - for (AvatarAMSInterface interf : interfaces) { - if (interf.getName().compareTo(_name) == 0) { - return interf; + public AvatarRelation getAvatarRelationWithBlocks (AvatarBlock block1, AvatarBlock block2, boolean synchronous) { + for(AvatarRelation rel: relations) { + if ( (block1 == rel.block1) || (block1 == rel.block2) ) { + if ( (block2 == rel.block1) || (block2 == rel.block2) ) { + if (rel.isAsynchronous() == !synchronous) { + return rel; + } + } } } - return null; } - public AvatarConstant getAvatarConstantWithName(String _name) { - for (AvatarConstant constant : constants) { - if (constant.getName().compareTo(_name) == 0) { - return constant; - } - } - - return null; - } - - /* Generates the Expression Solvers, returns the AvatarStateMachineElement - * containing the errors */ - public List<AvatarStateMachineElement> generateAllExpressionSolvers() { - List<AvatarStateMachineElement> errors = new ArrayList<>(); - AvatarTransition at; - boolean returnVal; - - AvatarExpressionSolver.emptyAttributesMap(); - - for (AvatarBlock block : getListOfBlocks()) { - AvatarStateMachine asm = block.getStateMachine(); - - for (AvatarStateMachineElement elt : asm.getListOfElements()) { - if (elt instanceof AvatarTransition) { - at = (AvatarTransition) elt; - if (at.isGuarded()) { - returnVal = at.buildGuardSolver(); - if (returnVal == false) { - errors.add(at); - } - } - if (at.hasDelay()) { - returnVal = at.buildDelaySolver(); - if (returnVal == false) { - errors.add(at); - } - } - for (AvatarAction aa : at.getActions()) { - if (aa instanceof AvatarActionAssignment) { - returnVal = ((AvatarActionAssignment) aa).buildActionSolver(block); - if (returnVal == false) { - errors.add(elt); - } - } - } - } else if (elt instanceof AvatarActionOnSignal) { - returnVal = ((AvatarActionOnSignal) elt).buildActionSolver(block); - if (returnVal == false) { - errors.add(elt); - } - } - } - } - - return errors; - } - - public void removeCompositeStates() { - for (AvatarBlock block : blocks) { - //TraceManager.addDev("- - - - - - - - Removing composite states of " + block); - block.getStateMachine().removeCompositeStates(block); - } - } - - public void makeFullStates() { - for (AvatarBlock block : blocks) { - block.getStateMachine().makeFullStates(block); - } - } - - public void removeRandoms() { - for (AvatarBlock block : blocks) { - block.getStateMachine().removeRandoms(block); - } - } - - public void removeAllDelays() { - for (AvatarBlock block : blocks) { - block.getStateMachine().removeAllDelays(); - } - } - - public void removeTimers() { - //renameTimers(); - - List<AvatarBlock> addedBlocks = new LinkedList<AvatarBlock>(); - for (AvatarBlock block : blocks) { - if (block.hasTimerAttribute()) { - block.removeTimers(this, addedBlocks); - } - } - - for (int i = 0; i < addedBlocks.size(); i++) { - addBlock(addedBlocks.get(i)); - } - } - - public void removeConstants() { - for (AvatarBlock block : blocks) { - block.removeConstantAttributes(); - } - } - - public void sortAttributes() { - for (AvatarBlock block : blocks) { - block.sortAttributes(); - } - } - - public void setAttributeOptRatio(int attributeOptRatio) { - for (AvatarBlock block : blocks) { - block.setAttributeOptRatio(attributeOptRatio); - } - } - -// -// private void renameTimers() { -// // Check whether timers have the same name in different blocks -// ArrayList<AvatarAttribute> allTimers = new ArrayList<AvatarAttribute>(); -// for(AvatarBlock block: blocks) { -// allTimers.clear(); -// block.putAllTimers(allTimers); -// for(AvatarAttribute att: allTimers) { -// for(AvatarBlock bl: blocks) { -// if (block != bl) { -// if (bl.hasTimer(att.getName())) { -// // Must change name of timer -// TraceManager.addDev("Changing name of Timer:" + att); -// att.setName(att.getName() + "__" + block.getName()); -// } -// } -// } -// } -// } -// -// } - - /** - * Removes all FIFOs by replacing them with - * synchronous relations and one block per FIFO - * The size of the infinite fifo is max 1024 - * and min 1 - * - * @param _maxSizeOfInfiniteFifo : the max size of the infinite fifo - */ - public void removeFIFOs(int _maxSizeOfInfiniteFifo) { - List<AvatarRelation> oldOnes = new LinkedList<AvatarRelation>(); - List<AvatarRelation> newOnes = new LinkedList<AvatarRelation>(); - - int FIFO_ID = 0; - for (AvatarRelation ar : relations) { - if (ar.isAsynchronous()) { - // Must be removed - int size = Math.min(_maxSizeOfInfiniteFifo, ar.getSizeOfFIFO()); - //TraceManager.addDev("***************************** Size of FIFO:" + size); - size = Math.max(1, size); - FIFO_ID = removeFIFO(ar, size, oldOnes, newOnes, FIFO_ID); - } - } - - for (AvatarRelation ar : oldOnes) { - relations.remove(ar); - } - - for (AvatarRelation ar : newOnes) { - relations.add(ar); - } - - } - - private int removeFIFO(AvatarRelation _ar, int _sizeOfInfiniteFifo, List<AvatarRelation> _oldOnes, List<AvatarRelation> _newOnes, int FIFO_ID) { - for (int i = 0; i < _ar.nbOfSignals(); i++) { - //TraceManager.addDev("FIFO for AR: " + _ar.getBlock1().getName() + " --> " + _ar.getBlock2().getName()); - if (_ar.getSignal1(i).isIn()) { - FIFO_ID = removeFIFO(_ar, _ar.getSignal2(i), _ar.getSignal1(i), _sizeOfInfiniteFifo, _oldOnes, _newOnes, FIFO_ID, _ar.block2, - _ar.block1); - } else { - FIFO_ID = removeFIFO(_ar, _ar.getSignal1(i), _ar.getSignal2(i), _sizeOfInfiniteFifo, _oldOnes, _newOnes, FIFO_ID, _ar.block1, - _ar.block2); - } - } - _oldOnes.add(_ar); - return FIFO_ID; - } - - private int removeFIFO(AvatarRelation _ar, AvatarSignal _sig1, AvatarSignal _sig2, int _sizeOfInfiniteFifo, List<AvatarRelation> _oldOnes, - List<AvatarRelation> _newOnes, int FIFO_ID, AvatarBlock block1, AvatarBlock block2) { - // We create the new block, and the new relation towards the new block - String nameOfBlock = "FIFO_" + _sig1.getName() + "_" + _sig2.getName() + "_" + FIFO_ID; - AvatarBlock fifoBlock = AvatarBlockTemplate.getFifoBlock(nameOfBlock, this, _ar, _ar.getReferenceObject(), _sig1, _sig2, - _sizeOfInfiniteFifo, FIFO_ID); - //fifoBlock.getStateMachine().groupUselessTransitions(fifoBlock); - blocks.add(fifoBlock); - - // We now need to create the new relation - AvatarRelation newAR1 = new AvatarRelation("FIFO_write_" + FIFO_ID, block1, fifoBlock, _ar.getReferenceObject()); - newAR1.setAsynchronous(false); - newAR1.setPrivate(_ar.isPrivate()); - //TraceManager.addDev("FIFO. Connecting " + _sig1.getName() + " to write of FIFO " + fifoBlock.getName()); - newAR1.addSignals(_sig1, fifoBlock.getSignalByName("write")); - _newOnes.add(newAR1); - - AvatarRelation newAR2 = new AvatarRelation("FIFO_read_" + FIFO_ID, fifoBlock, block2, _ar.getReferenceObject()); - newAR2.setAsynchronous(false); - newAR2.setPrivate(_ar.isPrivate()); - //TraceManager.addDev("FIFO. Connecting FIFO " + fifoBlock.getName() + " read to " + _sig2.getName()); - newAR2.addSignals(fifoBlock.getSignalByName("read"), _sig2); - _newOnes.add(newAR2); - - // We also add the query signals to the newAR2 relation - - - AvatarSignal queryS = new AvatarSignal("query_FIFO_read_" + FIFO_ID, AvatarSignal.IN, _sig2.getReferenceObject()); - block2.addSignal(queryS); - AvatarAttribute queryA = new AvatarAttribute("queryA", AvatarType.INTEGER, null, _sig2.getReferenceObject()); - queryS.addParameter(queryA); - - AvatarRelation newAR3 = new AvatarRelation("FIFO_query_" + FIFO_ID, fifoBlock, block2, _ar.getReferenceObject()); - newAR3.setAsynchronous(false); - newAR3.setPrivate(_ar.isPrivate()); - newAR3.addSignals(fifoBlock.getSignalByName("query"), queryS); - _newOnes.add(newAR3); - - // Replace query in block2 for _sig2 by readOnSignal with signal queryS. Use the same attribute as before - block2.replaceQueriesWithReadSignal(_sig2, queryS); - - - FIFO_ID++; - - return FIFO_ID; - } - - public boolean areSynchronized(AvatarSignal as1, AvatarSignal as2) { - AvatarRelation ar = getAvatarRelationWithSignal(as1); - if (ar == null) { - return false; - } - - int index1 = ar.getIndexOfSignal(as1); - int index2 = ar.getIndexOfSignal(as2); - - return (index1 == index2); - } - - public AvatarRelation getAvatarRelationWithSignal(AvatarSignal _as) { - for (AvatarRelation ar : relations) { - if (ar.hasSignal(_as) > -1) { - return ar; - } - } - return null; - } - - public AvatarStateMachineElement getStateMachineElementFromReferenceObject(Object _o) { - AvatarStateMachineElement asme; - for (AvatarBlock block : blocks) { - asme = block.getStateMachineElementFromReferenceObject(_o); - if (asme != null) { - return asme; - } - } - return null; - } - - public AvatarBlock getBlockFromReferenceObject(Object _o) { - for (AvatarBlock block : blocks) { - if (block.containsStateMachineElementWithReferenceObject(_o)) { - return block; - } - } - return null; - } - - public AvatarBlock getBlockWithAttribute(String _attributeName) { - int index; - - for (AvatarBlock block : blocks) { - index = block.getIndexOfAvatarAttributeWithName(_attributeName); - if (index > -1) { - return block; - } - } - return null; - } - - public void removeElseGuards() { - for (AvatarBlock block : blocks) { - removeElseGuards(block.getStateMachine()); - } - for (AvatarLibraryFunction function : libraryFunctions) { - removeElseGuards(function.getStateMachine()); - } - } - - - private void removeElseGuards(AvatarStateMachine asm) { - if (asm == null) - return; - - for (AvatarStateMachineElement asme : asm.getListOfElements()) { - if (!(asme instanceof AvatarState)) - continue; - - //TraceManager.addDev("Working with state " + asme.getNiceName()); - for (AvatarStateMachineElement next : asme.getNexts()) { - if (!(next instanceof AvatarTransition)) - continue; - AvatarTransition at = (AvatarTransition) next; - AvatarGuard ancientGuard = at.getGuard(); - - if (ancientGuard == null) - continue; - - //TraceManager.addDev("[[[[[[[[[[[[[[[ Guard before: " + ancientGuard.toString() + " type:" + ancientGuard.getClass().toString()); - at.setGuard(ancientGuard.getRealGuard(asme)); - //TraceManager.addDev("]]]]]]]]]]]]]]] Guard after: " + at.getGuard().toString()); - } - } - } - - /** - * Removes all function calls by inlining them. - */ - public void removeLibraryFunctionCalls() { - for (AvatarBlock block : this.blocks) { - AvatarStateMachine asm = block.getStateMachine(); - if (asm == null) - continue; - - asm.removeLibraryFunctionCalls(block); - } - - - //TraceManager.addDev("\n\nNew spec:" + this.toString() + "\n"); - } - - public boolean hasLossyChannel() { - for (AvatarRelation relation : relations) - if (relation.isLossy()) - return true; - - return false; - } - - - public void removeEmptyTransitions(boolean _canOptimize) { - for (AvatarBlock block : this.blocks) { - AvatarStateMachine asm = block.getStateMachine(); - if (asm != null) - asm.removeEmptyTransitions(block, _canOptimize); - } - } - - public void groupUselessTransitions() { - for (AvatarBlock block : this.blocks) { - AvatarStateMachine asm = block.getStateMachine(); - if (asm != null) - asm.groupUselessTransitions(block); - } - } - - - public void makeRobustness() { - //TraceManager.addDev("Make robustness"); - if (robustnessMade) { - return; - } - - /*robustnessMade = true; - - TraceManager.addDev("Testing lossy channels"); - - if (hasLossyChannel()) { - TraceManager.addDev("Making robustness"); - int idstate = 0; - for(AvatarBlock block: blocks) { - idstate = block.getStateMachine().makeMessageLostRobustness(idstate); - } - - /*AvatarBlock ab = new AvatarBlock("Robustness__", this.getReferenceObject()); - addBlock(ab); - AvatarMethod am = new AvatarMethod("messageLost", null); - ab.addMethod(am); - AvatarStateMachine asm = ab.getStateMachine(); - AvatarStartState ass = new AvatarStartState("StartState", null); - asm.addElement(ass); - asm.setStartState(ass); - AvatarTransition at = new AvatarTransition("Transition", null); - asm.addElement(at); - ass.addNext(at); - AvatarState state = new AvatarState("MainState", null); - asm.addElement(state); - at.addNext(state); - - // Parsing all state machines to add robustness - AvatarStateMachine sm; - AvatarActionOnSignal aaos; - AvatarSignal as; - AvatarState state0; - int i; - - for(AvatarRelation ar: relations) { - if (ar.isAsynchronous() && ar.isLossy()) { - // Modify the relation - ar.makeRobustness(); - for(i=0; i<ar.nbOfSignals(); i = i+2) { - as = ar.getInSignal(i); - at = new AvatarTransition("TransitionToReceiving", null); - asm.addElement(at); - state.addNext(at); - aaos = new AvatarActionOnSignal("Receiving__" + as.getName(), as, null); - asm.addElement(aaos); - at.addNext(aaos); - at = new AvatarTransition("TransitionToIntermediateState", null); - asm.addElement(at); - state0 = new AvatarState("Choice__" + as.getName(), null); - asm.addElement(state0); - aaos.addNext(at); - at.addNext(state0); - at = new AvatarTransition("TransitionToMainState", null); - at.addAction("messageLost()"); - asm.addElement(at); - state0.addNext(at); - at.addNext(state); - - as = ar.getOutSignal(i+1); - at = new AvatarTransition("TransitionToSending", null); - asm.addElement(at); - aaos = new AvatarActionOnSignal("Sending__" + as.getName(), as, null); - asm.addElement(aaos); - state0.addNext(at); - at.addNext(aaos); - at = new AvatarTransition("TransitionAfterSending", null); - asm.addElement(at); - aaos.addNext(at); - at.addNext(state); - } - - } - } - }*/ - } - - public AvatarSpecification advancedClone() { - AvatarSpecification spec = new AvatarSpecification(this.getName(), this.getReferenceObject()); - Map<AvatarBlock, AvatarBlock> correspondenceBlocks = new HashMap<AvatarBlock, AvatarBlock>(); - - // Cloning block definition - for (AvatarBlock block : blocks) { - AvatarBlock nB = block.advancedClone(spec); - correspondenceBlocks.put(block, nB); - spec.addBlock(nB); - } - - // Handling the clone of fathers - for (AvatarBlock block : blocks) { - AvatarBlock father = block.getFather(); - if (father != null) { - AvatarBlock nb = spec.getBlockWithName(block.getName()); - if (nb != null) { - AvatarBlock nf = spec.getBlockWithName(father.getName()); - if (nf != null) { - //TraceManager.addDev("Setting "+ nf.getName() + " as the father of " + nb.getName()); - nb.setFather(nf); - } - } - } - } - - // Cloning asm - for (AvatarBlock block : blocks) { - AvatarBlock nb = spec.getBlockWithName(block.getName()); - block.getStateMachine().advancedClone(nb.getStateMachine(), nb); - } - - // Relations - for (AvatarRelation relation : relations) { - AvatarRelation nR = relation.advancedClone(correspondenceBlocks); - if (nR != null) { - spec.addRelation(nR); - } - } - - /*for(AvatarPragma pragma: pragmas) { - AvatarPragma nP = pragma.advancedClone(); - spec.addPragma(nP); - }*/ - - for (String safetyPragma : safetyPragmas) { - spec.addSafetyPragma(safetyPragma, safetyPragmasRefs.get(safetyPragma)); - } - - for (AvatarPragmaLatency latencyPragma : latencyPragmas) { - spec.addLatencyPragma(latencyPragma); - } - - for (AvatarConstant constant : constants) { - AvatarConstant cN = constant.advancedClone(); - spec.addConstant(cN); - } - for (String id : checkedIDs) { - spec.checkedIDs.add(id); - } - - spec.setInformationSource(getInformationSource()); - spec.addApplicationCode(getApplicationCode()); - - return spec; - } - - public AvatarAttribute getMatchingAttribute(AvatarAttribute aa) { - for (AvatarBlock block : this.blocks) { - if (block.getName().compareTo(aa.getBlock().getName()) == 0) { - return block.getAvatarAttributeWithName(aa.getName()); - } - } - - return null; - } - - public AvatarDependencyGraph makeDependencyGraph() { - return makeDependencyGraph(true); - } - - public AvatarDependencyGraph makeDependencyGraph(boolean withID) { - AvatarDependencyGraph adg = new AvatarDependencyGraph(); - adg.buildGraph(this, withID); - return adg; - } - - - public AvatarSpecification simplifyFromDependencies(ArrayList<AvatarElement> eltsOfInterest) { - AvatarSpecification clonedSpec = advancedClone(); - AvatarDependencyGraph adg = clonedSpec.makeDependencyGraph(); - AvatarDependencyGraph reducedGraph = adg.reduceGraphBefore(eltsOfInterest); - clonedSpec.reduceFromDependencyGraph(reducedGraph); - return clonedSpec; - } - - - public boolean isSignalUsed(AvatarSignal _sig) { - for(AvatarBlock block: blocks) { - if (block.getStateMachine().isSignalUsed(_sig)) { - return true; - } - } - - return false; - } - - - public void removeUselessSignalAssociations() { - ArrayList<AvatarRelation> mightBeRemoved = new ArrayList<>(); - ArrayList<AvatarSignal> toBeRemoved1 = new ArrayList<>(); - ArrayList<AvatarSignal> toBeRemoved2 = new ArrayList<>(); - - for(AvatarRelation rel: relations) { - // For each signal association, we look for whether it is used or not - for(int i=0; i<rel.getSignals1().size(); i++) { - AvatarSignal sig1 = rel.getSignal1(i); - if (!isSignalUsed(sig1)) { - AvatarSignal sig2 = rel.getSignal2(i); - if (!isSignalUsed(sig2)) { - // We can remove the signals. We remove its declaration in blocks and we remove the signals from the relation - toBeRemoved1.add(sig1); - toBeRemoved2.add(sig2); - mightBeRemoved.add(rel); - } - } - } - } - - // Removing useless signals from blocks - for(AvatarBlock block: blocks) { - block.getSignals().removeAll(toBeRemoved1); - block.getSignals().removeAll(toBeRemoved2); - } - - // Removing signals from relations, and removing relations if applicable - for(int cpt=0; cpt<mightBeRemoved.size(); cpt++) { - AvatarRelation rel = mightBeRemoved.get(cpt); - rel.removeAssociation(toBeRemoved1.get(cpt), toBeRemoved2.get(cpt)); - if (rel.getSignals1().size() == 0) { - relations.remove(rel); - } - } - - } - - public void removeEmptyBlocks() { - // Remove all blocks with no ASM and no signals - ArrayList<AvatarBlock> toBeRemoved = new ArrayList<>(); - for(AvatarBlock block: blocks) { - if (block.getStateMachine().isBasicStateMachine()) { - if (block.getSignals().size() == 0) { - toBeRemoved.add(block); - } - } - } - - // If a block has a father in toBeRemoved, then keep the father, and the father of the father, etc. - for(AvatarBlock block: blocks) { - AvatarBlock bl = block.getFather(); - while(bl != null) { - if (toBeRemoved.contains(bl)) { - toBeRemoved.remove(bl); - } - bl = bl.getFather(); - } - } - - - blocks.removeAll(toBeRemoved); - } - - /** - * Removes attributes that are not used - */ - public void removeUselessAttributes() { - ArrayList<AvatarBlock> toBeRemoved = new ArrayList<>(); - for(AvatarBlock block: blocks) { - block.removeUselessAttributes(); - } - } - - - - - - // TO BE COMPLETED - // We assume the graph has been reduced already to what is necessary: - // We now need to reduce the avatarspec accordingly - public void reduceFromDependencyGraph(AvatarDependencyGraph _adg) { - - // We have to update the state machines according to the graph - for(AvatarBlock block: blocks) { - //TraceManager.addDev("Handling block " + block.getName()); - AvatarStateMachine asm = block.getStateMachine(); - // We first check if the start is still in the graph - // If not, the state machine is empty: we just create a stop, and that's it - AvatarStartState ass = asm.getStartState(); - if (_adg.getFirstStateWithReference(ass) == null) { - TraceManager.addDev("No start state in " + block.getName()); - asm.makeBasicSM(block); - block.clearAttributes(); - } else { - - // Otherwise we keep the start and consider all other elements - // We remove all elements with no correspondence in the graph - // Then, we redo a valid ASM i.e. all elements with no nexts (apart from states) - // are given a stop state after - - TraceManager.addDev("Reducing state machine of " + block.getName()); - - ArrayList<AvatarElement> toRemove = new ArrayList<>(); - for(AvatarStateMachineElement asme: asm.getListOfElements()) { - if (_adg.getFirstStateWithReference(asme) == null) { - boolean toBeRemoved = false; - if (asme instanceof AvatarTransition) { - if (!((AvatarTransition) asme).isEmpty()) { - toBeRemoved = true; - } - } else { - toBeRemoved = true; - } - - if (toBeRemoved) - toRemove.add(asme); - - } - - } - TraceManager.addDev("To remove size: " + toRemove.size() + " size of ASM: " + asm.getListOfElements().size()); - asm.getListOfElements().removeAll(toRemove); - TraceManager.addDev("Removed. New size of ASM: " + asm.getListOfElements().size()); - asm.makeCorrect(block); - } - } - - - // Then we can remove useless attributes i.e attributes that are not used - - - - removeUselessSignalAssociations(); - - removeUselessAttributes(); - - removeEmptyBlocks(); - - } - - - public NameChecker.NamedElement[] getSubNamedElements() { - NameChecker.NamedElement[] lne = new NameChecker.NamedElement[blocks.size()]; - int index = 0; - for(AvatarBlock bl: blocks) { - lne[index] = bl; - index ++; - } - return lne; - } - /* * Typical JSON: * @@ -1452,70 +513,1108 @@ public class AvatarSpecification extends AvatarElement { * * */ - public static AvatarSpecification fromJSON(String _spec, String _name, Object _referenceObject) { - AvatarSpecification spec = new AvatarSpecification(_name, _referenceObject); + public static AvatarSpecification fromJSON(String _spec, String _name, Object _referenceObject) { + AvatarSpecification spec = new AvatarSpecification(_name, _referenceObject); + + int indexStart = _spec.indexOf('{'); + int indexStop = _spec.lastIndexOf('}'); + + if ((indexStart == -1) || (indexStop == -1) || (indexStart > indexStop)) { + throw new org.json.JSONException("Invalid JSON object"); + } + + _spec = _spec.substring(indexStart, indexStop + 1); + + TraceManager.addDev("Cut spec: " + _spec); + + JSONObject mainObject = new JSONObject(_spec); + + JSONArray blocksA = mainObject.getJSONArray("blocks"); + + if (blocksA == null) { + TraceManager.addDev("No blocks in json"); + return spec; + } + + for (int i = 0; i < blocksA.length(); i++) { + JSONObject blockO = blocksA.getJSONObject(i); + String name = spec.removeSpaces(blockO.getString("name")); + if (name != null) { + AvatarBlock newBlock = new AvatarBlock(name, spec, _referenceObject); + spec.addBlock(newBlock); + + try { + JSONArray attributesA = blockO.getJSONArray("attributes"); + + for (int j = 0; j < attributesA.length(); j++) { + String nameA = spec.removeSpaces(attributesA.getJSONObject(j).getString("name")); + String typeA = attributesA.getJSONObject(j).getString("type"); + AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.getType(typeA), newBlock, _referenceObject); + newBlock.addAttribute(aa); + } + } catch (JSONException je) { + } + + try { + JSONArray methodsA = blockO.getJSONArray("methods"); + for (int j = 0; j < methodsA.length(); j++) { + String nameM = spec.removeSpaces(methodsA.getJSONObject(j).getString("name")); + AvatarMethod am = new AvatarMethod(nameM, _referenceObject); + JSONArray params = methodsA.getJSONObject(j).getJSONArray("parameters"); + for (int k = 0; k < params.length(); k++) { + String nameA = spec.removeSpaces(params.getJSONObject(k).getString("name")); + String typeA = params.getJSONObject(k).getString("type"); + AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.getType(typeA), newBlock, _referenceObject); + am.addParameter(aa); + } + String returnT = methodsA.getJSONObject(j).getString("returnType"); + AvatarType at = AvatarType.getType(returnT); + if (at != AvatarType.UNDEFINED) { + am.addReturnParameter(new AvatarAttribute("returnType", at, newBlock, _referenceObject)); + } + + newBlock.addMethod(am); + } + } catch (JSONException je) { + } + + try { + JSONArray signalS = blockO.getJSONArray("signals"); + for (int j = 0; j < signalS.length(); j++) { + String nameS = spec.removeSpaces(signalS.getJSONObject(j).getString("name")); + String typeS = signalS.getJSONObject(j).getString("type"); + int inout = AvatarSignal.IN; + if (typeS.compareTo("output") == 0) { + inout = AvatarSignal.OUT; + } + AvatarSignal as = new AvatarSignal(nameS, inout, _referenceObject); + + JSONArray params = signalS.getJSONObject(j).getJSONArray("parameters"); + for (int k = 0; k < params.length(); k++) { + String nameA = spec.removeSpaces(params.getJSONObject(k).getString("name")); + String typeA = params.getJSONObject(k).getString("type"); + AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.getType(typeA), newBlock, _referenceObject); + as.addParameter(aa); + } + + newBlock.addSignal(as); + } + } catch (JSONException je) { + } + + } + } + + JSONArray connections = mainObject.getJSONArray("connections"); + + if (connections == null) { + TraceManager.addDev("No connections in json"); + return spec; + } + + for (int i = 0; i < connections.length(); i++) { + JSONObject blockO = connections.getJSONObject(i); + String sourceBlock = spec.removeSpaces(blockO.getString("sourceBlock")); + + AvatarBlock srcB = spec.getBlockWithName(sourceBlock); + if (srcB == null) { + srcB = new AvatarBlock(sourceBlock, spec, _referenceObject); + spec.addBlock(srcB); + } + String sourceSignal = spec.removeSpaces(blockO.getString("sourceSignal")); + AvatarSignal srcSig = srcB.getSignalByName(sourceSignal); + + if (srcSig == null) { + srcSig = new AvatarSignal(sourceSignal, AvatarSignal.OUT, _referenceObject); + srcB.addSignal(srcSig); + } + if (srcSig.isIn()) { + TraceManager.addDev("Signal " + sourceSignal + " in block: " + sourceBlock + " should be out"); + continue; + } + String destinationBlock = spec.removeSpaces(blockO.getString("destinationBlock")); + AvatarBlock dstB = spec.getBlockWithName(destinationBlock); + + if (dstB == null) { + dstB = new AvatarBlock(destinationBlock, spec, _referenceObject); + spec.addBlock(dstB); + } + String dstSignal = spec.removeSpaces(blockO.getString("destinationSignal")); + AvatarSignal dstSig = srcB.getSignalByName(dstSignal); + + if (dstSig == null) { + dstSig = new AvatarSignal(sourceSignal, AvatarSignal.IN, _referenceObject); + dstB.addSignal(dstSig); + } + if (srcSig.isOut()) { + TraceManager.addDev("Signal " + dstSignal + " in block: " + destinationBlock + " should be in"); + continue; + } + + if (!srcSig.isCompatibleWith(dstSig)) { + TraceManager.addDev("Signals " + srcSig + " and " + dstSignal + " are not compatible"); + continue; + } + + String communicationType = spec.removeSpaces(blockO.getString("communicationType")); + boolean synchronous = communicationType.compareTo("synchronous") == 0; + + AvatarRelation ar = spec.getAvatarRelationWithBlocks(srcB, dstB, synchronous); + + if (ar == null) { + ar = new AvatarRelation("relation", srcB, dstB, _referenceObject); + ar.setAsynchronous(!synchronous); + spec.addRelation(ar); + } + + ar.addSignals(srcSig, dstSig); + + } + + + return spec; + + } + + public String removeSpaces(String _input) { + return _input.trim().replaceAll(" ", "_"); + } + + public List<AvatarLibraryFunction> getListOfLibraryFunctions() { + return this.libraryFunctions; + } + + public void addLibraryFunction(AvatarLibraryFunction libraryFunction) { + this.libraryFunctions.add(libraryFunction); + } + + // For code generation + public void addApplicationCode(String _code) { + if (_code == null) { + return; + } + if (applicationCode == null) { + applicationCode = _code; + return; + } + applicationCode += _code + "\n"; + } + + public String getApplicationCode() { + if (applicationCode == null) { + return ""; + } + return applicationCode; + } + + public boolean hasApplicationCode() { + if (applicationCode == null) { + return false; + } + return (applicationCode.indexOf("__user_init()") != -1); + } + + public Object getInformationSource() { + return informationSource; + } + + public void setInformationSource(Object o) { + informationSource = o; + } + + public List<AvatarBlock> getListOfBlocks() { + return blocks; + } + + public List<AvatarAMSInterface> getListOfInterfaces() { + return interfaces; + } + + public List<AvatarRelation> getRelations() { + return relations; + } + + public List<AvatarPragma> getPragmas() { + return pragmas; + } + + public List<String> getSafetyPragmas() { + return safetyPragmas; + } + + public List<AvatarPragmaLatency> getLatencyPragmas() { + return latencyPragmas; + } + + public List<AvatarConstant> getAvatarConstants() { + return constants; + } + + public HashMap<String, String> getSafetyPragmasRefs() { + return safetyPragmasRefs; + } + + public int getNbOfASMGraphicalElements() { + int cpt = 0; + for (AvatarBlock block : blocks) { + cpt += block.getNbOfASMGraphicalElements(); + } + return cpt; + } + + public boolean isASynchronousSignal(AvatarSignal _as) { + for (AvatarRelation ar : relations) { + if (ar.containsSignal(_as)) { + return !(ar.isAsynchronous()); + } + } + + return false; + } + + public AvatarSignal getCorrespondingSignal(AvatarSignal _as) { + for (AvatarRelation ar : relations) { + if (ar.containsSignal(_as)) { + int index = ar.hasSignal(_as); + return ar.getInSignal(index); + } + } + return null; + } + + //DG + public boolean ASynchronousExist() { + List<AvatarRelation> asynchro = getRelations(); + + for (AvatarRelation ar : asynchro) + if (ar.isAsynchronous()) + return true; + + return false; + } + + public boolean AMSExist() { + List<AvatarRelation> ams = getRelations(); + + for (AvatarRelation ar : ams) + if (ar.isAMS()) + return true; + + return false; + } + + // end DG + public void addBlock(AvatarBlock _block) { + blocks.add(_block); + } + + /*public void addBroadcastSignal(AvatarSignal _as) { + if (!broadcast.containsSignal(_as)) { + broadcast.addSignal(_as); + } + } + + public AvatarBroadcast getBroadcast() { + return broadcast; + }*/ + + public void addInterface(AvatarAMSInterface _interface) { + interfaces.add(_interface); + } + + public void addRelation(AvatarRelation _relation) { + relations.add(_relation); + } + + public void addInterfaceRelation(AvatarInterfaceRelation _irelation) { + irelations.add(_irelation); + } + + public void addPragma(AvatarPragma _pragma) { + pragmas.add(_pragma); + } + + public void addSafetyPragma(String _pragma, String _refPragmas) { + safetyPragmas.add(_pragma); + safetyPragmasRefs.put(_pragma, _refPragmas); + } + + public void addLatencyPragma(AvatarPragmaLatency _pragma) { + latencyPragmas.add(_pragma); + } + + public void addConstant(AvatarConstant _constant) { + //Only add unique constants + if (this.getAvatarConstantWithName(_constant.getName()) == null) { + constants.add(_constant); + } + } + + @Override + public String toString() { + //Thread.currentThread().dumpStack(); + StringBuffer sb = new StringBuffer("Blocks:\n"); + //TraceManager.addDev("TS Block"); + for (AvatarBlock block : blocks) { + sb.append("*** " + block.toString() + "\n"); + } + //TraceManager.addDev("TS Relations"); + sb.append("\nRelations:\n"); + for (AvatarRelation relation : relations) { + sb.append("Relation:" + relation.toString() + "\n"); + } + sb.append("\nPragmas:\n"); + for (AvatarPragma pragma : pragmas) { + sb.append("Pragma:" + pragma.toString() + "\n"); + } + for (AvatarConstant constant : constants) { + sb.append("Constant:" + constant.toString() + "\n"); + } + + //TraceManager.addDev("TS All done"); + + return sb.toString(); + } + + public String toShortString() { + //TraceManager.addDev("To Short String"); + //Thread.currentThread().dumpStack(); + StringBuffer sb = new StringBuffer("Blocks:\n"); + for (AvatarBlock block : blocks) { + sb.append("*** " + block.toShortString() + "\n"); + } + sb.append("\nRelations:\n"); + for (AvatarRelation relation : relations) { + sb.append("Relation:" + relation.toString() + "\n"); + } + /*for (AvatarConstant constant: constants){ + sb.append("Constant:" + constant.toString() + "\n"); + }*/ + + return sb.toString(); + } + + public AvatarBlock getBlockWithName(String _name) { + for (AvatarBlock block : blocks) { + if (block.getName().compareTo(_name) == 0) { + return block; + } + } + + return null; + } + + public int getBlockIndex(AvatarBlock _block) { + int cpt = 0; + for (AvatarBlock block : blocks) { + if (block == _block) { + return cpt; + } + cpt++; + } + + return -1; + } + + public AvatarAMSInterface getAMSInterfaceWithName(String _name) { + for (AvatarAMSInterface interf : interfaces) { + if (interf.getName().compareTo(_name) == 0) { + return interf; + } + } + + return null; + } + + public AvatarConstant getAvatarConstantWithName(String _name) { + for (AvatarConstant constant : constants) { + if (constant.getName().compareTo(_name) == 0) { + return constant; + } + } + + return null; + } + + /* Generates the Expression Solvers, returns the AvatarStateMachineElement + * containing the errors */ + public List<AvatarStateMachineElement> generateAllExpressionSolvers() { + List<AvatarStateMachineElement> errors = new ArrayList<>(); + AvatarTransition at; + boolean returnVal; + + AvatarExpressionSolver.emptyAttributesMap(); + + for (AvatarBlock block : getListOfBlocks()) { + AvatarStateMachine asm = block.getStateMachine(); + + for (AvatarStateMachineElement elt : asm.getListOfElements()) { + if (elt instanceof AvatarTransition) { + at = (AvatarTransition) elt; + if (at.isGuarded()) { + returnVal = at.buildGuardSolver(); + if (returnVal == false) { + errors.add(at); + } + } + if (at.hasDelay()) { + returnVal = at.buildDelaySolver(); + if (returnVal == false) { + errors.add(at); + } + } + for (AvatarAction aa : at.getActions()) { + if (aa instanceof AvatarActionAssignment) { + returnVal = ((AvatarActionAssignment) aa).buildActionSolver(block); + if (returnVal == false) { + errors.add(elt); + } + } + } + } else if (elt instanceof AvatarActionOnSignal) { + returnVal = ((AvatarActionOnSignal) elt).buildActionSolver(block); + if (returnVal == false) { + errors.add(elt); + } + } + } + } + + return errors; + } + + public void removeCompositeStates() { + for (AvatarBlock block : blocks) { + //TraceManager.addDev("- - - - - - - - Removing composite states of " + block); + block.getStateMachine().removeCompositeStates(block); + } + } + + public void makeFullStates() { + for (AvatarBlock block : blocks) { + block.getStateMachine().makeFullStates(block); + } + } + + public void removeRandoms() { + for (AvatarBlock block : blocks) { + block.getStateMachine().removeRandoms(block); + } + } + + public void removeAllDelays() { + for (AvatarBlock block : blocks) { + block.getStateMachine().removeAllDelays(); + } + } + + public void removeTimers() { + //renameTimers(); + + List<AvatarBlock> addedBlocks = new LinkedList<AvatarBlock>(); + for (AvatarBlock block : blocks) { + if (block.hasTimerAttribute()) { + block.removeTimers(this, addedBlocks); + } + } + + for (int i = 0; i < addedBlocks.size(); i++) { + addBlock(addedBlocks.get(i)); + } + } + + public void removeConstants() { + for (AvatarBlock block : blocks) { + block.removeConstantAttributes(); + } + } + + public void sortAttributes() { + for (AvatarBlock block : blocks) { + block.sortAttributes(); + } + } + +// +// private void renameTimers() { +// // Check whether timers have the same name in different blocks +// ArrayList<AvatarAttribute> allTimers = new ArrayList<AvatarAttribute>(); +// for(AvatarBlock block: blocks) { +// allTimers.clear(); +// block.putAllTimers(allTimers); +// for(AvatarAttribute att: allTimers) { +// for(AvatarBlock bl: blocks) { +// if (block != bl) { +// if (bl.hasTimer(att.getName())) { +// // Must change name of timer +// TraceManager.addDev("Changing name of Timer:" + att); +// att.setName(att.getName() + "__" + block.getName()); +// } +// } +// } +// } +// } +// +// } + + public void setAttributeOptRatio(int attributeOptRatio) { + for (AvatarBlock block : blocks) { + block.setAttributeOptRatio(attributeOptRatio); + } + } + + /** + * Removes all FIFOs by replacing them with + * synchronous relations and one block per FIFO + * The size of the infinite fifo is max 1024 + * and min 1 + * + * @param _maxSizeOfInfiniteFifo : the max size of the infinite fifo + */ + public void removeFIFOs(int _maxSizeOfInfiniteFifo) { + List<AvatarRelation> oldOnes = new LinkedList<AvatarRelation>(); + List<AvatarRelation> newOnes = new LinkedList<AvatarRelation>(); + + int FIFO_ID = 0; + for (AvatarRelation ar : relations) { + if (ar.isAsynchronous()) { + // Must be removed + int size = Math.min(_maxSizeOfInfiniteFifo, ar.getSizeOfFIFO()); + //TraceManager.addDev("***************************** Size of FIFO:" + size); + size = Math.max(1, size); + FIFO_ID = removeFIFO(ar, size, oldOnes, newOnes, FIFO_ID); + } + } + + for (AvatarRelation ar : oldOnes) { + relations.remove(ar); + } + + for (AvatarRelation ar : newOnes) { + relations.add(ar); + } + + } + + private int removeFIFO(AvatarRelation _ar, int _sizeOfInfiniteFifo, List<AvatarRelation> _oldOnes, List<AvatarRelation> _newOnes, int FIFO_ID) { + for (int i = 0; i < _ar.nbOfSignals(); i++) { + //TraceManager.addDev("FIFO for AR: " + _ar.getBlock1().getName() + " --> " + _ar.getBlock2().getName()); + if (_ar.getSignal1(i).isIn()) { + FIFO_ID = removeFIFO(_ar, _ar.getSignal2(i), _ar.getSignal1(i), _sizeOfInfiniteFifo, _oldOnes, _newOnes, FIFO_ID, _ar.block2, + _ar.block1); + } else { + FIFO_ID = removeFIFO(_ar, _ar.getSignal1(i), _ar.getSignal2(i), _sizeOfInfiniteFifo, _oldOnes, _newOnes, FIFO_ID, _ar.block1, + _ar.block2); + } + } + _oldOnes.add(_ar); + return FIFO_ID; + } + + private int removeFIFO(AvatarRelation _ar, AvatarSignal _sig1, AvatarSignal _sig2, int _sizeOfInfiniteFifo, List<AvatarRelation> _oldOnes, + List<AvatarRelation> _newOnes, int FIFO_ID, AvatarBlock block1, AvatarBlock block2) { + // We create the new block, and the new relation towards the new block + String nameOfBlock = "FIFO_" + _sig1.getName() + "_" + _sig2.getName() + "_" + FIFO_ID; + AvatarBlock fifoBlock = AvatarBlockTemplate.getFifoBlock(nameOfBlock, this, _ar, _ar.getReferenceObject(), _sig1, _sig2, + _sizeOfInfiniteFifo, FIFO_ID); + //fifoBlock.getStateMachine().groupUselessTransitions(fifoBlock); + blocks.add(fifoBlock); + + // We now need to create the new relation + AvatarRelation newAR1 = new AvatarRelation("FIFO_write_" + FIFO_ID, block1, fifoBlock, _ar.getReferenceObject()); + newAR1.setAsynchronous(false); + newAR1.setPrivate(_ar.isPrivate()); + //TraceManager.addDev("FIFO. Connecting " + _sig1.getName() + " to write of FIFO " + fifoBlock.getName()); + newAR1.addSignals(_sig1, fifoBlock.getSignalByName("write")); + _newOnes.add(newAR1); + + AvatarRelation newAR2 = new AvatarRelation("FIFO_read_" + FIFO_ID, fifoBlock, block2, _ar.getReferenceObject()); + newAR2.setAsynchronous(false); + newAR2.setPrivate(_ar.isPrivate()); + //TraceManager.addDev("FIFO. Connecting FIFO " + fifoBlock.getName() + " read to " + _sig2.getName()); + newAR2.addSignals(fifoBlock.getSignalByName("read"), _sig2); + _newOnes.add(newAR2); + + // We also add the query signals to the newAR2 relation + + + AvatarSignal queryS = new AvatarSignal("query_FIFO_read_" + FIFO_ID, AvatarSignal.IN, _sig2.getReferenceObject()); + block2.addSignal(queryS); + AvatarAttribute queryA = new AvatarAttribute("queryA", AvatarType.INTEGER, null, _sig2.getReferenceObject()); + queryS.addParameter(queryA); + + AvatarRelation newAR3 = new AvatarRelation("FIFO_query_" + FIFO_ID, fifoBlock, block2, _ar.getReferenceObject()); + newAR3.setAsynchronous(false); + newAR3.setPrivate(_ar.isPrivate()); + newAR3.addSignals(fifoBlock.getSignalByName("query"), queryS); + _newOnes.add(newAR3); + + // Replace query in block2 for _sig2 by readOnSignal with signal queryS. Use the same attribute as before + block2.replaceQueriesWithReadSignal(_sig2, queryS); + + + FIFO_ID++; + + return FIFO_ID; + } + + public boolean areSynchronized(AvatarSignal as1, AvatarSignal as2) { + AvatarRelation ar = getAvatarRelationWithSignal(as1); + if (ar == null) { + return false; + } + + int index1 = ar.getIndexOfSignal(as1); + int index2 = ar.getIndexOfSignal(as2); + + return (index1 == index2); + } + + public AvatarRelation getAvatarRelationWithSignal(AvatarSignal _as) { + for (AvatarRelation ar : relations) { + if (ar.hasSignal(_as) > -1) { + return ar; + } + } + return null; + } + + public AvatarStateMachineElement getStateMachineElementFromReferenceObject(Object _o) { + AvatarStateMachineElement asme; + for (AvatarBlock block : blocks) { + asme = block.getStateMachineElementFromReferenceObject(_o); + if (asme != null) { + return asme; + } + } + return null; + } + + public AvatarBlock getBlockFromReferenceObject(Object _o) { + for (AvatarBlock block : blocks) { + if (block.containsStateMachineElementWithReferenceObject(_o)) { + return block; + } + } + return null; + } + + public AvatarBlock getBlockWithAttribute(String _attributeName) { + int index; + + for (AvatarBlock block : blocks) { + index = block.getIndexOfAvatarAttributeWithName(_attributeName); + if (index > -1) { + return block; + } + } + return null; + } + + public void removeElseGuards() { + for (AvatarBlock block : blocks) { + removeElseGuards(block.getStateMachine()); + } + for (AvatarLibraryFunction function : libraryFunctions) { + removeElseGuards(function.getStateMachine()); + } + } + + private void removeElseGuards(AvatarStateMachine asm) { + if (asm == null) + return; + + for (AvatarStateMachineElement asme : asm.getListOfElements()) { + if (!(asme instanceof AvatarState)) + continue; + + //TraceManager.addDev("Working with state " + asme.getNiceName()); + for (AvatarStateMachineElement next : asme.getNexts()) { + if (!(next instanceof AvatarTransition)) + continue; + AvatarTransition at = (AvatarTransition) next; + AvatarGuard ancientGuard = at.getGuard(); + + if (ancientGuard == null) + continue; + + //TraceManager.addDev("[[[[[[[[[[[[[[[ Guard before: " + ancientGuard.toString() + " type:" + ancientGuard.getClass().toString()); + at.setGuard(ancientGuard.getRealGuard(asme)); + //TraceManager.addDev("]]]]]]]]]]]]]]] Guard after: " + at.getGuard().toString()); + } + } + } + + /** + * Removes all function calls by inlining them. + */ + public void removeLibraryFunctionCalls() { + for (AvatarBlock block : this.blocks) { + AvatarStateMachine asm = block.getStateMachine(); + if (asm == null) + continue; + + asm.removeLibraryFunctionCalls(block); + } + + + //TraceManager.addDev("\n\nNew spec:" + this.toString() + "\n"); + } + + public boolean hasLossyChannel() { + for (AvatarRelation relation : relations) + if (relation.isLossy()) + return true; + + return false; + } + + public void removeEmptyTransitions(boolean _canOptimize) { + for (AvatarBlock block : this.blocks) { + AvatarStateMachine asm = block.getStateMachine(); + if (asm != null) + asm.removeEmptyTransitions(block, _canOptimize); + } + } + + public void groupUselessTransitions() { + for (AvatarBlock block : this.blocks) { + AvatarStateMachine asm = block.getStateMachine(); + if (asm != null) + asm.groupUselessTransitions(block); + } + } + + public void makeRobustness() { + //TraceManager.addDev("Make robustness"); + if (robustnessMade) { + return; + } + + /*robustnessMade = true; + + TraceManager.addDev("Testing lossy channels"); + + if (hasLossyChannel()) { + TraceManager.addDev("Making robustness"); + int idstate = 0; + for(AvatarBlock block: blocks) { + idstate = block.getStateMachine().makeMessageLostRobustness(idstate); + } + + /*AvatarBlock ab = new AvatarBlock("Robustness__", this.getReferenceObject()); + addBlock(ab); + AvatarMethod am = new AvatarMethod("messageLost", null); + ab.addMethod(am); + AvatarStateMachine asm = ab.getStateMachine(); + AvatarStartState ass = new AvatarStartState("StartState", null); + asm.addElement(ass); + asm.setStartState(ass); + AvatarTransition at = new AvatarTransition("Transition", null); + asm.addElement(at); + ass.addNext(at); + AvatarState state = new AvatarState("MainState", null); + asm.addElement(state); + at.addNext(state); + + // Parsing all state machines to add robustness + AvatarStateMachine sm; + AvatarActionOnSignal aaos; + AvatarSignal as; + AvatarState state0; + int i; + + for(AvatarRelation ar: relations) { + if (ar.isAsynchronous() && ar.isLossy()) { + // Modify the relation + ar.makeRobustness(); + for(i=0; i<ar.nbOfSignals(); i = i+2) { + as = ar.getInSignal(i); + at = new AvatarTransition("TransitionToReceiving", null); + asm.addElement(at); + state.addNext(at); + aaos = new AvatarActionOnSignal("Receiving__" + as.getName(), as, null); + asm.addElement(aaos); + at.addNext(aaos); + at = new AvatarTransition("TransitionToIntermediateState", null); + asm.addElement(at); + state0 = new AvatarState("Choice__" + as.getName(), null); + asm.addElement(state0); + aaos.addNext(at); + at.addNext(state0); + at = new AvatarTransition("TransitionToMainState", null); + at.addAction("messageLost()"); + asm.addElement(at); + state0.addNext(at); + at.addNext(state); + + as = ar.getOutSignal(i+1); + at = new AvatarTransition("TransitionToSending", null); + asm.addElement(at); + aaos = new AvatarActionOnSignal("Sending__" + as.getName(), as, null); + asm.addElement(aaos); + state0.addNext(at); + at.addNext(aaos); + at = new AvatarTransition("TransitionAfterSending", null); + asm.addElement(at); + aaos.addNext(at); + at.addNext(state); + } - int indexStart = _spec.indexOf('{'); - int indexStop = _spec.lastIndexOf('}'); + } + } + }*/ + } - if ((indexStart == -1) || (indexStop == -1) || (indexStart > indexStop)) { - throw new org.json.JSONException("Invalid JSON object"); + public AvatarSpecification advancedClone() { + AvatarSpecification spec = new AvatarSpecification(this.getName(), this.getReferenceObject()); + Map<AvatarBlock, AvatarBlock> correspondenceBlocks = new HashMap<AvatarBlock, AvatarBlock>(); + + // Cloning block definition + for (AvatarBlock block : blocks) { + AvatarBlock nB = block.advancedClone(spec); + correspondenceBlocks.put(block, nB); + spec.addBlock(nB); } - _spec = _spec.substring(indexStart, indexStop+1); + // Handling the clone of fathers + for (AvatarBlock block : blocks) { + AvatarBlock father = block.getFather(); + if (father != null) { + AvatarBlock nb = spec.getBlockWithName(block.getName()); + if (nb != null) { + AvatarBlock nf = spec.getBlockWithName(father.getName()); + if (nf != null) { + //TraceManager.addDev("Setting "+ nf.getName() + " as the father of " + nb.getName()); + nb.setFather(nf); + } + } + } + } - TraceManager.addDev("Cut spec: " + _spec); + // Cloning asm + for (AvatarBlock block : blocks) { + AvatarBlock nb = spec.getBlockWithName(block.getName()); + block.getStateMachine().advancedClone(nb.getStateMachine(), nb); + } - JSONObject mainObject = new JSONObject(_spec); + // Relations + for (AvatarRelation relation : relations) { + AvatarRelation nR = relation.advancedClone(correspondenceBlocks); + if (nR != null) { + spec.addRelation(nR); + } + } - JSONArray blocksA = mainObject.getJSONArray("blocks"); + /*for(AvatarPragma pragma: pragmas) { + AvatarPragma nP = pragma.advancedClone(); + spec.addPragma(nP); + }*/ - if (blocksA == null) { - TraceManager.addDev("No blocks in json"); - return spec; + for (String safetyPragma : safetyPragmas) { + spec.addSafetyPragma(safetyPragma, safetyPragmasRefs.get(safetyPragma)); } - for (int i=0; i<blocksA.length(); i++) { - JSONObject blockO = blocksA.getJSONObject(i); - String name = blockO.getString("name"); - if (name != null) { - AvatarBlock newBlock = new AvatarBlock(name, spec, _referenceObject); - spec.addBlock(newBlock); + for (AvatarPragmaLatency latencyPragma : latencyPragmas) { + spec.addLatencyPragma(latencyPragma); + } + + for (AvatarConstant constant : constants) { + AvatarConstant cN = constant.advancedClone(); + spec.addConstant(cN); + } + for (String id : checkedIDs) { + spec.checkedIDs.add(id); + } - JSONArray attributesA = blockO.getJSONArray("attributes"); + spec.setInformationSource(getInformationSource()); + spec.addApplicationCode(getApplicationCode()); - for (int j=0; j<attributesA.length(); j++) { - String nameA = attributesA.getJSONObject(j).getString("name"); - String typeA = attributesA.getJSONObject(j).getString("type"); - AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.getType(typeA), newBlock, _referenceObject); - newBlock.addAttribute(aa); - } + return spec; + } - JSONArray methodsA = blockO.getJSONArray("methods"); - for (int j=0; j<methodsA.length(); j++) { - String nameM = methodsA.getJSONObject(j).getString("name"); - AvatarMethod am = new AvatarMethod(nameM, _referenceObject); - JSONArray params = methodsA.getJSONObject(j).getJSONArray("paremeters"); - for(int k=0; k<params.length(); k++) { - String nameA = params.getJSONObject(k).getString("name"); - String typeA = params.getJSONObject(k).getString("type"); - AvatarAttribute aa = new AvatarAttribute(nameA, AvatarType.getType(typeA), newBlock, _referenceObject); - am.addParameter(aa); - } - String returnT = methodsA.getJSONObject(j).getString("returnType"); - AvatarType at = AvatarType.getType(returnT); - if (at != AvatarType.UNDEFINED) { - am.addReturnParameter(new AvatarAttribute("returnType", at, newBlock, _referenceObject)); + public AvatarAttribute getMatchingAttribute(AvatarAttribute aa) { + for (AvatarBlock block : this.blocks) { + if (block.getName().compareTo(aa.getBlock().getName()) == 0) { + return block.getAvatarAttributeWithName(aa.getName()); + } + } + + return null; + } + + public AvatarDependencyGraph makeDependencyGraph() { + return makeDependencyGraph(true); + } + + public AvatarDependencyGraph makeDependencyGraph(boolean withID) { + AvatarDependencyGraph adg = new AvatarDependencyGraph(); + adg.buildGraph(this, withID); + return adg; + } + + public AvatarSpecification simplifyFromDependencies(ArrayList<AvatarElement> eltsOfInterest) { + AvatarSpecification clonedSpec = advancedClone(); + AvatarDependencyGraph adg = clonedSpec.makeDependencyGraph(); + AvatarDependencyGraph reducedGraph = adg.reduceGraphBefore(eltsOfInterest); + clonedSpec.reduceFromDependencyGraph(reducedGraph); + return clonedSpec; + } + + public boolean isSignalUsed(AvatarSignal _sig) { + for (AvatarBlock block : blocks) { + if (block.getStateMachine().isSignalUsed(_sig)) { + return true; + } + } + + return false; + } + + public void removeUselessSignalAssociations() { + ArrayList<AvatarRelation> mightBeRemoved = new ArrayList<>(); + ArrayList<AvatarSignal> toBeRemoved1 = new ArrayList<>(); + ArrayList<AvatarSignal> toBeRemoved2 = new ArrayList<>(); + + for (AvatarRelation rel : relations) { + // For each signal association, we look for whether it is used or not + for (int i = 0; i < rel.getSignals1().size(); i++) { + AvatarSignal sig1 = rel.getSignal1(i); + if (!isSignalUsed(sig1)) { + AvatarSignal sig2 = rel.getSignal2(i); + if (!isSignalUsed(sig2)) { + // We can remove the signals. We remove its declaration in blocks and we remove the signals from the relation + toBeRemoved1.add(sig1); + toBeRemoved2.add(sig2); + mightBeRemoved.add(rel); } + } + } + } + + // Removing useless signals from blocks + for (AvatarBlock block : blocks) { + block.getSignals().removeAll(toBeRemoved1); + block.getSignals().removeAll(toBeRemoved2); + } + + // Removing signals from relations, and removing relations if applicable + for (int cpt = 0; cpt < mightBeRemoved.size(); cpt++) { + AvatarRelation rel = mightBeRemoved.get(cpt); + rel.removeAssociation(toBeRemoved1.get(cpt), toBeRemoved2.get(cpt)); + if (rel.getSignals1().size() == 0) { + relations.remove(rel); + } + } + + } - newBlock.addMethod(am); + public void removeEmptyBlocks() { + // Remove all blocks with no ASM and no signals + ArrayList<AvatarBlock> toBeRemoved = new ArrayList<>(); + for (AvatarBlock block : blocks) { + if (block.getStateMachine().isBasicStateMachine()) { + if (block.getSignals().size() == 0) { + toBeRemoved.add(block); } + } + } + // If a block has a father in toBeRemoved, then keep the father, and the father of the father, etc. + for (AvatarBlock block : blocks) { + AvatarBlock bl = block.getFather(); + while (bl != null) { + if (toBeRemoved.contains(bl)) { + toBeRemoved.remove(bl); + } + bl = bl.getFather(); } } - return spec; + blocks.removeAll(toBeRemoved); + } + + /** + * Removes attributes that are not used + */ + public void removeUselessAttributes() { + ArrayList<AvatarBlock> toBeRemoved = new ArrayList<>(); + for (AvatarBlock block : blocks) { + block.removeUselessAttributes(); + } + } + + // TO BE COMPLETED + // We assume the graph has been reduced already to what is necessary: + // We now need to reduce the avatarspec accordingly + public void reduceFromDependencyGraph(AvatarDependencyGraph _adg) { + + // We have to update the state machines according to the graph + for (AvatarBlock block : blocks) { + //TraceManager.addDev("Handling block " + block.getName()); + AvatarStateMachine asm = block.getStateMachine(); + // We first check if the start is still in the graph + // If not, the state machine is empty: we just create a stop, and that's it + AvatarStartState ass = asm.getStartState(); + if (_adg.getFirstStateWithReference(ass) == null) { + TraceManager.addDev("No start state in " + block.getName()); + asm.makeBasicSM(block); + block.clearAttributes(); + } else { + + // Otherwise we keep the start and consider all other elements + // We remove all elements with no correspondence in the graph + // Then, we redo a valid ASM i.e. all elements with no nexts (apart from states) + // are given a stop state after + + TraceManager.addDev("Reducing state machine of " + block.getName()); + + ArrayList<AvatarElement> toRemove = new ArrayList<>(); + for (AvatarStateMachineElement asme : asm.getListOfElements()) { + if (_adg.getFirstStateWithReference(asme) == null) { + boolean toBeRemoved = false; + if (asme instanceof AvatarTransition) { + if (!((AvatarTransition) asme).isEmpty()) { + toBeRemoved = true; + } + } else { + toBeRemoved = true; + } + + if (toBeRemoved) + toRemove.add(asme); + + } + + } + TraceManager.addDev("To remove size: " + toRemove.size() + " size of ASM: " + asm.getListOfElements().size()); + asm.getListOfElements().removeAll(toRemove); + TraceManager.addDev("Removed. New size of ASM: " + asm.getListOfElements().size()); + asm.makeCorrect(block); + } + } + + + // Then we can remove useless attributes i.e attributes that are not used + + + removeUselessSignalAssociations(); + + removeUselessAttributes(); + + removeEmptyBlocks(); + + } + + public NameChecker.NamedElement[] getSubNamedElements() { + NameChecker.NamedElement[] lne = new NameChecker.NamedElement[blocks.size()]; + int index = 0; + for (AvatarBlock bl : blocks) { + lne[index] = bl; + index++; + } + return lne; } } diff --git a/src/main/java/ui/util/IconManager.java b/src/main/java/ui/util/IconManager.java index 95ee2562bfb2a095719437cea1c9f0575f684937..f35f5964c736c58159abb692a8689cfd1adb3359 100755 --- a/src/main/java/ui/util/IconManager.java +++ b/src/main/java/ui/util/IconManager.java @@ -42,6 +42,11 @@ package ui.util; import javax.swing.*; import java.awt.*; import java.net.URL; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; +import java.awt.image.BufferedImage; +import javax.swing.ImageIcon; /** @@ -1329,4 +1334,24 @@ public class IconManager { imgic8030 = getIcon(icon8030); } + + + public static ImageIcon rotateImageIcon(ImageIcon icon, double degrees) { + int w = icon.getIconWidth(); + int h = icon.getIconHeight(); + int type = BufferedImage.TYPE_INT_ARGB; // Other options + BufferedImage image = new BufferedImage(h, w, type); + Graphics2D g2 = image.createGraphics(); + double x = (h - w)/2.0; + double y = (h - w)/2.0; + AffineTransform at = AffineTransform.getTranslateInstance(x, y); + at.rotate(Math.toRadians(degrees), w/2.0, h/2.0); + g2.setBackground(Color.white); + g2.drawImage(icon.getImage(), at, null); + g2.dispose(); + icon = new ImageIcon(image); + return icon; + } + + } // Class diff --git a/src/main/java/ui/window/JFrameAI.java b/src/main/java/ui/window/JFrameAI.java index f6523ccb96ae532cda4f2a6b83737782654b5416..8459cfca2f223e0fe40755563141eaa3de451b6f 100644 --- a/src/main/java/ui/window/JFrameAI.java +++ b/src/main/java/ui/window/JFrameAI.java @@ -62,6 +62,7 @@ import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; +import java.util.HashMap; /** @@ -102,13 +103,13 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable { private String KNOWLEDGE_ON_JSON_FOR_BLOCKS = "JSON for block diagram is as follows: " + "{blocks: [{ \"name\": \"Name of block\", \"attributes\": [\"name\": \"name of attribute\", \"type\": \"int or boolean\" ...}" + " same" + "(with its parameters : int, boolean ; and its return type : nothing, int or boolean)" + - "and signals (with its list of parameters : int or boolean ; and each signal is either an output signal or an input signal), ..." + + "and signals (with its list of parameters : int or boolean, and a type (input, output)" + " then the list of connections between block signals: \"connections\": [\n" +"{\n" + " \"sourceBlock\": \"name of block\",\n" + " \"sourceSignal\": \"name of output signal\",\n" + " \"destinationBlock\": \"name of destination block\",\n" + " \"destinationSignal\": \"rechargeBattery\",\n" + " \"communicationType\": \"synchronous (or asynchronous)\"\n" + - "},"; + "}. A connection must connect one output signal of a block to one input signal of a block"; private String QUESTION_IDENTIFY_SYSTEM_BLOCKS = "From the following system specification, using the specified JSON format, identify the " + "typical system blocks. All this in JSON.\n"; @@ -133,7 +134,9 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable { private boolean go = false; - private class ChatData { + private HashMap<Integer, ImageIcon> rotatedI = new HashMap<>(); + + private class ChatData implements Runnable { public AIInterface aiinterface; public boolean knowledgeOnProperties = false; public boolean knowledgeOnBlockJSON = false; @@ -141,6 +144,9 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable { public String lastAnswer = ""; public int previousKind; public TDiagramPanel tdp; + public boolean doIconRotation = false; + private Thread t; + public ChatData() {} @@ -148,8 +154,49 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable { lastAnswer = ""; answer.setText(""); } + + public void startAnimation() { + doIconRotation = true; + t = new Thread(this); + t.start(); + } + + public void stopAnimation() { + doIconRotation = false; + if (t != null) { + t.interrupt(); + } + t = null; + } + + + public void run() { + int angle = 0; + + while( doIconRotation ) { + angle = (angle - 15) % 360; + ImageIcon rotated = rotatedI.get(angle); + if ( rotated == null ) { + rotated = IconManager.rotateImageIcon(IconManager.imgic154, angle); + rotatedI.put(angle, rotated); + } + + setIcon(this, rotated); + try { + Thread.currentThread().sleep(100); + } catch (Exception e) { + TraceManager.addDev("Interrupted"); + doIconRotation = false; + }; + } + setIcon(this, IconManager.imgic154); + } } + public void setIcon(ChatData _data, Icon newIcon) { + int index = chats.indexOf(_data); + answerPane.setIconAt(index, newIcon); + } private JButton buttonClose, buttonStart, buttonApplyResponse; @@ -325,6 +372,9 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable { private void close() { + for(ChatData data: chats) { + data.stopAnimation(); + } dispose(); } @@ -480,6 +530,8 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable { } public void run() { + ChatData selected = selectedChat(); + selected.startAnimation(); go = true; enableDisableActions(); @@ -506,6 +558,7 @@ public class JFrameAI extends JFrame implements ActionListener, Runnable { } go = false; + selected.stopAnimation(); enableDisableActions(); }