summaryrefslogtreecommitdiffstats
path: root/src/uscxml/transform
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml/transform')
-rw-r--r--src/uscxml/transform/ChartToFSM.cpp179
-rw-r--r--src/uscxml/transform/ChartToFSM.h38
-rw-r--r--src/uscxml/transform/ChartToPromela.cpp288
-rw-r--r--src/uscxml/transform/ChartToPromela.h10
-rw-r--r--src/uscxml/transform/Transformer.h6
5 files changed, 266 insertions, 255 deletions
diff --git a/src/uscxml/transform/ChartToFSM.cpp b/src/uscxml/transform/ChartToFSM.cpp
index 971ee10..ef59d84 100644
--- a/src/uscxml/transform/ChartToFSM.cpp
+++ b/src/uscxml/transform/ChartToFSM.cpp
@@ -21,6 +21,7 @@
#include "uscxml/transform/FlatStateIdentifier.h"
#include "uscxml/Convenience.h"
#include "uscxml/Factory.h"
+#include "uscxml/debug/Complexity.h"
#include <DOM/io/Stream.hpp>
#include <glog/logging.h>
@@ -91,171 +92,6 @@ for (int i = 0; i < contents.size(); i++) { \
} \
std::cerr << ")";
-std::list<std::set<Element<std::string> > > Complexity::getAllConfigurations(const Arabica::DOM::Element<std::string>& root) {
-
- std::list<std::set<Element<std::string> > > allConfigurations;
- std::string nsPrefix = (root.getPrefix().size() > 0 ? root.getPrefix() + ":" : "");
- std::string localName = root.getLocalName();
- bool isAtomic = true;
-
- NodeList<std::string> children = root.getChildNodes();
- for (int i = 0; i < children.getLength(); i++) {
- if (children.item(i).getNodeType() != Node_base::ELEMENT_NODE)
- continue;
- Element<std::string> childElem(children.item(i));
- if (childElem.getTagName() == nsPrefix + "state" ||
- childElem.getTagName() == nsPrefix + "parallel" ||
- childElem.getTagName() == nsPrefix + "final") {
- // nested child state
- std::list<std::set<Element<std::string> > > nestedConfigurations = getAllConfigurations(childElem);
- isAtomic = false;
- if (localName == "parallel" && allConfigurations.size() > 0) {
- // for every nested configuration, every new nested is valid
- std::list<std::set<Element<std::string> > > combinedConfigurations;
- for (std::list<std::set<Element<std::string> > >::iterator existIter = allConfigurations.begin(); existIter != allConfigurations.end(); existIter++) {
- std::set<Element<std::string> > existingConfig = *existIter;
-
- for (std::list<std::set<Element<std::string> > >::iterator newIter = nestedConfigurations.begin(); newIter != nestedConfigurations.end(); newIter++) {
-
- std::set<Element<std::string> > newConfig = *newIter;
- std::set<Element<std::string> > combinedSet;
- combinedSet.insert(existingConfig.begin(), existingConfig.end());
- combinedSet.insert(newConfig.begin(), newConfig.end());
-
- combinedConfigurations.push_back(combinedSet);
- }
- }
- allConfigurations = combinedConfigurations;
- } else {
- // just add nested configurations and this
- for (std::list<std::set<Element<std::string> > >::iterator newIter = nestedConfigurations.begin(); newIter != nestedConfigurations.end(); newIter++) {
- std::set<Element<std::string> > newConfig = *newIter;
- if (localName != "scxml")
- newConfig.insert(root);
- allConfigurations.push_back(newConfig);
- }
- }
- }
- }
-
- if (isAtomic) {
- std::set<Element<std::string> > soleConfig;
- soleConfig.insert(root);
- allConfigurations.push_back(soleConfig);
- }
- return allConfigurations;
-}
-
-std::map<size_t, size_t> Complexity::getTransitionHistogramm(const Arabica::DOM::Element<std::string>& root) {
- std::map<size_t, size_t> histogram;
- std::string nameSpace;
-
- std::list<std::set<Element<std::string> > > allConfig = Complexity::getAllConfigurations(root);
-
- // for every legal configuration, count the transitions
- for (std::list<std::set<Element<std::string> > >::iterator confIter = allConfig.begin(); confIter != allConfig.end(); confIter++) {
- NodeSet<std::string> configNodeSet;
- std::set<Element<std::string> > config = *confIter;
- for (std::set<Element<std::string> >::iterator elemIter = config.begin(); elemIter != config.end(); elemIter++) {
- configNodeSet.push_back(*elemIter);
- if (nameSpace.size() == 0 && elemIter->getPrefix().size() > 0)
- nameSpace = elemIter->getPrefix() + ":";
- }
- NodeSet<std::string> transitions = InterpreterImpl::filterChildElements(nameSpace + "transition", configNodeSet);
- histogram[transitions.size()]++;
- }
-
- return histogram;
-}
-
-
-uint64_t Complexity::stateMachineComplexity(const Arabica::DOM::Element<std::string>& root, Variant variant) {
- Complexity complexity = calculateStateMachineComplexity(root);
- uint64_t value = complexity.value;
-
- if (variant != IGNORE_HISTORY_AND_NESTED_DATA && variant != IGNORE_HISTORY) {
- for (std::list<uint64_t>::const_iterator histIter = complexity.history.begin(); histIter != complexity.history.end(); histIter++) {
- value *= *histIter;
- }
- }
-
- if (variant != IGNORE_HISTORY_AND_NESTED_DATA && variant != IGNORE_NESTED_DATA) {
- bool ignoreNestedData = false;
- if (root.getLocalName() == "scxml" && (!HAS_ATTR_CAST(root, "binding") || boost::to_lower_copy(ATTR_CAST(root, "binding")) == "early")) {
- ignoreNestedData = true;
- }
-
- if (!ignoreNestedData) {
- uint64_t power = complexity.nestedData;
- while(power--) {
- value *= 2;
- }
- }
- }
-
- return value;
-}
-
-Complexity Complexity::calculateStateMachineComplexity(const Arabica::DOM::Element<std::string>& root) {
- Complexity complexity;
-
- bool hasFlatHistory = false;
- bool hasDeepHistory = false;
- bool hasNestedData = false;
-
- Arabica::DOM::NodeList<std::string> childElems = root.getChildNodes();
- for (int i = 0; i < childElems.getLength(); i++) {
- if (childElems.item(i).getNodeType() != Node_base::ELEMENT_NODE)
- continue;
- Element<std::string> childElem = Element<std::string>(childElems.item(i));
- if (InterpreterImpl::isHistory(childElem)) {
- if (HAS_ATTR(childElem, "type") && ATTR(childElem, "type") == "deep") {
- hasDeepHistory = true;
- } else {
- hasFlatHistory = true;
- }
- }
- if (!hasNestedData && childElem.getLocalName() == "datamodel") {
- Arabica::DOM::NodeList<std::string> dataElemChilds = childElem.getChildNodes();
- for (int j = 0; j < dataElemChilds.getLength(); j++) {
- if (dataElemChilds.item(j).getLocalName() == "data")
- hasNestedData = true;
- }
- }
- }
-
- if (hasNestedData)
- complexity.nestedData++;
-
- if (InterpreterImpl::isCompound(root) || TAGNAME(root) == "scxml") {
- // compounds can be in any of the child state -> add
- NodeSet<std::string> childs = InterpreterImpl::getChildStates(root);
- for (int i = 0; i < childs.size(); i++) {
- complexity += calculateStateMachineComplexity(Element<std::string>(childs[i]));
- }
- if (hasFlatHistory) {
- complexity.history.push_back(childs.size());
- }
- if (hasDeepHistory) {
- complexity.history.push_back(complexity.value);
- }
- } else if (InterpreterImpl::isParallel(root)) {
- // parallels are in all states -> multiply
- NodeSet<std::string> childs = InterpreterImpl::getChildStates(root);
- complexity.value = 1;
- for (int i = 0; i < childs.size(); i++) {
- complexity *= calculateStateMachineComplexity(Element<std::string>(childs[i]));
- }
- if (hasDeepHistory) {
- complexity.history.push_back(complexity.value);
- }
-
- } else if (InterpreterImpl::isAtomic(root)) {
- return 1;
- }
-
- return complexity;
-}
ChartToFSM::ChartToFSM(const Interpreter& other) {
@@ -314,7 +150,6 @@ ChartToFSM::~ChartToFSM() {
for (int i = 0; i < allTransitions.size(); i++) {
_transParents.erase(allTransitions[i]);
}
-
}
Document<std::string> ChartToFSM::getDocument() const {
@@ -325,10 +160,6 @@ Document<std::string> ChartToFSM::getDocument() const {
InterpreterState ChartToFSM::interpret() {
- // create a _flatDoc for the FSM
- DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
- _flatDoc = domFactory.createDocument(_document.getNamespaceURI(), "", 0);
-
init();
setupIOProcessors();
@@ -350,9 +181,9 @@ InterpreterState ChartToFSM::interpret() {
std::map<size_t, size_t> histoGramm = Complexity::getTransitionHistogramm(_scxml);
// abort();
- uint64_t complexity = Complexity::stateMachineComplexity(_scxml) + 1;
+ uint64_t complexity = Complexity::stateMachineComplexity(this) + 1;
std::cerr << "Approximate Complexity: " << complexity << std::endl;
- std::cerr << "Approximate Active Complexity: " << Complexity::stateMachineComplexity(_scxml, Complexity::IGNORE_HISTORY_AND_NESTED_DATA) + 1 << std::endl;
+ std::cerr << "Approximate Active Complexity: " << Complexity::stateMachineComplexity(this, Complexity::IGNORE_HISTORY | Complexity::IGNORE_NESTED_DATA) + 1 << std::endl;
if (complexity > 1000) {
_skipEventChainCalculations = true;
@@ -478,6 +309,10 @@ InterpreterState ChartToFSM::interpret() {
// std::cerr << _scxml << std::endl;
+ // create a _flatDoc for the FSM
+ DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation();
+ _flatDoc = domFactory.createDocument(_document.getNamespaceURI(), "", 0);
+
GlobalTransition* globalTransition = new GlobalTransition(initialTransitions, _dataModel, this);
globalTransition->index = _lastTransIndex++;
diff --git a/src/uscxml/transform/ChartToFSM.h b/src/uscxml/transform/ChartToFSM.h
index 1dc8813..9d1ed97 100644
--- a/src/uscxml/transform/ChartToFSM.h
+++ b/src/uscxml/transform/ChartToFSM.h
@@ -33,44 +33,6 @@ class GlobalState;
class GlobalTransition;
class ChartToFSM;
-class USCXML_API Complexity {
-public:
-
- enum Variant {
- IGNORE_NOTHING,
- IGNORE_HISTORY,
- IGNORE_NESTED_DATA,
- IGNORE_HISTORY_AND_NESTED_DATA,
- };
-
- Complexity() : value(0), nestedData(0) {}
- Complexity(uint64_t value) : value(value), nestedData(0) {}
-
- Complexity& operator+=(const Complexity& rhs) {
- value += rhs.value;
- nestedData += rhs.nestedData;
- history.insert(history.end(), rhs.history.begin(), rhs.history.end());
- return *this;
- }
-
- Complexity& operator*=(const Complexity& rhs) {
- value *= rhs.value;
- nestedData += rhs.nestedData;
- history.insert(history.end(), rhs.history.begin(), rhs.history.end());
- return *this;
- }
-
- static uint64_t stateMachineComplexity(const Arabica::DOM::Element<std::string>& root, Complexity::Variant variant = IGNORE_NOTHING);
- static std::list<std::set<Arabica::DOM::Element<std::string> > > getAllConfigurations(const Arabica::DOM::Element<std::string>& root);
- static std::map<size_t, size_t> getTransitionHistogramm(const Arabica::DOM::Element<std::string>& root);
-
-protected:
- static Complexity calculateStateMachineComplexity(const Arabica::DOM::Element<std::string>& root);
-
- uint64_t value;
- uint64_t nestedData;
- std::list<uint64_t> history;
-};
class USCXML_API GlobalState {
public:
diff --git a/src/uscxml/transform/ChartToPromela.cpp b/src/uscxml/transform/ChartToPromela.cpp
index 806c1f4..867092d 100644
--- a/src/uscxml/transform/ChartToPromela.cpp
+++ b/src/uscxml/transform/ChartToPromela.cpp
@@ -17,6 +17,8 @@
* @endcond
*/
+#define NEW_DELAY_RESHUFFLE 1
+
#include "uscxml/transform/ChartToFSM.h"
#include "uscxml/transform/ChartToPromela.h"
#include "uscxml/transform/FlatStateIdentifier.h"
@@ -99,6 +101,16 @@ for (int indentIndex = start; indentIndex < cols; indentIndex++) \
} \
}
+#define TRANSITION_TRACE(transList, value) \
+if (_traceTransitions) { \
+for (std::set<int>::iterator transRefIter = transList->transitionRefs.begin(); \
+ transRefIter != transList->transitionRefs.end(); \
+ transRefIter++) { \
+ stream << padding << _prefix << "transitions[" << *transRefIter << "] = "#value"; " << std::endl; \
+ } \
+} \
+
+
#define DUMP_STATS(disregardTime) \
uint64_t now = tthread::chrono::system_clock::now(); \
if (now - _lastTimeStamp > 1000 || disregardTime) { \
@@ -372,6 +384,47 @@ std::string PromelaCodeAnalyzer::createMacroName(const std::string& literal) {
return macroName;
}
+std::string PromelaCodeAnalyzer::getTypeReset(const std::string& var, const PromelaTypedef& type, const std::string padding) {
+ std::stringstream assignment;
+
+ std::map<std::string, PromelaTypedef>::const_iterator typeIter = type.types.begin();
+ while(typeIter != type.types.end()) {
+ const PromelaTypedef& innerType = typeIter->second;
+ if (innerType.arraySize > 0) {
+ for (int i = 0; i < innerType.arraySize; i++) {
+ assignment << padding << var << "." << typeIter->first << "[" << i << "] = 0;" << std::endl;
+ }
+ } else if (innerType.types.size() > 0) {
+ assignment << getTypeReset(var + "." + typeIter->first, typeIter->second, padding);
+ } else {
+ assignment << padding << var << "." << typeIter->first << " = 0;" << std::endl;
+ }
+ typeIter++;
+ }
+ return assignment.str();
+
+}
+
+std::string PromelaCodeAnalyzer::getTypeAssignment(const std::string& varTo, const std::string& varFrom, const PromelaTypedef& type, const std::string padding) {
+ std::stringstream assignment;
+
+ std::map<std::string, PromelaTypedef>::const_iterator typeIter = type.types.begin();
+ while(typeIter != type.types.end()) {
+ const PromelaTypedef& innerType = typeIter->second;
+ if (innerType.arraySize > 0) {
+ for (int i = 0; i < innerType.arraySize; i++) {
+ assignment << padding << varTo << "." << typeIter->first << "[" << i << "] = " << varFrom << "." << typeIter->first << "[" << i << "];" << std::endl;
+ }
+ } else if (innerType.types.size() > 0) {
+ assignment << getTypeAssignment(varTo + "." + typeIter->first, varFrom + "." + typeIter->first, typeIter->second, padding);
+ } else {
+ assignment << padding << varTo << "." << typeIter->first << " = " << varFrom << "." << typeIter->first << ";" << std::endl;
+ }
+ typeIter++;
+ }
+ return assignment.str();
+}
+
std::string PromelaCodeAnalyzer::macroForLiteral(const std::string& literal) {
if (boost::starts_with(literal, "'"))
throw std::runtime_error("Literal " + literal + " passed with quotes");
@@ -617,7 +670,10 @@ void ChartToPromela::writeTypeDefs(std::ostream& stream) {
if (_analyzer->usesEventField("delay")) {
// make sure delay is the first member for sorted enqueuing to work
stream << " int delay;" << std::endl;
- stream << " int seqNr;" << std::endl;
+#if NEW_DELAY_RESHUFFLE
+#else
+ stream << " int seqNr;" << std::endl;
+#endif
}
stream << " int name;" << std::endl;
if (_analyzer->usesEventField("invokeid")) {
@@ -1147,11 +1203,13 @@ void ChartToPromela::writeTransition(std::ostream& stream, GlobalTransition* tra
// stream << padding << "}" << std::endl;
stream << padding << "fi;" << std::endl;
}
+
+ TRANSITION_TRACE(transition, false);
- // moved up here for goto from d_step
padding = padding.substr(2);
- stream << padding << "}" << std::endl;
+ stream << padding << "}" << std::endl;
+ // moved up here for goto from d_step
writeTransitionClosure(stream, transition, origNewState, indent-1);
_perfTransProcessed++;
@@ -1409,11 +1467,11 @@ void ChartToPromela::writeTransitionClosure(std::ostream& stream, GlobalTransiti
padding += " ";
}
- if (_traceTransitions) {
- for (std::set<int>::iterator transRefIter = transition->transitionRefs.begin(); transRefIter != transition->transitionRefs.end(); transRefIter++) {
- stream << padding << _prefix << "transitions[" << *transRefIter << "] = false; " << std::endl;
- }
- }
+// if (_traceTransitions) {
+// for (std::set<int>::iterator transRefIter = transition->transitionRefs.begin(); transRefIter != transition->transitionRefs.end(); transRefIter++) {
+// stream << padding << _prefix << "transitions[" << *transRefIter << "] = false; " << std::endl;
+// }
+// }
if (state->isFinal) {
stream << padding << "goto " << _prefix << "terminate;" << std::endl;
@@ -1518,20 +1576,21 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica:
} else if(TAGNAME(nodeElem) == "send" || TAGNAME(nodeElem) == "raise") {
std::string targetQueue;
+ std::string insertOp = "!";
if (TAGNAME(nodeElem) == "raise") {
- targetQueue = _prefix + "iQ!";
+ targetQueue = _prefix + "iQ";
} else if (!HAS_ATTR(nodeElem, "target")) {
if (_allowEventInterleaving) {
- targetQueue = _prefix + "tmpQ!";
+ targetQueue = _prefix + "tmpQ";
} else {
- targetQueue = _prefix + "eQ!";
+ targetQueue = _prefix + "eQ";
}
} else if (ATTR(nodeElem, "target").compare("#_internal") == 0) {
- targetQueue = _prefix + "iQ!";
+ targetQueue = _prefix + "iQ";
} else if (ATTR(nodeElem, "target").compare("#_parent") == 0) {
- targetQueue = _parent->_prefix + "eQ!";
+ targetQueue = _parent->_prefix + "eQ";
} else if (boost::starts_with(ATTR(nodeElem, "target"), "#_") && _machinesPerId.find(ATTR(nodeElem, "target").substr(2)) != _machinesPerId.end()) {
- targetQueue = _machines[_machinesPerId[ATTR(nodeElem, "target").substr(2)]]->_prefix + "eQ!";
+ targetQueue = _machines[_machinesPerId[ATTR(nodeElem, "target").substr(2)]]->_prefix + "eQ";
}
if (targetQueue.length() > 0) {
// this is for our external queue
@@ -1544,8 +1603,8 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica:
}
if (_analyzer->usesComplexEventStruct()) {
stream << padding << "{" << std::endl;
- stream << padding << " _event_t tmpE;" << std::endl;
- stream << padding << " tmpE.name = " << event << ";" << std::endl;
+ stream << _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), padding + " ");
+ stream << padding << " tmpE.name = " << event << ";" << std::endl;
if (HAS_ATTR(nodeElem, "idlocation")) {
stream << padding << " /* idlocation */" << std::endl;
@@ -1564,13 +1623,16 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica:
stream << padding << " tmpE.invokeid = " << _analyzer->macroForLiteral(_invokerid) << ";" << std::endl;
}
- if (_analyzer->usesEventField("origintype") && !boost::ends_with(targetQueue, "iQ!")) {
+ if (_analyzer->usesEventField("origintype") && !boost::ends_with(targetQueue, "iQ")) {
stream << padding << " tmpE.origintype = " << _analyzer->macroForLiteral("http://www.w3.org/TR/scxml/#SCXMLEventProcessor") << ";" << std::endl;
}
if (_analyzer->usesEventField("delay")) {
- targetQueue += "!";
+#if NEW_DELAY_RESHUFFLE
+#else
+ insertOp += "!";
stream << padding << " _lastSeqId = _lastSeqId + 1;" << std::endl;
+#endif
if (HAS_ATTR_CAST(nodeElem, "delay")) {
stream << padding << " tmpE.delay = " << ATTR_CAST(nodeElem, "delay") << ";" << std::endl;
} else if (HAS_ATTR_CAST(nodeElem, "delayexpr")) {
@@ -1578,7 +1640,10 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica:
} else {
stream << padding << " tmpE.delay = 0;" << std::endl;
}
- stream << padding << " tmpE.seqNr = _lastSeqId;" << std::endl;
+#if NEW_DELAY_RESHUFFLE
+#else
+ stream << padding << " tmpE.seqNr = _lastSeqId;" << std::endl;
+#endif
}
if (_analyzer->usesEventField("type")) {
@@ -1617,10 +1682,17 @@ void ChartToPromela::writeExecutableContent(std::ostream& stream, const Arabica:
stream << padding << " tmpE.data = " << ADAPT_SRC(ATTR(contentElem, "expr")) << ";" << std::endl;
}
}
- stream << padding << " " << targetQueue << "tmpE;" << std::endl;
+ stream << padding << " " << targetQueue << insertOp <<"tmpE;" << std::endl;
+
+#if NEW_DELAY_RESHUFFLE
+ if (_analyzer->usesEventField("delay") && !boost::ends_with(targetQueue, "iQ")) {
+ stream << padding << " insertWithDelay(" << targetQueue << ");" << std::endl;
+ }
+#endif
+
stream << padding << "}" << std::endl;
} else {
- stream << padding << targetQueue << event << ";" << std::endl;
+ stream << padding << targetQueue << insertOp << event << ";" << std::endl;
}
}
} else if(TAGNAME(nodeElem) == "cancel") {
@@ -1961,7 +2033,10 @@ void ChartToPromela::writeDeclarations(std::ostream& stream) {
}
if (_analyzer->usesEventField("delay")) {
+#if NEW_DELAY_RESHUFFLE
+#else
stream << "hidden int _lastSeqId = 0; /* sequential counter for delayed events */" << std::endl;
+#endif
}
}
// if (_analyzer->usesPlatformVars()) {
@@ -2107,10 +2182,12 @@ void ChartToPromela::writeFSM(std::ostream& stream) {
NodeSet<std::string> transitions;
stream << "proctype " << (_prefix.size() == 0 ? "machine_" : _prefix) << "run() {" << std::endl;
- stream << " " << _prefix << "done = false;" << std::endl;
- stream << " " << _prefix << "canceled = false;" << std::endl;
- stream << " " << _prefix << "spontaneous = true;" << std::endl;
- stream << " " << _prefix << "procid = _pid;" << std::endl;
+ stream << " d_step {" << std::endl;
+ stream << " " << _prefix << "done = false;" << std::endl;
+ stream << " " << _prefix << "canceled = false;" << std::endl;
+ stream << " " << _prefix << "spontaneous = true;" << std::endl;
+ stream << " " << _prefix << "procid = _pid;" << std::endl;
+ stream << " }" << std::endl;
// write initial transition
// transitions = filterChildElements(_nsInfo.xmlNSPrefix + "transition", _startState);
// assert(transitions.size() == 1);
@@ -2160,8 +2237,12 @@ void ChartToPromela::writeFSM(std::ostream& stream) {
stream << " /* push send events to external queue - this needs to be interleavable! */" << std::endl;
stream << " do" << std::endl;
if (_analyzer->usesEventField("delay")) {
- stream << " :: len(" << _prefix << "tmpQ) != 0 -> { " << _prefix << "tmpQ?" << _prefix << "_event; " << _prefix << "eQ!!" << _prefix << "_event }" << std::endl;
- } else {
+#if NEW_DELAY_RESHUFFLE
+ stream << " :: len(" << _prefix << "tmpQ) != 0 -> { " << _prefix << "tmpQ?" << _prefix << "_event; " << _prefix << "eQ!" << _prefix << "_event; insertWithDelay(" << _prefix << "eQ); }" << std::endl;
+#else
+ stream << " :: len(" << _prefix << "tmpQ) != 0 -> { " << _prefix << "tmpQ?" << _prefix << "_event; " << _prefix << "eQ!!" << _prefix << "_event }" << std::endl;
+#endif
+ } else {
stream << " :: len(" << _prefix << "tmpQ) != 0 -> { " << _prefix << "tmpQ?" << _prefix << "_event; " << _prefix << "eQ!" << _prefix << "_event }" << std::endl;
}
stream << " :: else -> break;" << std::endl;
@@ -2326,7 +2407,11 @@ void ChartToPromela::writeFSM(std::ostream& stream) {
stream << " if" << std::endl;
stream << " :: " << invIter->second->_prefix << "done -> skip;" << std::endl;
stream << " :: " << invIter->second->_prefix << "canceled -> skip;" << std::endl;
- stream << " :: else -> { " << invIter->second->_prefix << "eQ!!" << _prefix << "_event" << " }" << std::endl;
+#if NEW_DELAY_RESHUFFLE
+ stream << " :: else -> { " << invIter->second->_prefix << "eQ!" << _prefix << "_event" << "; insertWithDelay(" << invIter->second->_prefix << "eQ" << "); }" << std::endl;
+#else
+ stream << " :: else -> { " << invIter->second->_prefix << "eQ!!" << _prefix << "_event" << " }" << std::endl;
+#endif
stream << " fi;" << std::endl << std::endl;
}
@@ -2347,16 +2432,22 @@ void ChartToPromela::writeFSM(std::ostream& stream) {
if (_parent != NULL) {
stream << " {" << std::endl;
- stream << " _event_t tmpE;" << std::endl;
+ stream << _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), " ");
stream << " tmpE.name = " << _analyzer->macroForLiteral("done.invoke." + _invokerid) << ";" << std::endl;
if (_invokerid.length() > 0) {
stream << " tmpE.invokeid = " << _analyzer->macroForLiteral(_invokerid) << ";" << std::endl;
}
if (_analyzer->usesEventField("delay")) {
- stream << " _lastSeqId = _lastSeqId + 1;" << std::endl;
- stream << " tmpE.seqNr = _lastSeqId;" << std::endl;
- stream << " " << _parent->_prefix << "eQ!!tmpE;" << std::endl;
- } else {
+#if NEW_DELAY_RESHUFFLE
+ stream << " " << _parent->_prefix << "eQ!tmpE;" << std::endl;
+ stream << " insertWithDelay(" << _parent->_prefix << "eQ);" << std::endl;
+
+#else
+ stream << " _lastSeqId = _lastSeqId + 1;" << std::endl;
+ stream << " tmpE.seqNr = _lastSeqId;" << std::endl;
+ stream << " " << _parent->_prefix << "eQ!!tmpE;" << std::endl;
+#endif
+ } else {
stream << " " << _parent->_prefix << "eQ!tmpE;" << std::endl;
}
stream << " }" << std::endl;
@@ -2380,7 +2471,7 @@ void ChartToPromela::writeRescheduleProcess(std::ostream& stream, int indent) {
} else {
stream << padding << "inline rescheduleProcess(smallestDelay, procId, internalQ, externalQ) {" << std::endl;
}
- stream << padding << " _event_t tmpE;" << std::endl;
+// stream << _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), " ");
stream << padding << " set_priority(procId, 1);" << std::endl;
stream << padding << " if" << std::endl;
@@ -2420,7 +2511,7 @@ void ChartToPromela::writeDetermineShortestDelay(std::ostream& stream, int inden
}
stream << padding << "inline determineSmallestDelay(smallestDelay, queue) {" << std::endl;
- stream << padding << " _event_t tmpE;" << std::endl;
+// stream << padding << _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), " ");
stream << padding << " if" << std::endl;
stream << padding << " :: len(queue) > 0 -> {" << std::endl;
stream << padding << " queue?<tmpE>;" << std::endl;
@@ -2434,6 +2525,100 @@ void ChartToPromela::writeDetermineShortestDelay(std::ostream& stream, int inden
stream << padding << "}" << std::endl;
}
+void ChartToPromela::writeInsertWithDelay(std::ostream& stream, int indent) {
+ std::string padding;
+ for (int i = 0; i < indent; i++) {
+ padding += " ";
+ }
+
+ uint32_t maxExternalQueueLength = 1;
+ std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator machineIter = _machinesAll->begin();
+ while(machineIter != _machinesAll->end()) {
+ maxExternalQueueLength = std::max(maxExternalQueueLength, machineIter->second->_externalQueueLength);
+ machineIter++;
+ }
+
+ maxExternalQueueLength += 6;
+
+ if (maxExternalQueueLength <= 1) {
+ stream << padding << "/* noop for external queues with length <= 1 */" << std::endl;
+ stream << padding << "inline insertWithDelay(queue) {}" << std::endl;
+ }
+
+ stream << padding << "hidden _event_t _iwdQ[" << maxExternalQueueLength - 1 << "];" << std::endl;
+ stream << padding << "hidden int _iwdQLength = 0;" << std::endl;
+ stream << padding << "hidden int _iwdIdx1 = 0;" << std::endl;
+ stream << padding << "hidden int _iwdIdx2 = 0;" << std::endl;
+ stream << padding << "hidden _event_t _iwdTmpE;" << std::endl;
+ stream << padding << "hidden _event_t _iwdLastE;" << std::endl;
+ stream << padding << "bool _iwdInserted = false;" << std::endl;
+ stream << padding << "" << std::endl;
+ stream << padding << "/* last event in given queue is potentially at wrong position */" << std::endl;
+ stream << padding << "inline insertWithDelay(queue) {" << std::endl;
+ stream << padding << " d_step {" << std::endl;
+ stream << padding << "" << std::endl;
+ stream << padding << " /* only process for non-trivial queues */" << std::endl;
+ stream << padding << " if" << std::endl;
+ stream << padding << " :: len(queue) > 1 -> {" << std::endl;
+ stream << padding << "" << std::endl;
+ stream << padding << " /* move all events but last over and remember the last one */" << std::endl;
+ stream << padding << " _iwdIdx1 = 0;" << std::endl;
+ stream << padding << " _iwdQLength = len(queue) - 1;" << std::endl;
+ stream << padding << "" << std::endl;
+ stream << padding << " do" << std::endl;
+ stream << padding << " :: _iwdIdx1 < _iwdQLength -> {" << std::endl;
+ stream << padding << " queue?_iwdTmpE;" << std::endl;
+ stream << padding << " _iwdQ[_iwdIdx1].name = _iwdTmpE.name;" << std::endl;
+
+ stream << _analyzer->getTypeAssignment("_iwdQ[_iwdIdx1]", "_iwdTmpE", _analyzer->getType("_event"), padding + " ");
+
+ stream << padding << " _iwdIdx1++;" << std::endl;
+ stream << padding << " }" << std::endl;
+ stream << padding << " :: else -> break;" << std::endl;
+ stream << padding << " od" << std::endl;
+ stream << padding << "" << std::endl;
+ stream << padding << " queue?_iwdLastE;" << std::endl;
+ stream << padding << "" << std::endl;
+ stream << padding << " /* _iwdQ now contains all but last item in _iwdLastE */" << std::endl;
+ stream << padding << " assert(len(queue) == 0);" << std::endl;
+ stream << padding << "" << std::endl;
+ stream << padding << " /* reinsert into queue and place _iwdLastE correctly */" << std::endl;
+ stream << padding << " _iwdInserted = false;" << std::endl;
+ stream << padding << " _iwdIdx2 = 0;" << std::endl;
+ stream << padding << "" << std::endl;
+ stream << padding << " do" << std::endl;
+ stream << padding << " :: _iwdIdx2 < _iwdIdx1 -> {" << std::endl;
+ stream << padding << " _iwdTmpE.name = _iwdQ[_iwdIdx2].name;" << std::endl;
+
+ stream << _analyzer->getTypeAssignment("_iwdTmpE", "_iwdQ[_iwdIdx2]", _analyzer->getType("_event"), padding + " ");
+
+ stream << padding << "" << std::endl;
+ stream << padding << " if" << std::endl;
+ stream << padding << " :: _iwdTmpE.delay > _iwdLastE.delay -> {" << std::endl;
+ stream << padding << " queue!_iwdLastE;" << std::endl;
+ stream << padding << " _iwdInserted = true;" << std::endl;
+ stream << padding << " }" << std::endl;
+ stream << padding << " :: else -> skip" << std::endl;
+ stream << padding << " fi;" << std::endl;
+ stream << padding << "" << std::endl;
+ stream << padding << " queue!_iwdTmpE;" << std::endl;
+ stream << padding << " _iwdIdx2++;" << std::endl;
+ stream << padding << " }" << std::endl;
+ stream << padding << " :: else -> break;" << std::endl;
+ stream << padding << " od" << std::endl;
+ stream << padding << "" << std::endl;
+ stream << padding << " if" << std::endl;
+ stream << padding << " :: !_iwdInserted -> queue!_iwdLastE;" << std::endl;
+ stream << padding << " :: else -> skip;" << std::endl;
+ stream << padding << " fi;" << std::endl;
+ stream << padding << "" << std::endl;
+ stream << padding << " }" << std::endl;
+ stream << padding << " :: else -> skip;" << std::endl;
+ stream << padding << " fi;" << std::endl;
+ stream << padding << " }" << std::endl;
+ stream << padding << "}" << std::endl;
+}
+
void ChartToPromela::writeAdvanceTime(std::ostream& stream, int indent) {
std::string padding;
for (int i = 0; i < indent; i++) {
@@ -2441,8 +2626,7 @@ void ChartToPromela::writeAdvanceTime(std::ostream& stream, int indent) {
}
stream << padding << "inline advanceTime(increment, queue) {" << std::endl;
- stream << padding << " int tmpIndex = 0;" << std::endl;
- stream << padding << " _event_t tmpE;" << std::endl;
+ stream << padding << " tmpIndex = 0;" << std::endl;
stream << padding << " do" << std::endl;
stream << padding << " :: tmpIndex < len(queue) -> {" << std::endl;
stream << padding << " queue?tmpE;" << std::endl;
@@ -2474,8 +2658,8 @@ void ChartToPromela::writeRemovePendingEventsFromInvoker(std::ostream& stream, i
stream << std::endl;
stream << "inline removePendingEventsForInvokerOnQueue(invokeIdentifier, queue) {" << std::endl;
- stream << " int tmpIndex = 0;" << std::endl;
- stream << " _event_t tmpE;" << std::endl;
+ stream << " tmpIndex = 0;" << std::endl;
+// stream << _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), " ");
stream << " do" << std::endl;
stream << " :: tmpIndex < len(queue) -> {" << std::endl;
stream << " queue?tmpE;" << std::endl;
@@ -2507,8 +2691,8 @@ void ChartToPromela::writeCancelEvents(std::ostream& stream, int indent) {
stream << "inline cancelSendIdOnQueue(sendIdentifier, queue, invokerIdentifier) {" << std::endl;
- stream << " int tmpIndex = 0;" << std::endl;
- stream << " _event_t tmpE;" << std::endl;
+ stream << " tmpIndex = 0;" << std::endl;
+// stream << _analyzer->getTypeReset("tmpE", _analyzer->getType("_event"), " ");
stream << " do" << std::endl;
stream << " :: tmpIndex < len(queue) -> {" << std::endl;
stream << " queue?tmpE;" << std::endl;
@@ -2709,6 +2893,7 @@ void ChartToPromela::writeDispatchingBlock(std::ostream& stream, std::list<Globa
}
stream << padding << " " << _prefix << "s = s" << newState->activeIndex << ";" << std::endl;
+ TRANSITION_TRACE(currTrans, false);
writeTransitionClosure(stream, currTrans, newState, indent + 1);
stream << padding << "}" << std::endl;
}
@@ -2979,7 +3164,10 @@ void ChartToPromela::initNodes() {
for (int i = 0; i < sends.size(); i++) {
if (HAS_ATTR_CAST(sends[i], "delay") || HAS_ATTR_CAST(sends[i], "delayexpr")) {
_analyzer->addCode("_event.delay", this);
- _analyzer->addCode("_event.seqNr", this);
+#if NEW_DELAY_RESHUFFLE
+#else
+ _analyzer->addCode("_event.seqNr", this);
+#endif
}
}
}
@@ -3287,9 +3475,23 @@ void ChartToPromela::writeProgram(std::ostream& stream) {
stream << std::endl << "/* global inline functions */" << std::endl;
+ if (_analyzer->usesComplexEventStruct()) {
+ stream << "hidden _event_t tmpE;" << std::endl;
+ } else {
+ stream << "hidden int tmpE;" << std::endl;
+ }
+ stream << "hidden int tmpIndex;" << std::endl;
+
+
+#if NEW_DELAY_RESHUFFLE
+ if (_analyzer->usesEventField("delay")) {
+ writeInsertWithDelay(stream);
+ stream << std::endl;
+ }
+#endif
if (_analyzer->usesEventField("delay") && _machines.size() > 0) {
- writeDetermineShortestDelay(stream);
+ writeDetermineShortestDelay(stream);
stream << std::endl;
writeAdvanceTime(stream);
stream << std::endl;
diff --git a/src/uscxml/transform/ChartToPromela.h b/src/uscxml/transform/ChartToPromela.h
index 1b0b16d..9c3c99b 100644
--- a/src/uscxml/transform/ChartToPromela.h
+++ b/src/uscxml/transform/ChartToPromela.h
@@ -205,6 +205,9 @@ public:
return false;
}
+ std::string getTypeAssignment(const std::string& varTo, const std::string& varFrom, const PromelaTypedef& type, const std::string padding = "");
+ std::string getTypeReset(const std::string& var, const PromelaTypedef& type, const std::string padding = "");
+
bool usesInPredicate() {
return _usesInPredicate;
}
@@ -248,6 +251,10 @@ public:
return _typeDefs;
}
+ PromelaTypedef& getType(const std::string& typeName) {
+ return _typeDefs.types.at(typeName);
+ }
+
protected:
std::string createMacroName(const std::string& literal);
int enumerateLiteral(const std::string& literal, int forceIndex = -1);
@@ -372,7 +379,8 @@ protected:
//void writeRemovePendingEventsFromInvoker(std::ostream& stream, ChartToPromela* invoker, int indent = 0, bool atomic = true);
void writeDetermineShortestDelay(std::ostream& stream, int indent = 0);
- void writeAdvanceTime(std::ostream& stream, int indent = 0);
+ void writeInsertWithDelay(std::ostream& stream, int indent = 0);
+ void writeAdvanceTime(std::ostream& stream, int indent = 0);
void writeRescheduleProcess(std::ostream& stream, int indent = 0);
void writeScheduleMachines(std::ostream& stream, int indent = 0);
void writeCancelEvents(std::ostream& stream, int indent = 0);
diff --git a/src/uscxml/transform/Transformer.h b/src/uscxml/transform/Transformer.h
index 8ea19d9..313bfaa 100644
--- a/src/uscxml/transform/Transformer.h
+++ b/src/uscxml/transform/Transformer.h
@@ -36,7 +36,7 @@ public:
};
-class USCXML_API Transformer {
+class USCXML_API Transformer : public boost::enable_shared_from_this<Transformer> {
public:
// Transformer(const Interpreter& source) { _impl = new (source) }
@@ -69,6 +69,10 @@ public:
return _impl->operator Interpreter();
}
+ boost::shared_ptr<TransformerImpl> getImpl() {
+ return _impl;
+ }
+
protected:
boost::shared_ptr<TransformerImpl> _impl;