summaryrefslogtreecommitdiffstats
path: root/src/uscxml
diff options
context:
space:
mode:
authorStefan Radomski <sradomski@mintwerk.de>2016-02-29 22:32:08 (GMT)
committerStefan Radomski <sradomski@mintwerk.de>2016-02-29 22:32:08 (GMT)
commit1bdf058cf07cfd53885c81af4c0c943d3baac4c6 (patch)
treed66e529bf6a4315966f6b560c16f3d084b887f2e /src/uscxml
parent938bc217b59c6f0a23f7e27baf897cdd9890ae98 (diff)
downloaduscxml-1bdf058cf07cfd53885c81af4c0c943d3baac4c6.zip
uscxml-1bdf058cf07cfd53885c81af4c0c943d3baac4c6.tar.gz
uscxml-1bdf058cf07cfd53885c81af4c0c943d3baac4c6.tar.bz2
More work on VHDL
Diffstat (limited to 'src/uscxml')
-rw-r--r--src/uscxml/transform/ChartToC.cpp28
-rw-r--r--src/uscxml/transform/ChartToVHDL.cpp490
-rw-r--r--src/uscxml/transform/ChartToVHDL.h7
3 files changed, 330 insertions, 195 deletions
diff --git a/src/uscxml/transform/ChartToC.cpp b/src/uscxml/transform/ChartToC.cpp
index ee0b431..159b4c5 100644
--- a/src/uscxml/transform/ChartToC.cpp
+++ b/src/uscxml/transform/ChartToC.cpp
@@ -785,6 +785,7 @@ void ChartToC::writeTypes(std::ostream& stream) {
stream << " const char target[USCXML_MAX_NR_STATES_BYTES];" << std::endl;
stream << " const char* event;" << std::endl;
stream << " const char* condition;" << std::endl;
+ stream << " const is_enabled_t is_enabled;" << std::endl;
stream << " const exec_content_t on_transition;" << std::endl;
stream << " const unsigned char type;" << std::endl;
stream << " const char conflicts[USCXML_MAX_NR_TRANS_BYTES];" << std::endl;
@@ -884,7 +885,6 @@ void ChartToC::writeTypes(std::ostream& stream) {
stream << std::endl;
stream << " dequeue_internal_t dequeue_internal;" << std::endl;
stream << " dequeue_external_t dequeue_external;" << std::endl;
- stream << " is_enabled_t is_enabled;" << std::endl;
stream << " is_matched_t is_matched;" << std::endl;
stream << " is_true_t is_true;" << std::endl;
stream << " raise_done_event_t raise_done_event;" << std::endl;
@@ -1147,6 +1147,19 @@ void ChartToC::writeExecContent(std::ostream& stream) {
Element<std::string> transition(_transitions[i]);
NodeSet<std::string> execContent = DOMUtils::filterChildType(Node_base::ELEMENT_NODE, transition);
+ if (HAS_ATTR(transition, "cond")) {
+ stream << "static int " << _prefix << "_" << DOMUtils::idForNode(transition) << "_is_enabled(const uscxml_ctx* ctx, const uscxml_transition* transition) {" << std::endl;
+ if (HAS_ATTR(_scxml, "datamodel") && ATTR(_scxml, "datamodel") == "native") {
+ stream << " return (" << ATTR(transition, "cond") << ");" << std::endl;
+ } else {
+ stream << " if likely(ctx->is_true != NULL) {" << std::endl;
+ stream << " return (ctx->is_true(ctx, \"" << escape(ATTR(transition, "cond")) << "\"));" << std::endl;
+ stream << " }" << std::endl;
+ stream << " return USCXML_ERR_MISSING_CALLBACK;" << std::endl;
+ }
+ stream << "}" << std::endl;
+ }
+
if (execContent.size() > 0) {
stream << "static int " << _prefix << "_" << DOMUtils::idForNode(transition) << "_on_trans(const uscxml_ctx* ctx, const uscxml_state* state, const void* event) {" << std::endl;
stream << " int err = USCXML_ERR_OK;" << std::endl;
@@ -1971,6 +1984,16 @@ void ChartToC::writeTransitions(std::ostream& stream) {
stream << (HAS_ATTR(transition, "cond") ? "\"" + escape(ATTR(transition, "cond")) + "\"" : "NULL");
stream << "," << std::endl;
+
+ // is enabled
+ stream << " /* is_enabled */ ";
+ if (HAS_ATTR(transition, "cond")) {
+ stream << _prefix << "_" << DOMUtils::idForNode(transition) << "_is_enabled";
+ } else {
+ stream << "NULL";
+ }
+ stream << "," << std::endl;
+
// on transition handlers
stream << " /* ontrans */ ";
if (DOMUtils::filterChildType(Arabica::DOM::Node_base::ELEMENT_NODE, transition).size() > 0) {
@@ -2209,7 +2232,8 @@ void ChartToC::writeFSM(std::ostream& stream) {
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 || ctx->is_enabled(ctx, &USCXML_GET_TRANS(i)) > 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;
diff --git a/src/uscxml/transform/ChartToVHDL.cpp b/src/uscxml/transform/ChartToVHDL.cpp
index 6f104ac..d3abcf1 100644
--- a/src/uscxml/transform/ChartToVHDL.cpp
+++ b/src/uscxml/transform/ChartToVHDL.cpp
@@ -120,14 +120,77 @@ void ChartToVHDL::writeTo(std::ostream& stream) {
// same preparations as the C transformation
prepare();
-// checkDocument();
+ // checkDocument();
findEvents();
+ stream << "-- generated from " << _sourceURL.asString() << 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);
writeFSM(stream);
+ writeTestbench(stream);
}
+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;
+ stream << " -- Module declaration" << std::endl;
+ stream << " component fsm_scxml 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 << " en :in std_logic;" << std::endl;
+ stream << " next_event_i :in event_type;" << std::endl;
+ stream << " next_event_en_i :in std_logic;" << std::endl;
+ stream << " --outputs" << std::endl;
+ stream << " completed_o :out std_logic;" << std::endl;
+ stream << " error_o :out std_logic;" << std::endl;
+ stream << " current_state_o :out state_type" << std::endl;
+ stream << " );" << std::endl;
+ stream << " end component;" << std::endl;
+ stream << " " << std::endl;
+ stream << " -- input" << std::endl;
+ stream << " signal clk : std_logic := '0';" << std::endl;
+ stream << " signal reset : std_logic;" << std::endl;
+ stream << " signal next_event_i : event_type;" << std::endl;
+ stream << " " << std::endl;
+ stream << " -- output" << std::endl;
+ stream << " signal error_o, next_event_en_i, completed_o : std_logic;" << std::endl;
+ stream << " " << std::endl;
+ 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 : fsm_scxml" << std::endl;
+ stream << " port map (" << std::endl;
+ stream << " clk => clk," << std::endl;
+ stream << " rst => reset," << std::endl;
+ stream << " en => '1'," << std::endl;
+ stream << " " << std::endl;
+ stream << " next_event_i => next_event_i," << std::endl;
+ stream << " next_event_en_i => next_event_en_i," << std::endl;
+ stream << " completed_o => completed_o," << std::endl;
+ stream << " error_o => error_o," << std::endl;
+ stream << " current_state_o => open" << std::endl;
+ stream << " );" << std::endl;
+ stream << " " << std::endl;
+ stream << "end architecture;" << std::endl;
+ stream << "-- END TESTBENCH" << std::endl;
+
+}
void ChartToVHDL::writeFSM(std::ostream & stream) {
@@ -164,11 +227,14 @@ void ChartToVHDL::writeFSM(std::ostream & stream) {
writeModuleInstantiation(stream);
// write fsm architecture
-// writeNextStateLogic(stream);
+ writeNextStateLogic(stream);
writeOptimalTransitionSetSelection(stream);
writeExitSet(stream);
writeEntrySet(stream);
+ writeDefaultCompletions(stream);
+ writeCompleteEntrySet(stream);
+ writeActiveStateNplusOne(stream);
// writeOutputLogic(stream);
writeErrorHandler(stream);
@@ -180,6 +246,7 @@ void ChartToVHDL::writeFSM(std::ostream & stream) {
}
#if 0
+
void ChartToVHDL::writeTopDown(std::ostream & stream) {
// create hardware top level
stream << "-- top level" << std::endl;
@@ -235,11 +302,11 @@ void ChartToVHDL::writeTypes(std::ostream & stream) {
// create event type
stream << " type event_type is (";
seperator = "";
-// for (size_t i = 0; i < _events.size(); i++) {
-// stream << seperator;
-// stream << _events[i];
-// seperator = ", ";
-// }
+ // for (size_t i = 0; i < _events.size(); i++) {
+ // stream << seperator;
+ // stream << _events[i];
+ // seperator = ", ";
+ // }
if (seperator.size() == 0) {
stream << "NO_EVENTS";
}
@@ -359,16 +426,14 @@ void ChartToVHDL::writeSignals(std::ostream & stream) {
stream << "-- system signals" << std::endl;
stream << "signal stall : std_logic;" << std::endl;
stream << "-- state signals" << std::endl;
-// stream << "signal next_state : state_type;" << std::endl;
-// stream << "signal current_state : state_type;" << std::endl;
+ // stream << "signal next_state : state_type;" << std::endl;
+ // stream << "signal current_state : state_type;" << std::endl;
for (size_t i = 0; i < _states.size(); i++) {
Element<std::string> state(_states[i]);
- stream << "signal " << DOMUtils::idForNode(state) << "_curr : std_logic;" << std::endl;
- stream << "signal " << DOMUtils::idForNode(state) << "_next : std_logic;" << std::endl;
- }
- for (size_t i = 0; i < _states.size(); i++) {
- Element<std::string> state(_states[i]);
+ stream << "signal is_active_" << toStr(i) << "_sig : std_logic;" << std::endl;
+ stream << "signal is_active_np1_" << toStr(i) << "_sig : std_logic;" << std::endl;
+ stream << "signal in_entry_set_" << toStr(i) << "_sig : std_logic;" << std::endl;
stream << "signal in_exit_set_" << ATTR(state, "documentOrder") << "_sig : std_logic;" << std::endl;
stream << "signal in_complete_entry_set_up_" << ATTR(state, "documentOrder") << "_sig : std_logic;" << std::endl;
stream << "signal in_complete_entry_set_" << ATTR(state, "documentOrder") << "_sig : std_logic;" << std::endl;
@@ -476,6 +541,23 @@ std::string ChartToVHDL::eventNameEscape(const std::string& eventName) {
return escaped;
}
+void ChartToVHDL::writeActiveStateNplusOne(std::ostream & stream) {
+ stream << "-- active configuration" << std::endl;
+
+ for (size_t i = 0; i < _states.size(); i++) {
+
+ VBranch* tree = (VASSIGN ,
+ VLINE("is_active_np1_" + toStr(i) + "_sig"),
+ (VAND ,
+ VLINE("in_complete_entry_set_"+toStr(i)+"_sig"),
+ (VOR , VLINE("in_exit_set_"+toStr(i)+"_sig"), (VNOT, VLINE("is_active_"+toStr(i)+"_sig")))));
+
+ tree->print(stream);
+ stream << ";" << std::endl;
+
+ }
+}
+
void ChartToVHDL::writeOptimalTransitionSetSelection(std::ostream & stream) {
stream << "-- optimal transition set selection" << std::endl;
for (size_t i = 0; i < _transitions.size(); i++) {
@@ -503,46 +585,18 @@ void ChartToVHDL::writeOptimalTransitionSetSelection(std::ostream & stream) {
}
}
- VBranch* tree = (VASSIGN ,
- VLINE("in_optimal_transition_set_" + ATTR(transition, "postFixOrder") + "_sig") ,
- (VAND ,
+ VBranch* tree = (VASSIGN,
+ VLINE("in_optimal_transition_set_" + ATTR(transition, "postFixOrder") + "_sig"),
+ (VAND,
(HAS_ATTR(transition, "event")
- ? ( VNOT , VLINE("spontaneous_en") )
- : ( VNOP , VLINE("spontaneous_en") ) ) ,
+ ? (VNOT, VLINE("spontaneous_en"))
+ : (VNOP, VLINE("spontaneous_en"))),
VLINE("state_active_" + ATTR(transition, "source") + "_sig"),
nameMatchers,
- (VNOT , conflicters) ) );
+ (VNOT, conflicters)));
tree->print(stream);
stream << ";" << std::endl;
-
-
-#if 0
- stream << "in_optimal_transition_set_" << ATTR(transition, "postFixOrder") << "_sig "
- << "<= " << (HAS_ATTR(transition, "event") ? "(not spontaneous_en)" : "spontaneous_en") << " and " << std::endl
- << " state_active_" << ATTR(transition, "source") << "_sig and not ( '0' " << std::endl;
- for (size_t j = 0; j < i; j++) {
- if (conflicts[j] == '1') {
- stream << " or in_optimal_transition_set_" << toStr(j) << "_sig" << std::endl;
- }
- }
- stream << " )";
- if (HAS_ATTR(transition, "event")) {
- stream << " and ( '0' " << std::endl;;
-
- // find all matching event literals
- 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++) {
- stream << " or event_" << eventNameEscape((*eventIter)->value) << "_sig" << std::endl;
- }
- }
- stream << " )";
-
- }
- stream << ";" << std::endl;
-#endif
}
}
@@ -565,34 +619,75 @@ void ChartToVHDL::writeExitSet(std::ostream & stream) {
}
}
- VBranch* tree = (VASSIGN ,
+ VBranch* tree = (VASSIGN,
VLINE("in_exit_set_" + toStr(i) + "_sig"),
(VAND,
VLINE("state_active_" + toStr(i) + "_sig"),
- exitsetters ));
+ exitsetters));
tree->print(stream);
stream << ";" << std::endl;
+ }
+}
-#if 0
- stream << "in_exit_set_" << toStr(i) << "_sig "
- << "<= state_active_" << toStr(i) << "_sig and ('0'" << std::endl;
- for (size_t j = 0; j < _transitions.size(); j++) {
- Element<std::string> transition(_transitions[j]);
- std::string exitSet = ATTR(transition, "exitSetBools");
- if (exitSet[i] == '1') {
- stream << " or in_optimal_transition_set_" << toStr(j) << "_sig " << std::endl;
+void ChartToVHDL::writeEntrySet(std::ostream & stream) {
+ stream << "-- entry set selection" << std::endl;
+
+ for (size_t i = 0; i < _states.size(); i++) {
+
+ VBranch* tree = (VASSIGN ,
+ VLINE("in_entry_set_" + toStr(i) + "_sig"),
+ (VAND ,
+ VLINE("in_complete_entry_set_"+toStr(i)+"_sig"),
+ (VOR , VLINE("is_active_"+toStr(i)+"_sig"), (VNOT, VLINE("in_exit_set_"+toStr(i)+"_sig")))));
+
+ tree->print(stream);
+ stream << ";" << std::endl;
+ }
+}
+
+void ChartToVHDL::writeDefaultCompletions(std::ostream & stream) {
+ stream << "-- default completion assignments" << std::endl;
+
+ std::map<Element<std::string>, NodeSet<std::string> > completions;
+ for (size_t i = 0; i < _states.size(); i++) {
+ Element<std::string> state(_states[i]);
+ completions[state]; // initialize other completions to 0
+
+ std::string completion = ATTR(state, "completionBools");
+ for (size_t j = 0; j < _states.size(); j++) {
+ if (completion[j] == '1') {
+ completions[Element<std::string>(_states[j])].push_back(state);
}
}
+ }
+
+ std::map<Element<std::string>, NodeSet<std::string> >::const_iterator complIter = completions.begin();
+ while(complIter != completions.end()) {
+ const Element<std::string>& state(complIter->first);
+ const NodeSet<std::string>& refs(complIter->second);
+
+ std::string index = ATTR(state, "documentOrder");
+ VContainer defaultCompleters = VOR;
+
+ for (size_t i =0 ; i< refs.size(); i++) {
+ *defaultCompleters += VLINE("in_complete_entry_set_" + toStr(i) + "_sig ");
+ }
+
+ VBranch* tree = (VASSIGN ,
+ VLINE("default_completion_" + index + "_sig"), defaultCompleters);
- stream << ")";
+ tree->print(stream);
stream << ";" << std::endl;
-#endif
+
+ complIter++;
}
+
+
}
-void ChartToVHDL::writeEntrySet(std::ostream & stream) {
- stream << "-- entry set selection" << std::endl;
+void ChartToVHDL::writeCompleteEntrySet(std::ostream & stream) {
+ stream << "-- complete entry set selection" << std::endl;
for (size_t i = 0; i < _states.size(); i++) {
Element<std::string> state(_states[i]);
@@ -619,7 +714,7 @@ void ChartToVHDL::writeEntrySet(std::ostream & stream) {
}
}
- VBranch* tree = (VASSIGN ,
+ VBranch* tree = (VASSIGN,
VLINE("in_complete_entry_set_up_" + toStr(i) + "_sig"),
optimalEntrysetters,
completeEntrysetters);
@@ -632,7 +727,7 @@ void ChartToVHDL::writeEntrySet(std::ostream & stream) {
for (size_t j = 0; j < _transitions.size(); j++) {
Element<std::string> transition(_transitions[j]);
-// std::cout << transition;
+ // std::cout << transition;
std::string targetSet = ATTR(transition, "targetBools");
if (targetSet[i] == '1') {
stream << " or in_optimal_transition_set_" << toStr(j) << std::endl;
@@ -669,12 +764,12 @@ void ChartToVHDL::writeEntrySet(std::ostream & stream) {
for (size_t j = 0; j < _states.size(); j++) {
if (children[j] != '1')
continue;
- *tmp1 += ( VAND,
- ( VNOT,
- ( VAND,
- VLINE("is_active" + toStr(j) + "_sig"),
- ( VNOT,
- VLINE("in_exit_set_" + toStr(j) + "_sig") ) ) ) );
+ *tmp1 += (VAND,
+ (VNOT,
+ (VAND,
+ VLINE("is_active" + toStr(j) + "_sig"),
+ (VNOT,
+ VLINE("in_exit_set_" + toStr(j) + "_sig")))));
}
@@ -684,7 +779,7 @@ void ChartToVHDL::writeEntrySet(std::ostream & stream) {
*tmp1 += VLINE("in_complete_entry_set_" + toStr(parent) + "_sig");
}
- VBranch* tree = (VASSIGN ,
+ VBranch* tree = (VASSIGN,
VLINE("in_complete_entry_set_" + toStr(i) + "_sig"), tmp1);
tree->print(stream);
@@ -716,135 +811,146 @@ void ChartToVHDL::writeEntrySet(std::ostream & stream) {
// process bauen der bei fail 0 ausgibt und bei accept 1
void ChartToVHDL::writeNextStateLogic(std::ostream & stream) {
- stream << "-- state logic" << std::endl;
- stream << "-- only gets active when state changes (microstep?) " << std::endl;
- stream << "state_decode_proc: process(current_state)" << std::endl;
+ // stream << "-- state logic" << std::endl;
+ // stream << "-- only gets active when state changes (microstep?) " << std::endl;
+ // stream << "state_decode_proc: process(current_state)" << std::endl;
+ // stream << "begin" << std::endl;
+ //
+ // std::stringstream nextStateBuffer;
+ // for (size_t i = 0; i < _states.size(); i++) {
+ // Element<std::string> state(_states[i]);
+ //
+ // // calculate event choices
+ // // _transitions is sorted in Postfix order
+ // // by stating with smalest index the most important
+ // // will be written first
+ // std::vector< Element<std::string> > choices;
+ // std::string spntaneous_trans_sig = "";
+ // for (size_t j = 0; j < _transitions.size(); j++) {
+ // Element<std::string> transition(_transitions[j]);
+ // if (ATTR_CAST(transition.getParentNode(), "id") == ATTR(state, "id")) {
+ // choices.push_back(transition);
+ // if (ATTR(transition, "event") == CONST_TRANS_SPONTANIOUS) {
+ // spntaneous_trans_sig = ATTR(transition, "id");
+ // // FIXME hofully there are just single spntaneous transitions allowed
+ // // else we have to handle this
+ // }
+ // }
+ // }
+ //
+ // // calculate incomming transitions (for later use)
+ // std::vector< Element<std::string> > incommingTransitions;
+ // for (size_t j = 0; j < _transitions.size(); j++) {
+ // Element<std::string> transition(_transitions[j]);
+ // if (ATTR_CAST(transition, "target") == ATTR(state, "id")) {
+ // incommingTransitions.push_back(transition);
+ // }
+ // }
+ //
+ // if (choices.size() > 0) {// if no outgoing transitions (maybe final state :D) we don't write anything
+ //
+ // stream << " if ( " << ATTR(state, "id") << " = '1' ) then" << std::endl;
+ // stream << " if ( transition_spntaneous_en = '1' ) then" << std::endl;
+ // // enable spntaneous transition (if any) and disable all other
+ // for (size_t j = 0; j < choices.size(); j++) {
+ // Element<std::string> transition(choices[j]);
+ // if (ATTR(transition, "id") == spntaneous_trans_sig) {
+ // stream << " " << ATTR(transition, "id") << "_sig <= '1';" << std::endl;
+ // } else {
+ // stream << " " << ATTR(transition, "id") << "_sig <= '0';" << std::endl;
+ // }
+ // }
+ //
+ // stream << " elsif ( next_event_re = '1' ) then" << std::endl;
+ // // if no spntaneous transition enables, look at events
+ // // since there is just one event at a time, we use case statement
+ // // to check transitions matching in postfix order
+ // // FIXME hopefully there is just one transition per state and event at a time
+ // stream << " case next_event is" << std::endl;
+ // bool hasWildcardTransition = false;
+ // for (size_t j = 0; j < choices.size(); j++) {
+ // Element<std::string> transition(choices[j]);
+ // std::string eventName = ATTR(transition, "event");
+ // if (eventName == CONST_EVENT_ANY) {
+ // eventName = "others";
+ // hasWildcardTransition = true;
+ // }
+ // stream << " when " << eventName << " =>" << std::endl;
+ // // activate transition and deactivete others
+ // for (size_t k = 0; k < choices.size(); k++) {
+ // Element<std::string> tmp_t(choices[k]);
+ // if (ATTR(tmp_t, "event") == ATTR(transition, "event")) {
+ // stream << " " << ATTR(tmp_t, "id") << "_sig <= '1';" << std::endl;
+ // } else {
+ // stream << " " << ATTR(tmp_t, "id") << "_sig <= '0';" << std::endl;
+ // }
+ // }
+ // }
+ // if (!hasWildcardTransition) {
+ // // if there is no others we create one for deactivating everything
+ // stream << " when others =>" << std::endl;
+ // for (size_t j = 0; j < choices.size(); j++) {
+ // Element<std::string> tmp_t(choices[j]);
+ // stream << " " << ATTR(tmp_t, "id") << "_sig <= '0';" << std::endl;
+ // }
+ // }
+ // stream << " end case;" << std::endl;
+ // //TODO umkehren oder other abfangen
+ // //stream << " when others =>" << std::endl;
+ // //stream << " next_state <= current_state;" << std::endl;
+ //
+ // stream << " else" << std::endl;
+ // // no enabled event ? disable all transitions (looks like we have to wait)
+ // for (size_t j = 0; j < choices.size(); j++) {
+ // Element<std::string> transition(choices[j]);
+ // stream << " " << ATTR(transition, "id") << "_sig <= '0';" << std::endl;
+ // }
+ // stream << " end if;" << std::endl;
+ // stream << " end if;" << std::endl;
+ // stream << std::endl;
+ // }
+ // // write next state calculation in buffer for later use
+ // nextStateBuffer << ATTR(state, "id") << "_next <= ( ( '0'";
+ // std::string seperator = " or ";
+ // for (size_t j = 0; j < incommingTransitions.size(); j++) {
+ // nextStateBuffer << seperator
+ // << ATTR(incommingTransitions[j], "id") << "_sig";
+ // }
+ // nextStateBuffer << " ) or ";
+ // nextStateBuffer << "( ( not ( '0'";
+ // seperator = " or ";
+ // for (size_t j = 0; j < choices.size(); j++) {
+ // nextStateBuffer << seperator
+ // << ATTR(choices[j], "id") << "_sig";
+ // }
+ // nextStateBuffer << " ) ) and " << ATTR(state, "id")
+ // << "_curr ));" << std::endl;
+ // }
+ // stream << "end process;" << std::endl;
+ // stream << std::endl;
+ // // write outgoing transition buffer
+ // stream << nextStateBuffer.str() << std::endl;
+
+ // updater for current state
+ stream << "-- update current state" << std::endl;
+ stream << "state_proc: process(clk, rst, stall)" << std::endl;
stream << "begin" << std::endl;
+ stream << " if rst = '1' then" << std::endl;
- std::stringstream nextStateBuffer;
for (size_t i = 0; i < _states.size(); i++) {
Element<std::string> state(_states[i]);
+ stream << " is_active_" << toStr(i) << "_sig <= " << "'0';" << std::endl;
+ }
- // calculate event choices
- // _transitions is sorted in Postfix order
- // by stating with smalest index the most important
- // will be written first
- std::vector< Element<std::string> > choices;
- std::string spntaneous_trans_sig = "";
- for (size_t j = 0; j < _transitions.size(); j++) {
- Element<std::string> transition(_transitions[j]);
- if (ATTR_CAST(transition.getParentNode(), "id") == ATTR(state, "id")) {
- choices.push_back(transition);
- if (ATTR(transition, "event") == CONST_TRANS_SPONTANIOUS) {
- spntaneous_trans_sig = ATTR(transition, "id");
- // FIXME hofully there are just single spntaneous transitions allowed
- // else we have to handle this
- }
- }
- }
-
- // calculate incomming transitions (for later use)
- std::vector< Element<std::string> > incommingTransitions;
- for (size_t j = 0; j < _transitions.size(); j++) {
- Element<std::string> transition(_transitions[j]);
- if (ATTR_CAST(transition, "target") == ATTR(state, "id")) {
- incommingTransitions.push_back(transition);
- }
- }
-
- if (choices.size() > 0) {// if no outgoing transitions (maybe final state :D) we don't write anything
-
- stream << " if ( " << ATTR(state, "id") << " = '1' ) then" << std::endl;
- stream << " if ( transition_spntaneous_en = '1' ) then" << std::endl;
- // enable spntaneous transition (if any) and disable all other
- for (size_t j = 0; j < choices.size(); j++) {
- Element<std::string> transition(choices[j]);
- if (ATTR(transition, "id") == spntaneous_trans_sig) {
- stream << " " << ATTR(transition, "id") << "_sig <= '1';" << std::endl;
- } else {
- stream << " " << ATTR(transition, "id") << "_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;
- stream << " elsif ( next_event_re = '1' ) then" << std::endl;
- // if no spntaneous transition enables, look at events
- // since there is just one event at a time, we use case statement
- // to check transitions matching in postfix order
- // FIXME hopefully there is just one transition per state and event at a time
- stream << " case next_event is" << std::endl;
- bool hasWildcardTransition = false;
- for (size_t j = 0; j < choices.size(); j++) {
- Element<std::string> transition(choices[j]);
- std::string eventName = ATTR(transition, "event");
- if (eventName == CONST_EVENT_ANY) {
- eventName = "others";
- hasWildcardTransition = true;
- }
- stream << " when " << eventName << " =>" << std::endl;
- // activate transition and deactivete others
- for (size_t k = 0; k < choices.size(); k++) {
- Element<std::string> tmp_t(choices[k]);
- if (ATTR(tmp_t, "event") == ATTR(transition, "event")) {
- stream << " " << ATTR(tmp_t, "id") << "_sig <= '1';" << std::endl;
- } else {
- stream << " " << ATTR(tmp_t, "id") << "_sig <= '0';" << std::endl;
- }
- }
- }
- if (!hasWildcardTransition) {
- // if there is no others we create one for deactivating everything
- stream << " when others =>" << std::endl;
- for (size_t j = 0; j < choices.size(); j++) {
- Element<std::string> tmp_t(choices[j]);
- stream << " " << ATTR(tmp_t, "id") << "_sig <= '0';" << std::endl;
- }
- }
- stream << " end case;" << std::endl;
- //TODO umkehren oder other abfangen
- //stream << " when others =>" << std::endl;
- //stream << " next_state <= current_state;" << std::endl;
-
- stream << " else" << std::endl;
- // no enabled event ? disable all transitions (looks like we have to wait)
- for (size_t j = 0; j < choices.size(); j++) {
- Element<std::string> transition(choices[j]);
- stream << " " << ATTR(transition, "id") << "_sig <= '0';" << std::endl;
- }
- stream << " end if;" << std::endl;
- stream << " end if;" << std::endl;
- stream << std::endl;
- }
- // write next state calculation in buffer for later use
- nextStateBuffer << ATTR(state, "id") << "_next <= ( ( '0'";
- std::string seperator = " or ";
- for (size_t j = 0; j < incommingTransitions.size(); j++) {
- nextStateBuffer << seperator
- << ATTR(incommingTransitions[j], "id") << "_sig";
- }
- nextStateBuffer << " ) or ";
- nextStateBuffer << "( ( not ( '0'";
- seperator = " or ";
- for (size_t j = 0; j < choices.size(); j++) {
- nextStateBuffer << seperator
- << ATTR(choices[j], "id") << "_sig";
- }
- nextStateBuffer << " ) ) and " << ATTR(state, "id")
- << "_curr ));" << std::endl;
+ for (size_t i = 0; i < _states.size(); i++) {
+ Element<std::string> state(_states[i]);
+ stream << " is_active_" << toStr(i) << "_sig <= " << "is_active_np1_" << toStr(i) << "_sig;" << std::endl;
}
- stream << "end process;" << std::endl;
- stream << std::endl;
- // write outgoing transition buffer
- stream << nextStateBuffer.str() << std::endl;
- // updater for current state
- stream << "-- update current state" << std::endl;
- stream << "state_proc: process(clk, rst, stall)" << std::endl;
- stream << "begin" << std::endl;
- stream << " if rst = '1' then" << std::endl;
- stream << " current_state <= (others => '0');" << std::endl;
-// stream << " " << _initState << "_curr <= '1';" << std::endl;
- stream << " elsif (rising_edge(clk) and stall = '0') then" << std::endl;
- stream << " current_state <= next_state;" << std::endl;
stream << " end if;" << std::endl;
stream << "end process;" << std::endl;
stream << std::endl;
diff --git a/src/uscxml/transform/ChartToVHDL.h b/src/uscxml/transform/ChartToVHDL.h
index 84d8f7f..a63cba2 100644
--- a/src/uscxml/transform/ChartToVHDL.h
+++ b/src/uscxml/transform/ChartToVHDL.h
@@ -180,6 +180,11 @@ protected:
void writeFSM(std::ostream& stream);
void writeTransitionSet(std::ostream & stream);
+ void writeActiveStateNplusOne(std::ostream & stream);
+ void writeDefaultCompletions(std::ostream & stream);
+ void writeCompleteEntrySet(std::ostream & stream);
+
+ void writeTestbench(std::ostream & stream);
Trie _eventTrie;
@@ -191,4 +196,4 @@ private:
}
-#endif /* end of include guard: FSMTOCPP_H_201672B0 */
+#endif /* end of include guard: FSMTOCPP_H_201672B0 */ \ No newline at end of file