summaryrefslogtreecommitdiffstats
path: root/src/uscxml/transform
diff options
context:
space:
mode:
authorStefan Radomski <github@mintwerk.de>2016-10-25 11:59:18 (GMT)
committerStefan Radomski <github@mintwerk.de>2016-10-25 11:59:18 (GMT)
commit954a1eb75f2abc81da1e09701d700674f0baddfb (patch)
tree873eb6412e958ecd53214ddbd6a3e17465da5100 /src/uscxml/transform
parent1a1513c6497e8818eb2a92a8fbf77d4c60bc911e (diff)
downloaduscxml-954a1eb75f2abc81da1e09701d700674f0baddfb.zip
uscxml-954a1eb75f2abc81da1e09701d700674f0baddfb.tar.gz
uscxml-954a1eb75f2abc81da1e09701d700674f0baddfb.tar.bz2
Worked on PROMELA transformation
Diffstat (limited to 'src/uscxml/transform')
-rw-r--r--src/uscxml/transform/ChartToC.cpp6
-rw-r--r--src/uscxml/transform/ChartToC.h2
-rw-r--r--src/uscxml/transform/ChartToPromela.cpp2625
-rw-r--r--src/uscxml/transform/ChartToPromela.h130
-rw-r--r--src/uscxml/transform/ChartToVHDL.cpp2558
-rw-r--r--src/uscxml/transform/ChartToVHDL.h26
-rw-r--r--src/uscxml/transform/promela/PromelaCodeAnalyzer.cpp596
-rw-r--r--src/uscxml/transform/promela/PromelaCodeAnalyzer.h150
-rw-r--r--src/uscxml/transform/promela/PromelaInlines.cpp165
-rw-r--r--src/uscxml/transform/promela/PromelaInlines.h113
10 files changed, 5075 insertions, 1296 deletions
diff --git a/src/uscxml/transform/ChartToC.cpp b/src/uscxml/transform/ChartToC.cpp
index 04f0378..10eee0c 100644
--- a/src/uscxml/transform/ChartToC.cpp
+++ b/src/uscxml/transform/ChartToC.cpp
@@ -50,7 +50,7 @@ ChartToC::ChartToC(const Interpreter& other) : TransformerImpl(other), _topMostM
ss << _document;
_md5 = md5(ss.str());
- _prefix = "_uscxml_" + _md5.substr(0, 8);
+ _prefix = "_uscxml_" + _md5.substr(0, 8) + "_";
_allMachines.push_back(this);
prepare();
@@ -1189,7 +1189,7 @@ void ChartToC::writeExecContent(std::ostream& stream) {
}
-void ChartToC::writeExecContent(std::ostream& stream, const DOMNode* node, int indent) {
+void ChartToC::writeExecContent(std::ostream& stream, const DOMNode* node, size_t indent) {
if (!node)
return;
@@ -2560,4 +2560,4 @@ void ChartToC::writeFSM(std::ostream& stream) {
ChartToC::~ChartToC() {
}
-} \ No newline at end of file
+}
diff --git a/src/uscxml/transform/ChartToC.h b/src/uscxml/transform/ChartToC.h
index 43ffc45..9fe6a9f 100644
--- a/src/uscxml/transform/ChartToC.h
+++ b/src/uscxml/transform/ChartToC.h
@@ -58,7 +58,7 @@ protected:
void writeFSM(std::ostream& stream);
void writeCharArrayInitList(std::ostream& stream, const std::string& boolString);
- void writeExecContent(std::ostream& stream, const XERCESC_NS::DOMNode* node, int indent = 0);
+ void writeExecContent(std::ostream& stream, const XERCESC_NS::DOMNode* node, size_t indent = 0);
void resortStates(XERCESC_NS::DOMNode* node);
void setHistoryCompletion();
diff --git a/src/uscxml/transform/ChartToPromela.cpp b/src/uscxml/transform/ChartToPromela.cpp
new file mode 100644
index 0000000..a697d99
--- /dev/null
+++ b/src/uscxml/transform/ChartToPromela.cpp
@@ -0,0 +1,2625 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#include "uscxml/transform/ChartToPromela.h"
+#include "uscxml/util/Predicates.h"
+#include "uscxml/util/String.h"
+#include "uscxml/plugins/datamodel/promela/PromelaParser.h"
+#include "uscxml/plugins/datamodel/promela/parser/promela.tab.hpp"
+
+#include <boost/algorithm/string.hpp>
+#include <easylogging++.h>
+
+#include <algorithm>
+
+#define ADAPT_SRC(code) _analyzer.adaptCode(code, _prefix)
+#define BIT_WIDTH(number) (number > 1 ? (int)ceil(log((double)number) / log((double)2.0)) : 1)
+#define EVENT_NAME (_analyzer.usesComplexEventStruct() ? "_event.name" : "_event")
+
+namespace uscxml {
+
+using namespace XERCESC_NS;
+
+
+Transformer ChartToPromela::transform(const Interpreter& other) {
+ return std::shared_ptr<TransformerImpl>(new ChartToPromela(other));
+}
+
+ChartToPromela::~ChartToPromela() {
+}
+
+/**
+ The following tests FAILED:
+ 1740 - w3c/spin/promela/test150.scxml (Failed)
+ 1741 - w3c/spin/promela/test151.scxml (Failed)
+ 1742 - w3c/spin/promela/test152.scxml (Failed)
+ 1743 - w3c/spin/promela/test153.scxml (Failed)
+ 1744 - w3c/spin/promela/test155.scxml (Failed)
+ 1745 - w3c/spin/promela/test156.scxml (Failed)
+ 1749 - w3c/spin/promela/test173.scxml (Failed)
+ 1750 - w3c/spin/promela/test174.scxml (Failed)
+ 1752 - w3c/spin/promela/test176.scxml (Failed)
+ 1753 - w3c/spin/promela/test178.scxml (Failed)
+ 1754 - w3c/spin/promela/test179.scxml (Failed)
+ 1757 - w3c/spin/promela/test186.scxml (Failed)
+ 1762 - w3c/spin/promela/test192.scxml (Failed)
+ 1763 - w3c/spin/promela/test193.scxml (Failed)
+ 1765 - w3c/spin/promela/test198.scxml (Failed)
+ 1769 - w3c/spin/promela/test205.scxml (Failed)
+ 1770 - w3c/spin/promela/test207.scxml (Failed)
+ 1771 - w3c/spin/promela/test208.scxml (Failed)
+ 1772 - w3c/spin/promela/test210.scxml (Failed)
+ 1773 - w3c/spin/promela/test215.scxml (Failed)
+ 1774 - w3c/spin/promela/test216.scxml (Failed)
+ 1776 - w3c/spin/promela/test223.scxml (Failed)
+ 1777 - w3c/spin/promela/test224.scxml (Failed)
+ 1778 - w3c/spin/promela/test225.scxml (Failed)
+ 1780 - w3c/spin/promela/test228.scxml (Failed)
+ 1782 - w3c/spin/promela/test230.scxml (Failed)
+ 1783 - w3c/spin/promela/test232.scxml (Failed)
+ 1785 - w3c/spin/promela/test234.scxml (Failed)
+ 1787 - w3c/spin/promela/test236.scxml (Failed)
+ 1788 - w3c/spin/promela/test237.scxml (Failed)
+ 1789 - w3c/spin/promela/test239.scxml (Failed)
+ 1790 - w3c/spin/promela/test240.scxml (Failed)
+ 1791 - w3c/spin/promela/test241.scxml (Failed)
+ 1792 - w3c/spin/promela/test242.scxml (Failed)
+ 1797 - w3c/spin/promela/test250.scxml (Failed)
+ 1798 - w3c/spin/promela/test252.scxml (Failed)
+ 1799 - w3c/spin/promela/test253.scxml (Failed)
+ 1802 - w3c/spin/promela/test278.scxml (Failed)
+ 1803 - w3c/spin/promela/test279.scxml (Failed)
+ 1805 - w3c/spin/promela/test286.scxml (Failed)
+ 1808 - w3c/spin/promela/test294.scxml (Failed)
+ 1809 - w3c/spin/promela/test298.scxml (Failed)
+ 1811 - w3c/spin/promela/test302.scxml (Failed)
+ 1813 - w3c/spin/promela/test304.scxml (Failed)
+ 1814 - w3c/spin/promela/test309.scxml (Failed)
+ 1815 - w3c/spin/promela/test310.scxml (Failed)
+ 1816 - w3c/spin/promela/test311.scxml (Failed)
+ 1817 - w3c/spin/promela/test312.scxml (Failed)
+ 1818 - w3c/spin/promela/test313.scxml (Failed)
+ 1819 - w3c/spin/promela/test314.scxml (Failed)
+ 1820 - w3c/spin/promela/test318.scxml (Failed)
+ 1823 - w3c/spin/promela/test322.scxml (Failed)
+ 1825 - w3c/spin/promela/test324.scxml (Failed)
+ 1827 - w3c/spin/promela/test326.scxml (Failed)
+ 1828 - w3c/spin/promela/test329.scxml (Failed)
+ 1829 - w3c/spin/promela/test330.scxml (Failed)
+ 1830 - w3c/spin/promela/test331.scxml (Failed)
+ 1831 - w3c/spin/promela/test332.scxml (Failed)
+ 1832 - w3c/spin/promela/test333.scxml (Failed)
+ 1833 - w3c/spin/promela/test335.scxml (Failed)
+ 1835 - w3c/spin/promela/test337.scxml (Failed)
+ 1837 - w3c/spin/promela/test339.scxml (Failed)
+ 1838 - w3c/spin/promela/test342.scxml (Failed)
+ 1839 - w3c/spin/promela/test343.scxml (Failed)
+ 1840 - w3c/spin/promela/test344.scxml (Failed)
+ 1841 - w3c/spin/promela/test346.scxml (Failed)
+ 1842 - w3c/spin/promela/test347.scxml (Failed)
+ 1846 - w3c/spin/promela/test351.scxml (Failed)
+ 1847 - w3c/spin/promela/test352.scxml (Failed)
+ 1848 - w3c/spin/promela/test354.scxml (Failed)
+ 1849 - w3c/spin/promela/test355.scxml (Failed)
+ 1850 - w3c/spin/promela/test364.scxml (Failed)
+ 1851 - w3c/spin/promela/test372.scxml (Failed)
+ 1854 - w3c/spin/promela/test377.scxml (Failed)
+ 1855 - w3c/spin/promela/test378.scxml (Failed)
+ 1856 - w3c/spin/promela/test387.scxml (Failed)
+ 1857 - w3c/spin/promela/test388.scxml (Failed)
+ 1858 - w3c/spin/promela/test396.scxml (Failed)
+ 1859 - w3c/spin/promela/test399.scxml (Failed)
+ 1860 - w3c/spin/promela/test401.scxml (Failed)
+ 1861 - w3c/spin/promela/test402.scxml (Failed)
+ 1862 - w3c/spin/promela/test403a.scxml (Failed)
+ 1863 - w3c/spin/promela/test403b.scxml (Failed)
+ 1864 - w3c/spin/promela/test403c.scxml (Failed)
+ 1865 - w3c/spin/promela/test404.scxml (Failed)
+ 1866 - w3c/spin/promela/test405.scxml (Failed)
+ 1867 - w3c/spin/promela/test406.scxml (Failed)
+ 1868 - w3c/spin/promela/test407.scxml (Failed)
+ 1869 - w3c/spin/promela/test409.scxml (Failed)
+ 1870 - w3c/spin/promela/test411.scxml (Failed)
+ 1871 - w3c/spin/promela/test412.scxml (Failed)
+ 1872 - w3c/spin/promela/test413.scxml (Failed)
+ 1873 - w3c/spin/promela/test415.scxml (Failed)
+ 1874 - w3c/spin/promela/test416.scxml (Failed)
+ 1875 - w3c/spin/promela/test417.scxml (Failed)
+ 1877 - w3c/spin/promela/test421.scxml (Failed)
+ 1878 - w3c/spin/promela/test422.scxml (Failed)
+ 1880 - w3c/spin/promela/test487.scxml (Failed)
+ 1881 - w3c/spin/promela/test488.scxml (Failed)
+ 1882 - w3c/spin/promela/test495.scxml (Failed)
+ 1886 - w3c/spin/promela/test503.scxml (Failed)
+ 1887 - w3c/spin/promela/test504.scxml (Failed)
+ 1888 - w3c/spin/promela/test505.scxml (Failed)
+ 1890 - w3c/spin/promela/test509.scxml (Failed)
+ 1892 - w3c/spin/promela/test518.scxml (Failed)
+ 1893 - w3c/spin/promela/test519.scxml (Failed)
+ 1894 - w3c/spin/promela/test520.scxml (Failed)
+ 1897 - w3c/spin/promela/test525.scxml (Failed)
+ 1898 - w3c/spin/promela/test527.scxml (Failed)
+ 1899 - w3c/spin/promela/test528.scxml (Failed)
+ 1900 - w3c/spin/promela/test529.scxml (Failed)
+ 1901 - w3c/spin/promela/test530.scxml (Failed)
+ 1902 - w3c/spin/promela/test531.scxml (Failed)
+ 1903 - w3c/spin/promela/test532.scxml (Failed)
+ 1904 - w3c/spin/promela/test533.scxml (Failed)
+ 1905 - w3c/spin/promela/test534.scxml (Failed)
+ 1906 - w3c/spin/promela/test550.scxml (Failed)
+ 1907 - w3c/spin/promela/test551.scxml (Failed)
+ 1911 - w3c/spin/promela/test567.scxml (Failed)
+ 1912 - w3c/spin/promela/test570.scxml (Failed)
+ 1913 - w3c/spin/promela/test576.scxml (Failed)
+ 1915 - w3c/spin/promela/test579.scxml (Failed)
+ 1916 - w3c/spin/promela/test580.scxml (Failed)
+*/
+
+void ChartToPromela::prepare() {
+ if (_machinesAll == NULL) {
+ _machinesAll = new std::map<DOMNode*, ChartToPromela*>();
+ (*_machinesAll)[_scxml] = this;
+ }
+
+ if (_machinesAllPerId == NULL)
+ _machinesAllPerId = new std::map<std::string, XERCESC_NS::DOMNode* >();
+
+ if (_parentTopMost == NULL)
+ _parentTopMost = this;
+
+ // transform data / assign json into PROMELA statements
+ std::list<DOMElement*> values;
+
+ values.splice(values.end(), DOMUtils::inDocumentOrder({XML_PREFIX(_scxml).str() + "assign"}, _scxml));
+ values.splice(values.end(), DOMUtils::inDocumentOrder({XML_PREFIX(_scxml).str() + "data"}, _scxml));
+
+ for (auto element : values) {
+ std::string key;
+ if (HAS_ATTR(element, "id")) {
+ key = ATTR(element, "id");
+ } else if (HAS_ATTR(element, "location")) {
+ key = ATTR(element, "location");
+ }
+
+ if (key.length() == 0)
+ continue;
+
+ std::string value;
+ if (HAS_ATTR(element, "expr")) {
+ value = ATTR(element, "expr");
+ } else if (HAS_ATTR(element, "src")) {
+ URL absUrl = URL::resolve(ATTR_CAST(element, "src"), _baseURL);
+ value = absUrl.getInContent();
+ } else {
+ std::list<DOMNode*> assignTexts = DOMUtils::filterChildType(DOMNode::TEXT_NODE, element, true);
+ if (assignTexts.size() > 0) {
+ for (auto assignText : assignTexts) {
+ value += X(assignText->getNodeValue()).str();
+ }
+ }
+ }
+
+ boost::trim(value);
+ if (value.size() == 0)
+ continue;
+
+ // remove all children, we will replae by suitable promela statements
+ while(element->hasChildNodes())
+ element->removeChild(element->getFirstChild());
+
+ std::string newValue;
+ Data json = Data::fromJSON(value);
+ if (!json.empty()) {
+ newValue = dataToAssignments(key, json);
+ } else {
+ newValue = key + " = " + value + ";";
+ }
+
+ if (LOCALNAME(element) == "data")
+ _varInitializers.push_back(newValue);
+
+ DOMText* newText = _document->createTextNode(X(newValue));
+ element->insertBefore(newText, NULL);
+
+ _analyzer.addCode(newValue, this);
+
+ }
+}
+
+void ChartToPromela::writeTo(std::ostream& stream) {
+
+ _analyzer.analyze(this);
+ // same preparations as the C transformation
+ prepare();
+
+ stream << "/** generated from " << std::endl;
+ stream << " " << std::string(_baseURL) << std::endl;
+ stream << " Use as:" << std::endl;
+ stream << " $ spin -a this.pml" << std::endl;
+ stream << " $ gcc pan.c -o pan" << std::endl;
+ stream << " $ ./pan -a -n -N w3c" << std::endl;
+ stream << " */" << std::endl;
+ stream << std::endl;
+
+
+ writeMacros(stream);
+ stream << std::endl;
+ writeTypeDefs(stream);
+ stream << std::endl;
+ writeTypes(stream);
+ stream << std::endl;
+ writeStrings(stream);
+ stream << std::endl;
+ writeCancelEvents(stream);
+ stream << std::endl;
+ writeFSM(stream);
+ stream << std::endl;
+
+
+ stream << "init {" << std::endl;
+
+ stream << "/* initialize state and transition information */" << std::endl;
+ writeTransitions(stream);
+ stream << std::endl;
+ writeStates(stream);
+ stream << std::endl;
+
+ stream << "/* initialize data model variables */" << std::endl;
+ stream << " " << _prefix << "flags[USCXML_CTX_PRISTINE] = true;" << std::endl;
+ stream << " " << _prefix << "flags[USCXML_CTX_SPONTANEOUS] = true;" << std::endl;
+
+ for (auto initializer : _varInitializers) {
+ stream << ADAPT_SRC(beautifyIndentation(initializer, 1)) << std::endl;
+ }
+
+ stream << std::endl;
+
+ stream << " run " << _prefix << "step() priority 10;" << std::endl;
+ stream << "}" << std::endl;
+ stream << std::endl;
+ stream << "ltl w3c { eventually (" << _prefix << "config[" << _prefix << "PASS]) }" << std::endl;
+
+}
+
+void ChartToPromela::bit_clear_all(std::ostream& stream,
+ const std::string& identifier,
+ size_t length,
+ size_t indent) {
+ std::string padding;
+ while (indent--)
+ padding += " ";
+ stream << std::endl;
+ stream << padding << "/** clearing all bits of " << identifier << " */" << std::endl;
+ for (size_t i = 0; i < length; i++) {
+ stream << padding << identifier << "[" << i << "] = false;" << std::endl;
+ }
+}
+
+void ChartToPromela::bit_copy(std::ostream& stream,
+ const std::string& from,
+ const std::string& to,
+ size_t length,
+ size_t indent) {
+ std::string padding;
+ while (indent--)
+ padding += " ";
+ stream << std::endl;
+ stream << padding << "/** copy bits from " << from << " to " << to << " */" << std::endl;
+ for (size_t i = 0; i < length; i++) {
+ stream << padding << to << "[" << i << "] = "<< from << "[" << i << "];" << std::endl;
+ }
+}
+
+void ChartToPromela::bit_or(std::ostream& stream,
+ const std::string& to,
+ const std::string& mask,
+ size_t length,
+ size_t indent) {
+ std::string padding;
+ while (indent--)
+ padding += " ";
+ stream << std::endl;
+ stream << padding << "/** or'ing bits in " << to << " with mask " << mask << " */" << std::endl;
+ for (size_t i = 0; i < length; i++) {
+ stream << padding << to << "[" << i << "] = "<< to << "[" << i << "] | " << mask << "[" << i << "];" << std::endl;
+ }
+}
+
+void ChartToPromela::bit_and(std::ostream& stream,
+ const std::string& to,
+ const std::string& mask,
+ size_t length,
+ size_t indent) {
+ std::string padding;
+ while (indent--)
+ padding += " ";
+ stream << std::endl;
+ stream << padding << "/** and'ing bits in " << to << " with mask " << mask << " */" << std::endl;
+ for (size_t i = 0; i < length; i++) {
+ stream << padding << to << "[" << i << "] = "<< to << "[" << i << "] & " << mask << "[" << i << "];" << std::endl;
+ }
+}
+
+void ChartToPromela::bit_and_not(std::ostream& stream,
+ const std::string& to,
+ const std::string& mask,
+ size_t length,
+ size_t indent) {
+ std::string padding;
+ while (indent--)
+ padding += " ";
+ stream << std::endl;
+ stream << padding << "/** not and'ing bits in " << to << " with mask " << mask << " */" << std::endl;
+ for (size_t i = 0; i < length; i++) {
+ stream << padding << to << "[" << i << "] = "<< to << "[" << i << "] & !" << mask << "[" << i << "];" << std::endl;
+ }
+}
+
+void ChartToPromela::bit_has_and(std::ostream& stream,
+ const std::string& a,
+ const std::string& b,
+ size_t length,
+ size_t indent) {
+ std::string padding;
+ while (indent--)
+ padding += " ";
+ stream << "(false /** is there a common bit in " << a << " and " << b << " */" << std::endl;
+ for (size_t i = 0; i < length; i++) {
+ stream << padding << " || " << a << "[" << i << "] & "<< b << "[" << i << "]" << std::endl;
+ }
+ stream << padding << ")";
+
+}
+
+void ChartToPromela::printBitArray(std::ostream& stream,
+ const std::string& array,
+ size_t length,
+ size_t indent) {
+ std::string padding;
+ while (indent--)
+ padding += " ";
+
+ stream << padding << "printf(\"";
+ for (size_t i = 0; i < length; i++) {
+ stream << "%d";
+ }
+ stream << "\", " << std::endl;
+ for (size_t i = 0; i < length; i++) {
+ stream << padding << " " << array << "[" << toStr(i) << "]";
+ if (i + 1 < length) {
+ stream << ", " << std::endl;
+ }
+ }
+ stream << ");" << std::endl;
+}
+
+void ChartToPromela::writeMacros(std::ostream& stream) {
+ stream << "/* machine state flags */" << std::endl;
+ stream << "#define USCXML_CTX_PRISTINE 0" << std::endl;
+ stream << "#define USCXML_CTX_SPONTANEOUS 1" << std::endl;
+ stream << "#define USCXML_CTX_INITIALIZED 2" << std::endl;
+ stream << "#define USCXML_CTX_TOP_LEVEL_FINAL 3" << std::endl;
+ stream << "#define USCXML_CTX_TRANSITION_FOUND 4" << std::endl;
+ stream << "#define USCXML_CTX_FINISHED 5" << std::endl;
+ stream << std::endl;
+
+ stream << "#define USCXML_TRANS_SPONTANEOUS 0" << std::endl;
+ stream << "#define USCXML_TRANS_TARGETLESS 1" << std::endl;
+ stream << "#define USCXML_TRANS_INTERNAL 2" << std::endl;
+ stream << "#define USCXML_TRANS_HISTORY 3" << std::endl;
+ stream << "#define USCXML_TRANS_INITIAL 4" << std::endl;
+ stream << std::endl;
+
+ stream << "#define USCXML_STATE_ATOMIC 0" << std::endl;
+ stream << "#define USCXML_STATE_PARALLEL 1" << std::endl;
+ stream << "#define USCXML_STATE_COMPOUND 2" << std::endl;
+ stream << "#define USCXML_STATE_FINAL 3" << std::endl;
+ stream << "#define USCXML_STATE_HISTORY_DEEP 4" << std::endl;
+ stream << "#define USCXML_STATE_HISTORY_SHALLOW 5" << std::endl;
+ stream << "#define USCXML_STATE_INITIAL 6" << std::endl;
+ stream << "#define USCXML_STATE_HAS_HISTORY 7" << std::endl;
+ stream << std::endl;
+
+ stream << "#define USCXML_ERR_OK 0" << std::endl;
+ stream << "#define USCXML_ERR_DONE 1" << std::endl;
+ stream << std::endl;
+
+ stream << "#define USCXML_EVENT_SPONTANEOUS 0" << std::endl;
+ stream << std::endl;
+ stream << "#define TRACE_EXECUTION 1" << std::endl;
+ stream << std::endl;
+
+
+}
+
+void ChartToPromela::writeTypeDefs(std::ostream& stream) {
+ stream << "/* type definitions */" << std::endl;
+ PromelaCodeAnalyzer::PromelaTypedef typeDefs = _analyzer.getTypes();
+ if (typeDefs.types.size() == 0)
+ return;
+
+ std::list<PromelaCodeAnalyzer::PromelaTypedef> individualDefs;
+ std::list<PromelaCodeAnalyzer::PromelaTypedef> currDefs;
+ currDefs.push_back(typeDefs);
+
+ while(currDefs.size() > 0) {
+ if (std::find(individualDefs.begin(), individualDefs.end(), currDefs.front()) == individualDefs.end()) {
+ individualDefs.push_back(currDefs.front());
+ for (std::map<std::string, PromelaCodeAnalyzer::PromelaTypedef>::iterator typeIter = currDefs.front().types.begin(); typeIter != currDefs.front().types.end(); typeIter++) {
+ currDefs.push_back(typeIter->second);
+ }
+ }
+ currDefs.pop_front();
+ }
+ individualDefs.pop_front();
+
+ for (std::list<PromelaCodeAnalyzer::PromelaTypedef>::reverse_iterator rIter = individualDefs.rbegin(); rIter != individualDefs.rend(); rIter++) {
+ PromelaCodeAnalyzer::PromelaTypedef currDef = *rIter;
+
+ if (currDef.types.size() == 0 || currDef.name.size() == 0)
+ continue;
+
+ stream << "typedef " << currDef.name << " {" << std::endl;
+ if (currDef.name.compare("_event_t") ==0) {
+ if (_analyzer.usesEventField("delay")) {
+ // make sure delay is the first member for sorted enqueuing to work
+ stream << " int delay;" << std::endl;
+#if NEW_DELAY_RESHUFFLE
+#else
+ stream << " int seqNr;" << std::endl;
+#endif
+ }
+ stream << " int name;" << std::endl;
+ if (_analyzer.usesEventField("invokeid")) {
+ stream << " int invokeid;" << std::endl;
+ }
+ }
+ for (std::map<std::string, PromelaCodeAnalyzer::PromelaTypedef>::iterator tIter = currDef.types.begin(); tIter != currDef.types.end(); tIter++) {
+ if (currDef.name.compare("_event_t") == 0 && (tIter->first.compare("name") == 0 ||
+ tIter->first.compare("seqNr") == 0 ||
+ tIter->first.compare("invokeid") == 0 ||
+ tIter->first.compare("delay") == 0)) { // special treatment for _event
+ continue;
+ }
+ if (tIter->second.types.size() == 0) {
+ stream << " " << declForRange(tIter->first, tIter->second.minValue, tIter->second.maxValue, true) << ";" << std::endl; // not further nested
+ // stream << " int " << tIter->first << ";" << std::endl; // not further nested
+ } else {
+ stream << " " << tIter->second.name << " " << tIter->first << ";" << std::endl;
+ }
+ }
+ stream << "};" << std::endl << std::endl;
+ }
+
+ // stream << "/* typedef instances */" << std::endl;
+ // PromelaCodeAnalyzer::PromelaTypedef allTypes = _analyzer->getTypes();
+ // std::map<std::string, PromelaCodeAnalyzer::PromelaTypedef>::iterator typeIter = allTypes.types.begin();
+ // while(typeIter != allTypes.types.end()) {
+ // if (typeIter->second.types.size() > 0) {
+ // // an actual typedef
+ // stream << "hidden " << typeIter->second.name << " " << typeIter->first << ";" << std::endl;
+ // } else {
+ // stream << "hidden " << declForRange(typeIter->first, typeIter->second.minValue, typeIter->second.maxValue) << ";" << std::endl;
+ // }
+ // typeIter++;
+ // }
+
+}
+
+
+void ChartToPromela::writeTypes(std::ostream& stream) {
+ stream << "/* type definitions and global variables */" << std::endl;
+ stream << "bool " << _prefix << "flags[6];" << std::endl;
+ stream << "bool " << _prefix << "config[" << _states.size() << "];" << std::endl;
+ stream << "bool " << _prefix << "history[" << _states.size() << "];" << std::endl;
+ stream << "bool " << _prefix << "invocations[" << _states.size() << "];" << std::endl;
+ stream << "bool " << _prefix << "initialized_data[" << _states.size() << "];" << std::endl;
+
+ size_t tolerance = 6;
+
+ if (_analyzer.usesComplexEventStruct()) {
+ // event is defined with the typedefs
+ stream << "_event_t " << _prefix << "_event; /* current event */" << std::endl;
+ stream << "chan " << _prefix << "iQ = [" << (std::max)(_internalQueueLength, (size_t)1) << "] of {_event_t} /* internal queue */" << std::endl;
+ stream << "chan " << _prefix << "eQ = [" << _externalQueueLength + tolerance << "] of {_event_t} /* external queue */" << std::endl;
+ if (_allowEventInterleaving)
+ stream << "chan " << _prefix << "tmpQ = [" << (std::max)(_externalQueueLength + tolerance, (size_t)1) << "] of {_event_t} /* temporary queue for external events in transitions */" << std::endl;
+ } else {
+ stream << "unsigned " << _prefix << "_event : " << BIT_WIDTH(_analyzer.getLiterals().size() + 1) << "; /* current event */" << std::endl;
+ stream << "chan " << _prefix << "iQ = [" << (std::max)(_internalQueueLength, (size_t)1) << "] of {int} /* internal queue */" << std::endl;
+ stream << "chan " << _prefix << "eQ = [" << _externalQueueLength + tolerance << "] of {int} /* external queue */" << std::endl;
+ if (_allowEventInterleaving)
+ stream << "chan " << _prefix << "tmpQ = [" << (std::max)(_externalQueueLength + tolerance, (size_t)1) << "] of {int} /* temporary queue for external events in transitions */" << std::endl;
+ }
+
+ stream << std::endl;
+ stream << "typedef transition {" << std::endl;
+ stream << " unsigned source : " << BIT_WIDTH(_states.size()) << ";" << std::endl;
+ stream << " bool target[" << _states.size() << "];" << std::endl;
+ stream << " bool type[5];" << std::endl;
+ stream << " bool conflicts[" << _transitions.size() << "];" << std::endl;
+ stream << " bool exit_set[" << _states.size() << "];" << std::endl;
+ stream << "}" << std::endl;
+ if (_transitions.size() > 0) {
+ stream << "hidden transition " << _prefix << "transitions[" << toStr(_transitions.size()) << "];" << std::endl;
+ }
+ stream << std::endl;
+
+ stream << "typedef state {" << std::endl;
+ stream << " unsigned parent : " << BIT_WIDTH(_states.size()) << ";" << std::endl;
+ stream << " bool children[" << _states.size() << "];" << std::endl;
+ stream << " bool completion[" << _states.size() << "];" << std::endl;
+ stream << " bool ancestors[" << _states.size() << "];" << std::endl;
+ stream << " bool type[8];" << std::endl;
+ stream << "}" << std::endl;
+ if (_states.size() > 0) {
+ stream << "hidden state " << _prefix << "states[" << toStr(_states.size()) << "];" << std::endl;
+ }
+ stream << std::endl;
+
+ stream << "hidden int tmpIndex;" << std::endl;
+ if (_analyzer.usesComplexEventStruct()) {
+ stream << "hidden _event_t tmpE;" << std::endl;
+ } else {
+ stream << "hidden int tmpE;" << std::endl;
+ }
+
+ if (_analyzer.hasIndexLessLoops())
+ stream << "hidden int " << _prefix << "_index; /* helper for indexless foreach loops */" << std::endl;
+
+ if (_analyzer.usesEventField("sendid"))
+ stream << "hidden int _lastSendId = 0; /* sequential counter for send ids */" << std::endl;
+
+ if (_analyzer.usesEventField("delay"))
+ stream << "hidden int _lastSeqId = 0; /* sequential counter for delayed events */" << std::endl;
+
+ stream << std::endl;
+
+ std::set<std::string> processedIdentifiers;
+
+ // automatic types
+ std::list<DOMElement*> datas = DOMUtils::inDocumentOrder({ XML_PREFIX(_scxml).str() + "data" }, _scxml, false);
+ PromelaCodeAnalyzer::PromelaTypedef allTypes = _analyzer.getTypes();
+
+ for (auto data : datas) {
+ std::string identifier = (HAS_ATTR_CAST(data, "id") ? ATTR_CAST(data, "id") : "");
+ std::string type = boost::trim_copy(HAS_ATTR_CAST(data, "type") ? ATTR_CAST(data, "type") : "");
+
+ _dataModelVars.insert(identifier);
+ if (processedIdentifiers.find(identifier) != processedIdentifiers.end())
+ continue;
+
+ processedIdentifiers.insert(identifier);
+
+ if (boost::starts_with(type, "string")) {
+ type = "int" + type.substr(6, type.length() - 6);
+ }
+
+ if (type.length() == 0 || type == "auto") {
+ if (allTypes.types.find(identifier) != allTypes.types.end()) {
+ type = allTypes.types[identifier].name;
+ } else {
+ LOG(ERROR) << "Automatic or no type for '" << identifier << "' but no type resolved";
+ continue;
+ }
+ }
+
+ std::string arrSize;
+ size_t bracketPos = type.find("[");
+ if (bracketPos != std::string::npos) {
+ arrSize = type.substr(bracketPos, type.length() - bracketPos);
+ type = type.substr(0, bracketPos);
+ }
+ std::string decl = type + " " + _prefix + identifier + arrSize;
+ stream << decl << ";" << std::endl;
+
+ }
+
+ // implicit and dynamic types
+ std::map<std::string, PromelaCodeAnalyzer::PromelaTypedef>::iterator typeIter = allTypes.types.begin();
+ while(typeIter != allTypes.types.end()) {
+ if (typeIter->second.occurrences.find(this) == typeIter->second.occurrences.end()) {
+ typeIter++;
+ continue;
+ }
+
+ if (processedIdentifiers.find(typeIter->first) != processedIdentifiers.end()) {
+ typeIter++;
+ continue;
+ }
+
+ if (typeIter->first == "_event"
+ || typeIter->first == "config"
+ || typeIter->first == "_ioprocessors"
+ || typeIter->first == "_SESSIONID"
+ || typeIter->first == "_NAME"
+ || !std::any_of(typeIter->first.begin(), typeIter->first.end(), ::islower)
+ ) {
+ typeIter++;
+ continue;
+ }
+
+ processedIdentifiers.insert(typeIter->first);
+
+ if (typeIter->second.types.size() == 0) {
+ stream << "hidden " << declForRange(_prefix + typeIter->first, typeIter->second.minValue, typeIter->second.maxValue) << ";" << std::endl;
+ } else {
+ stream << "hidden " << _prefix << typeIter->second.name << " " << typeIter->first << ";" << std::endl;
+ }
+ typeIter++;
+ }
+
+}
+
+void ChartToPromela::writeStrings(std::ostream& stream) {
+ stream << "/* states, events and string literals */" << std::endl;
+ std::set<std::string> literals = _analyzer.getLiterals();
+
+ {
+ for (size_t i = 0; i < _states.size(); i++) {
+ if (HAS_ATTR(_states[i], "id")) {
+ stream << "#define " << _prefix << _analyzer.macroForLiteral(ATTR(_states[i], "id")) << " " << toStr(i);
+ stream << " /* index for state " << ATTR(_states[i], "id") << " */" << std::endl;
+ }
+ }
+ }
+
+
+ for (auto literal : literals) {
+ stream << "#define " << _analyzer.macroForLiteral(literal) << " " << _analyzer.indexForLiteral(literal) << " /* " << literal << " */" << std::endl;
+ }
+}
+
+void ChartToPromela::writeTransitions(std::ostream& stream) {
+ for (size_t i = 0; i < _transitions.size(); i++) {
+ DOMElement* transition(_transitions[i]);
+
+ /** source */
+ stream << " " << _prefix << "transitions[" << toStr(i) << "].source = ";
+ stream << ATTR_CAST(transition->getParentNode(), "documentOrder") ;
+ stream << ";" << std::endl;
+
+ /** target */
+ if (HAS_ATTR(transition, "targetBools")) {
+ std::string targetBools = ATTR(transition, "targetBools");
+ for (size_t j = 0; j < _states.size(); j++) {
+ if (targetBools[j] == '1')
+ stream << " " << _prefix << "transitions[" << toStr(i) << "].target[" << toStr(j) << "] = 1;" << std::endl;
+ }
+ }
+
+#if 0
+ /** events */
+ if (HAS_ATTR(transition, "event")) {
+ std::list<std::string> events = tokenize(ATTR(transition, "event"), ' ', true);
+ for(auto& event : events) {
+ auto trieNodes = _analyzer.getTrie().getWordsWithPrefix(event);
+ for(auto trieNode : trieNodes) {
+ stream << " " << _prefix << "transitions[" << toStr(i) << "].event[" << _analyzer.macroForLiteral(trieNode->value) << "] = 1;" << std::endl;
+ }
+ }
+ }
+#endif
+
+ if (!HAS_ATTR(transition, "event"))
+ stream << " " << _prefix << "transitions[" << toStr(i) << "].type[USCXML_TRANS_SPONTANEOUS] = 1;" << std::endl;
+
+ if (!HAS_ATTR(transition, "target"))
+ stream << " " << _prefix << "transitions[" << toStr(i) << "].type[USCXML_TRANS_TARGETLESS] = 1;" << std::endl;
+
+ if (HAS_ATTR(transition, "type") && ATTR(transition, "type") == "internal")
+ stream << " " << _prefix << "transitions[" << toStr(i) << "].type[USCXML_TRANS_INTERNAL] = 1;" << std::endl;
+
+ if (TAGNAME_CAST(transition->getParentNode()) == XML_PREFIX(transition).str() + "history")
+ stream << " " << _prefix << "transitions[" << toStr(i) << "].type[USCXML_TRANS_HISTORY] = 1;" << std::endl;
+
+ if (TAGNAME_CAST(transition->getParentNode()) == XML_PREFIX(transition).str() + "initial")
+ stream << " " << _prefix << "transitions[" << toStr(i) << "].type[USCXML_TRANS_INITIAL] = 1;" << std::endl;
+
+ if (HAS_ATTR(transition, "conflictBools")) {
+ std::string conflicts = ATTR(transition, "conflictBools");
+ for (auto j = 0; j < conflicts.size(); j++) {
+ if (conflicts[j] == '1')
+ stream << " " << _prefix << "transitions[" << toStr(i) << "].conflicts[" << toStr(j) << "] = 1;" << std::endl;
+ }
+ }
+
+ if (HAS_ATTR(transition, "exitSetBools")) {
+ std::string exitSet = ATTR(transition, "exitSetBools");
+ for (auto j = 0; j < exitSet.size(); j++) {
+ if (exitSet[j] == '1')
+ stream << " " << _prefix << "transitions[" << toStr(i) << "].exit_set[" << toStr(j) << "] = 1;" << std::endl;
+ }
+ }
+
+ stream << std::endl;
+
+ }
+}
+
+
+
+void ChartToPromela::writeStates(std::ostream& stream) {
+ for (size_t i = 0; i < _states.size(); i++) {
+ DOMElement* state(_states[i]);
+
+ stream << " " << _prefix << "states[" << toStr(i) << "].parent = ";
+ stream << (i == 0 ? "0" : ATTR_CAST(state->getParentNode(), "documentOrder"));
+ stream << ";" << std::endl;
+
+
+ if (HAS_ATTR(state, "childBools")) {
+ std::string childs = ATTR(state, "childBools");
+ for (auto j = 0; j < childs.size(); j++) {
+ if (childs[j] == '1')
+ stream << " " << _prefix << "states[" << toStr(i) << "].children[" << toStr(j) << "] = 1;" << std::endl;
+ }
+ }
+
+ if (HAS_ATTR(state, "completionBools")) {
+ std::string completions = ATTR(state, "completionBools");
+ for (auto j = 0; j < completions.size(); j++) {
+ if (completions[j] == '1')
+ stream << " " << _prefix << "states[" << toStr(i) << "].completion[" << toStr(j) << "] = 1;" << std::endl;
+ }
+ }
+
+ if (HAS_ATTR(state, "ancBools")) {
+ std::string ancestors = ATTR(state, "ancBools");
+ for (auto j = 0; j < ancestors.size(); j++) {
+ if (ancestors[j] == '1')
+ stream << " " << _prefix << "states[" << toStr(i) << "].ancestors[" << toStr(j) << "] = 1;" << std::endl;
+ }
+ }
+ if (false) {
+ } else if (iequals(TAGNAME(state), "initial")) {
+ stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_INITIAL] = 1;" << std::endl;
+ } else if (isFinal(state)) {
+ stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_FINAL] = 1;" << std::endl;
+ } else if (isHistory(state)) {
+ if (HAS_ATTR(state, "type") && iequals(ATTR(state, "type"), "deep")) {
+ stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_HISTORY_DEEP] = 1;" << std::endl;
+ } else {
+ stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_HISTORY_SHALLOW] = 1;" << std::endl;
+ }
+ } else if (isAtomic(state)) {
+ stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_ATOMIC] = 1;" << std::endl;
+ } else if (isParallel(state)) {
+ stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_PARALLEL] = 1;" << std::endl;
+ } else if (isCompound(state)) {
+ stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_COMPOUND] = 1;" << std::endl;
+ } else { // <scxml>
+ stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_COMPOUND] = 1;" << std::endl;
+ }
+ if (HAS_ATTR(state, "hasHistoryChild")) {
+ stream << " " << _prefix << "states[" << toStr(i) << "].type[USCXML_STATE_HAS_HISTORY] = 1;" << std::endl;
+ }
+
+ stream << std::endl;
+
+ }
+}
+
+
+void ChartToPromela::writeHelpers(std::ostream& stream) {
+
+
+}
+
+void ChartToPromela::writeExecContent(std::ostream& stream, const XERCESC_NS::DOMNode* node, size_t indent) {
+ if (!node)
+ return;
+
+ std::string padding;
+ for (size_t i = 0; i < indent; i++) {
+ padding += " ";
+ }
+
+ if (node->getNodeType() == DOMNode::TEXT_NODE) {
+ if (boost::trim_copy(X(node->getNodeValue()).str()).length() > 0)
+ stream << beautifyIndentation(ADAPT_SRC(X(node->getNodeValue()).str()), indent) << std::endl;
+ }
+
+ if (node->getNodeType() != DOMNode::ELEMENT_NODE)
+ return; // skip anything not an element
+
+ const XERCESC_NS::DOMElement* element = static_cast<const XERCESC_NS::DOMElement*>(node);
+
+ if (false) {
+ } else if(TAGNAME(element) == "onentry" ||
+ TAGNAME(element) == "onexit" ||
+ TAGNAME(element) == "transition" ||
+ TAGNAME(element) == "finalize") {
+ // descent into childs and write their contents
+ const XERCESC_NS::DOMNode* child = node->getFirstChild();
+ while(child) {
+ writeExecContent(stream, child, indent);
+ child = child->getNextSibling();
+ }
+ } else if(TAGNAME(element) == "script") {
+ std::list<DOMNode*> scriptTexts = DOMUtils::filterChildType(DOMNode::TEXT_NODE, node, true);
+ for (auto scriptText : scriptTexts) {
+ stream << ADAPT_SRC(beautifyIndentation(X(scriptText->getNodeValue()).str(), indent)) << std::endl;
+ }
+
+ } else if(TAGNAME(element) == "log") {
+ std::string label = (HAS_ATTR(element, "label") ? ATTR(element, "label") : "");
+ std::string expr = (HAS_ATTR(element, "expr") ? ADAPT_SRC(ATTR(element, "expr")) : "");
+ std::string trimmedExpr = boost::trim_copy(expr);
+ bool isStringLiteral = (boost::starts_with(trimmedExpr, "\"") || boost::starts_with(trimmedExpr, "'"));
+
+ std::string formatString;
+ std::string varString;
+ std::string seperator;
+
+ if (label.size() > 0) {
+ if (expr.size() > 0) {
+ formatString += label + ": ";
+ } else {
+ formatString += label;
+ }
+ }
+
+ if (isStringLiteral) {
+ formatString += expr;
+ } else if (expr.size() > 0) {
+ formatString += "%d";
+ varString += seperator + expr;
+ }
+
+ if (varString.length() > 0) {
+ stream << padding << "printf(\"" + formatString + "\", " + varString + ");" << std::endl;
+ } else {
+ stream << padding << "printf(\"" + formatString + "\");" << std::endl;
+ }
+
+ } else if(TAGNAME(element) == "foreach") {
+ stream << padding << "for (" << _prefix << (HAS_ATTR(element, "index") ? ATTR(element, "index") : "_index") << " in " << _prefix << ATTR(element, "array") << ") {" << std::endl;
+ if (HAS_ATTR(element, "item")) {
+ stream << padding << " " << _prefix << ATTR(element, "item") << " = " << _prefix << ATTR(element, "array") << "[" << _prefix << (HAS_ATTR(element, "index") ? ATTR(element, "index") : "_index") << "];" << std::endl;
+ }
+ const XERCESC_NS::DOMNode* child = element->getFirstChild();
+ while(child) {
+ writeExecContent(stream, child, indent + 1);
+ child = child->getNextSibling();
+ }
+ // if (HAS_ATTR(nodeElem, "index"))
+ // stream << padding << " " << _prefix << ATTR(nodeElem, "index") << "++;" << std::endl;
+ stream << padding << "}" << std::endl;
+
+ } else if(TAGNAME(element) == "if") {
+ std::list<DOMElement*> condChain;
+ condChain.push_back(const_cast<DOMElement*>(element));
+
+ condChain.splice(condChain.end(), DOMUtils::filterChildElements(XML_PREFIX(element).str() + "elseif", element));
+ condChain.splice(condChain.end(), DOMUtils::filterChildElements(XML_PREFIX(element).str() + "else", element));
+
+ writeIfBlock(stream, condChain, indent);
+
+ } else if(TAGNAME(element) == "assign") {
+
+ std::list<DOMNode*> assignTexts = DOMUtils::filterChildType(DOMNode::TEXT_NODE, element, true);
+ assert(assignTexts.size() > 0);
+ stream << beautifyIndentation(ADAPT_SRC(boost::trim_copy(X(assignTexts.front()->getNodeValue()).str())), indent) << std::endl;
+
+ } else if(TAGNAME(element) == "send" || TAGNAME(element) == "raise") {
+ std::string targetQueue;
+ std::string insertOp = "!";
+ if (TAGNAME(element) == "raise") {
+ targetQueue = _prefix + "iQ";
+ } else if (!HAS_ATTR(element, "target")) {
+// if (_allowEventInterleaving) {
+// targetQueue = _prefix + "tmpQ";
+// } else {
+ targetQueue = _prefix + "eQ";
+// }
+ } else if (ATTR(element, "target").compare("#_internal") == 0) {
+ targetQueue = _prefix + "iQ";
+ } else if (ATTR(element, "target").compare("#_parent") == 0) {
+ targetQueue = _parent->_prefix + "eQ";
+ } else if (boost::starts_with(ATTR(element, "target"), "#_") && _machinesPerId.find(ATTR(element, "target").substr(2)) != _machinesPerId.end()) {
+ targetQueue = _machines[_machinesPerId[ATTR(element, "target").substr(2)]]->_prefix + "eQ";
+ }
+ if (targetQueue.length() > 0) {
+ // this is for our external queue
+ std::string event;
+
+ if (HAS_ATTR(element, "event")) {
+ event = _analyzer.macroForLiteral(ATTR(element, "event"));
+ } else if (HAS_ATTR(element, "eventexpr")) {
+ event = ADAPT_SRC(ATTR(element, "eventexpr"));
+ }
+ if (_analyzer.usesComplexEventStruct()) {
+ stream << padding << "{" << std::endl;
+ std::string typeReset = _analyzer.getTypeReset(_prefix + "_event", _analyzer.getType("_event"), padding + " ");
+ std::stringstream typeAssignSS;
+ typeAssignSS << padding << " " << _prefix << EVENT_NAME << " = " << event << ";" << std::endl;
+
+ if (HAS_ATTR(element, "idlocation")) {
+ typeAssignSS << padding << " /* idlocation */" << std::endl;
+ typeAssignSS << padding << " _lastSendId = _lastSendId + 1;" << std::endl;
+ typeAssignSS << padding << " " << _prefix << ATTR(element, "idlocation") << " = _lastSendId;" << std::endl;
+ typeAssignSS << padding << " " << _prefix << "_event.sendid = _lastSendId;" << std::endl;
+ typeAssignSS << padding << " if" << std::endl;
+ typeAssignSS << padding << " :: _lastSendId == 2147483647 -> _lastSendId = 0;" << std::endl;
+ typeAssignSS << padding << " :: else -> skip;" << std::endl;
+ typeAssignSS << padding << " fi;" << std::endl;
+ } else if (HAS_ATTR(element, "id")) {
+ typeAssignSS << padding << " " << _prefix << "_event.sendid = " << _analyzer.macroForLiteral(ATTR(element, "id")) << ";" << std::endl;
+ }
+
+ if (_invokerid.length() > 0) { // do not send invokeid if we send / raise to ourself
+ typeAssignSS << padding << " " << _prefix << "_event.invokeid = " << _analyzer.macroForLiteral(_invokerid) << ";" << std::endl;
+ }
+
+ if (_analyzer.usesEventField("origintype") && !boost::ends_with(targetQueue, "iQ")) {
+ typeAssignSS << padding << " " << _prefix << "_event.origintype = " << _analyzer.macroForLiteral("http://www.w3.org/TR/scxml/#SCXMLEventProcessor") << ";" << std::endl;
+ }
+
+ if (_analyzer.usesEventField("delay")) {
+#if NEW_DELAY_RESHUFFLE
+#else
+ insertOp += "!";
+ typeAssignSS << padding << " _lastSeqId = _lastSeqId + 1;" << std::endl;
+#endif
+ if (HAS_ATTR_CAST(element, "delay")) {
+ typeAssignSS << padding << " " << _prefix << "_event.delay = " << ATTR_CAST(element, "delay") << ";" << std::endl;
+ } else if (HAS_ATTR_CAST(element, "delayexpr")) {
+ typeAssignSS << padding << " " << _prefix << "_event.delay = " << ADAPT_SRC(ATTR_CAST(element, "delayexpr")) << ";" << std::endl;
+ } else {
+ typeAssignSS << padding << " " << _prefix << "_event.delay = 0;" << std::endl;
+ }
+#if NEW_DELAY_RESHUFFLE
+#else
+ typeAssignSS << padding << " " << _prefix << "_event.seqNr = _lastSeqId;" << std::endl;
+#endif
+ }
+
+ if (_analyzer.usesEventField("type")) {
+ std::string eventType = (targetQueue.compare("iQ!") == 0 ? _analyzer.macroForLiteral("internal") : _analyzer.macroForLiteral("external"));
+ typeAssignSS << padding << " " << _prefix << "_event.type = " << eventType << ";" << std::endl;
+ }
+
+ std::list<DOMElement*> sendParams = DOMUtils::filterChildElements(XML_PREFIX(element).str() + "param", element);
+ std::list<DOMElement*> sendContents = DOMUtils::filterChildElements(XML_PREFIX(element).str() + "content", element);
+ std::string sendNameList = ATTR(element, "namelist");
+ if (sendParams.size() > 0) {
+ for (auto sendParam : sendParams) {
+ typeAssignSS << padding << " " << _prefix << "_event.data." << ATTR(sendParam, "name") << " = " << ADAPT_SRC(ATTR(sendParam, "expr")) << ";" << std::endl;
+ }
+ }
+ if (sendNameList.size() > 0) {
+ std::list<std::string> nameListIds = tokenize(sendNameList);
+ std::list<std::string>::iterator nameIter = nameListIds.begin();
+ while(nameIter != nameListIds.end()) {
+ typeAssignSS << padding << " " << _prefix << "_event.data." << *nameIter << " = " << ADAPT_SRC(*nameIter) << ";" << std::endl;
+ nameIter++;
+ }
+ }
+
+ if (sendParams.size() == 0 && sendNameList.size() == 0 && sendContents.size() > 0) {
+ DOMElement* contentElem = sendContents.front();
+ if (contentElem->hasChildNodes() && contentElem->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) {
+ std::string content = spaceNormalize(X(contentElem->getFirstChild()->getNodeValue()).str());
+ if (!isNumeric(content.c_str(), 10)) {
+ typeAssignSS << padding << " " << _prefix << "_event.data = " << _analyzer.macroForLiteral(content) << ";" << std::endl;
+ } else {
+ typeAssignSS << padding << " " << _prefix << "_event.data = " << content << ";" << std::endl;
+ }
+ } else if (HAS_ATTR(contentElem, "expr")) {
+ typeAssignSS << padding << " " << _prefix << "_event.data = " << ADAPT_SRC(ATTR(contentElem, "expr")) << ";" << std::endl;
+ }
+ }
+
+ // remove all fields from typeReset that are indeed set by typeAssign
+ // for (std::string assigned; std::getline(typeAssignSS, assigned); ) {
+ // assigned = assigned.substr(0, assigned.find('='));
+ // assigned = assigned.substr(assigned.find('.'));
+ // std::istringstream typeResetSS (typeReset);
+ // for (std::string reset; std::getline(typeResetSS, reset); ) {
+ // if (!boost::find_first(reset, assigned)) {
+ // stream << reset << std::endl;
+ // }
+ // }
+ // }
+ // stream << typeAssignSS.str();
+
+ std::istringstream typeResetSS (typeReset);
+ for (std::string reset; std::getline(typeResetSS, reset); ) {
+ std::string resetField = reset.substr(0, reset.find('='));
+ resetField = resetField.substr(resetField.find('.'));
+ for (std::string assigned; std::getline(typeAssignSS, assigned); ) {
+ if (boost::find_first(resetField, assigned)) {
+ break;
+ }
+ }
+ stream << reset << std::endl;
+ }
+ stream << typeAssignSS.str();
+
+
+ stream << padding << " " << targetQueue << insertOp << _prefix <<"_event;" << 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 << insertOp << event << ";" << std::endl;
+ }
+ }
+ } else if(TAGNAME(element) == "cancel") {
+ if (HAS_ATTR(element, "sendid")) {
+ stream << padding << "cancelSendId(" << _analyzer.macroForLiteral(ATTR(element, "sendid")) << ", " << (_invokerid.size() > 0 ? _analyzer.macroForLiteral(_invokerid) : "0") << ");" << std::endl;
+ } else if (HAS_ATTR(element, "sendidexpr")) {
+ stream << padding << "cancelSendId(" << ADAPT_SRC(ATTR(element, "sendidexpr")) << ", " << (_invokerid.size() > 0 ? _analyzer.macroForLiteral(_invokerid) : "0") << ");" << std::endl;
+ }
+ } else {
+ std::cerr << "'" << TAGNAME(element) << "' not supported" << std::endl << element << std::endl;
+ assert(false);
+ }
+
+
+}
+
+
+
+void ChartToPromela::writeFSM(std::ostream& stream) {
+ stream << "/* machine microstep function */" << std::endl;
+ stream << "#define USCXML_NUMBER_STATES " << _states.size() << std::endl;
+ stream << "#define USCXML_NUMBER_TRANS " << _transitions.size() << std::endl;
+
+ stream << "proctype " << _prefix << "step() { atomic {" << std::endl;
+ stream << std::endl;
+ stream << "/* ---------------------------- */" << std::endl;
+ stream << "MICROSTEP:" << std::endl;
+
+ stream << "do" << std::endl;
+ stream << ":: !" << _prefix << "flags[USCXML_CTX_FINISHED] -> {" << std::endl;
+ stream << std::endl;
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Taking a step\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+
+
+ size_t largestBitWidth = (_states.size() > _transitions.size() ?
+ BIT_WIDTH(_states.size() + 1) :
+ BIT_WIDTH(_transitions.size() + 1));
+
+ stream << " unsigned";
+ stream << " i : " << largestBitWidth << ", ";
+ stream << " j : " << largestBitWidth << ", ";
+ stream << " k : " << largestBitWidth << ";" << std::endl;
+
+ stream << " int err = USCXML_ERR_OK;" << std::endl;
+
+ stream << " bool conflicts[" << _transitions.size() << "];" << std::endl;
+ stream << " bool trans_set[" << _transitions.size() << "];" << std::endl;
+
+ stream << " bool target_set[" << _states.size() << "];" << std::endl;
+ stream << " bool exit_set[" << _states.size() << "];" << std::endl;
+ stream << " bool entry_set[" << _states.size() << "];" << std::endl;
+ stream << " bool tmp_states[" << _states.size() << "];" << std::endl;
+ stream << std::endl;
+
+#if 0
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "flags[USCXML_CTX_FINISHED]" << std::endl;
+ stream << " ACCEPT: {" << std::endl;
+ stream << " false;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << std::endl;
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Machine not finished\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+#endif
+
+#if 0
+ stream << " if (ctx->flags & USCXML_CTX_TOP_LEVEL_FINAL) -> {" << std::endl;
+ stream << " /* exit all remaining states */" << std::endl;
+ stream << " i = USCXML_NUMBER_STATES;" << std::endl;
+ stream << " while(i-- > 0) {" << std::endl;
+ stream << " if (BIT_HAS(i, ctx->config)) {" << std::endl;
+ stream << " /* call all on exit handlers */" << std::endl;
+ stream << " if (USCXML_GET_STATE(i).on_exit != NULL) {" << std::endl;
+ stream << " if unlikely((err = USCXML_GET_STATE(i).on_exit(ctx, &USCXML_GET_STATE(i), ctx->event)) != USCXML_ERR_OK)" << std::endl;
+ stream << " return err;" << std::endl;
+ stream << " }" << std::endl;
+ // stream << " BIT_CLEAR(i, ctx->config);" << std::endl;
+ stream << " }" << std::endl;
+ stream << " if (BIT_HAS(i, ctx->invocations)) {" << std::endl;
+ stream << " if (USCXML_GET_STATE(i).invoke != NULL)" << std::endl;
+ stream << " USCXML_GET_STATE(i).invoke(ctx, &USCXML_GET_STATE(i), NULL, 1);" << std::endl;
+ stream << " BIT_CLEAR(i, ctx->invocations);" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " ctx->flags |= USCXML_CTX_FINISHED;" << std::endl;
+ stream << " return USCXML_ERR_DONE;" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+
+#endif
+
+ stream << " if" << std::endl;
+ stream << " ::" << _prefix << "flags[USCXML_CTX_TOP_LEVEL_FINAL] -> {" << std::endl;
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Top level final state reached\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+ stream << " /* exit all remaining states */" << std::endl;
+ stream << " i = USCXML_NUMBER_STATES;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: i > 0 -> {" << std::endl;
+ stream << " i = i - 1;" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "config[i] -> {" << std::endl;
+ stream << " /* TODO: call all on exit handlers */" << std::endl;
+ stream << " skip;" << std::endl;
+ stream << " " << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << std::endl;
+
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "invocations[i] -> {" << std::endl;
+ stream << " /* TODO: cancel invocations */" << std::endl;
+ stream << " skip;" << std::endl;
+ stream << " " << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od;" << std::endl;
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Ending machine!\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+ stream << " " << _prefix << "flags[USCXML_CTX_FINISHED] = true;" << std::endl;
+ stream << " goto MICROSTEP;" << std::endl;
+
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << std::endl;
+
+#if 0
+ stream << " bit_clear_all(target_set, nr_states_bytes);" << std::endl;
+ stream << " bit_clear_all(trans_set, nr_trans_bytes);" << std::endl;
+ stream << " if unlikely(ctx->flags == USCXML_CTX_PRISTINE) {" << std::endl;
+ stream << " if (ctx->machine->script != NULL)" << std::endl;
+ stream << " ctx->machine->script(ctx, &ctx->machine->states[0], NULL);" << std::endl;
+ stream << " bit_or(target_set, ctx->machine->states[0].completion, nr_states_bytes);" << std::endl;
+ stream << " ctx->flags |= USCXML_CTX_SPONTANEOUS | USCXML_CTX_INITIALIZED;" << std::endl;
+ stream << " goto ESTABLISH_ENTRY_SET;" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << " if" << std::endl;
+ stream << " ::" << _prefix << "flags[USCXML_CTX_PRISTINE] -> {" << std::endl;
+ stream << " /* run global scripts */" << std::endl;
+
+ std::list<DOMElement*> globalScripts = DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "script", _scxml, false);
+ for (auto globalScript : globalScripts) {
+ writeExecContent(stream, globalScript);
+ }
+ stream << std::endl;
+
+ stream << " /* Enter initial configuration */" << std::endl;
+ bit_copy(stream, _prefix + "states[0].completion", "target_set", _states.size(), 2);
+ stream << " " << _prefix << "flags[USCXML_CTX_SPONTANEOUS] = true;" << std::endl;
+ stream << " " << _prefix << "flags[USCXML_CTX_PRISTINE] = false;" << std::endl;
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Entering initial default completion\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+
+ stream << " goto ESTABLISH_ENTRY_SET;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << std::endl;
+
+
+#if 0
+ stream << "DEQUEUE_EVENT:" << std::endl;
+ stream << " if (ctx->flags & USCXML_CTX_SPONTANEOUS) {" << std::endl;
+ stream << " ctx->event = NULL;" << std::endl;
+ stream << " goto SELECT_TRANSITIONS;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " if (ctx->dequeue_internal != NULL && (ctx->event = ctx->dequeue_internal(ctx)) != NULL) {" << std::endl;
+ stream << " goto SELECT_TRANSITIONS;" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+#endif
+
+
+ stream << "/* ---------------------------- */" << std::endl;
+ stream << "DEQUEUE_EVENT:" << std::endl;
+ stream << " if" << std::endl;
+ stream << " ::" << _prefix << "flags[USCXML_CTX_SPONTANEOUS] -> {" << std::endl;
+ stream << " " << _prefix << EVENT_NAME << " = USCXML_EVENT_SPONTANEOUS;" << std::endl;
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Trying with a spontaneuous event\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+ stream << " goto SELECT_TRANSITIONS;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << std::endl;
+
+ stream << " if" << std::endl;
+ stream << " :: len(" << _prefix << "iQ) != 0 -> {" << std::endl;
+ stream << " " << _prefix << "iQ ? " << _prefix << "_event;" << std::endl;
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Deqeued an internal event\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+ stream << " goto SELECT_TRANSITIONS;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+
+
+#if 0
+ stream << " /* manage invocations */" << std::endl;
+ stream << " for (i = 0; i < USCXML_NUMBER_STATES; i++) {" << std::endl;
+ stream << " /* uninvoke */" << std::endl;
+ stream << " if (!BIT_HAS(i, ctx->config) && BIT_HAS(i, ctx->invocations)) {" << std::endl;
+ stream << " if (USCXML_GET_STATE(i).invoke != NULL)" << std::endl;
+ stream << " USCXML_GET_STATE(i).invoke(ctx, &USCXML_GET_STATE(i), NULL, 1);" << std::endl;
+ stream << " BIT_CLEAR(i, ctx->invocations)" << std::endl;
+ stream << " }" << std::endl;
+ stream << " /* invoke */" << std::endl;
+ stream << " if (BIT_HAS(i, ctx->config) && !BIT_HAS(i, ctx->invocations)) {" << std::endl;
+ stream << " if (USCXML_GET_STATE(i).invoke != NULL)" << std::endl;
+ stream << " USCXML_GET_STATE(i).invoke(ctx, &USCXML_GET_STATE(i), NULL, 0);" << std::endl;
+ stream << " BIT_SET_AT(i, ctx->invocations)" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << " /* manage invocations */" << std::endl;
+ stream << " i = 0;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: i < USCXML_NUMBER_STATES -> {" << std::endl;
+ stream << " /* uninvoke */" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: !" << _prefix << "config[i] && " << _prefix << "invocations[i] -> {" << std::endl;
+ stream << " skip;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << std::endl;
+
+ stream << " /* invoke */" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "config[i] && !" << _prefix << "invocations[i] -> {" << std::endl;
+ stream << " skip;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << " i = i + 1;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od;" << std::endl;
+ stream << std::endl;
+
+#if 0
+ stream << " if (ctx->dequeue_external != NULL && (ctx->event = ctx->dequeue_external(ctx)) != NULL) {" << std::endl;
+ stream << " goto SELECT_TRANSITIONS;" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+ stream << " if (ctx->dequeue_external == NULL) {" << std::endl;
+ stream << " return USCXML_ERR_DONE;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " return USCXML_ERR_IDLE;" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << " if" << std::endl;
+ stream << " :: len(" << _prefix << "eQ) != 0 -> {" << std::endl;
+ stream << " " << _prefix << "eQ ? " << _prefix << "_event;" << std::endl;
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Deqeued an external event\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+ stream << " goto SELECT_TRANSITIONS;" << std::endl;
+ stream << " }" << std::endl;
+// stream << " :: else -> quit;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << std::endl;
+
+#if 0
+ stream << "SELECT_TRANSITIONS:" << std::endl;
+ stream << " bit_clear_all(conflicts, nr_trans_bytes);" << std::endl;
+ stream << " bit_clear_all(exit_set, nr_states_bytes);" << std::endl;
+ stream << " for (i = 0; i < USCXML_NUMBER_TRANS; i++) {" << std::endl;
+ stream << " /* never select history or initial transitions automatically */" << std::endl;
+ stream << " if unlikely(USCXML_GET_TRANS(i).type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL))" << std::endl;
+ stream << " continue;" << std::endl;
+ stream << std::endl;
+ stream << " /* is the transition active? */" << std::endl;
+ stream << " if (BIT_HAS(USCXML_GET_TRANS(i).source, ctx->config)) {" << std::endl;
+ stream << " /* is it non-conflicting? */" << std::endl;
+ stream << " if (!BIT_HAS(i, conflicts)) {" << std::endl;
+ stream << " /* is it spontaneous with an event or vice versa? */" << std::endl;
+ stream << " if ((USCXML_GET_TRANS(i).event == NULL && ctx->event == NULL) || " << std::endl;
+ stream << " (USCXML_GET_TRANS(i).event != NULL && ctx->event != NULL)) {" << std::endl;
+ stream << " /* is it enabled? */" << std::endl;
+ stream << " if ((ctx->event == NULL || ctx->is_matched(ctx, &USCXML_GET_TRANS(i), ctx->event) > 0) &&" << std::endl;
+ stream << " (USCXML_GET_TRANS(i).condition == NULL || " << std::endl;
+ stream << " USCXML_GET_TRANS(i).is_enabled(ctx, &USCXML_GET_TRANS(i)) > 0)) {" << std::endl;
+ stream << " /* remember that we found a transition */" << std::endl;
+ stream << " ctx->flags |= USCXML_CTX_TRANSITION_FOUND;" << std::endl;
+ stream << std::endl;
+
+ stream << " /* transitions that are pre-empted */" << std::endl;
+ stream << " bit_or(conflicts, USCXML_GET_TRANS(i).conflicts, nr_trans_bytes);" << std::endl;
+ stream << std::endl;
+ stream << " /* states that are directly targeted (resolve as entry-set later) */" << std::endl;
+ stream << " bit_or(target_set, USCXML_GET_TRANS(i).target, nr_states_bytes);" << std::endl;
+ stream << std::endl;
+ stream << " /* states that will be left */" << std::endl;
+ stream << " bit_or(exit_set, USCXML_GET_TRANS(i).exit_set, nr_states_bytes);" << std::endl;
+ stream << std::endl;
+ stream << " BIT_SET_AT(i, trans_set);" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " bit_and(exit_set, ctx->config, nr_states_bytes);" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << "/* ---------------------------- */" << std::endl;
+ stream << "SELECT_TRANSITIONS:" << std::endl;
+ bit_clear_all(stream, "conflicts", _transitions.size(), 1);
+ bit_clear_all(stream, "trans_set", _transitions.size(), 1);
+ bit_clear_all(stream, "target_set", _states.size(), 1);
+ bit_clear_all(stream, "exit_set", _states.size(), 1);
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Establishing optimal transition set for event %d\\n\", " << _prefix << EVENT_NAME << ");" << std::endl;
+ stream << "#endif" << std::endl;
+ stream << " " << _prefix << "flags[USCXML_CTX_TRANSITION_FOUND] = false;" << std::endl;
+ stream << " i = 0;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: i < USCXML_NUMBER_TRANS -> {" << std::endl;
+
+ stream << " /* only select non-history, non-initial transitions */" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: !" << _prefix << "transitions[i].type[USCXML_TRANS_HISTORY] &&" << std::endl;
+ stream << " !" << _prefix << "transitions[i].type[USCXML_TRANS_INITIAL] -> {" << std::endl;
+
+ stream << " if" << std::endl;
+ stream << " :: /* is the transition active? */" << std::endl;
+ stream << " " << _prefix << "config[" << _prefix << "transitions[i].source] && " << std::endl;
+ stream << std::endl;
+ stream << " /* is it non-conflicting? */" << std::endl;
+ stream << " !conflicts[i] && " << std::endl;
+ stream << std::endl;
+ stream << " /* is it spontaneous with an event or vice versa? */" << std::endl;
+ stream << " ((" << _prefix << EVENT_NAME << " == USCXML_EVENT_SPONTANEOUS && " << std::endl;
+ stream << " " << _prefix << "transitions[i].type[USCXML_TRANS_SPONTANEOUS]) || " << std::endl;
+ stream << " (" << _prefix << EVENT_NAME << " != USCXML_EVENT_SPONTANEOUS && " << std::endl;
+ stream << " !" << _prefix << "transitions[i].type[USCXML_TRANS_SPONTANEOUS])) &&" << std::endl;
+ stream << std::endl;
+ stream << " /* is it matching and enabled? */" << std::endl;
+ stream << " (false " << std::endl;
+
+
+ for (auto i = 0; i < _transitions.size(); i++) {
+ stream << " || (i == " << toStr(i);
+ if (HAS_ATTR(_transitions[i], "event") && ATTR(_transitions[i], "event") != "*") {
+ stream << " && (false";
+ std::list<TrieNode*> events =_analyzer.getTrie().getWordsWithPrefix(ATTR(_transitions[i], "event"));
+ for (auto event : events) {
+ stream << " || " << _prefix << EVENT_NAME << " == " << _analyzer.macroForLiteral(event->value);
+ }
+ stream << ")";
+ }
+ if (HAS_ATTR(_transitions[i], "cond")) {
+ stream << " && " << ADAPT_SRC(ATTR(_transitions[i], "cond"));
+ }
+ stream << ")" << std::endl;
+ }
+
+ stream << " ) -> {" << std::endl;
+
+ stream << " /* remember that we found a transition */" << std::endl;
+ stream << " " << _prefix << "flags[USCXML_CTX_TRANSITION_FOUND] = true;" << std::endl;
+ stream << std::endl;
+
+ stream << " /* transitions that are pre-empted */" << std::endl;
+ bit_or(stream, "conflicts", _prefix + "transitions[i].conflicts", _transitions.size(), 4);
+ stream << std::endl;
+
+ stream << " /* states that are directly targeted (resolve as entry-set later) */" << std::endl;
+ bit_or(stream, "target_set", _prefix + "transitions[i].target", _states.size(), 4);
+ stream << std::endl;
+
+ stream << " /* states that will be left */" << std::endl;
+ bit_or(stream, "exit_set", _prefix + "transitions[i].exit_set", _states.size(), 4);
+ stream << std::endl;
+
+ stream << " trans_set[i] = true;" << std::endl;
+
+
+ stream << " }" << std::endl;
+ stream << " :: else {" << std::endl;
+ stream << " skip;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " fi" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " fi" << std::endl;
+
+ stream << " i = i + 1;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od;" << std::endl;
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Selected Transitions: \");" << std::endl;
+ printBitArray(stream, "trans_set", _transitions.size());
+ stream << "printf(\"\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Target Set: \");" << std::endl;
+ printBitArray(stream, "target_set", _states.size());
+ stream << "printf(\"\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+
+#if 0
+ stream << " if (ctx->flags & USCXML_CTX_TRANSITION_FOUND) {" << std::endl;
+ stream << " ctx->flags |= USCXML_CTX_SPONTANEOUS;" << std::endl;
+ stream << " ctx->flags &= ~USCXML_CTX_TRANSITION_FOUND;" << std::endl;
+ stream << " } else {" << std::endl;
+ stream << " ctx->flags &= ~USCXML_CTX_SPONTANEOUS;" << std::endl;
+ stream << " goto DEQUEUE_EVENT;" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "flags[USCXML_CTX_TRANSITION_FOUND] -> {" << std::endl;
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Found transitions\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+ stream << " " << _prefix << "flags[USCXML_CTX_SPONTANEOUS] = true;" << std::endl;
+ stream << " " << _prefix << "flags[USCXML_CTX_TRANSITION_FOUND] = false;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else {" << std::endl;
+ stream << " " << _prefix << "flags[USCXML_CTX_SPONTANEOUS] = false;" << std::endl;
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Found NO transitions\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+ stream << " goto DEQUEUE_EVENT;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " fi" << std::endl;
+ stream << std::endl;
+
+#if 0
+ stream << "/* REMEMBER_HISTORY: */" << std::endl;
+ stream << " for (i = 0; i < USCXML_NUMBER_STATES; i++) {" << std::endl;
+ stream << " if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_SHALLOW ||" << std::endl;
+ stream << " USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP) {" << std::endl;
+ stream << " /* a history state whose parent is about to be exited */" << std::endl;
+ stream << " if unlikely(BIT_HAS(USCXML_GET_STATE(i).parent, exit_set)) {" << std::endl;
+ stream << " bit_copy(tmp_states, USCXML_GET_STATE(i).completion, nr_states_bytes);" << std::endl;
+ stream << std::endl;
+ stream << " /* set those states who were enabled */" << std::endl;
+ stream << " bit_and(tmp_states, ctx->config, nr_states_bytes);" << std::endl;
+ stream << std::endl;
+ stream << " /* clear current history with completion mask */" << std::endl;
+ stream << " bit_and_not(ctx->history, USCXML_GET_STATE(i).completion, nr_states_bytes);" << std::endl;
+ stream << std::endl;
+ stream << " /* set history */" << std::endl;
+ stream << " bit_or(ctx->history, tmp_states, nr_states_bytes);" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << "/* ---------------------------- */" << std::endl;
+ stream << "/* REMEMBER_HISTORY: */" << std::endl;
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Save history configurations\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+ stream << " i = 0;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: i < USCXML_NUMBER_STATES -> {" << std::endl;
+
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "states[i].type[USCXML_STATE_HISTORY_SHALLOW] ||" << std::endl;
+ stream << " " << _prefix << "states[i].type[USCXML_STATE_HISTORY_DEEP] -> {" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: exit_set[" << _prefix << "states[i].parent] -> {" << std::endl;
+ stream << " /* a history state whose parent is about to be exited */" << std::endl;
+
+ bit_copy(stream, _prefix + "states[i].completion", "tmp_states", _states.size(), 3);
+ bit_and(stream, "tmp_states", _prefix + "config", _states.size(), 3);
+ bit_and_not(stream, "tmp_states", _prefix + "states[i].completion", _states.size(), 3);
+ bit_or(stream, _prefix + "history", "tmp_states", _states.size(), 3);
+ stream << std::endl;
+
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+
+
+ stream << " i = i + 1;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od;" << std::endl;
+ stream << std::endl;
+
+#if 0
+ stream << "ESTABLISH_ENTRY_SET:" << std::endl;
+ stream << " /* calculate new entry set */" << std::endl;
+ stream << " bit_copy(entry_set, target_set, nr_states_bytes);" << std::endl;
+ stream << std::endl;
+ stream << " /* iterate for ancestors */" << std::endl;
+ stream << " for (i = 0; i < USCXML_NUMBER_STATES; i++) {" << std::endl;
+ stream << " if (BIT_HAS(i, entry_set)) {" << std::endl;
+ stream << " bit_or(entry_set, USCXML_GET_STATE(i).ancestors, nr_states_bytes);" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << "/* ---------------------------- */" << std::endl;
+ stream << "ESTABLISH_ENTRY_SET:" << std::endl;
+ stream << " /* calculate new entry set */" << std::endl;
+ bit_copy(stream, "target_set", "entry_set", _states.size(), 1);
+ stream << std::endl;
+
+ stream << " i = 0;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: i < USCXML_NUMBER_STATES -> {" << std::endl;
+
+ stream << " if" << std::endl;
+ stream << " :: entry_set[i] -> {" << std::endl;
+ stream << " /* ancestor completion */" << std::endl;
+ bit_or(stream, "entry_set", _prefix + "states[i].ancestors", _states.size(), 3);
+
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+
+ stream << " i = i + 1;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od;" << std::endl;
+ stream << std::endl;
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Entry Set (after ancestor completion)\");" << std::endl;
+ printBitArray(stream, "entry_set", _states.size());
+ stream << "printf(\"\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+
+#if 0
+ stream << " /* iterate for descendants */" << std::endl;
+ stream << " for (i = 0; i < USCXML_NUMBER_STATES; i++) {" << std::endl;
+ stream << " if (BIT_HAS(i, entry_set)) {" << std::endl;
+ stream << " switch (USCXML_STATE_MASK(USCXML_GET_STATE(i).type)) {" << std::endl;
+#endif
+
+ stream << " /* iterate for descendants */" << std::endl;
+ stream << " i = 0;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: i < USCXML_NUMBER_STATES -> {" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: entry_set[i] -> {" << std::endl;
+ stream << " if" << std::endl;
+
+#if 0
+ stream << " case USCXML_STATE_PARALLEL: {" << std::endl;
+ stream << " bit_or(entry_set, USCXML_GET_STATE(i).completion, nr_states_bytes);" << std::endl;
+ stream << " break;" << std::endl;
+ stream << " }" << std::endl;
+#endif
+
+ stream << " :: " << _prefix << "states[i].type[USCXML_STATE_PARALLEL] -> {" << std::endl;
+ bit_or(stream, "entry_set", _prefix + "states[i].completion", _states.size(), 4);
+ stream << " }" << std::endl;
+
+
+#if 0
+ stream << " case USCXML_STATE_HISTORY_SHALLOW:" << std::endl;
+ stream << " case USCXML_STATE_HISTORY_DEEP: {" << std::endl;
+ stream << " if (!bit_has_and(USCXML_GET_STATE(i).completion, ctx->history, nr_states_bytes) &&" << std::endl;
+ stream << " !BIT_HAS(USCXML_GET_STATE(i).parent, ctx->config)) {" << std::endl;
+ stream << " /* nothing set for history, look for a default transition */" << std::endl;
+ stream << " for (j = 0; j < USCXML_NUMBER_TRANS; j++) {" << std::endl;
+ stream << " if unlikely(ctx->machine->transitions[j].source == i) {" << std::endl;
+ stream << " bit_or(entry_set, ctx->machine->transitions[j].target, nr_states_bytes);" << std::endl;
+ stream << " if(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP &&" << std::endl;
+ stream << " !bit_has_and(ctx->machine->transitions[j].target, USCXML_GET_STATE(i).children, nr_states_bytes)) {" << std::endl;
+ stream << " for (k = i + 1; k < USCXML_NUMBER_STATES; k++) {" << std::endl;
+ stream << " if (BIT_HAS(k, ctx->machine->transitions[j].target)) {" << std::endl;
+ stream << " bit_or(entry_set, ctx->machine->states[k].ancestors, nr_states_bytes);" << std::endl;
+ stream << " break;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " BIT_SET_AT(j, trans_set);" << std::endl;
+ stream << " break;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " /* Note: SCXML mandates every history to have a transition! */" << std::endl;
+ stream << " }" << std::endl;
+ stream << " } else {" << std::endl;
+ stream << " bit_copy(tmp_states, USCXML_GET_STATE(i).completion, nr_states_bytes);" << std::endl;
+ stream << " bit_and(tmp_states, ctx->history, nr_states_bytes);" << std::endl;
+ stream << " bit_or(entry_set, tmp_states, nr_states_bytes);" << std::endl;
+ stream << " if (USCXML_GET_STATE(i).type == (USCXML_STATE_HAS_HISTORY | USCXML_STATE_HISTORY_DEEP)) {" << std::endl;
+ stream << " /* a deep history state with nested histories -> more completion */" << std::endl;
+ stream << " for (j = i + 1; j < USCXML_NUMBER_STATES; j++) {" << std::endl;
+ stream << " if (BIT_HAS(j, USCXML_GET_STATE(i).completion) &&" << std::endl;
+ stream << " BIT_HAS(j, entry_set) &&" << std::endl;
+ stream << " (ctx->machine->states[j].type & USCXML_STATE_HAS_HISTORY)) {" << std::endl;
+ stream << " for (k = j + 1; k < USCXML_NUMBER_STATES; k++) {" << std::endl;
+ stream << " /* add nested history to entry_set */" << std::endl;
+ stream << " if ((USCXML_STATE_MASK(ctx->machine->states[k].type) == USCXML_STATE_HISTORY_DEEP ||" << std::endl;
+ stream << " USCXML_STATE_MASK(ctx->machine->states[k].type) == USCXML_STATE_HISTORY_SHALLOW) &&" << std::endl;
+ stream << " BIT_HAS(k, ctx->machine->states[j].children)) {" << std::endl;
+ stream << " /* a nested history state */" << std::endl;
+ stream << " BIT_SET_AT(k, entry_set);" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " break;" << std::endl;
+ stream << " }" << std::endl;
+#endif
+
+
+ stream << " :: " << _prefix << "states[i].type[USCXML_STATE_HISTORY_SHALLOW] ||" << std::endl;
+ stream << " " << _prefix << "states[i].type[USCXML_STATE_HISTORY_DEEP] -> {" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: !";
+ bit_has_and(stream, _prefix + "states[i].completion", _prefix + "history", _states.size(), 5);
+ stream << " && !" << _prefix << "config[" << _prefix << "states[i].parent]" << " -> {" << std::endl;
+ stream << " /* nothing set for history, look for a default transition */" << std::endl;
+ stream << " j = 0;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: j < USCXML_NUMBER_TRANS -> {" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "transitions[j].source == i -> {" << std::endl;
+
+ bit_or(stream, "entry_set", _prefix + "transitions[j].target", _states.size(), 8);
+ stream << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: (" << _prefix << "states[i].type[USCXML_STATE_HISTORY_DEEP] &&" << std::endl;
+ stream << " !";
+ bit_has_and(stream, _prefix + "transitions[j].target", _prefix + "states[i].children", _states.size(), 10);
+ stream << " ) -> {" << std::endl;
+ stream << " k = i + 1" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: k < USCXML_NUMBER_STATES -> {" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "transitions[j].target[k] -> {" << std::endl;
+ bit_or(stream, "entry_set", _prefix + "states[k].ancestors", _states.size(), 11);
+ stream << " break;" << std::endl;
+ stream << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od" << std::endl;
+ stream << " trans_set[j] = true;" << std::endl;
+ stream << " break;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << " j = j + 1;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break" << std::endl;
+ stream << " od" << std::endl;
+ stream << " skip;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> {" << std::endl;
+ bit_copy(stream, "tmp_states", _prefix + "states[i].completion", _states.size(), 5);
+ bit_and(stream, "tmp_states", _prefix + "history", _states.size(), 5);
+ bit_or(stream, "entry_set", "tmp_states", _states.size(), 5);
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "states[i].type[USCXML_STATE_HAS_HISTORY] ||" << std::endl;
+ stream << " " << _prefix << "states[i].type[USCXML_STATE_HISTORY_DEEP] -> { " << std::endl;
+ stream << " /* a deep history state with nested histories -> more completion */" << std::endl;
+ stream << " j = i + 1;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: j < USCXML_NUMBER_STATES -> {" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: (" << _prefix << "states[i].completion[j] &&" << std::endl;
+ stream << " entry_set[j] && " << std::endl;
+ stream << " " << _prefix << "states[j].type[USCXML_STATE_HAS_HISTORY]) -> {" << std::endl;
+ stream << " k = j + 1;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: k < USCXML_NUMBER_STATES -> {" << std::endl;
+ stream << " /* add nested history to entry_set */" << std::endl;
+ stream << " k = k + 1;" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: (" << _prefix << "states[k].type[USCXML_STATE_HISTORY_DEEP] ||" << std::endl;
+ stream << " " << _prefix << "states[k].type[USCXML_STATE_HISTORY_SHALLOW]) &&" << std::endl;
+ stream << " " << _prefix << "states[j].children[k] -> {" << std::endl;
+ stream << " /* a nested history state */" << std::endl;
+ stream << " entry_set[k] = true;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+
+ stream << " }" << std::endl;
+ stream << " fi;" << std::endl;
+
+ stream << " }" << std::endl;
+
+#if 0
+ stream << " case USCXML_STATE_INITIAL: {" << std::endl;
+ stream << " for (j = 0; j < USCXML_NUMBER_TRANS; j++) {" << std::endl;
+ stream << " if (ctx->machine->transitions[j].source == i) {" << std::endl;
+ stream << " BIT_SET_AT(j, trans_set);" << std::endl;
+ stream << " BIT_CLEAR(i, entry_set);" << std::endl;
+ stream << " bit_or(entry_set, ctx->machine->transitions[j].target, nr_states_bytes);" << std::endl;
+ stream << " for (k = i + 1; k < USCXML_NUMBER_STATES; k++) {" << std::endl;
+ stream << " if (BIT_HAS(k, ctx->machine->transitions[j].target)) {" << std::endl;
+ stream << " bit_or(entry_set, ctx->machine->states[k].ancestors, nr_states_bytes);" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " break;" << std::endl;
+ stream << " }" << std::endl;
+#endif
+
+ stream << " :: " << _prefix << "states[i].type[USCXML_STATE_INITIAL] -> {" << std::endl;
+ stream << " j = 0" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: j < USCXML_NUMBER_TRANS -> {" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "transitions[j].source == i -> {" << std::endl;
+ stream << " trans_set[j] = true;" << std::endl;
+ stream << " entry_set[i] = false;" << std::endl;
+
+ bit_or(stream, "entry_set", _prefix + "transitions[j].target", _states.size(), 6);
+ stream << std::endl;
+
+ stream << " k = i + 1;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: k < USCXML_NUMBER_STATES -> {" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "transitions[j].target[k] -> {" << std::endl;
+
+ bit_or(stream, "entry_set", _prefix + "states[k].ancestors", _states.size(), 8);
+ stream << std::endl;
+
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << " k = k + 1;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break" << std::endl;
+ stream << " od" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << " j = j + 1;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break" << std::endl;
+ stream << " od;" << std::endl;
+
+ stream << " }" << std::endl;
+
+
+#if 0
+ stream << " case USCXML_STATE_COMPOUND: { /* we need to check whether one child is already in entry_set */" << std::endl;
+ stream << " if (!bit_has_and(entry_set, USCXML_GET_STATE(i).children, nr_states_bytes) &&" << std::endl;
+ stream << " (!bit_has_and(ctx->config, USCXML_GET_STATE(i).children, nr_states_bytes) ||" << std::endl;
+ stream << " bit_has_and(exit_set, USCXML_GET_STATE(i).children, nr_states_bytes)))" << std::endl;
+ stream << " {" << std::endl;
+ stream << " bit_or(entry_set, USCXML_GET_STATE(i).completion, nr_states_bytes);" << std::endl;
+ stream << " if (!bit_has_and(USCXML_GET_STATE(i).completion, USCXML_GET_STATE(i).children, nr_states_bytes)) {" << std::endl;
+ stream << " /* deep completion */" << std::endl;
+ stream << " for (j = i + 1; j < USCXML_NUMBER_STATES; j++) {" << std::endl;
+ stream << " if (BIT_HAS(j, USCXML_GET_STATE(i).completion)) {" << std::endl;
+ stream << " bit_or(entry_set, ctx->machine->states[j].ancestors, nr_states_bytes);" << std::endl;
+ stream << " break; /* completion of compound is single state */" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " break;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << " :: " << _prefix << "states[i].type[USCXML_STATE_COMPOUND] -> {" << std::endl;
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Descendant completion for compound state %d\\n\", i);" << std::endl;
+ stream << "#endif" << std::endl;
+
+ stream << " /* we need to check whether one child is already in entry_set */" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: (" << std::endl;
+ stream << " !";
+ bit_has_and(stream, "entry_set", _prefix + "states[i].children", _states.size(), 5);
+ stream << " && " << std::endl;
+ stream << " (!";
+ bit_has_and(stream, _prefix + "config", _prefix + "states[i].children", _states.size(), 5);
+ stream << " || " << std::endl;
+ bit_has_and(stream, "exit_set", _prefix + "states[i].children", _states.size(), 5);
+ stream << ")) "<< std::endl;
+ stream << " -> {" << std::endl;
+
+ bit_or(stream, "entry_set", _prefix + "states[i].completion", _states.size(), 5);
+
+ stream << " if" << std::endl;
+ stream << " :: (";
+ bit_has_and(stream, _prefix + "states[i].completion", _prefix + "states[i].children", _states.size(), 5);
+ stream << std::endl;
+ stream << " ) -> {" << std::endl;
+ stream << " /* deep completion */" << std::endl;
+ stream << " j = i + 1;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: j < USCXML_NUMBER_STATES - 1 -> {" << std::endl;
+ stream << " j = j + 1;" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "states[i].completion[j] -> {" << std::endl;
+
+ bit_or(stream, "entry_set", _prefix + "states[j].ancestors", _states.size(), 9);
+ stream << std::endl;
+
+ stream << " /* completion of compound is single state */" << std::endl;
+ stream << " break;" << std::endl;
+ stream << " } " << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od" << std::endl;
+
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << " }" << std::endl;
+
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << " i = i + 1;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od;" << std::endl;
+ stream << std::endl;
+
+#if 0
+ stream << "/* EXIT_STATES: */" << std::endl;
+ stream << " i = USCXML_NUMBER_STATES;" << std::endl;
+ stream << " while(i-- > 0) {" << std::endl;
+ stream << " if (BIT_HAS(i, exit_set) && BIT_HAS(i, ctx->config)) {" << std::endl;
+ stream << " /* call all on exit handlers */" << std::endl;
+ stream << " if (USCXML_GET_STATE(i).on_exit != NULL) {" << std::endl;
+ stream << " if unlikely((err = USCXML_GET_STATE(i).on_exit(ctx, &USCXML_GET_STATE(i), ctx->event)) != USCXML_ERR_OK)" << std::endl;
+ stream << " return err;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " BIT_CLEAR(i, ctx->config);" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Entry Set (after descendant completion)\");" << std::endl;
+ printBitArray(stream, "entry_set", _states.size());
+ stream << "printf(\"\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+
+ stream << "/* ---------------------------- */" << std::endl;
+ stream << "/* EXIT_STATES: */" << std::endl;
+ stream << " i = USCXML_NUMBER_STATES;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: i > 0 -> {" << std::endl;
+ stream << " i = i - 1;" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: exit_set[i] && " << _prefix << "config[i] -> {" << std::endl;
+ stream << " /* call all on-exit handlers */" << std::endl;
+
+ stream << " if" << std::endl;
+ for (auto i = 0; i < _states.size(); i++) {
+ std::list<DOMElement*> onentries = DOMUtils::filterChildElements(XML_PREFIX(_states[i]).str() + "onexit" , _states[i]);
+ if (onentries.size() > 0) {
+ stream << " :: i == " << toStr(i) << " -> {" << std::endl;
+ for (auto onentry : onentries)
+ writeExecContent(stream, onentry, 3);
+ stream << " }" << std::endl;
+ }
+ }
+ stream << " :: else ->skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << std::endl;
+
+
+ stream << " " << _prefix << "config[i] = false;" << std::endl;
+ stream << " skip;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od;" << std::endl;
+ stream << std::endl;
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Exited States\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+
+#if 0
+ stream << "/* TAKE_TRANSITIONS: */" << std::endl;
+ stream << " for (i = 0; i < USCXML_NUMBER_TRANS; i++) {" << std::endl;
+ stream << " if (BIT_HAS(i, trans_set) && (USCXML_GET_TRANS(i).type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) == 0) {" << std::endl;
+ stream << " /* call executable content in transition */" << std::endl;
+ stream << " if (USCXML_GET_TRANS(i).on_transition != NULL) {" << std::endl;
+ stream << " if unlikely((err = USCXML_GET_TRANS(i).on_transition(ctx," << std::endl;
+ stream << " &ctx->machine->states[USCXML_GET_TRANS(i).source]," << std::endl;
+ stream << " ctx->event)) != USCXML_ERR_OK)" << std::endl;
+ stream << " return err;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << "/* ---------------------------- */" << std::endl;
+ stream << "/* TAKE_TRANSITIONS: */" << std::endl;
+ stream << " i = 0;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: i < USCXML_NUMBER_TRANS -> {" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: trans_set[i] && " << std::endl;
+ stream << " !" << _prefix << "transitions[i].type[USCXML_TRANS_HISTORY] && " << std::endl;
+ stream << " !" << _prefix << "transitions[i].type[USCXML_TRANS_INITIAL] -> {" << std::endl;
+ stream << " /* Call executable content in normal transition */" << std::endl;
+ stream << " if" << std::endl;
+ for (auto i = 0; i < _transitions.size(); i++) {
+ stream << " :: i == " << toStr(i) << " -> {" << std::endl;
+ writeExecContent(stream, _transitions[i], 4);
+ stream << " skip;" << std::endl;
+ stream << " }" << std::endl;
+ }
+ stream << " :: else ->skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << " i = i + 1;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od;" << std::endl;
+ stream << std::endl;
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Took Transitions\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+
+#if 0
+ stream << "/* ENTER_STATES: */" << std::endl;
+ stream << " for (i = 0; i < USCXML_NUMBER_STATES; i++) {" << std::endl;
+ stream << " if (BIT_HAS(i, entry_set) && !BIT_HAS(i, ctx->config)) {" << std::endl;
+ stream << " /* these are no proper states */" << std::endl;
+ stream << " if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_DEEP ||" << std::endl;
+ stream << " USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_HISTORY_SHALLOW ||" << std::endl;
+ stream << " USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_INITIAL)" << std::endl;
+ stream << " continue;" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << "/* ---------------------------- */" << std::endl;
+ stream << "/* ENTER_STATES: */" << std::endl;
+ stream << " i = 0;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: i < USCXML_NUMBER_STATES -> {" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: (entry_set[i] &&" << std::endl;
+ stream << " !" << _prefix << "config[i] && " << std::endl;
+ stream << " /* these are no proper states */" << std::endl;
+ stream << " !" << _prefix << "states[i].type[USCXML_STATE_HISTORY_DEEP] && " << std::endl;
+ stream << " !" << _prefix << "states[i].type[USCXML_STATE_HISTORY_SHALLOW] && " << std::endl;
+ stream << " !" << _prefix << "states[i].type[USCXML_STATE_INITIAL]" << std::endl;
+ stream << " ) -> {" << std::endl;
+
+#if 0
+ stream << " BIT_SET_AT(i, ctx->config);" << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Entering State %d\\n\", i);" << std::endl;
+ stream << "#endif" << std::endl;
+
+ stream << " " << _prefix << "config[i] = true;" << std::endl;
+ stream << std::endl;
+
+
+#if 0
+ stream << " /* initialize data */" << std::endl;
+ stream << " if (!BIT_HAS(i, ctx->initialized_data)) {" << std::endl;
+ stream << " if unlikely(USCXML_GET_STATE(i).data != NULL && ctx->exec_content_init != NULL) {" << std::endl;
+ stream << " ctx->exec_content_init(ctx, USCXML_GET_STATE(i).data);" << std::endl;
+ stream << " }" << std::endl;
+ stream << " BIT_SET_AT(i, ctx->initialized_data);" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+
+#endif
+
+ stream << " if" << std::endl;
+ stream << " :: !" << _prefix << "initialized_data[i] -> {" << std::endl;
+ stream << " /* TODO: late data binding not supported yet */" << std::endl;
+ stream << " " << _prefix << "initialized_data[i] = true;" << std::endl;
+ stream << " skip" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << std::endl;
+
+#if 0
+ stream << " if (USCXML_GET_STATE(i).on_entry != NULL) {" << std::endl;
+ stream << " if unlikely((err = USCXML_GET_STATE(i).on_entry(ctx, &USCXML_GET_STATE(i), ctx->event)) != USCXML_ERR_OK)" << std::endl;
+ stream << " return err;" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+
+#endif
+
+ stream << " /* Process executable content for entering a state */" << std::endl;
+ stream << " if" << std::endl;
+ for (auto i = 0; i < _states.size(); i++) {
+ std::list<DOMElement*> onentries = DOMUtils::filterChildElements(XML_PREFIX(_states[i]).str() + "onentry" , _states[i]);
+ if (onentries.size() > 0) {
+ stream << " :: i == " << toStr(i) << " -> {" << std::endl;
+ for (auto onentry : onentries)
+ writeExecContent(stream, onentry, 5);
+ stream << " }" << std::endl;
+ }
+ }
+ stream << " :: else ->skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << std::endl;
+
+#if 0
+ stream << " /* take history and initial transitions */" << std::endl;
+ stream << " for (j = 0; j < USCXML_NUMBER_TRANS; j++) {" << std::endl;
+ stream << " if unlikely(BIT_HAS(j, trans_set) &&" << std::endl;
+ stream << " (ctx->machine->transitions[j].type & (USCXML_TRANS_HISTORY | USCXML_TRANS_INITIAL)) &&" << std::endl;
+ stream << " ctx->machine->states[ctx->machine->transitions[j].source].parent == i) {" << std::endl;
+ stream << " /* call executable content in transition */" << std::endl;
+ stream << " if (ctx->machine->transitions[j].on_transition != NULL) {" << std::endl;
+ stream << " if unlikely((err = ctx->machine->transitions[j].on_transition(ctx," << std::endl;
+ stream << " &USCXML_GET_STATE(i)," << std::endl;
+ stream << " ctx->event)) != USCXML_ERR_OK)" << std::endl;
+ stream << " return err;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+
+#endif
+
+ stream << " /* take history and initial transitions */" << std::endl;
+ stream << " j = 0;" << std::endl;
+ stream << " do" << std::endl;
+ stream << " :: j < USCXML_NUMBER_TRANS -> {" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: (trans_set[j] &&" << std::endl;
+ stream << " (" << _prefix << "transitions[j].type[USCXML_TRANS_HISTORY] ||" << std::endl;
+ stream << " " << _prefix << "transitions[j].type[USCXML_TRANS_INITIAL]) && " << std::endl;
+ stream << " " << _prefix << "states[" << _prefix << "transitions[j].source].parent == i) -> {" << std::endl;
+ stream << " /* Call executable content in history or initial transition */" << std::endl;
+ stream << " if" << std::endl;
+ for (auto i = 0; i < _transitions.size(); i++) {
+ stream << " :: j == " << toStr(i) << " -> {" << std::endl;
+ writeExecContent(stream, _transitions[i], 8);
+ stream << " skip;" << std::endl;
+ stream << " }" << std::endl;
+ }
+ stream << " :: else ->skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << std::endl;
+
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << " j = j + 1;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od" << std::endl;
+
+
+#if 0
+ stream << " /* handle final states */" << std::endl;
+ stream << " if unlikely(USCXML_STATE_MASK(USCXML_GET_STATE(i).type) == USCXML_STATE_FINAL) {" << std::endl;
+#endif
+
+ stream << " /* handle final states */" << std::endl;
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "states[i].type[USCXML_STATE_FINAL] -> {" << std::endl;
+
+
+#if 0
+ stream << " if unlikely(USCXML_GET_STATE(i).ancestors[0] == 0x01) {" << std::endl;
+ stream << " ctx->flags |= USCXML_CTX_TOP_LEVEL_FINAL;" << std::endl;
+ stream << " } else {" << std::endl;
+ stream << " /* raise done event */" << std::endl;
+ stream << " const uscxml_elem_donedata* donedata = &ctx->machine->donedata[0];" << std::endl;
+ stream << " while(USCXML_ELEM_DONEDATA_IS_SET(donedata)) {" << std::endl;
+ stream << " if unlikely(donedata->source == i)" << std::endl;
+ stream << " break;" << std::endl;
+ stream << " donedata++;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " ctx->raise_done_event(ctx, &ctx->machine->states[USCXML_GET_STATE(i).parent], (USCXML_ELEM_DONEDATA_IS_SET(donedata) ? donedata : NULL));" << std::endl;
+ stream << " }" << std::endl;
+#endif
+
+ stream << " if" << std::endl;
+ stream << " :: " << _prefix << "states[" << _prefix << "states[i].parent].children[1] -> {" << std::endl;
+ stream << " " << _prefix << "flags[USCXML_CTX_TOP_LEVEL_FINAL] = true;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> {" << std::endl;
+ stream << " /* TODO: raise done event */" << std::endl;
+ stream << " skip;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " fi" << std::endl;
+
+
+#if 0
+ stream << std::endl;
+ stream << " /**" << std::endl;
+ stream << " * are we the last final state to leave a parallel state?:" << std::endl;
+ stream << " * 1. Gather all parallel states in our ancestor chain" << std::endl;
+ stream << " * 2. Find all states for which these parallels are ancestors" << std::endl;
+ stream << " * 3. Iterate all active final states and remove their ancestors" << std::endl;
+ stream << " * 4. If a state remains, not all children of a parallel are final" << std::endl;
+ stream << " */" << std::endl;
+ stream << " for (j = 0; j < USCXML_NUMBER_STATES; j++) {" << std::endl;
+ stream << " if unlikely(USCXML_STATE_MASK(ctx->machine->states[j].type) == USCXML_STATE_PARALLEL &&" << std::endl;
+ stream << " BIT_HAS(j, USCXML_GET_STATE(i).ancestors)) {" << std::endl;
+ stream << " bit_clear_all(tmp_states, nr_states_bytes);" << std::endl;
+ stream << " for (k = 0; k < USCXML_NUMBER_STATES; k++) {" << std::endl;
+ stream << " if unlikely(BIT_HAS(j, ctx->machine->states[k].ancestors) && BIT_HAS(k, ctx->config)) {" << std::endl;
+ stream << " if (USCXML_STATE_MASK(ctx->machine->states[k].type) == USCXML_STATE_FINAL) {" << std::endl;
+ stream << " bit_and_not(tmp_states, ctx->machine->states[k].ancestors, nr_states_bytes);" << std::endl;
+ stream << " } else {" << std::endl;
+ stream << " BIT_SET_AT(k, tmp_states);" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " if unlikely(!bit_has_any(tmp_states, nr_states_bytes)) {" << std::endl;
+ stream << " ctx->raise_done_event(ctx, &ctx->machine->states[j], NULL);" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << " }" << std::endl;
+ stream << std::endl;
+
+ stream << " return USCXML_ERR_OK;" << std::endl;
+ stream << "}" << std::endl;
+ stream << std::endl;
+ stream << std::endl;
+#endif
+
+ stream << " /** TODO:" << std::endl;
+ stream << " * are we the last final state to leave a parallel state?:" << std::endl;
+ stream << " * 1. Gather all parallel states in our ancestor chain" << std::endl;
+ stream << " * 2. Find all states for which these parallels are ancestors" << std::endl;
+ stream << " * 3. Iterate all active final states and remove their ancestors" << std::endl;
+ stream << " * 4. If a state remains, not all children of a parallel are final" << std::endl;
+ stream << " */" << std::endl;
+
+
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+
+ stream << "" << std::endl;
+
+ stream << " }" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " i = i + 1;" << std::endl;
+ stream << " fi;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od;" << std::endl;
+ stream << std::endl;
+
+ stream << "#if TRACE_EXECUTION" << std::endl;
+ stream << "printf(\"Done\\n\");" << std::endl;
+ stream << "#endif" << std::endl;
+
+ stream << "}" << std::endl;
+ stream << ":: else -> break;" << std::endl;
+ stream << "od" << std::endl;
+
+
+ stream << "} }" << std::endl;
+ stream << std::endl;
+
+}
+
+#if 0
+
+void ChartToPromela::writeProgram(std::ostream& stream) {
+
+ _traceTransitions = envVarIsTrue("USCXML_PROMELA_TRANSITION_TRACE");
+ _writeTransitionPrintfs = envVarIsTrue("USCXML_PROMELA_TRANSITION_DEBUG");
+
+ if (!HAS_ATTR(_scxml, "datamodel") || ATTR(_scxml, "datamodel") != "promela") {
+ LOG(ERROR) << "Can only convert SCXML documents with \"promela\" datamodel";
+ return;
+ }
+
+ if (HAS_ATTR(_scxml, "binding") && ATTR(_scxml, "binding") != "early") {
+ LOG(ERROR) << "Can only convert for early data bindings";
+ return;
+ }
+
+ // std::cerr << _scxml << std::endl;
+
+ stream << "/* " << (std::string)_baseURL << " */" << std::endl;
+ stream << std::endl;
+
+ initNodes();
+
+ for (std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator nestedIter = _machines.begin(); nestedIter != _machines.end(); nestedIter++) {
+ if (nestedIter->second->_start == NULL) {
+ nestedIter->second->interpret();
+ }
+ nestedIter->second->initNodes();
+ }
+
+ writeEvents(stream);
+ stream << std::endl;
+ writeStates(stream);
+ stream << std::endl;
+ writeStrings(stream);
+ stream << std::endl;
+ if (_analyzer->usesInPredicate()) {
+ writeStateMap(stream);
+ stream << std::endl;
+ }
+ if (_historyMembers.size() > 0) {
+ writeHistoryArrays(stream);
+ stream << std::endl;
+ }
+ writeTypeDefs(stream);
+ stream << std::endl;
+ writeDeclarations(stream);
+ stream << std::endl;
+
+ for (std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator nestedIter = _machines.begin(); nestedIter != _machines.end(); nestedIter++) {
+ nestedIter->second->writeDeclarations(stream);
+ stream << std::endl;
+ }
+
+ 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);
+ stream << std::endl;
+ writeAdvanceTime(stream);
+ stream << std::endl;
+ writeRescheduleProcess(stream);
+ stream << std::endl;
+ writeScheduleMachines(stream);
+ stream << std::endl;
+ }
+
+ {
+ NodeSet<std::string> cancels = DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "cancel", _scxml, true);
+ if (cancels.size() > 0) {
+ writeCancelEvents(stream);
+ stream << std::endl;
+ }
+ }
+ {
+ NodeSet<std::string> invokes = DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "invoke", _scxml, true);
+ if (invokes.size() > 0 && _analyzer->usesEventField("delay")) {
+ writeRemovePendingEventsFromInvoker(stream);
+ stream << std::endl;
+ }
+
+ }
+ stream << std::endl;
+ writeEventSources(stream);
+ stream << std::endl;
+ writeFSM(stream);
+ stream << std::endl;
+ writeMain(stream);
+ stream << std::endl;
+
+ for (std::map<Arabica::DOM::Node<std::string>, ChartToPromela*>::iterator nestedIter = _machines.begin(); nestedIter != _machines.end(); nestedIter++) {
+ nestedIter->second->writeFSM(stream);
+ stream << std::endl;
+ }
+
+ // write ltl expression for success
+ std::stringstream acceptingStates;
+ std::string seperator;
+
+ for (std::map<std::string, GlobalState*>::iterator stateIter = _activeConf.begin(); stateIter != _activeConf.end(); stateIter++) {
+ FlatStateIdentifier flatId(stateIter->first);
+ if (std::find(flatId.getActive().begin(), flatId.getActive().end(), "pass") != flatId.getActive().end()) {
+ acceptingStates << seperator << _prefix << "s == s" << stateIter->second->activeIndex;
+ seperator = " || ";
+ }
+ }
+ if (acceptingStates.str().size() > 0) {
+ stream << "ltl { eventually (" << acceptingStates.str() << ") }" << std::endl;
+ }
+}
+#endif
+
+void ChartToPromela::writeIfBlock(std::ostream& stream, std::list<DOMElement*>& condChain, size_t indent) {
+ if (condChain.size() == 0)
+ return;
+
+ std::string padding;
+ for (size_t i = 0; i < indent; i++) {
+ padding += " ";
+ }
+
+ bool noNext = condChain.size() == 1;
+ bool nextIsElse = false;
+
+ DOMElement* ifNode = condChain.front();
+ condChain.pop_front();
+
+ if (condChain.size() > 0) {
+ if (TAGNAME_CAST(condChain.front()) == "else") {
+ nextIsElse = true;
+ }
+ }
+
+ stream << padding << "if" << std::endl;
+ // we need to nest the elseifs to resolve promela if semantics
+ stream << padding << ":: (" << ADAPT_SRC(ATTR(ifNode, "cond")) << ") -> {" << std::endl;
+
+ DOMNode* child;
+ if (TAGNAME(ifNode) == "if") {
+ child = ifNode->getFirstChild();
+ } else {
+ child = ifNode->getNextSibling();
+ }
+ while(child) {
+ if (child->getNodeType() == DOMNode::ELEMENT_NODE) {
+ DOMElement* childElem = static_cast<DOMElement*>(child);
+ if (TAGNAME(childElem) == "elseif" || TAGNAME_CAST(childElem) == "else")
+ break;
+ writeExecContent(stream, childElem, indent + 1);
+ }
+ child = child->getNextSibling();
+ }
+ stream << padding << "}" << std::endl;
+ stream << padding << ":: else -> ";
+
+ if (nextIsElse) {
+ child = condChain.front()->getNextSibling();
+ stream << "{" << std::endl;
+ while(child) {
+ if (child->getNodeType() == DOMNode::ELEMENT_NODE) {
+ writeExecContent(stream, child, indent + 1);
+ }
+ child = child->getNextSibling();
+ }
+ stream << padding << "}" << std::endl;
+
+ } else if (noNext) {
+ stream << "skip;" << std::endl;
+ } else {
+ stream << "{" << std::endl;
+ writeIfBlock(stream, condChain, indent + 1);
+ stream << padding << "}" << std::endl;
+ }
+
+ stream << padding << "fi;" << std::endl;
+
+}
+
+std::string ChartToPromela::beautifyIndentation(const std::string& code, size_t indent) {
+
+ std::string padding;
+ for (size_t i = 0; i < indent; i++) {
+ padding += " ";
+ }
+
+ // remove topmost indentation from every line and reindent
+ std::stringstream beautifiedSS;
+
+ std::string initialIndent;
+ bool gotIndent = false;
+ bool isFirstLine = true;
+ std::stringstream ssLine(code);
+ std::string line;
+
+ while(std::getline(ssLine, line)) {
+ size_t firstChar = line.find_first_not_of(" \t\r\n");
+ if (firstChar != std::string::npos) {
+ if (!gotIndent) {
+ initialIndent = line.substr(0, firstChar);
+ gotIndent = true;
+ }
+ beautifiedSS << (isFirstLine ? "" : "\n") << padding << boost::replace_first_copy(line, initialIndent, "");
+ isFirstLine = false;
+ }
+ }
+
+ return beautifiedSS.str();
+}
+
+std::string ChartToPromela::dataToAssignments(const std::string& prefix, const Data& data) {
+ std::stringstream retVal;
+ if (data.atom.size() > 0) {
+ if (data.type == Data::VERBATIM) {
+ retVal << prefix << " = " << _analyzer.macroForLiteral(data.atom) << ";" << std::endl;
+ } else {
+ retVal << prefix << " = " << data.atom << ";" << std::endl;
+ }
+ } else if (data.compound.size() > 0) {
+ for (std::map<std::string, Data>::const_iterator cIter = data.compound.begin(); cIter != data.compound.end(); cIter++) {
+ retVal << dataToAssignments(prefix + "." + cIter->first, cIter->second);
+ }
+ } else if (data.array.size() > 0) {
+ size_t index = 0;
+ for(std::list<Data>::const_iterator aIter = data.array.begin(); aIter != data.array.end(); aIter++) {
+ retVal << dataToAssignments(prefix + "[" + toStr(index) + "]", *aIter);
+ index++;
+ }
+ }
+ return retVal.str();
+}
+
+std::string ChartToPromela::sanitizeCode(const std::string& code) {
+ std::string replaced = code;
+ boost::replace_all(replaced, "\"", "'");
+ boost::replace_all(replaced, "_sessionid", "_SESSIONID");
+ boost::replace_all(replaced, "_name", "_NAME");
+ return replaced;
+}
+
+std::string ChartToPromela::declForRange(const std::string& identifier, long minValue, long maxValue, bool nativeOnly) {
+ // return "int " + identifier; // just for testing
+
+ // we know nothing about this type
+ if (minValue == 0 && maxValue == 0)
+ return "int " + identifier;
+
+ if (minValue < 0) {
+ // only short or int for negatives
+ if (minValue < -32769 || maxValue > 32767)
+ return "int " + identifier;
+ return "short " + identifier;
+ }
+
+ // type is definitely positive
+ if (nativeOnly) {
+ if (maxValue > 32767)
+ return "int " + identifier;
+ if (maxValue > 255)
+ return "short " + identifier;
+ if (maxValue > 1)
+ return "byte " + identifier;
+ return "bool " + identifier;
+ } else {
+ return "unsigned " + identifier + " : " + toStr(BIT_WIDTH(maxValue));
+ }
+}
+
+void ChartToPromela::writeCancelEvents(std::ostream& stream, int indent) {
+ std::list<std::string> queues;
+ queues.push_back("eQ");
+ if (_allowEventInterleaving)
+ queues.push_back("tmpQ");
+
+ stream << "inline cancelSendId(sendIdentifier, invokerIdentifier) {" << std::endl;
+ for (auto machine : *_machinesAll) {
+ for (auto queue : queues) {
+ stream << " cancelSendIdOnQueue(sendIdentifier, " << machine.second->_prefix << queue << ", invokerIdentifier);" << std::endl;
+ }
+ }
+ stream << "}" << std::endl;
+ stream << std::endl;
+
+
+ stream << "inline cancelSendIdOnQueue(sendIdentifier, queue, invokerIdentifier) {" << 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;
+ stream << " if" << std::endl;
+ stream << " :: tmpE.invokeid != invokerIdentifier || tmpE.sendid != sendIdentifier || tmpE.delay == 0 -> queue!tmpE;" << std::endl;
+ stream << " :: else -> skip;" << std::endl;
+ stream << " fi" << std::endl;
+ stream << " tmpIndex++;" << std::endl;
+ stream << " }" << std::endl;
+ stream << " :: else -> break;" << std::endl;
+ stream << " od" << std::endl;
+ stream << "}" << std::endl;
+}
+
+
+}
diff --git a/src/uscxml/transform/ChartToPromela.h b/src/uscxml/transform/ChartToPromela.h
new file mode 100644
index 0000000..cfba760
--- /dev/null
+++ b/src/uscxml/transform/ChartToPromela.h
@@ -0,0 +1,130 @@
+/**
+ * @file
+ * @author 2012-2014 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#ifndef CHARTTOPROMELA_H_RP48RFDJ
+#define CHARTTOPROMELA_H_RP48RFDJ
+
+#include "Transformer.h"
+#include "ChartToC.h"
+#include "uscxml/util/DOM.h"
+
+#include "promela/PromelaInlines.h"
+#include "promela/PromelaCodeAnalyzer.h"
+
+#include <ostream>
+
+namespace uscxml {
+
+class USCXML_API ChartToPromela : public ChartToC {
+public:
+ virtual ~ChartToPromela();
+ static Transformer transform(const Interpreter& other);
+
+ void writeTo(std::ostream& stream);
+
+protected:
+ ChartToPromela(const Interpreter& other) : ChartToC(other) {
+ _prefix = "U" + _md5.substr(0, 8) + "_";
+ }
+
+ void writeTransitions(std::ostream& stream);
+ void writeStates(std::ostream& stream);
+ void writeTypeDefs(std::ostream& stream);
+ void writeTypes(std::ostream& stream);
+ void writeMacros(std::ostream& stream);
+ void writeHelpers(std::ostream& stream);
+ void writeFSM(std::ostream& stream);
+ void writeExecContent(std::ostream& stream, const XERCESC_NS::DOMNode* node, size_t indent = 0);
+ void writeStrings(std::ostream& stream);
+
+ void writeCancelEvents(std::ostream& stream, int indent = 0);
+
+ void prepare();
+
+ void bit_clear_all(std::ostream& stream,
+ const std::string& identifier,
+ size_t length,
+ size_t indent = 0);
+
+ void bit_copy(std::ostream& stream,
+ const std::string& from,
+ const std::string& to,
+ size_t length,
+ size_t indent = 0);
+
+ void bit_or(std::ostream& stream,
+ const std::string& to,
+ const std::string& mask,
+ size_t length,
+ size_t indent = 0);
+
+ void bit_and(std::ostream& stream,
+ const std::string& to,
+ const std::string& mask,
+ size_t length,
+ size_t indent = 0);
+
+ void bit_and_not(std::ostream& stream,
+ const std::string& to,
+ const std::string& mask,
+ size_t length,
+ size_t indent = 0);
+
+ void bit_has_and(std::ostream& stream,
+ const std::string& a,
+ const std::string& b,
+ size_t length,
+ size_t indent = 0);
+
+ void printBitArray(std::ostream& stream,
+ const std::string& array,
+ size_t length,
+ size_t indent = 0);
+
+ PromelaCodeAnalyzer _analyzer;
+
+ ChartToPromela* _parentTopMost;
+ ChartToPromela* _parent;
+ std::string _invokerid;
+
+ size_t _internalQueueLength = 7;
+ size_t _externalQueueLength = 7;
+ bool _allowEventInterleaving = false;
+
+ std::map<std::string, XERCESC_NS::DOMNode* > _machinesPerId;
+ std::map<std::string, XERCESC_NS::DOMNode* >* _machinesAllPerId = NULL;
+ std::map<XERCESC_NS::DOMNode*, ChartToPromela*> _machines;
+ std::map<XERCESC_NS::DOMNode*, ChartToPromela*>* _machinesAll = NULL;
+
+ std::set<std::string> _dataModelVars;
+ std::list<std::string> _varInitializers; // pending initializations for arrays
+
+ std::string beautifyIndentation(const std::string& code, size_t indent = 0);
+ void writeIfBlock(std::ostream& stream, std::list<XERCESC_NS::DOMElement*>& condChain, size_t indent = 0);
+
+ std::string dataToAssignments(const std::string& prefix, const Data& data);
+ std::string sanitizeCode(const std::string& code);
+ std::string declForRange(const std::string& identifier, long minValue, long maxValue, bool nativeOnly = false);
+
+ friend class PromelaCodeAnalyzer;
+};
+
+}
+
+#endif /* end of include guard: CHARTTOPROMELA_H_RP48RFDJ */
diff --git a/src/uscxml/transform/ChartToVHDL.cpp b/src/uscxml/transform/ChartToVHDL.cpp
index 37fa03c..13e8120 100644
--- a/src/uscxml/transform/ChartToVHDL.cpp
+++ b/src/uscxml/transform/ChartToVHDL.cpp
@@ -40,9 +40,9 @@ namespace uscxml {
using namespace XERCESC_NS;
Transformer ChartToVHDL::transform(const Interpreter& other) {
- ChartToVHDL* c2c = new ChartToVHDL(other);
+ ChartToVHDL* c2c = new ChartToVHDL(other);
- return std::shared_ptr<TransformerImpl>(c2c);
+ return std::shared_ptr<TransformerImpl>(c2c);
}
ChartToVHDL::ChartToVHDL(const Interpreter& other) : ChartToC(other), _eventTrie(".") {
@@ -52,1383 +52,1383 @@ ChartToVHDL::~ChartToVHDL() {
}
void ChartToVHDL::checkDocument() {
- // filter unsupported stuff
- std::list<DOMElement*> unsupported;
- unsupported = DOMUtils::inDocumentOrder({
- XML_PREFIX(_scxml).str() + "datamodel",
- XML_PREFIX(_scxml).str() + "data",
- XML_PREFIX(_scxml).str() + "assign",
- XML_PREFIX(_scxml).str() + "donedata",
- XML_PREFIX(_scxml).str() + "content",
- XML_PREFIX(_scxml).str() + "param",
- XML_PREFIX(_scxml).str() + "script",
- XML_PREFIX(_scxml).str() + "parallel",
- XML_PREFIX(_scxml).str() + "history",
- XML_PREFIX(_scxml).str() + "if",
- XML_PREFIX(_scxml).str() + "foreach",
- XML_PREFIX(_scxml).str() + "send",
- XML_PREFIX(_scxml).str() + "cancel",
- XML_PREFIX(_scxml).str() + "invoke",
- XML_PREFIX(_scxml).str() + "finalize"
- }, _scxml);
-
- std::stringstream ss;
- if (unsupported.size() > 0) {
- for (auto elem : unsupported) {
- ss << " " << DOMUtils::xPathForNode(elem) << " unsupported" << std::endl;
- }
- throw std::runtime_error("Unsupported elements found:\n" + ss.str());
- }
-
- unsupported = DOMUtils::inDocumentOrder({ XML_PREFIX(_scxml).str() + "transition" }, _scxml);
-
- for (auto transition : unsupported) {
- if (HAS_ATTR(transition, "cond")) {
- ERROR_PLATFORM_THROW("transition with conditions not supported!");
- }
- if (!HAS_ATTR(transition, "target")) {
- ERROR_PLATFORM_THROW("targetless transition not supported!");
- }
- }
+ // filter unsupported stuff
+ std::list<DOMElement*> unsupported;
+ unsupported = DOMUtils::inDocumentOrder({
+ XML_PREFIX(_scxml).str() + "datamodel",
+ XML_PREFIX(_scxml).str() + "data",
+ XML_PREFIX(_scxml).str() + "assign",
+ XML_PREFIX(_scxml).str() + "donedata",
+ XML_PREFIX(_scxml).str() + "content",
+ XML_PREFIX(_scxml).str() + "param",
+ XML_PREFIX(_scxml).str() + "script",
+ XML_PREFIX(_scxml).str() + "parallel",
+ XML_PREFIX(_scxml).str() + "history",
+ XML_PREFIX(_scxml).str() + "if",
+ XML_PREFIX(_scxml).str() + "foreach",
+ XML_PREFIX(_scxml).str() + "send",
+ XML_PREFIX(_scxml).str() + "cancel",
+ XML_PREFIX(_scxml).str() + "invoke",
+ XML_PREFIX(_scxml).str() + "finalize"
+ }, _scxml);
+
+ std::stringstream ss;
+ if (unsupported.size() > 0) {
+ for (auto elem : unsupported) {
+ ss << " " << DOMUtils::xPathForNode(elem) << " unsupported" << std::endl;
+ }
+ throw std::runtime_error("Unsupported elements found:\n" + ss.str());
+ }
+
+ unsupported = DOMUtils::inDocumentOrder({ XML_PREFIX(_scxml).str() + "transition" }, _scxml);
+
+ for (auto transition : unsupported) {
+ if (HAS_ATTR(transition, "cond")) {
+ ERROR_PLATFORM_THROW("transition with conditions not supported!");
+ }
+ if (!HAS_ATTR(transition, "target")) {
+ ERROR_PLATFORM_THROW("targetless transition not supported!");
+ }
+ }
}
std::string ChartToVHDL::eventNameEscape(const std::string& eventName) {
- std::string escaped = escape(eventName);
- boost::replace_all(escaped, ".", "_");
- return escaped;
+ std::string escaped = escape(eventName);
+ boost::replace_all(escaped, ".", "_");
+ return escaped;
}
void ChartToVHDL::findEvents() {
- // elements with an event attribute
- std::list<DOMElement*> withEvents = DOMUtils::inDocumentOrder({
- XML_PREFIX(_scxml).str() + "raise",
- XML_PREFIX(_scxml).str() + "send",
- XML_PREFIX(_scxml).str() + "transition",
-
- }, _scxml);
-
- for (auto withEvent : withEvents) {
- if (HAS_ATTR_CAST(withEvent, "event")) {
- // TODO: tokenize!
- if (ATTR_CAST(withEvent, "event") != "*")
- _eventTrie.addWord(ATTR_CAST(withEvent, "event"));
- }
- }
-
- _execContent = DOMUtils::inDocumentOrder({
- XML_PREFIX(_scxml).str() + "raise",
- XML_PREFIX(_scxml).str() + "send"
- }, _scxml);
+ // elements with an event attribute
+ std::list<DOMElement*> withEvents = DOMUtils::inDocumentOrder({
+ XML_PREFIX(_scxml).str() + "raise",
+ XML_PREFIX(_scxml).str() + "send",
+ XML_PREFIX(_scxml).str() + "transition",
+
+ }, _scxml);
+
+ for (auto withEvent : withEvents) {
+ if (HAS_ATTR_CAST(withEvent, "event")) {
+ // TODO: tokenize!
+ if (ATTR_CAST(withEvent, "event") != "*")
+ _eventTrie.addWord(ATTR_CAST(withEvent, "event"));
+ }
+ }
+
+ _execContent = DOMUtils::inDocumentOrder({
+ XML_PREFIX(_scxml).str() + "raise",
+ XML_PREFIX(_scxml).str() + "send"
+ }, _scxml);
}
void ChartToVHDL::writeTo(std::ostream& stream) {
- // same preparations as the C transformation
- prepare();
+ // same preparations as the C transformation
+ prepare();
- // checkDocument();
- findEvents();
+ // checkDocument();
+ findEvents();
- stream << "-- generated from " << std::string(_baseURL) << std::endl;
- stream << "-- run as " << std::endl;
- stream << "-- ghdl --clean && ghdl -a foo.vhdl && ghdl -e tb && ./tb --stop-time=10ms --vcd=foo.vcd" << std::endl;
- stream << std::endl;
+ stream << "-- generated from " << std::string(_baseURL) << std::endl;
+ stream << "-- run as " << std::endl;
+ stream << "-- ghdl --clean && ghdl -a foo.vhdl && ghdl -e tb && ./tb --stop-time=10ms --vcd=foo.vcd" << std::endl;
+ stream << std::endl;
- writeTypes(stream);
- writeFiFo(stream);
- writeEventController(stream);
- writeMicroStepper(stream);
- writeTestbench(stream);
+ writeTypes(stream);
+ writeFiFo(stream);
+ writeEventController(stream);
+ writeMicroStepper(stream);
+ writeTestbench(stream);
}
void ChartToVHDL::writeTypes(std::ostream & stream) {
- std::string seperator;
-
- stream << "-- required global types" << std::endl;
- stream << "library IEEE;" << std::endl;
- stream << "use IEEE.std_logic_1164.all;" << std::endl;
- stream << std::endl;
- stream << "package machine" << _md5 << " is" << std::endl;
- // create state type
- stream << " subtype state_type is std_logic_vector( ";
- stream << _states.size() - 1;
- stream << " downto 0);" << std::endl;
-
- std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix("");
- stream << " type event_type is ( hwe_null, ";
- seperator = "";
-
- for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
- stream << seperator << "hwe_" << eventNameEscape((*eventIter)->value);
- seperator = ", ";
- }
- stream << " );" << std::endl;
-
- stream << "end machine" << _md5 << ";" << std::endl;
- stream << std::endl;
- stream << "-- END needed global types" << std::endl;
+ std::string seperator;
+
+ stream << "-- required global types" << std::endl;
+ stream << "library IEEE;" << std::endl;
+ stream << "use IEEE.std_logic_1164.all;" << std::endl;
+ stream << std::endl;
+ stream << "package machine" << _md5 << " is" << std::endl;
+ // create state type
+ stream << " subtype state_type is std_logic_vector( ";
+ stream << _states.size() - 1;
+ stream << " downto 0);" << std::endl;
+
+ std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix("");
+ stream << " type event_type is ( hwe_null, ";
+ seperator = "";
+
+ for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
+ stream << seperator << "hwe_" << eventNameEscape((*eventIter)->value);
+ seperator = ", ";
+ }
+ stream << " );" << std::endl;
+
+ stream << "end machine" << _md5 << ";" << std::endl;
+ stream << std::endl;
+ stream << "-- END needed global types" << std::endl;
}
void ChartToVHDL::writeIncludes(std::ostream & stream) {
- // Add controler specific stuff here
- stream << "library IEEE;" << std::endl;
- stream << "use IEEE.std_logic_1164.all;" << std::endl;
- stream << "use work.machine" << _md5 << ".all;" << std::endl;
- stream << std::endl;
+ // Add controler specific stuff here
+ stream << "library IEEE;" << std::endl;
+ stream << "use IEEE.std_logic_1164.all;" << std::endl;
+ stream << "use work.machine" << _md5 << ".all;" << std::endl;
+ stream << std::endl;
}
void ChartToVHDL::writeTestbench(std::ostream& stream) {
- stream << "-- TESTBENCH" << std::endl;
- writeIncludes(stream);
- stream << std::endl;
-
- stream << "-- empty entity" << std::endl;
- stream << "entity tb is" << std::endl;
- stream << "end entity tb;" << std::endl;
- stream << std::endl;
-
- stream << "architecture bhv of tb is" << std::endl;
- stream << std::endl;
-
- // modules
- stream << " -- Module declaration" << std::endl;
- stream << " component micro_stepper is" << std::endl;
- stream << " port (" << std::endl;
- stream << " --inputs" << std::endl;
- stream << " clk :in std_logic;" << std::endl;
- stream << " rst_i :in std_logic;" << std::endl;
- stream << " en :in std_logic;" << std::endl;
- stream << " next_event_i :in event_type;" << std::endl;
- stream << " next_event_we_i :in std_logic;" << std::endl;
- stream << " --outputs" << std::endl;
- stream << " error_o :out std_logic;" << std::endl;
-
- for (auto state : _states) {
- stream << " state_active_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
- stream << " entry_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
- }
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
- stream << " exit_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
- }
- }
-
- for (auto transition : _transitions) {
- if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
- stream << " transition_set_" << ATTR(transition, "postFixOrder") << "_o :out std_logic;"
- << std::endl;
- }
- }
-
- stream << " completed_o :out std_logic" << std::endl;
- stream << " );" << std::endl;
- stream << " end component;" << std::endl;
- stream << std::endl;
-
- stream << " component event_controller is" << std::endl;
- stream << " port(" << std::endl;
- stream << " --inputs" << std::endl;
- stream << " clk :in std_logic;" << std::endl;
- stream << " rst_i :in std_logic;" << std::endl;
-
- for (auto state : _states) {
- stream << " state_active_" << ATTR(state, "documentOrder")
- << "_i :in std_logic;" << std::endl;
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
- stream << " entry_set_" << ATTR(state, "documentOrder")
- << "_i :in std_logic;" << std::endl;
- }
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
- stream << " exit_set_" << ATTR(state, "documentOrder")
- << "_i :in std_logic;" << std::endl;
- }
- }
-
- for (auto transition : _transitions) {
- if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
- stream << " transition_set_" << ATTR(transition, "postFixOrder")
- << "_i :in std_logic;" << std::endl;
- }
- }
- stream << " --outputs" << std::endl;
- stream << " micro_stepper_en_o :out std_logic;" << std::endl;
- stream << " event_o :out event_type;" << std::endl;
- stream << " event_we_o :out std_logic" << std::endl;
- // stream << " done_o :out std_logic" << std::endl;
- stream << ");" << std::endl;
- stream << "end component; " << std::endl;
-
- // signals
- stream << " -- input" << std::endl;
- stream << " signal clk : std_logic := '0';" << std::endl;
- stream << " signal reset : std_logic;" << std::endl;
- stream << " signal dut_enable : std_logic;" << std::endl;
- stream << " signal next_event_we_i : std_logic;" << std::endl;
- stream << " signal next_event_i : event_type;" << std::endl;
- stream << std::endl;
-
- stream << " -- output" << std::endl;
- stream << " signal error_o, completed_o : std_logic;" << std::endl;
- stream << std::endl;
-
- stream << " -- wiring" << std::endl;
- for (auto state : _states) {
- stream << " signal state_active_" << ATTR(state, "documentOrder")
- << "_sig : std_logic;" << std::endl;
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
- stream << " signal entry_set_" << ATTR(state, "documentOrder")
- << "_sig : std_logic;" << std::endl;
- }
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
- stream << " signal exit_set_" << ATTR(state, "documentOrder")
- << "_sig : std_logic;" << std::endl;
- }
- }
-
- for (auto transition : _transitions) {
- if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
- stream << " signal transition_set_" << ATTR(transition, "postFixOrder")
- << "_sig : std_logic;" << std::endl;
- }
- }
-
- // wiring
- stream << "begin" << std::endl;
- stream << " clk <= not clk after 20 ns; -- 25 MHz clock frequency" << std::endl;
- stream << " reset <= '1', '0' after 100 ns; -- generates reset signal: --__" << std::endl;
- stream << std::endl;
-
- stream << " -- Module instantiation" << std::endl;
- stream << " dut : micro_stepper" << std::endl;
- stream << " port map (" << std::endl;
- stream << " clk => clk," << std::endl;
- stream << " rst_i => reset," << std::endl;
- stream << " en => dut_enable," << std::endl;
- stream << std::endl;
-
- stream << " next_event_i => next_event_i," << std::endl;
- stream << " next_event_we_i => next_event_we_i," << std::endl;
- stream << " error_o => error_o," << std::endl;
-
- for (auto state : _states) {
- stream << " state_active_" << ATTR(state, "documentOrder")
- << "_o => state_active_" << ATTR(state, "documentOrder")
- << "_sig," << std::endl;
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
- stream << " entry_set_" << ATTR(state, "documentOrder")
- << "_o => entry_set_" << ATTR(state, "documentOrder")
- << "_sig," << std::endl;
- }
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
- stream << " exit_set_" << ATTR(state, "documentOrder")
- << "_o => exit_set_" << ATTR(state, "documentOrder")
- << "_sig," << std::endl;
- }
- }
-
- for (auto transition : _transitions) {
- if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
- stream << " transition_set_" << ATTR(transition, "postFixOrder")
- << "_o => transition_set_" << ATTR(transition, "postFixOrder")
- << "_sig," << std::endl;
- }
- }
-
- stream << " completed_o => completed_o" << std::endl;
- stream << " );" << std::endl;
- stream << std::endl;
-
- stream << " ec : event_controller" << std::endl;
- stream << " port map (" << std::endl;
- stream << " clk => clk," << std::endl;
- stream << " rst_i => reset," << std::endl;
- stream << std::endl;
-
- stream << " event_o => next_event_i," << std::endl;
- stream << " event_we_o => next_event_we_i," << std::endl;
-
- for (auto state : _states) {
- stream << " state_active_" << ATTR(state, "documentOrder")
- << "_i => state_active_" << ATTR(state, "documentOrder")
- << "_sig," << std::endl;
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
- stream << " entry_set_" << ATTR(state, "documentOrder")
- << "_i => entry_set_" << ATTR(state, "documentOrder")
- << "_sig," << std::endl;
- }
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
- stream << " exit_set_" << ATTR(state, "documentOrder")
- << "_i => exit_set_" << ATTR(state, "documentOrder")
- << "_sig," << std::endl;
- }
- }
-
- for (auto transition : _transitions) {
- if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
- stream << " transition_set_" << ATTR(transition, "postFixOrder")
- << "_i => transition_set_" << ATTR(transition, "postFixOrder")
- << "_sig," << std::endl;
- }
- }
-
- stream << " micro_stepper_en_o => dut_enable" << std::endl;
- // stream << " done_o => open" << std::endl;
- stream << " );" << std::endl;
- stream << std::endl;
-
- stream << "end architecture;" << std::endl;
- stream << "-- END TESTBENCH" << std::endl;
+ stream << "-- TESTBENCH" << std::endl;
+ writeIncludes(stream);
+ stream << std::endl;
+
+ stream << "-- empty entity" << std::endl;
+ stream << "entity tb is" << std::endl;
+ stream << "end entity tb;" << std::endl;
+ stream << std::endl;
+
+ stream << "architecture bhv of tb is" << std::endl;
+ stream << std::endl;
+
+ // modules
+ stream << " -- Module declaration" << std::endl;
+ stream << " component micro_stepper is" << std::endl;
+ stream << " port (" << std::endl;
+ stream << " --inputs" << std::endl;
+ stream << " clk :in std_logic;" << std::endl;
+ stream << " rst_i :in std_logic;" << std::endl;
+ stream << " en :in std_logic;" << std::endl;
+ stream << " next_event_i :in event_type;" << std::endl;
+ stream << " next_event_we_i :in std_logic;" << std::endl;
+ stream << " --outputs" << std::endl;
+ stream << " error_o :out std_logic;" << std::endl;
+
+ for (auto state : _states) {
+ stream << " state_active_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
+ stream << " entry_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
+ }
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
+ stream << " exit_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
+ }
+ }
+
+ for (auto transition : _transitions) {
+ if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
+ stream << " transition_set_" << ATTR(transition, "postFixOrder") << "_o :out std_logic;"
+ << std::endl;
+ }
+ }
+
+ stream << " completed_o :out std_logic" << std::endl;
+ stream << " );" << std::endl;
+ stream << " end component;" << std::endl;
+ stream << std::endl;
+
+ stream << " component event_controller is" << std::endl;
+ stream << " port(" << std::endl;
+ stream << " --inputs" << std::endl;
+ stream << " clk :in std_logic;" << std::endl;
+ stream << " rst_i :in std_logic;" << std::endl;
+
+ for (auto state : _states) {
+ stream << " state_active_" << ATTR(state, "documentOrder")
+ << "_i :in std_logic;" << std::endl;
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
+ stream << " entry_set_" << ATTR(state, "documentOrder")
+ << "_i :in std_logic;" << std::endl;
+ }
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
+ stream << " exit_set_" << ATTR(state, "documentOrder")
+ << "_i :in std_logic;" << std::endl;
+ }
+ }
+
+ for (auto transition : _transitions) {
+ if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
+ stream << " transition_set_" << ATTR(transition, "postFixOrder")
+ << "_i :in std_logic;" << std::endl;
+ }
+ }
+ stream << " --outputs" << std::endl;
+ stream << " micro_stepper_en_o :out std_logic;" << std::endl;
+ stream << " event_o :out event_type;" << std::endl;
+ stream << " event_we_o :out std_logic" << std::endl;
+ // stream << " done_o :out std_logic" << std::endl;
+ stream << ");" << std::endl;
+ stream << "end component; " << std::endl;
+
+ // signals
+ stream << " -- input" << std::endl;
+ stream << " signal clk : std_logic := '0';" << std::endl;
+ stream << " signal reset : std_logic;" << std::endl;
+ stream << " signal dut_enable : std_logic;" << std::endl;
+ stream << " signal next_event_we_i : std_logic;" << std::endl;
+ stream << " signal next_event_i : event_type;" << std::endl;
+ stream << std::endl;
+
+ stream << " -- output" << std::endl;
+ stream << " signal error_o, completed_o : std_logic;" << std::endl;
+ stream << std::endl;
+
+ stream << " -- wiring" << std::endl;
+ for (auto state : _states) {
+ stream << " signal state_active_" << ATTR(state, "documentOrder")
+ << "_sig : std_logic;" << std::endl;
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
+ stream << " signal entry_set_" << ATTR(state, "documentOrder")
+ << "_sig : std_logic;" << std::endl;
+ }
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
+ stream << " signal exit_set_" << ATTR(state, "documentOrder")
+ << "_sig : std_logic;" << std::endl;
+ }
+ }
+
+ for (auto transition : _transitions) {
+ if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
+ stream << " signal transition_set_" << ATTR(transition, "postFixOrder")
+ << "_sig : std_logic;" << std::endl;
+ }
+ }
+
+ // wiring
+ stream << "begin" << std::endl;
+ stream << " clk <= not clk after 20 ns; -- 25 MHz clock frequency" << std::endl;
+ stream << " reset <= '1', '0' after 100 ns; -- generates reset signal: --__" << std::endl;
+ stream << std::endl;
+
+ stream << " -- Module instantiation" << std::endl;
+ stream << " dut : micro_stepper" << std::endl;
+ stream << " port map (" << std::endl;
+ stream << " clk => clk," << std::endl;
+ stream << " rst_i => reset," << std::endl;
+ stream << " en => dut_enable," << std::endl;
+ stream << std::endl;
+
+ stream << " next_event_i => next_event_i," << std::endl;
+ stream << " next_event_we_i => next_event_we_i," << std::endl;
+ stream << " error_o => error_o," << std::endl;
+
+ for (auto state : _states) {
+ stream << " state_active_" << ATTR(state, "documentOrder")
+ << "_o => state_active_" << ATTR(state, "documentOrder")
+ << "_sig," << std::endl;
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
+ stream << " entry_set_" << ATTR(state, "documentOrder")
+ << "_o => entry_set_" << ATTR(state, "documentOrder")
+ << "_sig," << std::endl;
+ }
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
+ stream << " exit_set_" << ATTR(state, "documentOrder")
+ << "_o => exit_set_" << ATTR(state, "documentOrder")
+ << "_sig," << std::endl;
+ }
+ }
+
+ for (auto transition : _transitions) {
+ if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
+ stream << " transition_set_" << ATTR(transition, "postFixOrder")
+ << "_o => transition_set_" << ATTR(transition, "postFixOrder")
+ << "_sig," << std::endl;
+ }
+ }
+
+ stream << " completed_o => completed_o" << std::endl;
+ stream << " );" << std::endl;
+ stream << std::endl;
+
+ stream << " ec : event_controller" << std::endl;
+ stream << " port map (" << std::endl;
+ stream << " clk => clk," << std::endl;
+ stream << " rst_i => reset," << std::endl;
+ stream << std::endl;
+
+ stream << " event_o => next_event_i," << std::endl;
+ stream << " event_we_o => next_event_we_i," << std::endl;
+
+ for (auto state : _states) {
+ stream << " state_active_" << ATTR(state, "documentOrder")
+ << "_i => state_active_" << ATTR(state, "documentOrder")
+ << "_sig," << std::endl;
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
+ stream << " entry_set_" << ATTR(state, "documentOrder")
+ << "_i => entry_set_" << ATTR(state, "documentOrder")
+ << "_sig," << std::endl;
+ }
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
+ stream << " exit_set_" << ATTR(state, "documentOrder")
+ << "_i => exit_set_" << ATTR(state, "documentOrder")
+ << "_sig," << std::endl;
+ }
+ }
+
+ for (auto transition : _transitions) {
+ if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
+ stream << " transition_set_" << ATTR(transition, "postFixOrder")
+ << "_i => transition_set_" << ATTR(transition, "postFixOrder")
+ << "_sig," << std::endl;
+ }
+ }
+
+ stream << " micro_stepper_en_o => dut_enable" << std::endl;
+ // stream << " done_o => open" << std::endl;
+ stream << " );" << std::endl;
+ stream << std::endl;
+
+ stream << "end architecture;" << std::endl;
+ stream << "-- END TESTBENCH" << std::endl;
}
void ChartToVHDL::writeExContentBlock(std::ostream & stream,
- std::string index, std::list< DOMElement* > commandSequence) {
- // index should be [entry, transition, exit]_<index of state/transition>_<optional index for block>
+ std::string index, std::list< DOMElement* > commandSequence) {
+ // index should be [entry, transition, exit]_<index of state/transition>_<optional index for block>
- // write clock blocks
+ // write clock blocks
}
void ChartToVHDL::writeEventController(std::ostream & stream) {
- // Add controler specific stuff here
- // create hardware top level
- stream << "-- Event Controller Logic" << std::endl;
- writeIncludes(stream);
- stream << "entity event_controller is" << std::endl;
- stream << "port(" << std::endl;
- stream << " --inputs" << std::endl;
- stream << " clk :in std_logic;" << std::endl;
- stream << " rst_i :in std_logic;" << std::endl;
-
- for (auto state : _states) {
- stream << " state_active_" << ATTR(state, "documentOrder")
- << "_i :in std_logic;" << std::endl;
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
- stream << " entry_set_" << ATTR(state, "documentOrder")
- << "_i :in std_logic;" << std::endl;
- }
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
- stream << " exit_set_" << ATTR(state, "documentOrder")
- << "_i :in std_logic;" << std::endl;
- }
- }
-
- for (auto transition : _transitions) {
- if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
- stream << " transition_set_" << ATTR(transition, "postFixOrder")
- << "_i :in std_logic;" << std::endl;
- }
- }
-
- stream << " --outputs" << std::endl;
- stream << " micro_stepper_en_o :out std_logic;" << std::endl;
- stream << " event_o :out event_type;" << std::endl;
- stream << " event_we_o :out std_logic" << std::endl;
- stream << ");" << std::endl;
- stream << "end event_controller; " << std::endl;
-
- stream << std::endl;
- stream << "architecture behavioral of event_controller is " << std::endl;
- stream << std::endl;
-
- // Add signals and components
- stream << "signal rst : std_logic;" << std::endl;
- stream << "signal micro_stepper_en : std_logic;" << std::endl;
- stream << "signal cmpl_buf : std_logic;" << std::endl;
- stream << "signal completed_sig : std_logic;" << std::endl;
- stream << "signal event_bus : event_type;" << std::endl;
- stream << "signal event_we : std_logic;" << std::endl;
-
- for (int i = 0; i < _execContent.size(); i++) {
- stream << "signal done_" << toStr(i) << "_sig : std_logic;" << std::endl;
- stream << "signal start_" << toStr(i) << "_sig : std_logic;" << std::endl;
- }
-
- stream << "-- sequence input line" << std::endl;
- for (int i = 0; i < _execContent.size(); i++) {
- stream << "signal seq_" << toStr(i) << "_sig : std_logic;" << std::endl;
- }
- stream << std::endl;
-
- stream << "begin" << std::endl;
- stream << std::endl;
- // system signal mapping
- stream << "rst <= rst_i;" << std::endl;
- stream << "micro_stepper_en_o <= micro_stepper_en;" << std::endl;
- stream << "event_o <= event_bus;" << std::endl;
- stream << "event_we_o <= event_we;" << std::endl;
- stream << std::endl;
-
- // stall management
- stream << "-- stalling microstepper" << std::endl;
- // stream << "ms_enable_manager : process (clk, rst) " << std::endl;
- // stream << "begin" << std::endl;
- // stream << " if rst = '1' then" << std::endl;
- // stream << " micro_stepper_en <= '1';" << std::endl;
- // stream << " elsif rising_edge(clk) then" << std::endl;
- // stream << " " << std::endl;
- stream << "micro_stepper_en <= completed_sig or not ( '0' ";
- for (auto state : _states) {
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
- stream << std::endl << " or entry_set_" << ATTR(state, "documentOrder")
- << "_i";
- }
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
- stream << std::endl << " or exit_set_" << ATTR(state, "documentOrder")
- << "_i";
- }
- }
- for (auto transition : _transitions) {
- if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
- stream << std::endl << " or transition_set_" << ATTR(transition, "postFixOrder")
- << "_i";
- }
- }
- stream << ");" << std::endl;
- // stream << " end if;" << std::endl;
- // stream << "end process;" << std::endl;
- stream << std::endl;
-
- // write enable management
- // stream << "-- write enable for FIFO buffer" << std::endl;
- // stream << "event_we <= not rst and ('0'";
- // for (int i = 0; i < _execContent.size(); i++) {
- // stream << std::endl << " or start_" << toStr(i) << "_sig";
- // }
- // stream << ");" << std::endl;
- // stream << std::endl;
-
- // sequential code operation
- stream << "-- seq code block " << std::endl;
- stream << "ex_content_block : process (clk, rst) " << std::endl;
- stream << "begin" << std::endl;
- stream << " if rst = '1' then" << std::endl;
- for (int i = 0; i < _execContent.size(); i++) {
- stream << " done_" << toStr(i) << "_sig <= '0';" << std::endl;
- }
- stream << " event_bus <= hwe_null;" << std::endl;
- stream << " event_we <= '0';" << std::endl;
- stream << " cmpl_buf <= '0';" << std::endl;
- stream << " completed_sig <= '0';" << std::endl;
- stream << " elsif rising_edge(clk) then" << std::endl;
-
- stream << " if micro_stepper_en = '1' then" << std::endl;
- stream << " cmpl_buf <= '0' ;" << std::endl;
- stream << " else" << std::endl;
- stream << " cmpl_buf <= seq_" << toStr(_execContent.size() - 1)
- << "_sig;" << std::endl;
- stream << " end if;" << std::endl;
- stream << " completed_sig <= cmpl_buf;" << std::endl << std::endl;
-
- size_t i = 0;
- std::string seperator;
- for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) {
- DOMElement* exContentElem = *ecIter;
-
- //TODO if raise
- if (TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "raise" ||
- TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "send") {
- stream << seperator << "if start_" << toStr(i) << "_sig = '1' then"
- << std::endl;
- //TODO use escape
- stream << " event_bus <= hwe_" << ATTR(exContentElem, "event")
- << ";" << std::endl;
- stream << " done_" << toStr(i) << "_sig <= '1';" << std::endl;
- stream << " event_we <= '1';" << std::endl;
- seperator = " els";
- }
- }
- stream << " elsif micro_stepper_en = '1' then" << std::endl;
- for (auto exContentElem : _execContent) {
-
- //TODO if raise
- if (TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "raise") {
- stream << " done_" << toStr(i) << "_sig <= '0';" << std::endl;
- }
- }
- stream << " event_we <= '0';" << std::endl;
- stream << " end if;" << std::endl;
- stream << " end if;" << std::endl;
- stream << "end process;" << std::endl;
- stream << std::endl;
-
- i = 0;
- for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) {
- // start lines
- stream << "start_" << toStr(i) << "_sig <= "
- << getLineForExecContent(*ecIter) << " and "
- << "not done_" << toStr(i) << "_sig";
- if (i != 0) { // if not first element
- stream << " and seq_" << toStr(i) << "_sig";
- }
- stream << ";" << std::endl;
-
- }
-
- stream << "seq_0_sig <= '1';" << std::endl;
-
- if (_execContent.size() > 1) {
- i = 0;
- for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) {
- // seq lines (input if process i is in seqence now)
- stream << "seq_" << toStr(i) << "_sig <= "
- << "done_" << toStr(i - 1) << "_sig or "
- << "( not "
- << getLineForExecContent(*ecIter);
- stream << " and seq_" << toStr(i - 1) << "_sig";
- stream << " );" << std::endl;
- }
- }
- stream << std::endl;
-
- stream << "end behavioral; " << std::endl;
- stream << "-- END Event Controller Logic" << std::endl;
+ // Add controler specific stuff here
+ // create hardware top level
+ stream << "-- Event Controller Logic" << std::endl;
+ writeIncludes(stream);
+ stream << "entity event_controller is" << std::endl;
+ stream << "port(" << std::endl;
+ stream << " --inputs" << std::endl;
+ stream << " clk :in std_logic;" << std::endl;
+ stream << " rst_i :in std_logic;" << std::endl;
+
+ for (auto state : _states) {
+ stream << " state_active_" << ATTR(state, "documentOrder")
+ << "_i :in std_logic;" << std::endl;
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
+ stream << " entry_set_" << ATTR(state, "documentOrder")
+ << "_i :in std_logic;" << std::endl;
+ }
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
+ stream << " exit_set_" << ATTR(state, "documentOrder")
+ << "_i :in std_logic;" << std::endl;
+ }
+ }
+
+ for (auto transition : _transitions) {
+ if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
+ stream << " transition_set_" << ATTR(transition, "postFixOrder")
+ << "_i :in std_logic;" << std::endl;
+ }
+ }
+
+ stream << " --outputs" << std::endl;
+ stream << " micro_stepper_en_o :out std_logic;" << std::endl;
+ stream << " event_o :out event_type;" << std::endl;
+ stream << " event_we_o :out std_logic" << std::endl;
+ stream << ");" << std::endl;
+ stream << "end event_controller; " << std::endl;
+
+ stream << std::endl;
+ stream << "architecture behavioral of event_controller is " << std::endl;
+ stream << std::endl;
+
+ // Add signals and components
+ stream << "signal rst : std_logic;" << std::endl;
+ stream << "signal micro_stepper_en : std_logic;" << std::endl;
+ stream << "signal cmpl_buf : std_logic;" << std::endl;
+ stream << "signal completed_sig : std_logic;" << std::endl;
+ stream << "signal event_bus : event_type;" << std::endl;
+ stream << "signal event_we : std_logic;" << std::endl;
+
+ for (int i = 0; i < _execContent.size(); i++) {
+ stream << "signal done_" << toStr(i) << "_sig : std_logic;" << std::endl;
+ stream << "signal start_" << toStr(i) << "_sig : std_logic;" << std::endl;
+ }
+
+ stream << "-- sequence input line" << std::endl;
+ for (int i = 0; i < _execContent.size(); i++) {
+ stream << "signal seq_" << toStr(i) << "_sig : std_logic;" << std::endl;
+ }
+ stream << std::endl;
+
+ stream << "begin" << std::endl;
+ stream << std::endl;
+ // system signal mapping
+ stream << "rst <= rst_i;" << std::endl;
+ stream << "micro_stepper_en_o <= micro_stepper_en;" << std::endl;
+ stream << "event_o <= event_bus;" << std::endl;
+ stream << "event_we_o <= event_we;" << std::endl;
+ stream << std::endl;
+
+ // stall management
+ stream << "-- stalling microstepper" << std::endl;
+ // stream << "ms_enable_manager : process (clk, rst) " << std::endl;
+ // stream << "begin" << std::endl;
+ // stream << " if rst = '1' then" << std::endl;
+ // stream << " micro_stepper_en <= '1';" << std::endl;
+ // stream << " elsif rising_edge(clk) then" << std::endl;
+ // stream << " " << std::endl;
+ stream << "micro_stepper_en <= completed_sig or not ( '0' ";
+ for (auto state : _states) {
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
+ stream << std::endl << " or entry_set_" << ATTR(state, "documentOrder")
+ << "_i";
+ }
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
+ stream << std::endl << " or exit_set_" << ATTR(state, "documentOrder")
+ << "_i";
+ }
+ }
+ for (auto transition : _transitions) {
+ if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
+ stream << std::endl << " or transition_set_" << ATTR(transition, "postFixOrder")
+ << "_i";
+ }
+ }
+ stream << ");" << std::endl;
+ // stream << " end if;" << std::endl;
+ // stream << "end process;" << std::endl;
+ stream << std::endl;
+
+ // write enable management
+ // stream << "-- write enable for FIFO buffer" << std::endl;
+ // stream << "event_we <= not rst and ('0'";
+ // for (int i = 0; i < _execContent.size(); i++) {
+ // stream << std::endl << " or start_" << toStr(i) << "_sig";
+ // }
+ // stream << ");" << std::endl;
+ // stream << std::endl;
+
+ // sequential code operation
+ stream << "-- seq code block " << std::endl;
+ stream << "ex_content_block : process (clk, rst) " << std::endl;
+ stream << "begin" << std::endl;
+ stream << " if rst = '1' then" << std::endl;
+ for (int i = 0; i < _execContent.size(); i++) {
+ stream << " done_" << toStr(i) << "_sig <= '0';" << std::endl;
+ }
+ stream << " event_bus <= hwe_null;" << std::endl;
+ stream << " event_we <= '0';" << std::endl;
+ stream << " cmpl_buf <= '0';" << std::endl;
+ stream << " completed_sig <= '0';" << std::endl;
+ stream << " elsif rising_edge(clk) then" << std::endl;
+
+ stream << " if micro_stepper_en = '1' then" << std::endl;
+ stream << " cmpl_buf <= '0' ;" << std::endl;
+ stream << " else" << std::endl;
+ stream << " cmpl_buf <= seq_" << toStr(_execContent.size() - 1)
+ << "_sig;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << " completed_sig <= cmpl_buf;" << std::endl << std::endl;
+
+ size_t i = 0;
+ std::string seperator;
+ for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) {
+ DOMElement* exContentElem = *ecIter;
+
+ //TODO if raise
+ if (TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "raise" ||
+ TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "send") {
+ stream << seperator << "if start_" << toStr(i) << "_sig = '1' then"
+ << std::endl;
+ //TODO use escape
+ stream << " event_bus <= hwe_" << ATTR(exContentElem, "event")
+ << ";" << std::endl;
+ stream << " done_" << toStr(i) << "_sig <= '1';" << std::endl;
+ stream << " event_we <= '1';" << std::endl;
+ seperator = " els";
+ }
+ }
+ stream << " elsif micro_stepper_en = '1' then" << std::endl;
+ for (auto exContentElem : _execContent) {
+
+ //TODO if raise
+ if (TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "raise") {
+ stream << " done_" << toStr(i) << "_sig <= '0';" << std::endl;
+ }
+ }
+ stream << " event_we <= '0';" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << "end process;" << std::endl;
+ stream << std::endl;
+
+ i = 0;
+ for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) {
+ // start lines
+ stream << "start_" << toStr(i) << "_sig <= "
+ << getLineForExecContent(*ecIter) << " and "
+ << "not done_" << toStr(i) << "_sig";
+ if (i != 0) { // if not first element
+ stream << " and seq_" << toStr(i) << "_sig";
+ }
+ stream << ";" << std::endl;
+
+ }
+
+ stream << "seq_0_sig <= '1';" << std::endl;
+
+ if (_execContent.size() > 1) {
+ i = 0;
+ for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) {
+ // seq lines (input if process i is in seqence now)
+ stream << "seq_" << toStr(i) << "_sig <= "
+ << "done_" << toStr(i - 1) << "_sig or "
+ << "( not "
+ << getLineForExecContent(*ecIter);
+ stream << " and seq_" << toStr(i - 1) << "_sig";
+ stream << " );" << std::endl;
+ }
+ }
+ stream << std::endl;
+
+ stream << "end behavioral; " << std::endl;
+ stream << "-- END Event Controller Logic" << std::endl;
}
std::string ChartToVHDL::getLineForExecContent(const DOMNode* elem) {
- const DOMNode* ecBlock = elem;
- while (ecBlock) {
- if (ecBlock->getNodeType() == DOMNode::ELEMENT_NODE) {
- std::string localName = LOCALNAME_CAST(ecBlock);
- if (localName == XML_PREFIX(_scxml).str() + "transition") {
- return "transition_set_" + ATTR_CAST(ecBlock, "postFixOrder") + "_i";
- }
-
- if (localName == XML_PREFIX(_scxml).str() + "onentry") {
- return "entry_set_" + ATTR_CAST(ecBlock->getParentNode(), "documentOrder") + "_i";
- }
-
- if (localName == XML_PREFIX(_scxml).str() + "onexit") {
- return "exit_set_" + ATTR_CAST(ecBlock->getParentNode(), "documentOrder") + "_i";
- }
-
- }
- ecBlock = ecBlock->getParentNode();
- }
-
- return "";
+ const DOMNode* ecBlock = elem;
+ while (ecBlock) {
+ if (ecBlock->getNodeType() == DOMNode::ELEMENT_NODE) {
+ std::string localName = LOCALNAME_CAST(ecBlock);
+ if (localName == XML_PREFIX(_scxml).str() + "transition") {
+ return "transition_set_" + ATTR_CAST(ecBlock, "postFixOrder") + "_i";
+ }
+
+ if (localName == XML_PREFIX(_scxml).str() + "onentry") {
+ return "entry_set_" + ATTR_CAST(ecBlock->getParentNode(), "documentOrder") + "_i";
+ }
+
+ if (localName == XML_PREFIX(_scxml).str() + "onexit") {
+ return "exit_set_" + ATTR_CAST(ecBlock->getParentNode(), "documentOrder") + "_i";
+ }
+
+ }
+ ecBlock = ecBlock->getParentNode();
+ }
+
+ return "";
}
void ChartToVHDL::writeMicroStepper(std::ostream & stream) {
- // create MicroStepper top level
- stream << "-- FSM Logic" << std::endl;
- writeIncludes(stream);
- stream << "entity micro_stepper is" << std::endl;
- stream << "port(" << std::endl;
- stream << " --inputs" << std::endl;
- stream << " clk :in std_logic;" << std::endl;
- stream << " rst_i :in std_logic;" << std::endl;
- stream << " en :in std_logic;" << std::endl;
- stream << " next_event_i :in event_type;" << std::endl;
- stream << " next_event_we_i :in std_logic;" << std::endl;
- stream << " --outputs" << std::endl;
- stream << " error_o :out std_logic;" << std::endl;
-
- for (auto state : _states) {
- stream << " state_active_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
- stream << " entry_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
- }
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
- stream << " exit_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
- }
- }
-
- for (auto transition : _transitions) {
- if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
- stream << " transition_set_" << ATTR(transition, "postFixOrder") << "_o :out std_logic;"
- << std::endl;
- }
- }
-
- stream << " completed_o :out std_logic" << std::endl;
- stream << ");" << std::endl;
- stream << "end micro_stepper; " << std::endl;
-
- stream << std::endl;
- stream << "architecture behavioral of micro_stepper is " << std::endl;
- stream << std::endl;
-
- // Add signals and components
- writeSignalsAndComponents(stream);
-
- stream << std::endl;
- stream << "begin" << std::endl;
- stream << std::endl;
-
- // signal mapping
- writeModuleInstantiation(stream);
-
- // signal handler
- writeSpontaneousHandler(stream);
- writeErrorHandler(stream);
- writeInternalEventHandler(stream);
- writeStateHandler(stream);
- writeResetHandler(stream);
-
- // combinatorial logic for Sn+1
- writeOptimalTransitionSetSelection(stream);
- writeExitSet(stream);
- writeCompleteEntrySet(stream);
- writeEntrySet(stream);
- writeDefaultCompletions(stream);
- writeActiveStateNplusOne(stream);
-
- // connect output signals
- writeSystemSignalMapping(stream);
-
-
- stream << std::endl;
- stream << "end behavioral; " << std::endl;
- stream << "-- END FSM Logic" << std::endl;
+ // create MicroStepper top level
+ stream << "-- FSM Logic" << std::endl;
+ writeIncludes(stream);
+ stream << "entity micro_stepper is" << std::endl;
+ stream << "port(" << std::endl;
+ stream << " --inputs" << std::endl;
+ stream << " clk :in std_logic;" << std::endl;
+ stream << " rst_i :in std_logic;" << std::endl;
+ stream << " en :in std_logic;" << std::endl;
+ stream << " next_event_i :in event_type;" << std::endl;
+ stream << " next_event_we_i :in std_logic;" << std::endl;
+ stream << " --outputs" << std::endl;
+ stream << " error_o :out std_logic;" << std::endl;
+
+ for (auto state : _states) {
+ stream << " state_active_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
+ stream << " entry_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
+ }
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
+ stream << " exit_set_" << ATTR(state, "documentOrder") << "_o :out std_logic;" << std::endl;
+ }
+ }
+
+ for (auto transition : _transitions) {
+ if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
+ stream << " transition_set_" << ATTR(transition, "postFixOrder") << "_o :out std_logic;"
+ << std::endl;
+ }
+ }
+
+ stream << " completed_o :out std_logic" << std::endl;
+ stream << ");" << std::endl;
+ stream << "end micro_stepper; " << std::endl;
+
+ stream << std::endl;
+ stream << "architecture behavioral of micro_stepper is " << std::endl;
+ stream << std::endl;
+
+ // Add signals and components
+ writeSignalsAndComponents(stream);
+
+ stream << std::endl;
+ stream << "begin" << std::endl;
+ stream << std::endl;
+
+ // signal mapping
+ writeModuleInstantiation(stream);
+
+ // signal handler
+ writeSpontaneousHandler(stream);
+ writeErrorHandler(stream);
+ writeInternalEventHandler(stream);
+ writeStateHandler(stream);
+ writeResetHandler(stream);
+
+ // combinatorial logic for Sn+1
+ writeOptimalTransitionSetSelection(stream);
+ writeExitSet(stream);
+ writeCompleteEntrySet(stream);
+ writeEntrySet(stream);
+ writeDefaultCompletions(stream);
+ writeActiveStateNplusOne(stream);
+
+ // connect output signals
+ writeSystemSignalMapping(stream);
+
+
+ stream << std::endl;
+ stream << "end behavioral; " << std::endl;
+ stream << "-- END FSM Logic" << std::endl;
}
void ChartToVHDL::writeFiFo(std::ostream & stream) {
- // taken from: http://www.deathbylogic.com/2013/07/vhdl-standard-fifo/
- // alternativly take fifo logic for a ram device: http://www.eng.auburn.edu/~strouce/class/elec4200/vhdlmods.pdf
- stream << "-- standard FIFO buffer" << std::endl;
- writeIncludes(stream);
- stream << "" << std::endl;
- stream << "entity std_fifo is" << std::endl;
- stream << "generic (" << std::endl;
- stream << " constant FIFO_DEPTH : positive := 256" << std::endl;
- stream << ");" << std::endl;
- stream << "port ( " << std::endl;
- stream << " clk : in std_logic;" << std::endl;
- stream << " rst : in std_logic;" << std::endl;
- stream << " write_en : in std_logic;" << std::endl;
- stream << " read_en : in std_logic;" << std::endl;
- stream << " data_in : in event_type;" << std::endl;
- stream << " data_out : out event_type;" << std::endl;
- stream << " empty : out std_logic;" << std::endl;
- stream << " full : out std_logic" << std::endl;
- stream << ");" << std::endl;
- stream << "end std_fifo;" << std::endl;
- stream << "" << std::endl;
- stream << "architecture behavioral of std_fifo is" << std::endl;
- stream << "begin" << std::endl;
- stream << "-- Memory Pointer Process" << std::endl;
- stream << "fifo_proc : process (clk)" << std::endl;
- stream << " type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of event_type;" << std::endl;
- stream << " variable Memory : FIFO_Memory;" << std::endl;
- stream << "" << std::endl;
- stream << " variable Head : natural range 0 to FIFO_DEPTH - 1;" << std::endl;
- stream << " variable Tail : natural range 0 to FIFO_DEPTH - 1;" << std::endl;
- stream << "" << std::endl;
- stream << " variable Looped : boolean;" << std::endl;
- stream << "begin" << std::endl;
- stream << " if rising_edge(clk) then" << std::endl;
- stream << " if rst = '1' then" << std::endl;
- stream << " Head := 0;" << std::endl;
- stream << " Tail := 0;" << std::endl;
- stream << "" << std::endl;
- stream << " Looped := false;" << std::endl;
- stream << "" << std::endl;
- stream << " full <= '0';" << std::endl;
- stream << " empty <= '1';" << std::endl;
- stream << " else" << std::endl;
- stream << " if (read_en = '1') then" << std::endl;
- stream << " if ((Looped = true) or (Head /= Tail)) then" << std::endl;
- stream << " -- Update data output" << std::endl;
- stream << " data_out <= Memory(Tail);" << std::endl;
- stream << " " << std::endl;
- stream << " -- Update Tail pointer as needed" << std::endl;
- stream << " if (Tail = FIFO_DEPTH - 1) then" << std::endl;
- stream << " Tail := 0;" << std::endl;
- stream << " " << std::endl;
- stream << " Looped := false;" << std::endl;
- stream << " else" << std::endl;
- stream << " Tail := Tail + 1;" << std::endl;
- stream << " end if;" << std::endl;
- stream << "" << std::endl;
- stream << " end if;" << std::endl;
- stream << " end if;" << std::endl;
- stream << "" << std::endl;
- stream << " if (write_en = '1') then" << std::endl;
- stream << " if ((Looped = false) or (Head /= Tail)) then" << std::endl;
- stream << " -- Write Data to Memory" << std::endl;
- stream << " Memory(Head) := data_in;" << std::endl;
- stream << " " << std::endl;
- stream << " -- Increment Head pointer as needed" << std::endl;
- stream << " if (Head = FIFO_DEPTH - 1) then" << std::endl;
- stream << " Head := 0;" << std::endl;
- stream << " " << std::endl;
- stream << " Looped := true;" << std::endl;
- stream << " else" << std::endl;
- stream << " Head := Head + 1;" << std::endl;
- stream << " end if;" << std::endl;
- stream << " end if;" << std::endl;
- stream << " end if;" << std::endl;
- stream << "" << std::endl;
- stream << " -- Update empty and full flags" << std::endl;
- stream << " if (Head = Tail) then" << std::endl;
- stream << " if Looped then" << std::endl;
- stream << " full <= '1';" << std::endl;
- stream << " else" << std::endl;
- stream << " empty <= '1';" << std::endl;
- stream << " end if;" << std::endl;
- stream << " else" << std::endl;
- stream << " empty <= '0';" << std::endl;
- stream << " full <= '0';" << std::endl;
- stream << " end if;" << std::endl;
- stream << " end if;" << std::endl;
- stream << " end if;" << std::endl;
- stream << "end process;" << std::endl;
- stream << "" << std::endl;
- stream << "end behavioral;" << std::endl;
- stream << "-- END standard FIFO buffer" << std::endl;
+ // taken from: http://www.deathbylogic.com/2013/07/vhdl-standard-fifo/
+ // alternativly take fifo logic for a ram device: http://www.eng.auburn.edu/~strouce/class/elec4200/vhdlmods.pdf
+ stream << "-- standard FIFO buffer" << std::endl;
+ writeIncludes(stream);
+ stream << "" << std::endl;
+ stream << "entity std_fifo is" << std::endl;
+ stream << "generic (" << std::endl;
+ stream << " constant FIFO_DEPTH : positive := 256" << std::endl;
+ stream << ");" << std::endl;
+ stream << "port ( " << std::endl;
+ stream << " clk : in std_logic;" << std::endl;
+ stream << " rst : in std_logic;" << std::endl;
+ stream << " write_en : in std_logic;" << std::endl;
+ stream << " read_en : in std_logic;" << std::endl;
+ stream << " data_in : in event_type;" << std::endl;
+ stream << " data_out : out event_type;" << std::endl;
+ stream << " empty : out std_logic;" << std::endl;
+ stream << " full : out std_logic" << std::endl;
+ stream << ");" << std::endl;
+ stream << "end std_fifo;" << std::endl;
+ stream << "" << std::endl;
+ stream << "architecture behavioral of std_fifo is" << std::endl;
+ stream << "begin" << std::endl;
+ stream << "-- Memory Pointer Process" << std::endl;
+ stream << "fifo_proc : process (clk)" << std::endl;
+ stream << " type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of event_type;" << std::endl;
+ stream << " variable Memory : FIFO_Memory;" << std::endl;
+ stream << "" << std::endl;
+ stream << " variable Head : natural range 0 to FIFO_DEPTH - 1;" << std::endl;
+ stream << " variable Tail : natural range 0 to FIFO_DEPTH - 1;" << std::endl;
+ stream << "" << std::endl;
+ stream << " variable Looped : boolean;" << std::endl;
+ stream << "begin" << std::endl;
+ stream << " if rising_edge(clk) then" << std::endl;
+ stream << " if rst = '1' then" << std::endl;
+ stream << " Head := 0;" << std::endl;
+ stream << " Tail := 0;" << std::endl;
+ stream << "" << std::endl;
+ stream << " Looped := false;" << std::endl;
+ stream << "" << std::endl;
+ stream << " full <= '0';" << std::endl;
+ stream << " empty <= '1';" << std::endl;
+ stream << " else" << std::endl;
+ stream << " if (read_en = '1') then" << std::endl;
+ stream << " if ((Looped = true) or (Head /= Tail)) then" << std::endl;
+ stream << " -- Update data output" << std::endl;
+ stream << " data_out <= Memory(Tail);" << std::endl;
+ stream << " " << std::endl;
+ stream << " -- Update Tail pointer as needed" << std::endl;
+ stream << " if (Tail = FIFO_DEPTH - 1) then" << std::endl;
+ stream << " Tail := 0;" << std::endl;
+ stream << " " << std::endl;
+ stream << " Looped := false;" << std::endl;
+ stream << " else" << std::endl;
+ stream << " Tail := Tail + 1;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << "" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << "" << std::endl;
+ stream << " if (write_en = '1') then" << std::endl;
+ stream << " if ((Looped = false) or (Head /= Tail)) then" << std::endl;
+ stream << " -- Write Data to Memory" << std::endl;
+ stream << " Memory(Head) := data_in;" << std::endl;
+ stream << " " << std::endl;
+ stream << " -- Increment Head pointer as needed" << std::endl;
+ stream << " if (Head = FIFO_DEPTH - 1) then" << std::endl;
+ stream << " Head := 0;" << std::endl;
+ stream << " " << std::endl;
+ stream << " Looped := true;" << std::endl;
+ stream << " else" << std::endl;
+ stream << " Head := Head + 1;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << "" << std::endl;
+ stream << " -- Update empty and full flags" << std::endl;
+ stream << " if (Head = Tail) then" << std::endl;
+ stream << " if Looped then" << std::endl;
+ stream << " full <= '1';" << std::endl;
+ stream << " else" << std::endl;
+ stream << " empty <= '1';" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << " else" << std::endl;
+ stream << " empty <= '0';" << std::endl;
+ stream << " full <= '0';" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << "end process;" << std::endl;
+ stream << "" << std::endl;
+ stream << "end behavioral;" << std::endl;
+ stream << "-- END standard FIFO buffer" << std::endl;
}
void ChartToVHDL::writeSignalsAndComponents(std::ostream & stream) {
- // create internal signals
- stream << "-- system signals" << std::endl;
- stream << "signal stall : std_logic;" << std::endl;
- stream << "signal completed_sig : std_logic;" << std::endl;
- // stream << "signal rst_2 : std_logic;" << std::endl;
- // stream << "signal rst_1 : std_logic;" << std::endl;
- stream << "signal rst : std_logic;" << std::endl;
- stream << std::endl;
-
- stream << "-- state signals" << std::endl;
-
- std::list<std::string> signalDecls;
-
- for (auto state : _states) {
-
- signalDecls.push_back("signal state_active_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
- signalDecls.push_back("signal state_next_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
- signalDecls.push_back("signal in_entry_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
- signalDecls.push_back("signal in_exit_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
- signalDecls.push_back("signal in_complete_entry_set_up_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
- signalDecls.push_back("signal in_complete_entry_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
- signalDecls.push_back("signal default_completion_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
- }
-
- signalDecls.sort();
- for (std::list<std::string>::iterator iter = signalDecls.begin(); iter != signalDecls.end(); iter++) {
- stream << *iter << std::endl;
- }
- stream << std::endl;
-
-
- stream << "-- transition signals" << std::endl;
- stream << "signal spontaneous_en : std_logic;" << std::endl;
- stream << "signal spontaneous_active : std_logic;" << std::endl;
- stream << "signal optimal_transition_set_combined_sig : std_logic;" << std::endl;
-
- for (auto transition : _transitions) {
- stream << "signal in_optimal_transition_set_" << ATTR(transition, "postFixOrder") << "_sig : std_logic;"
- << std::endl;
- }
- stream << std::endl;
-
- stream << "-- event signals" << std::endl;
- stream << "signal int_event_write_en : std_logic;" << std::endl;
- stream << "signal int_event_read_en : std_logic;" << std::endl;
- stream << "signal int_event_empty : std_logic;" << std::endl;
- stream << "signal int_event_input : event_type;" << std::endl;
- stream << "signal int_event_output : event_type;" << std::endl;
- stream << "signal next_event_re : std_logic;" << std::endl;
- stream << "signal next_event_dequeued : std_logic;" << std::endl;
- stream << "signal next_event : event_type;" << std::endl;
- stream << "signal event_consumed : std_logic;" << std::endl;
- stream << std::endl;
-
- std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix("");
- for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
- stream << "signal event_" << eventNameEscape((*eventIter)->value) << "_sig : std_logic;" << std::endl;
- }
- stream << std::endl;
-
- stream << "-- error signals" << std::endl;
- stream << "signal reg_error_out : std_logic;" << std::endl;
- stream << "signal error_full_int_event_fifo : std_logic;" << std::endl;
- stream << std::endl;
-
- // add components
- stream << "-- event FIFO" << std::endl;
- stream << "component std_fifo is" << std::endl;
- stream << "port ( " << std::endl;
- stream << " clk : in std_logic;" << std::endl;
- stream << " rst : in std_logic;" << std::endl;
- stream << " write_en : in std_logic;" << std::endl;
- stream << " read_en : in std_logic;" << std::endl;
- stream << " data_in : in event_type;" << std::endl;
- stream << " data_out : out event_type;" << std::endl;
- stream << " empty : out std_logic;" << std::endl;
- stream << " full : out std_logic" << std::endl; // we calculate how much we need
- stream << ");" << std::endl;
- stream << "end component;" << std::endl;
- stream << std::endl;
+ // create internal signals
+ stream << "-- system signals" << std::endl;
+ stream << "signal stall : std_logic;" << std::endl;
+ stream << "signal completed_sig : std_logic;" << std::endl;
+ // stream << "signal rst_2 : std_logic;" << std::endl;
+ // stream << "signal rst_1 : std_logic;" << std::endl;
+ stream << "signal rst : std_logic;" << std::endl;
+ stream << std::endl;
+
+ stream << "-- state signals" << std::endl;
+
+ std::list<std::string> signalDecls;
+
+ for (auto state : _states) {
+
+ signalDecls.push_back("signal state_active_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
+ signalDecls.push_back("signal state_next_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
+ signalDecls.push_back("signal in_entry_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
+ signalDecls.push_back("signal in_exit_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
+ signalDecls.push_back("signal in_complete_entry_set_up_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
+ signalDecls.push_back("signal in_complete_entry_set_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
+ signalDecls.push_back("signal default_completion_" + ATTR(state, "documentOrder") + "_sig : std_logic;");
+ }
+
+ signalDecls.sort();
+ for (std::list<std::string>::iterator iter = signalDecls.begin(); iter != signalDecls.end(); iter++) {
+ stream << *iter << std::endl;
+ }
+ stream << std::endl;
+
+
+ stream << "-- transition signals" << std::endl;
+ stream << "signal spontaneous_en : std_logic;" << std::endl;
+ stream << "signal spontaneous_active : std_logic;" << std::endl;
+ stream << "signal optimal_transition_set_combined_sig : std_logic;" << std::endl;
+
+ for (auto transition : _transitions) {
+ stream << "signal in_optimal_transition_set_" << ATTR(transition, "postFixOrder") << "_sig : std_logic;"
+ << std::endl;
+ }
+ stream << std::endl;
+
+ stream << "-- event signals" << std::endl;
+ stream << "signal int_event_write_en : std_logic;" << std::endl;
+ stream << "signal int_event_read_en : std_logic;" << std::endl;
+ stream << "signal int_event_empty : std_logic;" << std::endl;
+ stream << "signal int_event_input : event_type;" << std::endl;
+ stream << "signal int_event_output : event_type;" << std::endl;
+ stream << "signal next_event_re : std_logic;" << std::endl;
+ stream << "signal next_event_dequeued : std_logic;" << std::endl;
+ stream << "signal next_event : event_type;" << std::endl;
+ stream << "signal event_consumed : std_logic;" << std::endl;
+ stream << std::endl;
+
+ std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix("");
+ for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
+ stream << "signal event_" << eventNameEscape((*eventIter)->value) << "_sig : std_logic;" << std::endl;
+ }
+ stream << std::endl;
+
+ stream << "-- error signals" << std::endl;
+ stream << "signal reg_error_out : std_logic;" << std::endl;
+ stream << "signal error_full_int_event_fifo : std_logic;" << std::endl;
+ stream << std::endl;
+
+ // add components
+ stream << "-- event FIFO" << std::endl;
+ stream << "component std_fifo is" << std::endl;
+ stream << "port ( " << std::endl;
+ stream << " clk : in std_logic;" << std::endl;
+ stream << " rst : in std_logic;" << std::endl;
+ stream << " write_en : in std_logic;" << std::endl;
+ stream << " read_en : in std_logic;" << std::endl;
+ stream << " data_in : in event_type;" << std::endl;
+ stream << " data_out : out event_type;" << std::endl;
+ stream << " empty : out std_logic;" << std::endl;
+ stream << " full : out std_logic" << std::endl; // we calculate how much we need
+ stream << ");" << std::endl;
+ stream << "end component;" << std::endl;
+ stream << std::endl;
}
void ChartToVHDL::writeModuleInstantiation(std::ostream & stream) {
- // instantiate event fifo
- stream << "int_event_fifo : component std_fifo " << std::endl;
- stream << "port map ( " << std::endl;
- stream << " clk => clk," << std::endl;
- stream << " rst => rst_i," << std::endl;
- stream << " write_en => int_event_write_en," << std::endl;
- stream << " read_en => int_event_read_en," << std::endl;
- stream << " data_in => int_event_input," << std::endl;
- stream << " data_out => int_event_output," << std::endl;
- stream << " empty => int_event_empty," << std::endl;
- stream << " full => error_full_int_event_fifo" << std::endl; // we calculate how much we need
- stream << ");" << std::endl;
- stream << std::endl;
+ // instantiate event fifo
+ stream << "int_event_fifo : component std_fifo " << std::endl;
+ stream << "port map ( " << std::endl;
+ stream << " clk => clk," << std::endl;
+ stream << " rst => rst_i," << std::endl;
+ stream << " write_en => int_event_write_en," << std::endl;
+ stream << " read_en => int_event_read_en," << std::endl;
+ stream << " data_in => int_event_input," << std::endl;
+ stream << " data_out => int_event_output," << std::endl;
+ stream << " empty => int_event_empty," << std::endl;
+ stream << " full => error_full_int_event_fifo" << std::endl; // we calculate how much we need
+ stream << ");" << std::endl;
+ stream << std::endl;
}
void ChartToVHDL::writeErrorHandler(std::ostream & stream) {
- // sets error output signal if an error occures somewhere
- stream << "-- error handler" << std::endl;
- stream << "-- sets error output signal if an error occures somewhere" << std::endl;
- stream << "error_handler : process (clk, rst) " << std::endl;
- stream << "begin" << std::endl;
- stream << " if rst = '1' then" << std::endl;
- stream << " reg_error_out <= '0';" << std::endl;
- stream << " elsif rising_edge(clk) then" << std::endl;
- stream << " reg_error_out <= error_full_int_event_fifo;" << std::endl;
- stream << " end if;" << std::endl;
- stream << "end process;" << std::endl;
- stream << std::endl;
+ // sets error output signal if an error occures somewhere
+ stream << "-- error handler" << std::endl;
+ stream << "-- sets error output signal if an error occures somewhere" << std::endl;
+ stream << "error_handler : process (clk, rst) " << std::endl;
+ stream << "begin" << std::endl;
+ stream << " if rst = '1' then" << std::endl;
+ stream << " reg_error_out <= '0';" << std::endl;
+ stream << " elsif rising_edge(clk) then" << std::endl;
+ stream << " reg_error_out <= error_full_int_event_fifo;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << "end process;" << std::endl;
+ stream << std::endl;
}
void ChartToVHDL::writeResetHandler(std::ostream & stream) {
- stream << "-- reset handler" << std::endl;
- stream << "rst <= rst_i;" << std::endl;
- // stream << "rst_proc: process(clk, rst_i)" << std::endl;
- // stream << "begin" << std::endl;
- // stream << " if rst_i = '1' then" << std::endl;
- // stream << " rst_2 <= '1';" << std::endl;
- // stream << " rst_1 <= '1';" << std::endl;
- // stream << " rst <= '1';" << std::endl;
- // stream << " elsif (rising_edge(clk)) then" << std::endl;
- // stream << " rst_2 <= rst_i;" << std::endl;
- // stream << " rst_1 <= rst_i;" << std::endl;
- // stream << " rst <= rst_1;" << std::endl;
- // stream << " end if;" << std::endl;
- // stream << "end process;" << std::endl;
- stream << std::endl;
+ stream << "-- reset handler" << std::endl;
+ stream << "rst <= rst_i;" << std::endl;
+ // stream << "rst_proc: process(clk, rst_i)" << std::endl;
+ // stream << "begin" << std::endl;
+ // stream << " if rst_i = '1' then" << std::endl;
+ // stream << " rst_2 <= '1';" << std::endl;
+ // stream << " rst_1 <= '1';" << std::endl;
+ // stream << " rst <= '1';" << std::endl;
+ // stream << " elsif (rising_edge(clk)) then" << std::endl;
+ // stream << " rst_2 <= rst_i;" << std::endl;
+ // stream << " rst_1 <= rst_i;" << std::endl;
+ // stream << " rst <= rst_1;" << std::endl;
+ // stream << " end if;" << std::endl;
+ // stream << "end process;" << std::endl;
+ stream << std::endl;
}
void ChartToVHDL::writeSpontaneousHandler(std::ostream & stream) {
- // sets spontaneous signal
- stream << "-- spontaneous handler" << std::endl;
- stream << "spontaneous_handler : process (clk, rst) " << std::endl;
- stream << "begin" << std::endl;
- stream << " if rst = '1' then" << std::endl;
- stream << " spontaneous_en <= '1';" << std::endl;
- stream << " elsif rising_edge(clk) and stall = '0' then" << std::endl;
- stream << " if spontaneous_en = '1' then" << std::endl;
- stream << " spontaneous_en <= optimal_transition_set_combined_sig;" << std::endl;
- stream << " else" << std::endl;
- //TODO if new event is dequeued then 1 else stay 0
- stream << " spontaneous_en <= next_event_dequeued;" << std::endl;
- stream << " end if;" << std::endl;
- stream << " end if;" << std::endl;
- stream << "end process;" << std::endl;
- stream << std::endl;
+ // sets spontaneous signal
+ stream << "-- spontaneous handler" << std::endl;
+ stream << "spontaneous_handler : process (clk, rst) " << std::endl;
+ stream << "begin" << std::endl;
+ stream << " if rst = '1' then" << std::endl;
+ stream << " spontaneous_en <= '1';" << std::endl;
+ stream << " elsif rising_edge(clk) and stall = '0' then" << std::endl;
+ stream << " if spontaneous_en = '1' then" << std::endl;
+ stream << " spontaneous_en <= optimal_transition_set_combined_sig;" << std::endl;
+ stream << " else" << std::endl;
+ //TODO if new event is dequeued then 1 else stay 0
+ stream << " spontaneous_en <= next_event_dequeued;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << "end process;" << std::endl;
+ stream << std::endl;
}
void ChartToVHDL::writeInternalEventHandler(std::ostream & stream) {
- // Add controler specific stuff here
- stream << "-- event handler" << std::endl;
- stream << "-- pops events and set event signals" << std::endl;
- stream << "event_handler : process (clk, rst) " << std::endl;
- stream << "begin" << std::endl;
- stream << " if rst = '1' then" << std::endl;
-
- std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix("");
- for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
- stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl;
- }
-
- stream << " next_event_dequeued <= '0';" << std::endl;
- stream << " event_consumed <= '0';" << std::endl;
-
- stream << " elsif falling_edge(clk) and stall = '0' then" << std::endl;
-
- VContainer eventConsumed = VOR;
- for (auto transition : _transitions) {
-
- if (HAS_ATTR(transition, "event") == true) {
- *eventConsumed += VLINE("in_optimal_transition_set_"
- + ATTR(transition, "postFixOrder") + "_sig");
- }
- }
-
- VBranch* tree = (VASSIGN,
- VLINE("event_consumed"),
- eventConsumed);
- tree->print(stream);
- stream << ";" << std::endl;
-
- stream << " if int_event_empty = '0' then " << std::endl;
- stream << " case next_event is " << std::endl;
- for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
- stream << " when hwe_"
- << eventNameEscape((*eventIter)->value) << " =>" << std::endl;
- for (std::list<TrieNode*>::iterator eventIter2 = eventNames.begin(); eventIter2 != eventNames.end(); eventIter2++) {
- stream << " event_" << eventNameEscape((*eventIter2)->value);
- if (eventNameEscape((*eventIter)->value) == eventNameEscape((*eventIter2)->value)) {
- stream << "_sig <= '1';" << std::endl;
- } else {
- stream << "_sig <= '0';" << std::endl;
- }
- }
- stream << " next_event_dequeued <= '1';" << std::endl;
- }
- stream << " when others =>" << std::endl;
- for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
- stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl;
- }
- stream << " next_event_dequeued <= '0';" << std::endl;
- stream << " end case;" << std::endl;
- stream << " elsif int_event_empty = '1' and event_consumed = '1' then" << std::endl;
-
- for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
- stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl;
- }
- stream << " next_event_dequeued <= '0';" << std::endl;
- stream << " end if;" << std::endl;
- stream << " end if;" << std::endl;
- stream << "end process;" << std::endl;
- stream << std::endl;
-
- stream << "next_event_re <= not int_event_empty and not stall; " << std::endl;
- stream << "next_event <= int_event_output; " << std::endl;
- stream << "int_event_write_en <= next_event_we_i; " << std::endl;
- stream << "int_event_input <= next_event_i; " << std::endl;
- stream << "int_event_read_en <= not stall; --not spontaneous_en and " << std::endl;
- stream << std::endl;
+ // Add controler specific stuff here
+ stream << "-- event handler" << std::endl;
+ stream << "-- pops events and set event signals" << std::endl;
+ stream << "event_handler : process (clk, rst) " << std::endl;
+ stream << "begin" << std::endl;
+ stream << " if rst = '1' then" << std::endl;
+
+ std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix("");
+ for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
+ stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl;
+ }
+
+ stream << " next_event_dequeued <= '0';" << std::endl;
+ stream << " event_consumed <= '0';" << std::endl;
+
+ stream << " elsif falling_edge(clk) and stall = '0' then" << std::endl;
+
+ VContainer eventConsumed = VOR;
+ for (auto transition : _transitions) {
+
+ if (HAS_ATTR(transition, "event") == true) {
+ *eventConsumed += VLINE("in_optimal_transition_set_"
+ + ATTR(transition, "postFixOrder") + "_sig");
+ }
+ }
+
+ VBranch* tree = (VASSIGN,
+ VLINE("event_consumed"),
+ eventConsumed);
+ tree->print(stream);
+ stream << ";" << std::endl;
+
+ stream << " if int_event_empty = '0' then " << std::endl;
+ stream << " case next_event is " << std::endl;
+ for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
+ stream << " when hwe_"
+ << eventNameEscape((*eventIter)->value) << " =>" << std::endl;
+ for (std::list<TrieNode*>::iterator eventIter2 = eventNames.begin(); eventIter2 != eventNames.end(); eventIter2++) {
+ stream << " event_" << eventNameEscape((*eventIter2)->value);
+ if (eventNameEscape((*eventIter)->value) == eventNameEscape((*eventIter2)->value)) {
+ stream << "_sig <= '1';" << std::endl;
+ } else {
+ stream << "_sig <= '0';" << std::endl;
+ }
+ }
+ stream << " next_event_dequeued <= '1';" << std::endl;
+ }
+ stream << " when others =>" << std::endl;
+ for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
+ stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl;
+ }
+ stream << " next_event_dequeued <= '0';" << std::endl;
+ stream << " end case;" << std::endl;
+ stream << " elsif int_event_empty = '1' and event_consumed = '1' then" << std::endl;
+
+ for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
+ stream << " event_" << eventNameEscape((*eventIter)->value) << "_sig <= '0';" << std::endl;
+ }
+ stream << " next_event_dequeued <= '0';" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << " end if;" << std::endl;
+ stream << "end process;" << std::endl;
+ stream << std::endl;
+
+ stream << "next_event_re <= not int_event_empty and not stall; " << std::endl;
+ stream << "next_event <= int_event_output; " << std::endl;
+ stream << "int_event_write_en <= next_event_we_i; " << std::endl;
+ stream << "int_event_input <= next_event_i; " << std::endl;
+ stream << "int_event_read_en <= not stall; --not spontaneous_en and " << std::endl;
+ stream << std::endl;
}
void ChartToVHDL::writeActiveStateNplusOne(std::ostream & stream) {
- stream << "-- active configuration" << std::endl;
+ stream << "-- active configuration" << std::endl;
- size_t i = 0;
- for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
+ size_t i = 0;
+ for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
// DOMElement* state = *stateIter;
- // TÖDO: is there a case where complete entry set reflects not the next state ?
- VBranch* tree = (VASSIGN,
- VLINE("state_next_" + toStr(i) + "_sig"),
- (VOR,
- VLINE("in_complete_entry_set_" + toStr(i) + "_sig"),
- (VAND, (VNOT, VLINE("in_exit_set_" + toStr(i) + "_sig")), VLINE("state_active_" + toStr(i) + "_sig"))
- ) );
-
- tree->print(stream);
- stream << ";" << std::endl;
-
- }
+ // TÖDO: is there a case where complete entry set reflects not the next state ?
+ VBranch* tree = (VASSIGN,
+ VLINE("state_next_" + toStr(i) + "_sig"),
+ (VOR,
+ VLINE("in_complete_entry_set_" + toStr(i) + "_sig"),
+ (VAND, (VNOT, VLINE("in_exit_set_" + toStr(i) + "_sig")), VLINE("state_active_" + toStr(i) + "_sig"))
+ ) );
+
+ tree->print(stream);
+ stream << ";" << std::endl;
+
+ }
}
void ChartToVHDL::writeOptimalTransitionSetSelection(std::ostream & stream) {
- stream << "-- optimal transition set selection" << std::endl;
- VContainer optimalTransitions = VOR;
- VContainer spontaneoursActive = VOR;
- size_t i = 0;
- for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, i++) {
- DOMElement* transition = *transIter;
- std::string conflicts = ATTR(transition, "conflictBools");
-
-
- VContainer nameMatchers = VOR;
- if (HAS_ATTR(transition, "event")) {
- std::list<std::string> eventDescs = tokenize(ATTR(transition, "event"));
- for (std::list<std::string>::iterator descIter = eventDescs.begin(); descIter != eventDescs.end(); descIter++) {
- std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix((*descIter) == "*" ? "" : *descIter);
- for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
- *nameMatchers += VLINE("event_" + eventNameEscape((*eventIter)->value) + "_sig");
- }
- }
- } else {
- *nameMatchers += VLINE("'1'");
- }
-
- VContainer conflicters = VOR;
- for (size_t j = 0; j < i; j++) {
- if (conflicts[j] == '1') {
- *conflicters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig");
- }
- }
-
- VBranch* tree = (VASSIGN,
- VLINE("in_optimal_transition_set_" + ATTR(transition, "postFixOrder") + "_sig"),
- (VAND,
- (HAS_ATTR(transition, "event")
- ? (VNOT, VLINE("spontaneous_active"))
- : (VNOP, VLINE("spontaneous_en"))),
- VLINE("state_active_" + ATTR(transition, "source") + "_sig"),
- nameMatchers,
- (VNOT, conflicters)));
-
- tree->print(stream);
- stream << ";" << std::endl;
-
- *optimalTransitions += VLINE("in_optimal_transition_set_"
- + ATTR(transition, "postFixOrder") + "_sig");
- if (HAS_ATTR(transition, "event") == false) {
- *spontaneoursActive += VLINE("in_optimal_transition_set_"
- + ATTR(transition, "postFixOrder") + "_sig");
- }
- }
-
- VBranch* tree = (VASSIGN,
- VLINE("optimal_transition_set_combined_sig"),
- optimalTransitions);
- tree->print(stream);
- stream << ";" << std::endl;
-
- VBranch* tree2 = (VASSIGN,
- VLINE("spontaneous_active"),
- spontaneoursActive);
- tree2->print(stream);
- stream << ";" << std::endl;
+ stream << "-- optimal transition set selection" << std::endl;
+ VContainer optimalTransitions = VOR;
+ VContainer spontaneoursActive = VOR;
+ size_t i = 0;
+ for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, i++) {
+ DOMElement* transition = *transIter;
+ std::string conflicts = ATTR(transition, "conflictBools");
+
+
+ VContainer nameMatchers = VOR;
+ if (HAS_ATTR(transition, "event")) {
+ std::list<std::string> eventDescs = tokenize(ATTR(transition, "event"));
+ for (std::list<std::string>::iterator descIter = eventDescs.begin(); descIter != eventDescs.end(); descIter++) {
+ std::list<TrieNode*> eventNames = _eventTrie.getWordsWithPrefix((*descIter) == "*" ? "" : *descIter);
+ for (std::list<TrieNode*>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) {
+ *nameMatchers += VLINE("event_" + eventNameEscape((*eventIter)->value) + "_sig");
+ }
+ }
+ } else {
+ *nameMatchers += VLINE("'1'");
+ }
+
+ VContainer conflicters = VOR;
+ for (size_t j = 0; j < i; j++) {
+ if (conflicts[j] == '1') {
+ *conflicters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig");
+ }
+ }
+
+ VBranch* tree = (VASSIGN,
+ VLINE("in_optimal_transition_set_" + ATTR(transition, "postFixOrder") + "_sig"),
+ (VAND,
+ (HAS_ATTR(transition, "event")
+ ? (VNOT, VLINE("spontaneous_active"))
+ : (VNOP, VLINE("spontaneous_en"))),
+ VLINE("state_active_" + ATTR(transition, "source") + "_sig"),
+ nameMatchers,
+ (VNOT, conflicters)));
+
+ tree->print(stream);
+ stream << ";" << std::endl;
+
+ *optimalTransitions += VLINE("in_optimal_transition_set_"
+ + ATTR(transition, "postFixOrder") + "_sig");
+ if (HAS_ATTR(transition, "event") == false) {
+ *spontaneoursActive += VLINE("in_optimal_transition_set_"
+ + ATTR(transition, "postFixOrder") + "_sig");
+ }
+ }
+
+ VBranch* tree = (VASSIGN,
+ VLINE("optimal_transition_set_combined_sig"),
+ optimalTransitions);
+ tree->print(stream);
+ stream << ";" << std::endl;
+
+ VBranch* tree2 = (VASSIGN,
+ VLINE("spontaneous_active"),
+ spontaneoursActive);
+ tree2->print(stream);
+ stream << ";" << std::endl;
}
void ChartToVHDL::writeExitSet(std::ostream & stream) {
- stream << "-- exit set selection" << std::endl;
-
- size_t i = 0;
- for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
- DOMElement* state = *stateIter;
-
- std::string completion = ATTR(state, "completionBools");
- std::string ancestors = ATTR(state, "ancBools");
- std::string children = ATTR(state, "childBools");
- std::string parent = ATTR(state, "parent");
-
- VContainer exitsetters = VOR;
- size_t j = 0;
- for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, j++) {
- DOMElement* transition = *transIter;
- std::string exitSet = ATTR(transition, "exitSetBools");
- if (exitSet[i] == '1') {
- *exitsetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig ");
- }
- }
-
- VBranch* tree = (VASSIGN,
- VLINE("in_exit_set_" + toStr(i) + "_sig"),
- (VAND,
- VLINE("state_active_" + toStr(i) + "_sig"),
- exitsetters));
-
- tree->print(stream);
- stream << ";" << std::endl;
- }
+ stream << "-- exit set selection" << std::endl;
+
+ size_t i = 0;
+ for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
+ DOMElement* state = *stateIter;
+
+ std::string completion = ATTR(state, "completionBools");
+ std::string ancestors = ATTR(state, "ancBools");
+ std::string children = ATTR(state, "childBools");
+ std::string parent = ATTR(state, "parent");
+
+ VContainer exitsetters = VOR;
+ size_t j = 0;
+ for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, j++) {
+ DOMElement* transition = *transIter;
+ std::string exitSet = ATTR(transition, "exitSetBools");
+ if (exitSet[i] == '1') {
+ *exitsetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig ");
+ }
+ }
+
+ VBranch* tree = (VASSIGN,
+ VLINE("in_exit_set_" + toStr(i) + "_sig"),
+ (VAND,
+ VLINE("state_active_" + toStr(i) + "_sig"),
+ exitsetters));
+
+ tree->print(stream);
+ stream << ";" << std::endl;
+ }
}
void ChartToVHDL::writeEntrySet(std::ostream & stream) {
- stream << "-- entry set selection" << std::endl;
-
- size_t i = 0;
- for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
- DOMElement* state = *stateIter;
-
- VBranch* tree = (VASSIGN,
- VLINE("in_entry_set_" + toStr(i) + "_sig"),
- (VAND,
- VLINE("in_complete_entry_set_" + toStr(i) + "_sig"),
- (VOR, VLINE("in_exit_set_" + toStr(i) + "_sig"),
- (VNOT, VLINE("state_active_" + toStr(i) + "_sig")))));
-
- tree->print(stream);
- stream << ";" << std::endl;
- }
+ stream << "-- entry set selection" << std::endl;
+
+ size_t i = 0;
+ for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
+ DOMElement* state = *stateIter;
+
+ VBranch* tree = (VASSIGN,
+ VLINE("in_entry_set_" + toStr(i) + "_sig"),
+ (VAND,
+ VLINE("in_complete_entry_set_" + toStr(i) + "_sig"),
+ (VOR, VLINE("in_exit_set_" + toStr(i) + "_sig"),
+ (VNOT, VLINE("state_active_" + toStr(i) + "_sig")))));
+
+ tree->print(stream);
+ stream << ";" << std::endl;
+ }
}
void ChartToVHDL::writeDefaultCompletions(std::ostream & stream) {
- // TODO direct connect the line in complete entry set (no extra line needed ...)
- stream << "-- default completion assignments" << std::endl;
- stream << "-- indikates if the state for which I am the def-completion is active" << std::endl;
- std::map<DOMElement*, std::list<DOMNode*> > completions;
-
- size_t i = 0;
- for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
- DOMElement* state = *stateIter;
-
- completions[state]; // initialize other completions to 0
-
- // we just need this if parent is a compound state
- std::string parent = ATTR(state, "parent");
-
- if (getParentState(state) != NULL
- && isCompound(getParentState(state))) {
-
- // Am I default completen ?
- std::string completion = ATTR_CAST(_states[strTo<size_t>(parent)], "completionBools");
- if (completion[i] == '1') {
- // Yes? then give me the parent line
- completions[state].push_back(getParentState(state));
-
- }
- }
- }
-
- auto complIter = completions.begin();
- while (complIter != completions.end()) {
- const DOMElement* state(complIter->first);
- const std::list<DOMNode*> refs(complIter->second);
-
- std::string index = ATTR(state, "documentOrder");
- VContainer defaultCompleters = VOR;
-
- for (auto ref : refs) {
- // *defaultCompleters += VLINE("in_complete_entry_set_" +
- // TODO: default completion just when state is entered the first time ?
- // if yes then we use the following code. If not we have to revert
- *defaultCompleters += VLINE("in_entry_set_" +
- ATTR_CAST(ref, "documentOrder") + "_sig ");
- }
-
- VBranch* tree = (VASSIGN,
- VLINE("default_completion_" + index + "_sig"), defaultCompleters);
-
- tree->print(stream);
- stream << ";" << std::endl;
-
- complIter++;
- }
+ // TODO direct connect the line in complete entry set (no extra line needed ...)
+ stream << "-- default completion assignments" << std::endl;
+ stream << "-- indikates if the state for which I am the def-completion is active" << std::endl;
+ std::map<DOMElement*, std::list<DOMNode*> > completions;
+
+ size_t i = 0;
+ for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
+ DOMElement* state = *stateIter;
+
+ completions[state]; // initialize other completions to 0
+
+ // we just need this if parent is a compound state
+ std::string parent = ATTR(state, "parent");
+
+ if (getParentState(state) != NULL
+ && isCompound(getParentState(state))) {
+
+ // Am I default completen ?
+ std::string completion = ATTR_CAST(_states[strTo<size_t>(parent)], "completionBools");
+ if (completion[i] == '1') {
+ // Yes? then give me the parent line
+ completions[state].push_back(getParentState(state));
+
+ }
+ }
+ }
+
+ auto complIter = completions.begin();
+ while (complIter != completions.end()) {
+ const DOMElement* state(complIter->first);
+ const std::list<DOMNode*> refs(complIter->second);
+
+ std::string index = ATTR(state, "documentOrder");
+ VContainer defaultCompleters = VOR;
+
+ for (auto ref : refs) {
+ // *defaultCompleters += VLINE("in_complete_entry_set_" +
+ // TODO: default completion just when state is entered the first time ?
+ // if yes then we use the following code. If not we have to revert
+ *defaultCompleters += VLINE("in_entry_set_" +
+ ATTR_CAST(ref, "documentOrder") + "_sig ");
+ }
+
+ VBranch* tree = (VASSIGN,
+ VLINE("default_completion_" + index + "_sig"), defaultCompleters);
+
+ tree->print(stream);
+ stream << ";" << std::endl;
+
+ complIter++;
+ }
}
void ChartToVHDL::writeCompleteEntrySet(std::ostream & stream) {
- stream << "-- complete entry set selection" << std::endl;
-
- size_t i = 0;
- for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
- DOMElement* state = *stateIter;
-
- std::string completion = ATTR(state, "completionBools");
- std::string ancestors = ATTR(state, "ancBools");
- std::string children = ATTR(state, "childBools");
- std::string parent = ATTR(state, "parent");
-
- VContainer optimalEntrysetters = VOR;
- size_t j = 0;
- for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, j++) {
- DOMElement* transition = *transIter;
-
- std::string targetSet = ATTR(transition, "targetBools");
- if (targetSet[i] == '1') {// <- ? TODO Was ist hier der vergleich?
- *optimalEntrysetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig");
- }
- }
-
- VContainer completeEntrysetters = VOR;
- stream << "--" << state->getNodeName() << std::endl; // for debugging
- if (isCompound(state) || isParallel(state)) { // <- true for scxml? TODO
- for (size_t j = 0; j < _states.size(); j++) {
- if (children[j] != '1') // if is child of state j
- continue;
- *completeEntrysetters += VLINE("in_complete_entry_set_up_" + toStr(j) + "_sig");
- }
- }
-
- VBranch* tree = (VASSIGN,
- VLINE("in_complete_entry_set_up_" + toStr(i) + "_sig"),
- (VOR, optimalEntrysetters, completeEntrysetters)
- );
- tree->print(stream);
- stream << ";" << std::endl;
+ stream << "-- complete entry set selection" << std::endl;
+
+ size_t i = 0;
+ for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
+ DOMElement* state = *stateIter;
+
+ std::string completion = ATTR(state, "completionBools");
+ std::string ancestors = ATTR(state, "ancBools");
+ std::string children = ATTR(state, "childBools");
+ std::string parent = ATTR(state, "parent");
+
+ VContainer optimalEntrysetters = VOR;
+ size_t j = 0;
+ for (auto transIter = _transitions.begin(); transIter != _transitions.end(); transIter++, j++) {
+ DOMElement* transition = *transIter;
+
+ std::string targetSet = ATTR(transition, "targetBools");
+ if (targetSet[i] == '1') {// <- ? TODO Was ist hier der vergleich?
+ *optimalEntrysetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig");
+ }
+ }
+
+ VContainer completeEntrysetters = VOR;
+ stream << "--" << state->getNodeName() << std::endl; // for debugging
+ if (isCompound(state) || isParallel(state)) { // <- true for scxml? TODO
+ for (size_t j = 0; j < _states.size(); j++) {
+ if (children[j] != '1') // if is child of state j
+ continue;
+ *completeEntrysetters += VLINE("in_complete_entry_set_up_" + toStr(j) + "_sig");
+ }
+ }
+
+ VBranch* tree = (VASSIGN,
+ VLINE("in_complete_entry_set_up_" + toStr(i) + "_sig"),
+ (VOR, optimalEntrysetters, completeEntrysetters)
+ );
+ tree->print(stream);
+ stream << ";" << std::endl;
#if 0
- stream << "in_complete_entry_set_up_" << toStr(i) << "_sig <= ('0'" << std::endl;
-
- for (size_t j = 0; j < _transitions.size(); j++) {
- Element<std::string> transition(_transitions[j]);
- // std::cout << transition;
- std::string targetSet = ATTR(transition, "targetBools");
- if (targetSet[i] == '1') {
- stream << " or in_optimal_transition_set_" << toStr(j) << std::endl;
- }
- }
- if (isCompound(state)) {
- for (size_t j = 0; j < _states.size(); j++) {
- if (children[j] != '1')
- continue;
-
- stream << " or in_complete_entry_set_up_" << toStr(j) << "_sig" << std::endl;
- }
-
- }
- stream << ");" << std::endl;
+ stream << "in_complete_entry_set_up_" << toStr(i) << "_sig <= ('0'" << std::endl;
+
+ for (size_t j = 0; j < _transitions.size(); j++) {
+ Element<std::string> transition(_transitions[j]);
+ // std::cout << transition;
+ std::string targetSet = ATTR(transition, "targetBools");
+ if (targetSet[i] == '1') {
+ stream << " or in_optimal_transition_set_" << toStr(j) << std::endl;
+ }
+ }
+ if (isCompound(state)) {
+ for (size_t j = 0; j < _states.size(); j++) {
+ if (children[j] != '1')
+ continue;
+
+ stream << " or in_complete_entry_set_up_" << toStr(j) << "_sig" << std::endl;
+ }
+
+ }
+ stream << ");" << std::endl;
#endif
- }
-
- for (auto state : _states) {
- std::string completion = ATTR(state, "completionBools");
- std::string ancestors = ATTR(state, "ancBools");
- std::string parent = ATTR(state, "parent");
-
- if (parent.size() == 0) {
- continue; // TODO: FixMe <scxml> <-- ?
- }
-
- VContainer tmp1 = VAND;
- // if parent is compound
- if (getParentState(state) != NULL &&
- isCompound(getParentState(state))) {
- std::string children = ATTR_CAST(_states[strTo<size_t>(parent)],
- "childBools");
- // TODO: do not add default_completion line if not needed
- // --> just if this state is the default completion of parent
- // --> init attr. or if not present first in document order <-- = completion bool ?
- *tmp1 += VLINE("default_completion_" + ATTR(state, "documentOrder") + "_sig");
-
- //TODO check this
- for (size_t j = 0; j < _states.size(); j++) {
- if (children[j] != '1')
- continue;
- *tmp1 += (VAND,
- (VNOT,
- (VAND,
- VLINE("state_active_" + toStr(j) + "_sig"),
- (VNOT,
- VLINE("in_exit_set_" + toStr(j) + "_sig")))));
-
- }
-
- }
-
- // if parent is parallel
- if (getParentState(state) != NULL &&
- isParallel(getParentState(state))) {
- *tmp1 += VLINE("in_complete_entry_set_" + toStr(parent) + "_sig");
- }
-
- VBranch* tree = (VASSIGN,
- VLINE("in_complete_entry_set_" + toStr(i) + "_sig"),
- (VOR,
- VLINE("in_complete_entry_set_up_" + ATTR(state, "documentOrder") + "_sig"),
- tmp1));
-
- tree->print(stream);
- stream << ";" << std::endl;
+ }
+
+ for (auto state : _states) {
+ std::string completion = ATTR(state, "completionBools");
+ std::string ancestors = ATTR(state, "ancBools");
+ std::string parent = ATTR(state, "parent");
+
+ if (parent.size() == 0) {
+ continue; // TODO: FixMe <scxml> <-- ?
+ }
+
+ VContainer tmp1 = VAND;
+ // if parent is compound
+ if (getParentState(state) != NULL &&
+ isCompound(getParentState(state))) {
+ std::string children = ATTR_CAST(_states[strTo<size_t>(parent)],
+ "childBools");
+ // TODO: do not add default_completion line if not needed
+ // --> just if this state is the default completion of parent
+ // --> init attr. or if not present first in document order <-- = completion bool ?
+ *tmp1 += VLINE("default_completion_" + ATTR(state, "documentOrder") + "_sig");
+
+ //TODO check this
+ for (size_t j = 0; j < _states.size(); j++) {
+ if (children[j] != '1')
+ continue;
+ *tmp1 += (VAND,
+ (VNOT,
+ (VAND,
+ VLINE("state_active_" + toStr(j) + "_sig"),
+ (VNOT,
+ VLINE("in_exit_set_" + toStr(j) + "_sig")))));
+
+ }
+
+ }
+
+ // if parent is parallel
+ if (getParentState(state) != NULL &&
+ isParallel(getParentState(state))) {
+ *tmp1 += VLINE("in_complete_entry_set_" + toStr(parent) + "_sig");
+ }
+
+ VBranch* tree = (VASSIGN,
+ VLINE("in_complete_entry_set_" + toStr(i) + "_sig"),
+ (VOR,
+ VLINE("in_complete_entry_set_up_" + ATTR(state, "documentOrder") + "_sig"),
+ tmp1));
+
+ tree->print(stream);
+ stream << ";" << std::endl;
#if 0
- stream << "in_complete_entry_set_" << toStr(i) << "_sig <= (in_complete_entry_set_up_" << toStr(i) << "_sig or (" << std::endl;
+ stream << "in_complete_entry_set_" << toStr(i) << "_sig <= (in_complete_entry_set_up_" << toStr(i) << "_sig or (" << std::endl;
- if (isParallel(Element<std::string>(_states[strTo<size_t>(parent)]))) {
- stream << " in_complete_entry_set_" << toStr(parent) << "_sig" << std::endl;
- } else if (isCompound(Element<std::string>(_states[strTo<size_t>(parent)]))) {
- stream << " default_completion_" << toStr(parent) << "_sig" << std::endl;
+ if (isParallel(Element<std::string>(_states[strTo<size_t>(parent)]))) {
+ stream << " in_complete_entry_set_" << toStr(parent) << "_sig" << std::endl;
+ } else if (isCompound(Element<std::string>(_states[strTo<size_t>(parent)]))) {
+ stream << " default_completion_" << toStr(parent) << "_sig" << std::endl;
- for (size_t j = 0; j < _states.size(); j++) {
- if (children[j] != '1')
- continue;
- stream << " and not (is_active" << toStr(j) << "_sig and not in_exit_set_" << toStr(j) << "_sig)" << std::endl;
+ for (size_t j = 0; j < _states.size(); j++) {
+ if (children[j] != '1')
+ continue;
+ stream << " and not (is_active" << toStr(j) << "_sig and not in_exit_set_" << toStr(j) << "_sig)" << std::endl;
- }
- }
+ }
+ }
- stream << ");" << std::endl;
+ stream << ");" << std::endl;
#endif
- }
+ }
}
void ChartToVHDL::writeStateHandler(std::ostream & stream) {
- // updater for current state
- stream << "-- State Handler" << std::endl;
- stream << "-- updates current state" << std::endl;
- stream << "state_proc: process(clk, rst, stall)" << std::endl;
- stream << "begin" << std::endl;
- stream << " if rst = '1' then" << std::endl;
-
- size_t i = 0;
- for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
+ // updater for current state
+ stream << "-- State Handler" << std::endl;
+ stream << "-- updates current state" << std::endl;
+ stream << "state_proc: process(clk, rst, stall)" << std::endl;
+ stream << "begin" << std::endl;
+ stream << " if rst = '1' then" << std::endl;
+
+ size_t i = 0;
+ for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
// DOMElement* state = *stateIter;
- stream << " state_active_" << toStr(i) << "_sig <= " << "'0';" << std::endl;
- }
-
- stream << " in_complete_entry_set_0_sig <= '1';" << std::endl;
- stream << " elsif (rising_edge(clk) and stall = '0') then" << std::endl;
- stream << " in_complete_entry_set_0_sig <= '0';" << std::endl;
-
- i = 0;
- for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
- // DOMElement* state = *stateIter;
- stream << " state_active_" << toStr(i) << "_sig <= " << "state_next_" << toStr(i) << "_sig;" << std::endl;
- }
-
- stream << " end if;" << std::endl;
- stream << "end process;" << std::endl;
- stream << std::endl;
+ stream << " state_active_" << toStr(i) << "_sig <= " << "'0';" << std::endl;
+ }
+
+ stream << " in_complete_entry_set_0_sig <= '1';" << std::endl;
+ stream << " elsif (rising_edge(clk) and stall = '0') then" << std::endl;
+ stream << " in_complete_entry_set_0_sig <= '0';" << std::endl;
+
+ i = 0;
+ for (auto stateIter = _states.begin(); stateIter != _states.end(); stateIter++, i++) {
+ // DOMElement* state = *stateIter;
+ stream << " state_active_" << toStr(i) << "_sig <= " << "state_next_" << toStr(i) << "_sig;" << std::endl;
+ }
+
+ stream << " end if;" << std::endl;
+ stream << "end process;" << std::endl;
+ stream << std::endl;
}
void ChartToVHDL::writeSystemSignalMapping(std::ostream & stream) {
- stream << "-- system signals" << std::endl;
- std::list<DOMElement*> topLevelFinal = DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "final", _scxml);
-
- VContainer tlf = VOR;
- for (auto final : topLevelFinal) {
- *tlf += VLINE("state_active_" + ATTR(final, "documentOrder") + "_sig");
-
- }
-
- VBranch* tree = (VASSIGN,
- VLINE("completed_sig"),
- tlf);
-
- tree->print(stream);
- stream << ";" << std::endl;
-
- // tmp mapping for events
- stream << "stall <= not en or completed_sig or ( int_event_empty and not spontaneous_en ) ; " << std::endl;
- stream << std::endl;
-
- // interface signals
- stream << "-- interface signals" << std::endl;
- for (auto state : _states) {
- stream << "state_active_" << ATTR(state, "documentOrder")
- << "_o <= state_active_" << ATTR(state, "documentOrder")
- << "_sig;" << std::endl;
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
- stream << "exit_set_" << ATTR(state, "documentOrder")
- << "_o <= in_exit_set_" << ATTR(state, "documentOrder")
- << "_sig;" << std::endl;
- }
-
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
- stream << "entry_set_" << ATTR(state, "documentOrder")
- << "_o <= in_entry_set_" << ATTR(state, "documentOrder")
- << "_sig;" << std::endl;
- }
- }
-
- for (auto transition : _transitions) {
- if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
- stream << "transition_set_" << ATTR(transition, "postFixOrder")
- << "_o <= in_optimal_transition_set_" << ATTR(transition, "postFixOrder")
- << "_sig;" << std::endl;
- }
- }
-
- stream << "completed_o <= completed_sig; " << std::endl;
- stream << "error_o <= reg_error_out; " << std::endl;
- stream << std::endl;
+ stream << "-- system signals" << std::endl;
+ std::list<DOMElement*> topLevelFinal = DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "final", _scxml);
+
+ VContainer tlf = VOR;
+ for (auto final : topLevelFinal) {
+ *tlf += VLINE("state_active_" + ATTR(final, "documentOrder") + "_sig");
+
+ }
+
+ VBranch* tree = (VASSIGN,
+ VLINE("completed_sig"),
+ tlf);
+
+ tree->print(stream);
+ stream << ";" << std::endl;
+
+ // tmp mapping for events
+ stream << "stall <= not en or completed_sig or ( int_event_empty and not spontaneous_en ) ; " << std::endl;
+ stream << std::endl;
+
+ // interface signals
+ stream << "-- interface signals" << std::endl;
+ for (auto state : _states) {
+ stream << "state_active_" << ATTR(state, "documentOrder")
+ << "_o <= state_active_" << ATTR(state, "documentOrder")
+ << "_sig;" << std::endl;
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onexit", state).size() > 0) {
+ stream << "exit_set_" << ATTR(state, "documentOrder")
+ << "_o <= in_exit_set_" << ATTR(state, "documentOrder")
+ << "_sig;" << std::endl;
+ }
+
+ if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
+ stream << "entry_set_" << ATTR(state, "documentOrder")
+ << "_o <= in_entry_set_" << ATTR(state, "documentOrder")
+ << "_sig;" << std::endl;
+ }
+ }
+
+ for (auto transition : _transitions) {
+ if (DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, transition).size() > 0) {
+ stream << "transition_set_" << ATTR(transition, "postFixOrder")
+ << "_o <= in_optimal_transition_set_" << ATTR(transition, "postFixOrder")
+ << "_sig;" << std::endl;
+ }
+ }
+
+ stream << "completed_o <= completed_sig; " << std::endl;
+ stream << "error_o <= reg_error_out; " << std::endl;
+ stream << std::endl;
}
} \ No newline at end of file
diff --git a/src/uscxml/transform/ChartToVHDL.h b/src/uscxml/transform/ChartToVHDL.h
index 85fd30d..0a58b4e 100644
--- a/src/uscxml/transform/ChartToVHDL.h
+++ b/src/uscxml/transform/ChartToVHDL.h
@@ -161,19 +161,19 @@ protected:
void writeTypes(std::ostream& stream);
void writeIncludes(std::ostream& stream);
-
- // top layer components
+
+ // top layer components
void writeFiFo(std::ostream& stream);
void writeEventController(std::ostream & stream);
void writeMicroStepper(std::ostream& stream);
void writeTestbench(std::ostream & stream);
-
- // system
+
+ // system
void writeSignalsAndComponents(std::ostream& stream);
void writeSystemSignalMapping(std::ostream& stream);
void writeModuleInstantiation(std::ostream& stream);
- // combinatorial logic
+ // combinatorial logic
void writeOptimalTransitionSetSelection(std::ostream& stream);
void writeExitSet(std::ostream & stream);
void writeEntrySet(std::ostream & stream);
@@ -182,24 +182,24 @@ protected:
void writeCompleteEntrySet(std::ostream & stream);
void writeActiveStateNplusOne(std::ostream & stream);
- // handler
+ // handler
void writeStateHandler(std::ostream& stream);
void writeResetHandler(std::ostream & stream);
void writeSpontaneousHandler(std::ostream & stream);
void writeInternalEventHandler(std::ostream & stream);
void writeErrorHandler(std::ostream& stream);
-
- // event generation
- void writeExContentBlock(std::ostream & stream, std::string index,
- std::list< XERCESC_NS::DOMElement* > commandSequence);
-
+
+ // event generation
+ void writeExContentBlock(std::ostream & stream, std::string index,
+ std::list< XERCESC_NS::DOMElement* > commandSequence);
+
Trie _eventTrie;
- std::list< XERCESC_NS::DOMElement* > _execContent;
+ std::list< XERCESC_NS::DOMElement* > _execContent;
private:
std::string eventNameEscape(const std::string& eventName);
- std::string getLineForExecContent(const XERCESC_NS::DOMNode* elem);
+ std::string getLineForExecContent(const XERCESC_NS::DOMNode* elem);
};
diff --git a/src/uscxml/transform/promela/PromelaCodeAnalyzer.cpp b/src/uscxml/transform/promela/PromelaCodeAnalyzer.cpp
new file mode 100644
index 0000000..4d1d8d5
--- /dev/null
+++ b/src/uscxml/transform/promela/PromelaCodeAnalyzer.cpp
@@ -0,0 +1,596 @@
+/**
+ * @file
+ * @author 2016 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#define MAX_MACRO_CHARS 64
+
+#include "PromelaCodeAnalyzer.h"
+#include "uscxml/transform/ChartToPromela.h"
+#include "uscxml/util/Predicates.h"
+#include "uscxml/util/DOM.h"
+#include "uscxml/util/String.h"
+
+#include <boost/algorithm/string.hpp>
+
+namespace uscxml {
+
+using namespace XERCESC_NS;
+
+void PromelaCodeAnalyzer::analyze(ChartToPromela* interpreter) {
+
+ /**
+ Create macro names for state identifiers
+ Do not add as literals as they are not unique with nested state-charts
+ */
+ {
+ for (size_t i = 0; i < interpreter->_states.size(); i++) {
+ DOMElement* state = interpreter->_states[i];
+ if (HAS_ATTR(state, "id")) {
+ createMacroName(ATTR(state, "id"));
+ }
+ }
+ }
+// _lastStrIndex = interpreter->_states.size();
+
+ /** Find all event names that might occur */
+ {
+ std::list<XERCESC_NS::DOMElement*> internalEventNames = DOMUtils::inDocumentOrder({
+ XML_PREFIX(interpreter->_scxml).str() + "transition",
+ XML_PREFIX(interpreter->_scxml).str() + "raise",
+ XML_PREFIX(interpreter->_scxml).str() + "send"
+ }, interpreter->_scxml);
+
+ for (auto internalEventName : internalEventNames) {
+ if (HAS_ATTR_CAST(internalEventName, "event")) {
+ std::string eventNames = ATTR_CAST(internalEventName, "event");
+ std::list<std::string> events = tokenize(eventNames);
+ for (std::list<std::string>::iterator eventIter = events.begin();
+ eventIter != events.end(); eventIter++) {
+ std::string eventName = *eventIter;
+ if (boost::ends_with(eventName, "*"))
+ eventName = eventName.substr(0, eventName.size() - 1);
+ if (boost::ends_with(eventName, "."))
+ eventName = eventName.substr(0, eventName.size() - 1);
+ if (eventName.size() > 0)
+ _eventTrie.addWord(eventName);
+ }
+ }
+ }
+
+ for (auto state : interpreter->_states) {
+ if (HAS_ATTR(state, "id") && (isCompound(state) || isParallel(state))) {
+ _eventTrie.addWord("done.state." + ATTR(state, "id"));
+ }
+ }
+ }
+
+ // add event names from trie to string literals
+ std::list<TrieNode*> events = _eventTrie.getWordsWithPrefix("");
+ for (auto event : events) {
+ addLiteral(event->value);
+ }
+
+
+ /** Find all string literals */
+ {
+ // string literals for raise / send content
+ std::list<XERCESC_NS::DOMElement*> contents = DOMUtils::inDocumentOrder({
+ XML_PREFIX(interpreter->_scxml).str() + "content"
+ }, interpreter->_scxml);
+
+ for (auto content : contents) {
+ std::string contentStr = spaceNormalize(X(((DOMElement*)content)->getFirstChild()->getNodeValue()));
+ if (!isNumeric(contentStr.c_str(), 10)) {
+ addLiteral(contentStr);
+ }
+ }
+ }
+
+ /* add platform variables as string literals */
+ addLiteral(interpreter->_prefix + "_sessionid");
+ addLiteral(interpreter->_prefix + "_name");
+
+
+ /** Extract and analyze source code */
+ {
+ std::list<XERCESC_NS::DOMElement*> withCond = DOMUtils::inDocumentOrder({
+ XML_PREFIX(interpreter->_scxml).str() + "transition",
+ XML_PREFIX(interpreter->_scxml).str() + "if",
+ XML_PREFIX(interpreter->_scxml).str() + "elseif"
+ }, interpreter->_scxml);
+
+ for (auto cond : withCond) {
+ if (HAS_ATTR(cond, "cond")) {
+ std::string code = ATTR_CAST(cond, "cond");
+ code = sanitizeCode(code);
+ addCode(code, interpreter);
+ cond->setAttribute(X("cond"), X(code));
+ }
+ }
+
+ std::list<XERCESC_NS::DOMElement*> withExpr = DOMUtils::inDocumentOrder({
+ XML_PREFIX(interpreter->_scxml).str() + "log",
+ XML_PREFIX(interpreter->_scxml).str() + "data",
+ XML_PREFIX(interpreter->_scxml).str() + "assign",
+ XML_PREFIX(interpreter->_scxml).str() + "content",
+ XML_PREFIX(interpreter->_scxml).str() + "param"
+ }, interpreter->_scxml);
+
+ for (auto expr : withExpr) {
+ if (HAS_ATTR(expr, "expr")) {
+ std::string code = ATTR_CAST(expr, "expr");
+ code = sanitizeCode(code);
+ addCode(code, interpreter);
+ expr->setAttribute(X("expr"), X(code));
+ }
+ }
+
+ std::list<XERCESC_NS::DOMElement*> withLocation = DOMUtils::inDocumentOrder({
+ XML_PREFIX(interpreter->_scxml).str() + "assign"
+ }, interpreter->_scxml);
+
+ for (auto location : withLocation) {
+ if (HAS_ATTR(location, "location")) {
+ std::string code = ATTR_CAST(location, "location");
+ code = sanitizeCode(code);
+ addCode(code, interpreter);
+ location->setAttribute(X("location"), X(code));
+ }
+ }
+
+ std::list<XERCESC_NS::DOMElement*> withText = DOMUtils::inDocumentOrder({
+ XML_PREFIX(interpreter->_scxml).str() + "script"
+ }, interpreter->_scxml);
+
+ for (auto text : withText) {
+ std::list<XERCESC_NS::DOMNode*> texts = DOMUtils::filterChildType(DOMNode::TEXT_NODE, text, true);
+ for (auto textBlock : texts) {
+ DOMText* textText = static_cast<DOMText*>(textBlock);
+ std::string code = X(textText->getNodeValue()).str();
+ if (code.size() > 0) {
+ code = sanitizeCode(code);
+ addCode(code, interpreter);
+ textText->setNodeValue(X(code));
+ }
+ }
+ }
+
+ std::list<XERCESC_NS::DOMElement*> foreachs = DOMUtils::inDocumentOrder({
+ XML_PREFIX(interpreter->_scxml).str() + "foreach"
+ }, interpreter->_scxml);
+
+ for (auto foreach : foreachs) {
+ if (HAS_ATTR(foreach, "index")) {
+ addCode(ATTR(foreach, "index"), interpreter);
+ } else {
+ _hasIndexLessLoops = true;
+ }
+ if (HAS_ATTR(foreach, "item")) {
+ addCode(ATTR(foreach, "item"), interpreter);
+ }
+ }
+
+ // do we need sendid / invokeid?
+ {
+ std::list<DOMElement*> invokes = DOMUtils::inDocumentOrder({XML_PREFIX(interpreter->_scxml).str() + "invoke"}, interpreter->_scxml);
+ std::list<DOMElement*> sends = DOMUtils::inDocumentOrder({XML_PREFIX(interpreter->_scxml).str() + "send"}, interpreter->_scxml);
+ std::list<DOMElement*> cancels = DOMUtils::inDocumentOrder({XML_PREFIX(interpreter->_scxml).str() + "cancel"}, interpreter->_scxml);
+
+ if (cancels.size() > 0) {
+ addCode("_event.invokeid", interpreter);
+ _usesCancel = true;
+ }
+
+ for (auto send : sends) {
+ if (HAS_ATTR(send, "idlocation")) {
+ addCode("_event.sendid", interpreter);
+ }
+ if (HAS_ATTR(send, "id")) {
+ addLiteral(ATTR(send, "id"));
+ addCode("_event.sendid", interpreter);
+ }
+
+ // do we need delays?
+ if (HAS_ATTR(send, "delay") || HAS_ATTR(send, "delayexpr")) {
+ addCode("_event.delay", interpreter);
+#if NEW_DELAY_RESHUFFLE
+#else
+ addCode("_event.seqNr", interpreter);
+#endif
+ }
+ }
+ }
+
+ // add all namelist entries to the _event structure
+ {
+ std::list<DOMElement*> withNamelists;
+ withNamelists.splice(withNamelists.end(), DOMUtils::inDocumentOrder({XML_PREFIX(interpreter->_scxml).str() + "send"}, interpreter->_scxml));
+ withNamelists.splice(withNamelists.end(), DOMUtils::inDocumentOrder({XML_PREFIX(interpreter->_scxml).str() + "invoke"}, interpreter->_scxml));
+ for (auto withNamelist : withNamelists) {
+ if (HAS_ATTR(withNamelist, "namelist")) {
+ std::string namelist = ATTR(withNamelist, "namelist");
+ std::list<std::string> names = tokenize(namelist);
+ for (std::list<std::string>::iterator nameIter = names.begin(); nameIter != names.end(); nameIter++) {
+ addCode("_event.data." + *nameIter + " = 0;", interpreter); // introduce for _event_t typedef
+ }
+ }
+ }
+ }
+
+ }
+
+}
+
+std::string PromelaCodeAnalyzer::sanitizeCode(const std::string& code) {
+ std::string replaced = code;
+ boost::replace_all(replaced, "\"", "'");
+ boost::replace_all(replaced, "_sessionid", "_SESSIONID");
+ boost::replace_all(replaced, "_name", "_NAME");
+ return replaced;
+}
+
+void PromelaCodeAnalyzer::addCode(const std::string& code, ChartToPromela* interpreter) {
+ PromelaParser parser(code);
+ // parser.dump();
+
+ // find all strings
+ std::list<PromelaParserNode*> astNodes;
+ astNodes.push_back(parser.ast);
+
+ while(astNodes.size() > 0) {
+ PromelaParserNode* node = astNodes.front();
+ astNodes.pop_front();
+
+ // node->dump();
+
+ bool hasValue = false;
+ int assignedValue = 0;
+
+
+ switch (node->type) {
+ case PML_STRING: {
+ std::string unquoted = node->value;
+ if (boost::starts_with(unquoted, "'")) {
+ unquoted = unquoted.substr(1, unquoted.size() - 2);
+ }
+ addLiteral(unquoted);
+ break;
+ }
+ case PML_ASGN:
+ if (node->operands.back()->type == PML_CONST) {
+ hasValue = true;
+ if (isInteger(node->operands.back()->value.c_str(), 10)) {
+ assignedValue = strTo<int>(node->operands.back()->value);
+ }
+ }
+ if (node->operands.back()->type == PML_STRING) {
+ // remember strings for later
+ astNodes.push_back(node->operands.back());
+ }
+ if (node->operands.front()->type == PML_CMPND) {
+ node = node->operands.front();
+ } else {
+ break;
+ }
+ // if (node->operands.front()->type != PML_NAME)
+ // break; // this will skip array assignments
+ case PML_CMPND: {
+ std::string nameOfType;
+ std::list<PromelaParserNode*>::iterator opIter = node->operands.begin();
+ if ((*opIter)->type != PML_NAME) {
+ node->dump();
+ return;
+ assert(false);
+ }
+
+ PromelaTypedef* td = &_typeDefs;
+ std::string seperator;
+
+ while(opIter != node->operands.end()) {
+ switch ((*opIter)->type) {
+ case PML_NAME:
+ td = &td->types[(*opIter)->value];
+ td->occurrences.insert(interpreter);
+
+ nameOfType += seperator + (*opIter)->value;
+ if (nameOfType.compare("_x") == 0)
+ _usesPlatformVars = true;
+ seperator = "_";
+ td->name = nameOfType + "_t";
+ break;
+ case PML_VAR_ARRAY: {
+ PromelaParserNode* name = (*opIter)->operands.front();
+ PromelaParserNode* subscript = *(++(*opIter)->operands.begin());
+ td = &td->types[name->value];
+ td->occurrences.insert(interpreter);
+
+ nameOfType += seperator + name->value;
+ td->name = nameOfType + "_t";
+
+ if (isInteger(subscript->value.c_str(), 10)) {
+ td->arraySize = strTo<int>(subscript->value);
+ }
+ break;
+ }
+ default:
+ if ((*opIter)->type == PML_CONST) {
+ // break fall through from ASGN
+ break;
+ }
+ // node->dump();
+ // assert(false);
+ break;
+ }
+
+ if (nameOfType.compare("_x_states") == 0) {
+ _usesInPredicate = true;
+ }
+ if (nameOfType.compare("_event_type") == 0) {
+ addLiteral("internal");
+ addLiteral("external");
+ addLiteral("platform");
+ }
+ if (nameOfType.compare("_event_origintype") == 0) {
+ addLiteral("http://www.w3.org/TR/scxml/#SCXMLEventProcessor");
+ }
+ opIter++;
+ }
+
+ if (hasValue) {
+ if (td->maxValue < assignedValue)
+ td->maxValue = assignedValue;
+ if (td->minValue > assignedValue)
+ td->minValue = assignedValue;
+ }
+
+ continue; // skip processing nested AST nodes
+ }
+ case PML_NAME: {
+ _typeDefs.types[node->value].occurrences.insert(interpreter);
+ _typeDefs.types[node->value].minValue = 0;
+ _typeDefs.types[node->value].maxValue = 0;
+ // test325
+ if (node->value.compare("_ioprocessors") == 0) {
+ addCode("_ioprocessors.scxml.location", interpreter);
+ }
+
+ break;
+ }
+
+ default:
+ // node->dump();
+ break;
+ // assert(false);
+ }
+
+ astNodes.insert(astNodes.end(), node->operands.begin(), node->operands.end());
+
+ }
+}
+
+void PromelaCodeAnalyzer::addLiteral(const std::string& literal, int forceIndex) {
+ if (boost::starts_with(literal, "'"))
+ throw std::runtime_error("Literal " + literal + " passed with quotes");
+
+ if (_literals.find(literal) != _literals.end())
+ return;
+ _literals.insert(literal);
+ createMacroName(literal);
+ enumerateLiteral(literal, forceIndex);
+}
+
+int PromelaCodeAnalyzer::indexForLiteral(const std::string& literal) {
+ if (boost::starts_with(literal, "'"))
+ throw std::runtime_error("Literal " + literal + " passed with quotes");
+
+ if (_strIndex.find(literal) == _strIndex.end())
+ throw std::runtime_error("No index for literal " + literal + " known");
+ return _strIndex[literal];
+}
+
+std::string PromelaCodeAnalyzer::macroForLiteral(const std::string& literal) {
+ if (boost::starts_with(literal, "'"))
+ throw std::runtime_error("Literal " + literal + " passed with quotes");
+
+ if (_strMacros.find(literal) == _strMacros.end())
+ throw std::runtime_error("No macro for literal '" + literal + "' known");
+ return _strMacros[literal];
+}
+
+
+std::string PromelaCodeAnalyzer::createMacroName(const std::string& literal) {
+ if (_strMacros.find(literal) != _strMacros.end())
+ return _strMacros[literal];
+
+ // find a suitable macro name for the strings
+ std::string macroName = literal; //literal.substr(1, literal.size() - 2);
+
+ // cannot start with digit
+ if (isInteger(macroName.substr(0,1).c_str(), 10))
+ macroName = "_" + macroName;
+
+ macroName = macroName.substr(0, MAX_MACRO_CHARS);
+ boost::to_upper(macroName);
+
+ std::string illegalChars = "#\\/:?\"<>| \n\t()[]{}',.-";
+ std::string tmp;
+ std::string::iterator it = macroName.begin();
+ while (it < macroName.end()) {
+ bool found = illegalChars.find(*it) != std::string::npos;
+ if(found) {
+ tmp += '_';
+ it++;
+ while(it < macroName.end() && illegalChars.find(*it) != std::string::npos) {
+ it++;
+ }
+ } else {
+ tmp += *it++;
+ }
+ }
+ macroName = tmp;
+ if(macroName.length() < 1)
+ macroName = "_EMPTY_STRING";
+ if(macroName.length() < 2 && macroName[0] == '_')
+ macroName = "_WEIRD_CHARS";
+
+ unsigned int index = 2;
+ while (_macroNameSet.find(macroName) != _macroNameSet.end()) {
+ std::string suffix = toStr(index);
+ if (macroName.size() > suffix.size()) {
+ macroName = macroName.substr(0, macroName.size() - suffix.size()) + suffix;
+ } else {
+ macroName = suffix;
+ }
+ index++;
+ }
+
+ _macroNameSet.insert(macroName);
+ _strMacros[literal] = macroName;
+ return macroName;
+}
+
+int PromelaCodeAnalyzer::enumerateLiteral(const std::string& literal, int forceIndex) {
+ if (forceIndex >= 0) {
+ _strIndex[literal] = forceIndex;
+ return forceIndex;
+ }
+
+ if (_strIndex.find(literal) != _strIndex.end())
+ return _strIndex[literal];
+
+ _strIndex[literal] = _lastStrIndex++;
+ return _lastStrIndex + 1;
+}
+
+std::string PromelaCodeAnalyzer::adaptCode(const std::string& code, const std::string& prefix) {
+ // for (std::map<std::string, std::string>::const_iterator litIter = _strMacros.begin(); litIter != _strMacros.end(); litIter++) {
+ // boost::replace_all(replaced, "'" + litIter->first + "'", litIter->second);
+ // }
+ // boost::replace_all(replaced, "_event", prefix + "_event");
+ // replace all variables from analyzer
+
+ std::string processed = code;
+ std::stringstream processedStr;
+ std::list<std::pair<size_t, size_t> > posList;
+ std::list<std::pair<size_t, size_t> >::iterator posIter;
+ size_t lastPos;
+
+ // prepend all identifiers with our prefix
+ {
+ PromelaParser parsed(processed);
+ // parsed.dump();
+ posList = getTokenPositions(code, PML_NAME, parsed.ast);
+ posList.sort();
+ posIter = posList.begin();
+ lastPos = 0;
+
+ while (posIter != posList.end()) {
+ std::string token = code.substr(posIter->first, posIter->second - posIter->first);
+ if (std::all_of(token.begin(), token.end(), ::isupper) && false) {
+ // assume it is a state-name macro
+ processedStr << code.substr(lastPos, posIter->first - lastPos) << token;
+ } else {
+ processedStr << code.substr(lastPos, posIter->first - lastPos) << prefix << token;
+ }
+ lastPos = posIter->second;
+ posIter++;
+ }
+ processedStr << processed.substr(lastPos, processed.size() - lastPos);
+
+ processed = processedStr.str();
+ processedStr.clear();
+ processedStr.str("");
+ }
+
+ // replace string literals
+ {
+ PromelaParser parsed(processed);
+ posList = getTokenPositions(code, PML_STRING, parsed.ast);
+ posList.sort();
+ posIter = posList.begin();
+ lastPos = 0;
+
+ while (posIter != posList.end()) {
+ processedStr << processed.substr(lastPos, posIter->first - lastPos);
+ // std::cout << processed.substr(posIter->first + 1, posIter->second - posIter->first - 2) << std::endl;
+ assert(_strMacros.find(processed.substr(posIter->first + 1, posIter->second - posIter->first - 2)) != _strMacros.end());
+ processedStr << _strMacros[processed.substr(posIter->first + 1, posIter->second - posIter->first - 2)];
+ lastPos = posIter->second;
+ posIter++;
+ }
+ processedStr << processed.substr(lastPos, processed.size() - lastPos);
+
+ processed = processedStr.str();
+ processedStr.clear();
+ processedStr.str("");
+ }
+
+ return processed;
+}
+
+std::list<std::pair<size_t, size_t> > PromelaCodeAnalyzer::getTokenPositions(const std::string& expr, int type, PromelaParserNode* ast) {
+ std::list<std::pair<size_t, size_t> > posList;
+ if (ast->type == type && ast->loc != NULL) {
+ // ast->dump();
+ if (type == PML_NAME && ast->parent &&
+ ((ast->parent->type == PML_CMPND && ast->parent->operands.front() != ast) ||
+ (ast->parent->parent && ast->parent->type == PML_VAR_ARRAY && ast->parent->parent->type == PML_CMPND))) {
+ // field in a compound
+ } else {
+ if (ast->loc->firstLine == 0) {
+ posList.push_back(std::make_pair(ast->loc->firstCol, ast->loc->lastCol));
+ } else {
+ int line = ast->loc->firstLine;
+ size_t lastPos = 0;
+ while(line > 0) {
+ lastPos = expr.find_first_of('\n', lastPos + 1);
+ line--;
+ }
+ posList.push_back(std::make_pair(lastPos + ast->loc->firstCol, lastPos + ast->loc->lastCol));
+ }
+ }
+ }
+ for (std::list<PromelaParserNode*>::iterator opIter = ast->operands.begin(); opIter != ast->operands.end(); opIter++) {
+ std::list<std::pair<size_t, size_t> > tmp = getTokenPositions(expr, type, *opIter);
+ posList.insert(posList.end(), tmp.begin(), tmp.end());
+ }
+ return posList;
+}
+
+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 (size_t 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();
+
+}
+
+}
diff --git a/src/uscxml/transform/promela/PromelaCodeAnalyzer.h b/src/uscxml/transform/promela/PromelaCodeAnalyzer.h
new file mode 100644
index 0000000..656b24e
--- /dev/null
+++ b/src/uscxml/transform/promela/PromelaCodeAnalyzer.h
@@ -0,0 +1,150 @@
+/**
+ * @file
+ * @author 2016 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#ifndef PROMELACODEANALYZER_H_E89FF519
+#define PROMELACODEANALYZER_H_E89FF519
+
+#include "uscxml/transform/Trie.h"
+#include "uscxml/plugins/datamodel/promela/PromelaParser.h"
+#include "uscxml/plugins/datamodel/promela/parser/promela.tab.hpp"
+
+#include <set>
+
+namespace uscxml {
+
+class ChartToPromela;
+
+class USCXML_API PromelaCodeAnalyzer {
+public:
+ class PromelaTypedef {
+ public:
+ PromelaTypedef() {}
+ std::string name;
+ std::string type;
+ size_t arraySize = 0;
+ size_t minValue = 0;
+ size_t maxValue = 0;
+ std::map<std::string, PromelaTypedef> types;
+ std::set<ChartToPromela*> occurrences;
+
+ bool operator==(const PromelaTypedef& other) const {
+ return name == other.name;
+ }
+
+ };
+
+ PromelaCodeAnalyzer() : _eventTrie(".") {}
+
+ void analyze(ChartToPromela* interpreter);
+
+ void addCode(const std::string& code, ChartToPromela* interpreter);
+ void addLiteral(const std::string& stateName, int forceIndex = -1);
+
+ bool usesComplexEventStruct() {
+ return _typeDefs.types.find("_event") != _typeDefs.types.end() && _typeDefs.types["_event"].types.size() > 0;
+ }
+ bool usesEventField(const std::string& fieldName) {
+ if (usesComplexEventStruct() && _typeDefs.types["_event"].types.find(fieldName) != _typeDefs.types["_event"].types.end())
+ return true;
+ return false;
+ }
+ bool usesCancel(const std::string& elementName) {
+ return _usesCancel;
+ }
+
+ bool usesEventDataField(const std::string& fieldName) {
+ if (usesComplexEventStruct() &&
+ _typeDefs.types["_event"].types.find("data") != _typeDefs.types["_event"].types.end() &&
+ _typeDefs.types["_event"].types["data"].types.find(fieldName) != _typeDefs.types["_event"].types["data"].types.end())
+ return true;
+ 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;
+ }
+ void usesInPredicate(bool value) {
+ _usesInPredicate = value;
+ }
+ bool usesPlatformVars() {
+ return _usesPlatformVars;
+ }
+
+ bool hasIndexLessLoops() {
+ return _hasIndexLessLoops;
+ }
+
+ std::string macroForLiteral(const std::string& literal);
+ int indexForLiteral(const std::string& literal);
+
+ std::set<std::string> getLiterals() {
+ return _literals;
+ }
+ std::set<std::string> getEventsWithPrefix(const std::string& prefix);
+
+ Trie& getTrie() {
+ return _eventTrie;
+ }
+
+ std::string adaptCode(const std::string& code, const std::string& prefix);
+
+ static std::string prefixIdentifiers(const std::string& expr, const std::string& prefix);
+ static std::list<std::pair<size_t, size_t> > getTokenPositions(const std::string& expr, int type, PromelaParserNode* ast);
+
+ PromelaTypedef& getTypes() {
+ return _typeDefs;
+ }
+
+ PromelaTypedef& getType(const std::string& typeName) {
+ return _typeDefs.types.at(typeName);
+ }
+
+ std::string sanitizeCode(const std::string& code);
+
+protected:
+ void addEvent(const std::string& eventName);
+ void addState(const std::string& stateName, size_t index);
+
+ std::string createMacroName(const std::string& literal);
+ int enumerateLiteral(const std::string& literal, int forceIndex = -1);
+
+ std::map<std::string, std::string> _strMacros; // macronames for string literals
+ std::map<std::string, int> _strIndex; // integer enumeration for string
+ std::set<std::string> _literals;
+
+ PromelaTypedef _typeDefs;
+ Trie _eventTrie;
+
+private:
+ std::set<std::string> _macroNameSet; // helper set for uniqueness of macros
+ int _lastStrIndex = 1;
+ bool _usesCancel = false;
+ bool _usesInPredicate = false;
+ bool _usesPlatformVars = false;
+ bool _hasIndexLessLoops = false;
+};
+
+
+
+}
+
+#endif /* end of include guard: PROMELACODEANALYZER_H_E89FF519 */
diff --git a/src/uscxml/transform/promela/PromelaInlines.cpp b/src/uscxml/transform/promela/PromelaInlines.cpp
new file mode 100644
index 0000000..7d62762
--- /dev/null
+++ b/src/uscxml/transform/promela/PromelaInlines.cpp
@@ -0,0 +1,165 @@
+/**
+ * @file
+ * @author 2016 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#include "PromelaInlines.h"
+#include <boost/algorithm/string.hpp>
+
+namespace uscxml {
+
+using namespace XERCESC_NS;
+
+void PromelaInline::dump() {
+}
+
+PromelaInline::PromelaInline(const XERCESC_NS::DOMNode* node) {
+ if (node->getNodeType() != DOMNode::COMMENT_NODE && node->getNodeType() != DOMNode::TEXT_NODE)
+ return; // nothing to do
+
+ std::stringstream ssLine(X(node->getNodeValue()).str());
+ std::string line;
+
+ while(std::getline(ssLine, line)) {
+ // skip to first promela line
+ boost::trim(line);
+ if (boost::starts_with(line, "promela"))
+ break;
+ }
+
+ if (!boost::starts_with(line, "promela"))
+ return;
+
+ if (false) {
+ } else if (boost::starts_with(line, "promela-code")) {
+ type = PROMELA_CODE;
+ } else if (boost::starts_with(line, "promela-ltl")) {
+ type = PROMELA_LTL;
+ } else if (boost::starts_with(line, "promela-event-all")) {
+ type = PROMELA_EVENT_ALL_BUT;
+ } else if (boost::starts_with(line, "promela-event")) {
+ type = PROMELA_EVENT_ONLY;
+ } else if (boost::starts_with(line, "promela-progress")) {
+ type = PROMELA_PROGRESS_LABEL;
+ } else if (boost::starts_with(line, "promela-accept")) {
+ type = PROMELA_ACCEPT_LABEL;
+ } else if (boost::starts_with(line, "promela-end")) {
+ type = PROMELA_END_LABEL;
+ }
+
+ std::stringstream contentSS;
+ size_t endType = line.find_first_of(": \n");
+
+ std::string seperator;
+ if (endType != std::string::npos && endType + 1 < line.size()) {
+ contentSS << line.substr(endType + 1, line.size() - endType + 1);
+ seperator = "\n";
+ }
+
+ while(std::getline(ssLine, line)) {
+ boost::trim(line);
+ if (boost::starts_with(line, "promela")) {
+ std::cerr << "Split multiple #promela pragmas into multiple comments!" << std::endl;
+ break;
+ }
+ contentSS << seperator << line;
+ seperator = "\n";
+ }
+ content = contentSS.str();
+
+}
+
+PromelaInlines::PromelaInlines(const XERCESC_NS::DOMNode* node) {
+
+ std::list<DOMNode*> levelNodes;
+ levelNodes.push_back(const_cast<XERCESC_NS::DOMNode*>(node));
+
+ size_t level = 0;
+ while(levelNodes.size() > 0) {
+ PromelaInline* predecessor = NULL;
+
+ // iterate all nodes at given level
+ for (auto levelNode : levelNodes) {
+
+ // get all comments
+ std::list<DOMNode*> comments = DOMUtils::filterChildType(DOMNode::COMMENT_NODE, levelNode);
+ for (auto comment : comments) {
+
+ PromelaInline* tmp = new PromelaInline(comment);
+ if (tmp->type == PromelaInline::PROMELA_NIL) {
+ delete tmp;
+ continue;
+ }
+
+ if (predecessor != NULL) {
+ tmp->prevSibling = predecessor;
+ predecessor->nextSibling = tmp;
+ }
+ tmp->level = level;
+ tmp->container = static_cast<DOMElement*>(levelNode);
+ predecessor = tmp;
+ inlines[levelNode].push_back(tmp);
+ allInlines.push_back(tmp);
+ }
+ }
+
+ levelNodes = DOMUtils::filterChildType(DOMNode::ELEMENT_NODE, levelNodes);
+ level++;
+ }
+
+}
+
+PromelaInlines::~PromelaInlines() {
+}
+
+std::list<PromelaInline*> PromelaInlines::getRelatedTo(const XERCESC_NS::DOMNode* node,
+ PromelaInline::PromelaInlineType type) {
+ std::list<PromelaInline*> related;
+
+ auto inlIter = inlines.begin();
+ while (inlIter != inlines.end()) {
+ std::list<PromelaInline*>::iterator pmlIter = inlIter->second.begin();
+ while (pmlIter != inlIter->second.end()) {
+ if ((type != PromelaInline::PROMELA_NIL || (*pmlIter)->type == type) && (*pmlIter)->relatesTo(node)) {
+ related.push_back(*pmlIter);
+ }
+ pmlIter++;
+ }
+ inlIter++;
+ }
+ return related;
+}
+
+std::list<PromelaInline*> PromelaInlines::getAllOfType(uint32_t type) {
+ std::list<PromelaInline*> related;
+
+ auto inlIter = inlines.begin();
+ while (inlIter != inlines.end()) {
+ std::list<PromelaInline*>::iterator pmlIter = inlIter->second.begin();
+ while (pmlIter != inlIter->second.end()) {
+ if ((*pmlIter)->type & type) {
+ related.push_back(*pmlIter);
+ }
+ pmlIter++;
+ }
+ inlIter++;
+ }
+ return related;
+
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/transform/promela/PromelaInlines.h b/src/uscxml/transform/promela/PromelaInlines.h
new file mode 100644
index 0000000..2621f8d
--- /dev/null
+++ b/src/uscxml/transform/promela/PromelaInlines.h
@@ -0,0 +1,113 @@
+/**
+ * @file
+ * @author 2016 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#ifndef PROMELAINLINES_H_29BF8EF3
+#define PROMELAINLINES_H_29BF8EF3
+
+#include "uscxml/config.h"
+#include "uscxml/Common.h"
+#include "uscxml/messages/Data.h"
+#include "uscxml/util/DOM.h"
+
+#include <xercesc/dom/DOM.hpp>
+#include <list>
+#include <string>
+
+namespace uscxml {
+
+class USCXML_API PromelaInline {
+public:
+ enum PromelaInlineType {
+ PROMELA_NIL = 0x0000,
+ PROMELA_LTL = 0x0001,
+ PROMELA_CODE = 0x0002,
+ PROMELA_EVENT_ALL_BUT = 0x0004,
+ PROMELA_EVENT_ONLY = 0x0008,
+ PROMELA_PROGRESS_LABEL = 0x0010,
+ PROMELA_ACCEPT_LABEL = 0x0020,
+ PROMELA_END_LABEL = 0x0040
+ };
+
+ PromelaInline(const XERCESC_NS::DOMNode* node);
+ virtual ~PromelaInline() {}
+
+ operator bool() {
+ return (type != PROMELA_NIL);
+ }
+
+ std::list<PromelaInline*> children;
+ PromelaInline* prevSibling;
+ PromelaInline* nextSibling;
+
+ virtual void dump();
+
+ virtual bool relatesTo(const XERCESC_NS::DOMNode* node) {
+ return container == node;
+ }
+
+ size_t level;
+ std::string content;
+ const XERCESC_NS::DOMElement* container;
+ PromelaInlineType type;
+
+protected:
+ PromelaInline() : prevSibling(NULL), nextSibling(NULL), type(PROMELA_NIL) {};
+};
+
+
+class USCXML_API PromelaEventSource : public PromelaInline {
+public:
+ PromelaEventSource(const PromelaInline& pmlInline) {
+ type = pmlInline.type;
+ container = pmlInline.container;
+ content = pmlInline.content;
+ events = Data::fromJSON(pmlInline.content);
+ }
+
+ virtual bool relatesTo(const XERCESC_NS::DOMNode* node) {
+ return container == node || DOMUtils::isDescendant(node, container);
+ }
+
+ Data events;
+};
+
+
+class USCXML_API PromelaInlines {
+public:
+
+ PromelaInlines(const XERCESC_NS::DOMNode* node);
+ PromelaInlines() {}
+
+ virtual ~PromelaInlines();
+
+ std::list<PromelaInline*> getRelatedTo(const XERCESC_NS::DOMNode* node, PromelaInline::PromelaInlineType type);
+ std::list<PromelaInline*> getAllOfType(uint32_t type);
+
+ std::map<const XERCESC_NS::DOMNode*, std::list<PromelaInline*> > inlines;
+ std::list<PromelaInline*> allInlines;
+
+ static std::list<std::string> getStringLiterals(const Data& data);
+ static std::list<std::string> getEventNames(const Data& data);
+
+
+};
+
+}
+
+#endif /* end of include guard: PROMELAINLINES_H_29BF8EF3 */