diff options
author | Stefan Radomski <sradomski@mintwerk.de> | 2016-02-29 22:32:08 (GMT) |
---|---|---|
committer | Stefan Radomski <sradomski@mintwerk.de> | 2016-02-29 22:32:08 (GMT) |
commit | 1bdf058cf07cfd53885c81af4c0c943d3baac4c6 (patch) | |
tree | d66e529bf6a4315966f6b560c16f3d084b887f2e /src | |
parent | 938bc217b59c6f0a23f7e27baf897cdd9890ae98 (diff) | |
download | uscxml-1bdf058cf07cfd53885c81af4c0c943d3baac4c6.zip uscxml-1bdf058cf07cfd53885c81af4c0c943d3baac4c6.tar.gz uscxml-1bdf058cf07cfd53885c81af4c0c943d3baac4c6.tar.bz2 |
More work on VHDL
Diffstat (limited to 'src')
-rw-r--r-- | src/uscxml/transform/ChartToC.cpp | 28 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToVHDL.cpp | 490 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToVHDL.h | 7 |
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 |