diff options
author | Stefan Radomski <github@mintwerk.de> | 2016-11-23 09:44:43 (GMT) |
---|---|---|
committer | Stefan Radomski <github@mintwerk.de> | 2016-11-23 09:44:43 (GMT) |
commit | 63d1783beadf2f365de990e198dbb9c8cb885586 (patch) | |
tree | b7fd2b69529b6887e7e2b402e21614b31127902d | |
parent | 0c7c61257e8277ea6c05451da9a6f0bfd0fe7eea (diff) | |
parent | 84df16100bb76a99e6d6474dc118d94fc271d5dd (diff) | |
download | uscxml-63d1783beadf2f365de990e198dbb9c8cb885586.zip uscxml-63d1783beadf2f365de990e198dbb9c8cb885586.tar.gz uscxml-63d1783beadf2f365de990e198dbb9c8cb885586.tar.bz2 |
Merge branch 'master' of github.com:tklab-tud/uscxml
-rw-r--r-- | src/uscxml/transform/ChartToVHDL.cpp | 89 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToVHDL.h | 329 | ||||
-rw-r--r-- | src/uscxml/util/String.cpp | 27 | ||||
-rw-r--r-- | src/uscxml/util/String.h | 2 | ||||
-rw-r--r-- | test/w3c/ecma/test144.scxml | 2 |
5 files changed, 252 insertions, 197 deletions
diff --git a/src/uscxml/transform/ChartToVHDL.cpp b/src/uscxml/transform/ChartToVHDL.cpp index 6b4eebf..5061e33 100644 --- a/src/uscxml/transform/ChartToVHDL.cpp +++ b/src/uscxml/transform/ChartToVHDL.cpp @@ -138,6 +138,11 @@ namespace uscxml { } + bool ChartToVHDL::filterSupportedExecContent(DOMElement *execContentElement) { + return (TAGNAME(execContentElement) == XML_PREFIX(_scxml).str() + "raise" || + TAGNAME(execContentElement) == XML_PREFIX(_scxml).str() + "send"); + } + void ChartToVHDL::writeTo(std::ostream &stream) { // checkDocument(); findEvents(); @@ -176,7 +181,7 @@ namespace uscxml { for (std::list<TrieNode *>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << seperator << "hwe_" << escapedMacro((*eventIter)->value); + stream << seperator << "hwe_" << escapeMacro((*eventIter)->value); seperator = ", "; } stream << " );" << std::endl; @@ -205,7 +210,7 @@ namespace uscxml { stream << "end entity tb;" << std::endl; stream << std::endl; - stream << "architecture bhv of tb is" << std::endl; + stream << "architecture behavioral of tb is" << std::endl; stream << std::endl; // modules @@ -404,6 +409,40 @@ namespace uscxml { stream << " );" << std::endl; stream << std::endl; + // find pass state + std::list<DOMElement *> topLevelFinal = + DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "final", _scxml); + + std::string passStateNo = ""; + for (auto final : topLevelFinal) { + if (ATTR(final, "id") == "pass") { + passStateNo = ATTR(final, "documentOrder"); + } + } + + stream << " -- Test observation" << std::endl; + stream << " process (clk)" << std::endl; + stream << " variable count_clk : integer := 0;" << std::endl; + stream << " begin" << std::endl; + stream << " if rising_edge(clk) then" << std::endl; + stream << " count_clk := count_clk + 1;" << std::endl; + stream << " if (completed_o = '1') then" << std::endl; + if (!passStateNo.empty()) { + stream << " assert (state_active_" << passStateNo; + stream << "_sig = '1') report \"Complted with errors\" severity error;" << std::endl; + } + stream << " -- stop simulation" << std::endl; + stream << " assert false report \"Simulation Finished\" severity failure;" << std::endl; + stream << " else" << std::endl; + stream << " -- state machine not completed" << std::endl; + stream << " -- check if it is time to stop waiting (100 clk per state+transition+excontent)" << std::endl; + int tolleratedClocks = (_transitions.size() + _states.size() + _execContent.size()) * 100; + stream << " assert (count_clk < " << tolleratedClocks; + stream << ") report \"Clock count exceed\" severity failure;" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << " end process;" << std::endl; + stream << "end architecture;" << std::endl; stream << "-- END TESTBENCH" << std::endl; @@ -539,12 +578,11 @@ namespace uscxml { for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) { DOMElement *exContentElem = *ecIter; - if (TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "raise" || - TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "send") { + if (filterSupportedExecContent(exContentElem)) { stream << seperator << "if start_" << toStr(i) << "_sig = '1' then" << std::endl; - stream << " event_bus <= hwe_" << escapedMacro(ATTR(exContentElem, "event")) + stream << " event_bus <= hwe_" << escapeMacro(ATTR(exContentElem, "event")) << ";" << std::endl; stream << " done_" << toStr(i) << "_sig <= '1';" << std::endl; stream << " event_we <= '1';" << std::endl; @@ -556,8 +594,7 @@ namespace uscxml { //for (auto exContentElem : _execContent) { for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) { DOMElement *exContentElem = *ecIter; - //TODO y not send here --> general filter function ? - if (TAGNAME(exContentElem) == XML_PREFIX(_scxml).str() + "raise") { + if (filterSupportedExecContent(exContentElem)) { stream << " done_" << toStr(i) << "_sig <= '0';" << std::endl; } } @@ -588,18 +625,16 @@ namespace uscxml { if (_execContent.size() > 1) { i = 0; for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) { - if (i == 0) { - // prevent writing seq_0_sig since this should be hardcoded to '1' - continue; + // prevent writing seq_0_sig since this should be hardcoded to '1' + if (i != 0) { + // 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; } - // 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; @@ -866,7 +901,7 @@ namespace uscxml { std::list<TrieNode *> eventNames = _eventTrie.getWordsWithPrefix(""); for (std::list<TrieNode *>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << "signal event_" << escapedMacro((*eventIter)->value) << "_sig : std_logic;" << std::endl; + stream << "signal event_" << escapeMacro((*eventIter)->value) << "_sig : std_logic;" << std::endl; } stream << std::endl; @@ -940,7 +975,7 @@ namespace uscxml { 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 + //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; @@ -959,7 +994,7 @@ namespace uscxml { std::list<TrieNode *> eventNames = _eventTrie.getWordsWithPrefix(""); for (std::list<TrieNode *>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << " event_" << escapedMacro((*eventIter)->value) << "_sig <= '0';" << std::endl; + stream << " event_" << escapeMacro((*eventIter)->value) << "_sig <= '0';" << std::endl; } stream << " next_event_dequeued <= '0';" << std::endl; @@ -987,11 +1022,11 @@ namespace uscxml { for (std::list<TrieNode *>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { stream << " when hwe_" - << escapedMacro((*eventIter)->value) << " =>" << std::endl; + << escapeMacro((*eventIter)->value) << " =>" << std::endl; for (std::list<TrieNode *>::iterator eventIter2 = eventNames.begin(); eventIter2 != eventNames.end(); eventIter2++) { - stream << " event_" << escapedMacro((*eventIter2)->value); - if (escapedMacro((*eventIter)->value) == escapedMacro((*eventIter2)->value)) { + stream << " event_" << escapeMacro((*eventIter2)->value); + if (escapeMacro((*eventIter)->value) == escapeMacro((*eventIter2)->value)) { stream << "_sig <= '1';" << std::endl; } else { stream << "_sig <= '0';" << std::endl; @@ -1002,7 +1037,7 @@ namespace uscxml { stream << " when others =>" << std::endl; for (std::list<TrieNode *>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << " event_" << escapedMacro((*eventIter)->value) << "_sig <= '0';" << std::endl; + stream << " event_" << escapeMacro((*eventIter)->value) << "_sig <= '0';" << std::endl; } stream << " next_event_dequeued <= '0';" << std::endl; stream << " end case;" << std::endl; @@ -1010,7 +1045,7 @@ namespace uscxml { for (std::list<TrieNode *>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << " event_" << escapedMacro((*eventIter)->value) << "_sig <= '0';" << std::endl; + stream << " event_" << escapeMacro((*eventIter)->value) << "_sig <= '0';" << std::endl; } stream << " next_event_dequeued <= '0';" << std::endl; stream << " end if;" << std::endl; @@ -1072,7 +1107,7 @@ namespace uscxml { (*descIter) == "*" ? "" : *descIter); for (std::list<TrieNode *>::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - *nameMatchers += VLINE("event_" + escapedMacro((*eventIter)->value) + "_sig"); + *nameMatchers += VLINE("event_" + escapeMacro((*eventIter)->value) + "_sig"); } } } else { diff --git a/src/uscxml/transform/ChartToVHDL.h b/src/uscxml/transform/ChartToVHDL.h index a46265d..2506584 100644 --- a/src/uscxml/transform/ChartToVHDL.h +++ b/src/uscxml/transform/ChartToVHDL.h @@ -31,121 +31,129 @@ namespace uscxml { -class USCXML_API ChartToVHDL : public ChartToC { -public: - - virtual ~ChartToVHDL(); - static Transformer transform(const Interpreter& other); - - void writeTo(std::ostream& stream); - - - struct VNode { - virtual void print(std::ostream& stream, const std::string padding = "") = 0; - virtual ~VNode() {}; - }; - struct VBranch : VNode { - std::vector< VNode* > v; - virtual ~VBranch() { - for(unsigned i = 0; i < v.size(); i++) - delete v[i]; - } - - VBranch& operator +=(VNode* p ) { - v.push_back(p); - return *this; - } - }; - - struct VPointer { - VNode* ptr; - - operator VNode*() { - return ptr; - } - - operator VBranch*() { - return static_cast<VBranch*> (ptr); - } - - VPointer& operator /( VNode* p ) { - ptr = p; - return *this; - } - }; - - struct VContainer { - VBranch* ptr; - - operator VBranch*() { - return ptr; - } - VContainer& operator /( VBranch* p ) { - ptr = p; - return *this; - } - VContainer& operator , ( VPointer p ) { - if(ptr) ptr->v.push_back(p.ptr); - return *this; - } - VContainer& operator , ( VContainer c ) { - if(ptr) ptr->v.push_back(c.ptr); - return *this; - } - }; - - struct VLine : VNode { - VLine(const std::string& name) : name(name) {} - virtual void print(std::ostream& stream, const std::string padding = "") { - stream << " " << name; - } - - std::string name; - }; - - struct VAssign : VBranch { - virtual void print(std::ostream& stream, const std::string padding = "") { - v[0]->print(stream, padding); - stream << padding << " <="; - v[1]->print(stream, padding + " "); - } - }; - - struct VAnd : VBranch { - virtual void print(std::ostream& stream, const std::string padding = "") { - stream << std::endl << padding << "( '1' "; - for(unsigned i = 0; i < v.size(); i++) { - stream << std::endl << padding << " and"; - v[i]->print(stream, padding + " "); - } - stream << padding << ")" << std::endl; - } - }; - - struct VOr : VBranch { - virtual void print(std::ostream& stream, const std::string padding = "") { - stream << std::endl << padding << "( '0' "; - for(unsigned i = 0; i < v.size(); i++) { - stream << std::endl << padding << " or"; - v[i]->print(stream, padding + " "); - } - stream << std::endl << padding << ")" << std::endl; - } - }; - - struct VNot : VBranch { - virtual void print(std::ostream& stream, const std::string padding = "") { - stream << " ( not"; - v[0]->print(stream, padding + " "); - stream << " )"; - } - }; - - struct VNop : VBranch { - virtual void print(std::ostream& stream, const std::string padding = "") { - v[0]->print(stream, padding); - } - }; + class USCXML_API ChartToVHDL : public ChartToC { + public: + + virtual ~ChartToVHDL(); + + static Transformer transform(const Interpreter &other); + + void writeTo(std::ostream &stream); + + + struct VNode { + virtual void print(std::ostream &stream, const std::string padding = "") = 0; + + virtual ~VNode() { }; + }; + + struct VBranch : VNode { + std::vector<VNode *> v; + + virtual ~VBranch() { + for (unsigned i = 0; i < v.size(); i++) + delete v[i]; + } + + VBranch &operator+=(VNode *p) { + v.push_back(p); + return *this; + } + }; + + struct VPointer { + VNode *ptr; + + operator VNode *() { + return ptr; + } + + operator VBranch *() { + return static_cast<VBranch *> (ptr); + } + + VPointer &operator/(VNode *p) { + ptr = p; + return *this; + } + }; + + struct VContainer { + VBranch *ptr; + + operator VBranch *() { + return ptr; + } + + VContainer &operator/(VBranch *p) { + ptr = p; + return *this; + } + + VContainer &operator,(VPointer p) { + if (ptr) ptr->v.push_back(p.ptr); + return *this; + } + + VContainer &operator,(VContainer c) { + if (ptr) ptr->v.push_back(c.ptr); + return *this; + } + }; + + struct VLine : VNode { + VLine(const std::string &name) : name(name) { } + + virtual void print(std::ostream &stream, const std::string padding = "") { + stream << " " << name; + } + + std::string name; + }; + + struct VAssign : VBranch { + virtual void print(std::ostream &stream, const std::string padding = "") { + v[0]->print(stream, padding); + stream << padding << " <="; + v[1]->print(stream, padding + " "); + } + }; + + struct VAnd : VBranch { + virtual void print(std::ostream &stream, const std::string padding = "") { + stream << std::endl << padding << "( '1' "; + for (unsigned i = 0; i < v.size(); i++) { + stream << std::endl << padding << " and"; + v[i]->print(stream, padding + " "); + } + stream << padding << ")" << std::endl; + } + }; + + struct VOr : VBranch { + virtual void print(std::ostream &stream, const std::string padding = "") { + stream << std::endl << padding << "( '0' "; + for (unsigned i = 0; i < v.size(); i++) { + stream << std::endl << padding << " or"; + v[i]->print(stream, padding + " "); + } + stream << std::endl << padding << ")" << std::endl; + } + }; + + struct VNot : VBranch { + virtual void print(std::ostream &stream, const std::string padding = "") { + stream << " ( not"; + v[0]->print(stream, padding + " "); + stream << " )"; + } + }; + + struct VNop : VBranch { + virtual void print(std::ostream &stream, const std::string padding = "") { + v[0]->print(stream, padding); + } + }; //TODO can we create the macros without IDE errors ?! #define VLINE VPointer()/new VLine @@ -156,54 +164,71 @@ public: #define VNOP VContainer()/new VNop + protected: + ChartToVHDL(const Interpreter &other); -protected: - ChartToVHDL(const Interpreter& other); + void checkDocument(); - void checkDocument(); - void findEvents(); + void findEvents(); - void writeTypes(std::ostream& stream); - void writeIncludes(std::ostream& stream); + void writeTypes(std::ostream &stream); - // top layer components - void writeFiFo(std::ostream& stream); - void writeEventController(std::ostream & stream); - void writeMicroStepper(std::ostream& stream); - void writeTestbench(std::ostream & stream); + void writeIncludes(std::ostream &stream); - // system - void writeSignalsAndComponents(std::ostream& stream); - void writeSystemSignalMapping(std::ostream& stream); - void writeModuleInstantiation(std::ostream& stream); + // top layer components + void writeFiFo(std::ostream &stream); - // combinatorial logic - void writeOptimalTransitionSetSelection(std::ostream& stream); - void writeExitSet(std::ostream & stream); - void writeEntrySet(std::ostream & stream); - void writeTransitionSet(std::ostream & stream); - void writeDefaultCompletions(std::ostream & stream); - void writeCompleteEntrySet(std::ostream & stream); - void writeActiveStateNplusOne(std::ostream & stream); + void writeEventController(std::ostream &stream); - // 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); + void writeMicroStepper(std::ostream &stream); - // event generation - void writeExContentBlock(std::ostream & stream, std::string index, - std::list< XERCESC_NS::DOMElement* > commandSequence); + void writeTestbench(std::ostream &stream); - Trie _eventTrie; - std::list< XERCESC_NS::DOMElement* > _execContent; + // system + void writeSignalsAndComponents(std::ostream &stream); -private: - std::string getLineForExecContent(const XERCESC_NS::DOMNode* elem); + void writeSystemSignalMapping(std::ostream &stream); -}; + void writeModuleInstantiation(std::ostream &stream); + + // combinatorial logic + void writeOptimalTransitionSetSelection(std::ostream &stream); + + void writeExitSet(std::ostream &stream); + + void writeEntrySet(std::ostream &stream); + + void writeTransitionSet(std::ostream &stream); + + void writeDefaultCompletions(std::ostream &stream); + + void writeCompleteEntrySet(std::ostream &stream); + + void writeActiveStateNplusOne(std::ostream &stream); + + // 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); + + Trie _eventTrie; + std::list<XERCESC_NS::DOMElement *> _execContent; + + private: + std::string getLineForExecContent(const XERCESC_NS::DOMNode *elem); + + bool filterSupportedExecContent(XERCESC_NS::DOMElement *execContentElement); + }; } diff --git a/src/uscxml/util/String.cpp b/src/uscxml/util/String.cpp index 24c7d42..ae1aa68 100644 --- a/src/uscxml/util/String.cpp +++ b/src/uscxml/util/String.cpp @@ -25,31 +25,26 @@ namespace uscxml { #define ISWHITESPACE(char) (isspace(char)) -std::string escapedMacro(std::string const& s) { +std::string escapeMacro(std::string const &s) { // inspired by http://stackoverflow.com/questions/2417588/escaping-a-c-string std::string returnValue=""; + std::string specialChars=""; for (std::string::const_iterator iter = s.begin(), end = s.end(); iter != end; ++iter) { char c = *iter; - if (' ' <= c && c <= '~' && c != '\\' && c != '"') { + if (('0' <= c && c <= '9') || ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || c == '_') { returnValue += c; } else { - returnValue += "__"; - switch(c) { - case '"': returnValue += "COLON"; break; - case '\\': returnValue += "BACHSLASH"; break; - case '\t': returnValue += "TAB"; break; - case '\r': returnValue += "RETURN"; break; - case '\n': returnValue += "NEWLINE"; break; - default: - char const* const hexdig = "0123456789ABCDEF"; - returnValue += 'x'; - returnValue += hexdig[c >> 4]; - returnValue += hexdig[c & 0xF]; - } - returnValue += "__"; + specialChars += c; } } + if (!specialChars.empty()){ + // http://www.cplusplus.com/reference/functional/hash/ + // returns the same result for a given string within one execution + std::hash<std::string> strHash; + returnValue += "_"; + returnValue += strHash(specialChars); + } return returnValue; } diff --git a/src/uscxml/util/String.h b/src/uscxml/util/String.h index 9acd288..8d9c9ef 100644 --- a/src/uscxml/util/String.h +++ b/src/uscxml/util/String.h @@ -25,7 +25,7 @@ namespace uscxml { -std::string escapedMacro(std::string const& s); +std::string escapeMacro(std::string const &s); std::list<std::string> tokenize(const std::string& line, const char seperator = ' ', bool trimWhiteSpace = true); std::string spaceNormalize(const std::string& text); bool nameMatch(const std::string& eventDescs, const std::string& event); diff --git a/test/w3c/ecma/test144.scxml b/test/w3c/ecma/test144.scxml index e47f3f0..76ee416 100644 --- a/test/w3c/ecma/test144.scxml +++ b/test/w3c/ecma/test144.scxml @@ -5,7 +5,7 @@ foo occurs before bar, success, otherwise failure --> <state id="s0"> <onentry> <raise event="foo"/> - <raise event="*"/> + <raise event="bar"/> </onentry> <transition event="foo" target="s1"/> <transition event="*" target="fail"/> |