summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <github@mintwerk.de>2016-11-24 16:37:46 (GMT)
committerStefan Radomski <github@mintwerk.de>2016-11-24 16:37:46 (GMT)
commitfcfc842a1ccee7a6b2579889f3236d50849c0679 (patch)
treeb830cd41d4a1c912e1c16d48e8e4bb52a6fdc21d
parentc6740774eaa2a41442456cf588644c9693e8d5e2 (diff)
parente7c0fbce1c1a5b4fe327c6a1e551c347bb30a332 (diff)
downloaduscxml-fcfc842a1ccee7a6b2579889f3236d50849c0679.zip
uscxml-fcfc842a1ccee7a6b2579889f3236d50849c0679.tar.gz
uscxml-fcfc842a1ccee7a6b2579889f3236d50849c0679.tar.bz2
Merge branch 'master' of github.com:tklab-tud/uscxml
-rw-r--r--src/uscxml/transform/ChartToVHDL.cpp624
-rw-r--r--src/uscxml/transform/ChartToVHDL.h17
-rw-r--r--src/uscxml/util/String.cpp49
-rw-r--r--src/uscxml/util/String.h11
-rw-r--r--test/ctest/scripts/run_generated_test.cmake4
-rw-r--r--test/w3c/ecma/test145.scxml29
6 files changed, 496 insertions, 238 deletions
diff --git a/src/uscxml/transform/ChartToVHDL.cpp b/src/uscxml/transform/ChartToVHDL.cpp
index 9228a2d..cbd46ef 100644
--- a/src/uscxml/transform/ChartToVHDL.cpp
+++ b/src/uscxml/transform/ChartToVHDL.cpp
@@ -32,9 +32,6 @@
#include <sstream>
-#define CONST_TRANS_SPONTANIOUS "HWE_NOW"
-#define CONST_EVENT_ANY "HWE_ANY"
-
namespace uscxml {
using namespace XERCESC_NS;
@@ -51,48 +48,6 @@ ChartToVHDL::ChartToVHDL(const Interpreter &other) : ChartToC(other), _eventTrie
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!");
- }
- }
-
-}
-
void ChartToVHDL::findEvents() {
// elements with an event attribute
std::list<DOMElement *> withEvents = DOMUtils::inDocumentOrder({
@@ -128,9 +83,15 @@ void ChartToVHDL::findEvents() {
//TODO implement error events --> set by output logic to a signal line
}
-
}
+ // preprocess event names since they are often used
+ _eventNames = _eventTrie.getWordsWithPrefix("");
+ // Calculate needed bit size for the event fifo
+ // --> |log2(n)| +1 with n is number of events
+ // we do not add +1 because the std_logic_vector startes with 0
+ _eventBitSize = ceil(abs(log2(_eventNames.size())));
+
_execContent = DOMUtils::inDocumentOrder({
XML_PREFIX(_scxml).str() + "raise",
XML_PREFIX(_scxml).str() + "send"
@@ -138,13 +99,12 @@ void ChartToVHDL::findEvents() {
}
-bool ChartToVHDL::filterSupportedExecContent(DOMElement *execContentElement) {
+bool ChartToVHDL::isSupportedExecContent(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();
@@ -155,47 +115,19 @@ void ChartToVHDL::writeTo(std::ostream &stream) {
stream << "-- gtkwave tb.vcd" << std::endl;
stream << std::endl;
- writeTypes(stream);
writeFiFo(stream);
writeEventController(stream);
writeMicroStepper(stream);
writeTestbench(stream);
+ writeTopLevel(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_" << escapeMacro((*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 << "use work.machine" << _md5 << ".all;" << std::endl;
stream << std::endl;
}
@@ -222,7 +154,7 @@ void ChartToVHDL::writeTestbench(std::ostream &stream) {
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_i :in std_logic_vector( " << _eventBitSize << " downto 0);" << std::endl;
stream << " next_event_we_i :in std_logic;" << std::endl;
stream << " --outputs" << std::endl;
stream << " error_o :out std_logic;" << std::endl;
@@ -280,7 +212,7 @@ void ChartToVHDL::writeTestbench(std::ostream &stream) {
}
stream << " --outputs" << std::endl;
stream << " micro_stepper_en_o :out std_logic;" << std::endl;
- stream << " event_o :out event_type;" << std::endl;
+ stream << " event_o :out std_logic_vector( " << _eventBitSize << " downto 0);" << std::endl;
stream << " event_we_o :out std_logic" << std::endl;
// stream << " done_o :out std_logic" << std::endl;
stream << ");" << std::endl;
@@ -292,7 +224,7 @@ void ChartToVHDL::writeTestbench(std::ostream &stream) {
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 << " signal next_event_i : std_logic_vector( " << _eventBitSize << " downto 0);" << std::endl;
stream << std::endl;
stream << " -- output" << std::endl;
@@ -431,7 +363,7 @@ void ChartToVHDL::writeTestbench(std::ostream &stream) {
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 << "_sig = '1') report \"Completed with errors\" severity error;" << std::endl;
}
stream << " -- stop simulation" << std::endl;
stream << " finish(0);" << std::endl; // use 0 for ctest
@@ -457,11 +389,244 @@ void ChartToVHDL::writeTestbench(std::ostream &stream) {
}
-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>
+void ChartToVHDL::writeTopLevel(std::ostream &stream) {
+
+ stream << "-- TOP LEVEL entity for easy synthesis" << std::endl;
+ writeIncludes(stream);
+ stream << std::endl;
+
+ stream << "-- empty entity" << std::endl;
+ stream << "entity top_level_design is" << std::endl;
+ stream << "port (" << std::endl;
+ stream << " --inputs" << std::endl;
+ stream << " clk :in std_logic;" << std::endl;
+ stream << " rst :in std_logic;" << std::endl;
+ stream << " --outputs" << std::endl;
+ for (auto state : _states) {
+ stream << " state_active_" << ATTR(state, "documentOrder")
+ << "_o :out std_logic;" << std::endl;
+ }
+ stream << " completed_o :out std_logic" << std::endl;
+ stream << ");" << std::endl;
+ stream << "end entity top_level_design;" << std::endl;
+ stream << std::endl;
+
+ stream << "architecture behavioral of top_level_design 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 std_logic_vector( " << _eventBitSize << " downto 0);" << 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 std_logic_vector( " << _eventBitSize << " downto 0);" << 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 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 : std_logic_vector( " << _eventBitSize << " downto 0);" << std::endl;
+ stream << std::endl;
+
+ stream << " -- output" << std::endl;
+ stream << " signal error_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;
+ }
+ }
- // write clock blocks
+ // wiring
+ stream << "begin" << std::endl;
+ stream << " reset <= rst;" << std::endl;
+ stream << std::endl;
+
+ for (auto state : _states) {
+ stream << "state_active_" << ATTR(state, "documentOrder")
+ << "_o <= state_active_" << ATTR(state, "documentOrder")
+ << "_sig;" << 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;
+
+ // 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 << "end architecture;" << std::endl;
+ stream << "-- END TOP LEVEL" << std::endl;
}
void ChartToVHDL::writeEventController(std::ostream &stream) {
@@ -499,7 +664,7 @@ void ChartToVHDL::writeEventController(std::ostream &stream) {
stream << " --outputs" << std::endl;
stream << " micro_stepper_en_o :out std_logic;" << std::endl;
- stream << " event_o :out event_type;" << std::endl;
+ stream << " event_o :out std_logic_vector( " << _eventBitSize << " downto 0);" << std::endl;
stream << " event_we_o :out std_logic" << std::endl;
stream << ");" << std::endl;
stream << "end event_controller; " << std::endl;
@@ -508,12 +673,13 @@ void ChartToVHDL::writeEventController(std::ostream &stream) {
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_bus : std_logic_vector( " << _eventBitSize << " downto 0);" << std::endl;
stream << "signal event_we : std_logic;" << std::endl;
for (int i = 0; i < _execContent.size(); i++) {
@@ -529,128 +695,161 @@ void ChartToVHDL::writeEventController(std::ostream &stream) {
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 << "micro_stepper_en <= completed_sig or not ( '0' ";
- for (auto state : _states) {
+ // check if there is SUPPORTED executable content
+ bool foundSupportedExecContent = false;
+ for (auto exContentElem : _execContent) {
+ if (isSupportedExecContent(exContentElem)) {
+ foundSupportedExecContent = true;
+ break;
+ }
+ }
+ if (!foundSupportedExecContent) {
+ // set output correct if there is no supported excontent
- if (DOMUtils::filterChildElements(XML_PREFIX(_scxml).str() + "onentry", state).size() > 0) {
- stream << std::endl << " or entry_set_" << ATTR(state, "documentOrder")
- << "_i";
+ if (_execContent.size() > 0) {
+ // show warning if executable content is ignored
+ stream << "-- no supported executable content found" << std::endl;
+ stream << "-- state machine may not run correctly" << std::endl;
}
+ stream << "-- setting output lines to fulfil dummy functionality" << std::endl;
+ stream << "micro_stepper_en_o <= '1';" << std::endl;
+ stream << "event_o <= (others => '0');" << std::endl;
+ stream << "event_we_o <= '0';" << std::endl;
+ stream << std::endl;
+ } else {
+ // 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 << "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";
+ 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";
+ 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 << std::endl;
+ 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 <= (others => '0');" << 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;
- // 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;
- size_t i = 0;
- std::string seperator = " ";
- for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) {
- DOMElement *exContentElem = *ecIter;
+ if (isSupportedExecContent(exContentElem)) {
- if (filterSupportedExecContent(exContentElem)) {
+ stream << seperator << "if start_" << toStr(i) << "_sig = '1' then"
+ << std::endl;
- stream << seperator << "if start_" << toStr(i) << "_sig = '1' then"
- << std::endl;
- stream << " event_bus <= hwe_" << escapeMacro(ATTR(exContentElem, "event"))
- << ";" << std::endl;
- stream << " done_" << toStr(i) << "_sig <= '1';" << std::endl;
- stream << " event_we <= '1';" << std::endl;
- seperator = " els";
+ size_t jj = 0;
+ for (auto eventIter = _eventNames.begin(); eventIter != _eventNames.end(); eventIter++, jj++) {
+ if (((*eventIter)->value) == ATTR(exContentElem, "event")) {
+ break;
+ }
+ }
+ stream << " event_bus <= \"" << toBinStr(jj, _eventBitSize+1) << "\";" << 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;
- i = 0;
- //for (auto exContentElem : _execContent) {
- for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) {
- DOMElement *exContentElem = *ecIter;
- if (filterSupportedExecContent(exContentElem)) {
- stream << " done_" << toStr(i) << "_sig <= '0';" << std::endl;
+ stream << " elsif micro_stepper_en = '1' then" << std::endl;
+ i = 0;
+ //for (auto exContentElem : _execContent) {
+ for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) {
+ DOMElement *exContentElem = *ecIter;
+ if (isSupportedExecContent(exContentElem)) {
+ 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;
+ 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";
+ 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 not needed, since seq_0_sig is hard coded as '1'.
+ // if not needed, since seq_0_sig is hard coded as '1'.
// if (i != 0) { // if not first element
- stream << " and seq_" << toStr(i) << "_sig";
+ stream << " and seq_" << toStr(i) << "_sig";
// }
- stream << ";" << std::endl;
+ 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++) {
- // 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;
+ stream << "seq_0_sig <= '1';" << std::endl;
+
+ if (_execContent.size() > 1) {
+ i = 0;
+ for (auto ecIter = _execContent.begin(); ecIter != _execContent.end(); ecIter++, i++) {
+ // 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;
+ }
}
}
+ stream << std::endl;
}
- stream << std::endl;
- stream << "end behavioral; " << std::endl;
- stream << "-- END Event Controller Logic" << std::endl;
- stream << std::endl;
+ stream << "end behavioral; " <<
+ std::endl;
+ stream << "-- END Event Controller Logic" <<
+ std::endl;
+ stream <<
+ std::endl;
}
std::string ChartToVHDL::getLineForExecContent(const DOMNode *elem) {
@@ -687,7 +886,7 @@ void ChartToVHDL::writeMicroStepper(std::ostream &stream) {
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_i :in std_logic_vector( " << _eventBitSize << " downto 0);" << std::endl;
stream << " next_event_we_i :in std_logic;" << std::endl;
stream << " --outputs" << std::endl;
stream << " error_o :out std_logic;" << std::endl;
@@ -768,8 +967,8 @@ void ChartToVHDL::writeFiFo(std::ostream &stream) {
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 << " data_in : in std_logic_vector( " << _eventBitSize << " downto 0);" << std::endl;
+ stream << " data_out : out std_logic_vector( " << _eventBitSize << " downto 0);" << std::endl;
stream << " empty : out std_logic;" << std::endl;
stream << " full : out std_logic" << std::endl;
stream << ");" << std::endl;
@@ -779,7 +978,8 @@ void ChartToVHDL::writeFiFo(std::ostream &stream) {
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 << " type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of std_logic_vector( " << _eventBitSize <<
+ " downto 0);" << std::endl;
stream << " variable Memory : FIFO_Memory;" << std::endl;
stream << "" << std::endl;
stream << " variable Head : natural range 0 to FIFO_DEPTH - 1;" << std::endl;
@@ -899,17 +1099,16 @@ void ChartToVHDL::writeSignalsAndComponents(std::ostream &stream) {
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 int_event_input : std_logic_vector( " << _eventBitSize << " downto 0);" << std::endl;
+ stream << "signal int_event_output : std_logic_vector( " << _eventBitSize << " downto 0);" << 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 next_event : std_logic_vector( " << _eventBitSize << " downto 0);" << 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++) {
+ for (std::list<TrieNode *>::iterator eventIter = _eventNames.begin();
+ eventIter != _eventNames.end(); eventIter++) {
stream << "signal event_" << escapeMacro((*eventIter)->value) << "_sig : std_logic;" << std::endl;
}
stream << std::endl;
@@ -927,8 +1126,8 @@ void ChartToVHDL::writeSignalsAndComponents(std::ostream &stream) {
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 << " data_in : in std_logic_vector( " << _eventBitSize << " downto 0);" << std::endl;
+ stream << " data_out : out std_logic_vector( " << _eventBitSize << " downto 0);" << 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;
@@ -1000,9 +1199,8 @@ void ChartToVHDL::writeInternalEventHandler(std::ostream &stream) {
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++) {
+ for (std::list<TrieNode *>::iterator eventIter = _eventNames.begin();
+ eventIter != _eventNames.end(); eventIter++) {
stream << " event_" << escapeMacro((*eventIter)->value) << "_sig <= '0';" << std::endl;
}
@@ -1028,12 +1226,14 @@ void ChartToVHDL::writeInternalEventHandler(std::ostream &stream) {
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_"
- << escapeMacro((*eventIter)->value) << " =>" << std::endl;
- for (std::list<TrieNode *>::iterator eventIter2 = eventNames.begin();
- eventIter2 != eventNames.end(); eventIter2++) {
+
+ size_t jj = 0;
+ for (std::list<TrieNode *>::iterator eventIter = _eventNames.begin();
+ eventIter != _eventNames.end(); eventIter++, jj++) {
+
+ stream << " when \"" << toBinStr(jj, _eventBitSize+1) << "\" =>" << std::endl;
+ for (std::list<TrieNode *>::iterator eventIter2 = _eventNames.begin();
+ eventIter2 != _eventNames.end(); eventIter2++) {
stream << " event_" << escapeMacro((*eventIter2)->value);
if (escapeMacro((*eventIter)->value) == escapeMacro((*eventIter2)->value)) {
stream << "_sig <= '1';" << std::endl;
@@ -1044,16 +1244,16 @@ void ChartToVHDL::writeInternalEventHandler(std::ostream &stream) {
stream << " next_event_dequeued <= '1';" << std::endl;
}
stream << " when others =>" << std::endl;
- for (std::list<TrieNode *>::iterator eventIter = eventNames.begin();
- eventIter != eventNames.end(); eventIter++) {
+ for (std::list<TrieNode *>::iterator eventIter = _eventNames.begin();
+ eventIter != _eventNames.end(); eventIter++) {
stream << " event_" << escapeMacro((*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++) {
+ for (std::list<TrieNode *>::iterator eventIter = _eventNames.begin();
+ eventIter != _eventNames.end(); eventIter++) {
stream << " event_" << escapeMacro((*eventIter)->value) << "_sig <= '0';" << std::endl;
}
stream << " next_event_dequeued <= '0';" << std::endl;
diff --git a/src/uscxml/transform/ChartToVHDL.h b/src/uscxml/transform/ChartToVHDL.h
index 4b047da..e4d9c53 100644
--- a/src/uscxml/transform/ChartToVHDL.h
+++ b/src/uscxml/transform/ChartToVHDL.h
@@ -167,11 +167,8 @@ public:
protected:
ChartToVHDL(const Interpreter &other);
- void checkDocument();
-
void findEvents();
- void writeTypes(std::ostream &stream);
void writeIncludes(std::ostream &stream);
@@ -184,6 +181,8 @@ protected:
void writeTestbench(std::ostream &stream);
+ void writeTopLevel(std::ostream &stream);
+
// system
void writeSignalsAndComponents(std::ostream &stream);
@@ -198,10 +197,6 @@ protected:
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);
@@ -217,17 +212,17 @@ protected:
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<TrieNode *> _eventNames;
+ size_t _eventBitSize = 0;
+ std::map<std::string, std::string> _eventsOnBus;
std::list<XERCESC_NS::DOMElement *> _execContent;
private:
std::string getLineForExecContent(const XERCESC_NS::DOMNode *elem);
- bool filterSupportedExecContent(XERCESC_NS::DOMElement *execContentElement);
+ bool isSupportedExecContent(XERCESC_NS::DOMElement *execContentElement);
};
}
diff --git a/src/uscxml/util/String.cpp b/src/uscxml/util/String.cpp
index 6a80756..95d69e9 100644
--- a/src/uscxml/util/String.cpp
+++ b/src/uscxml/util/String.cpp
@@ -27,8 +27,8 @@ namespace uscxml {
std::string escapeMacro(std::string const &s) {
// inspired by http://stackoverflow.com/questions/2417588/escaping-a-c-string
- std::string returnValue="";
- std::string specialChars="";
+ std::string returnValue = "";
+ std::string specialChars = "";
for (std::string::const_iterator iter = s.begin(), end = s.end(); iter != end; ++iter) {
char c = *iter;
if (('0' <= c && c <= '9') || ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || c == '_') {
@@ -47,7 +47,36 @@ std::string escapeMacro(std::string const &s) {
return returnValue;
}
-std::list<std::string> tokenize(const std::string& line, const char sep, bool trimWhiteSpace) {
+std::string toBinStr(size_t val, size_t margin) {
+ // inspired by http://www.cplusplus.com/forum/general/65862/
+
+ // mask has only the leftmost bit set.
+ size_t mask = 1u << (std::numeric_limits<unsigned>::digits - 1);
+
+ // skip leading bits that are not set.
+ while (0 == (val & mask) && mask != 0)
+ mask >>= 1; // shift all bits to the right by 1
+
+ std::string binStr;
+ binStr.reserve(std::numeric_limits<unsigned>::digits + 1);
+
+ do {
+ // add a '1' or '0' depending the current bit.
+ binStr += static_cast<char>(val & mask) + '0';
+
+ } while ((mask >>= 1) != 0); // next bit, when mask is 0 we've processed all bits
+
+ // fill with leading 0
+ if (binStr.size() < margin) {
+ for (size_t i = 0; i < (margin - binStr.size()); i++) {
+ binStr = "0" + binStr;
+ }
+ }
+
+ return binStr;
+}
+
+std::list<std::string> tokenize(const std::string &line, const char sep, bool trimWhiteSpace) {
std::list<std::string> tokens;
// appr. 3x faster than stringstream
@@ -57,7 +86,7 @@ std::list<std::string> tokenize(const std::string& line, const char sep, bool tr
if (i > 0 && start < i) {
tokens.push_back(line.substr(start, i - start));
}
- while(line[i] == sep || (trimWhiteSpace && ISWHITESPACE(line[i]))) {
+ while (line[i] == sep || (trimWhiteSpace && ISWHITESPACE(line[i]))) {
i++; // skip multiple occurences of seperator and whitespaces
}
start = i;
@@ -69,7 +98,7 @@ std::list<std::string> tokenize(const std::string& line, const char sep, bool tr
return tokens;
}
-std::string spaceNormalize(const std::string& text) {
+std::string spaceNormalize(const std::string &text) {
std::stringstream content;
#if 1
@@ -83,7 +112,7 @@ std::string spaceNormalize(const std::string& text) {
content << seperator << text.substr(start, i - start);
seperator = " ";
}
- while(isspace(text[++i])); // skip whitespaces
+ while (isspace(text[++i])); // skip whitespaces
start = i;
} else if (i + 1 == text.size()) {
content << seperator << text.substr(start, i + 1 - start);
@@ -93,7 +122,7 @@ std::string spaceNormalize(const std::string& text) {
#else
-// 291ms with test-performance-events.scml
+ // 291ms with test-performance-events.scml
std::istringstream iss(text);
std::string seperator;
do {
@@ -110,9 +139,9 @@ std::string spaceNormalize(const std::string& text) {
}
// see: http://www.w3.org/TR/scxml/#EventDescriptors
-bool nameMatch(const std::string& eventDescs, const std::string& eventName) {
+bool nameMatch(const std::string &eventDescs, const std::string &eventName) {
#if 1
- if(eventDescs.length() == 0 || eventName.length() == 0)
+ if (eventDescs.length() == 0 || eventName.length() == 0)
return false;
// naive case of single descriptor and exact match
@@ -126,7 +155,7 @@ bool nameMatch(const std::string& eventDescs, const std::string& eventName) {
if (i > 0 && start < i - 1) {
eventDesc = eventDescs.substr(start, i - start);
}
- while(isspace(eventDescs[++i])); // skip whitespaces
+ while (isspace(eventDescs[++i])); // skip whitespaces
start = i;
} else if (i + 1 == eventDescs.size()) {
eventDesc = eventDescs.substr(start, i + 1 - start);
diff --git a/src/uscxml/util/String.h b/src/uscxml/util/String.h
index 8d9c9ef..974db3b 100644
--- a/src/uscxml/util/String.h
+++ b/src/uscxml/util/String.h
@@ -26,9 +26,14 @@
namespace uscxml {
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);
+
+std::string toBinStr(size_t val, size_t margin);
+
+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/ctest/scripts/run_generated_test.cmake b/test/ctest/scripts/run_generated_test.cmake
index 7057bd0..b91d4f2 100644
--- a/test/ctest/scripts/run_generated_test.cmake
+++ b/test/ctest/scripts/run_generated_test.cmake
@@ -44,9 +44,9 @@ if (${TARGETLANG} STREQUAL "vhdl")
endif ()
message(STATUS "time for transforming to binary")
- message(STATUS "${GHDL_BIN} -r ${VHDL_TESTBENCH_NAME} --vcd=${VHDL_TESTBENCH_NAME}.vcd")
+ message(STATUS "${GHDL_BIN} -r ${VHDL_TESTBENCH_NAME}")
execute_process(
- COMMAND time -p ${GHDL_BIN} -r ${VHDL_TESTBENCH_NAME} --vcd=${VHDL_TESTBENCH_NAME}.vcd
+ COMMAND time -p ${GHDL_BIN} -r ${VHDL_TESTBENCH_NAME}
WORKING_DIRECTORY ${OUTDIR} RESULT_VARIABLE CMD_RESULT)
if (CMD_RESULT)
message(FATAL_ERROR "Error running ghdl ${GHDL_BIN}: ${CMD_RESULT}")
diff --git a/test/w3c/ecma/test145.scxml b/test/w3c/ecma/test145.scxml
new file mode 100644
index 0000000..b0fdba6
--- /dev/null
+++ b/test/w3c/ecma/test145.scxml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- self defined test, to test spontaneous transitions after event driven transitions -->
+<scxml xmlns="http://www.w3.org/2005/07/scxml" xmlns:conf="http://www.w3.org/2005/scxml-conformance" initial="s0" version="1.0" datamodel="ecmascript">
+ <state id="s0">
+ <onentry>
+ <raise event="foo"/>
+ <raise event="bar"/>
+ </onentry>
+ <transition event="foo" target="s1"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s1">
+ <transition event="bar" target="s2"/>
+ <transition event="*" target="fail"/>
+ </state>
+ <state id="s2">
+ <transition target="s2"/>
+ </state>
+ <final id="pass">
+ <onentry>
+ <log label="Outcome" expr="'pass'"/>
+ </onentry>
+ </final>
+ <final id="fail">
+ <onentry>
+ <log label="Outcome" expr="'fail'"/>
+ </onentry>
+ </final>
+</scxml>