From 5e1477773b2dbcd1769fec3e52b61c02668e3034 Mon Sep 17 00:00:00 2001 From: juehv Date: Tue, 1 Mar 2016 13:49:30 +0100 Subject: clean up signals, add states to interface --- src/uscxml/transform/ChartToVHDL.cpp | 1840 +++++++++++++++++----------------- 1 file changed, 925 insertions(+), 915 deletions(-) diff --git a/src/uscxml/transform/ChartToVHDL.cpp b/src/uscxml/transform/ChartToVHDL.cpp index d3abcf1..b17bc84 100644 --- a/src/uscxml/transform/ChartToVHDL.cpp +++ b/src/uscxml/transform/ChartToVHDL.cpp @@ -37,944 +37,954 @@ namespace uscxml { -using namespace Arabica::DOM; -using namespace Arabica::XPath; - -Transformer ChartToVHDL::transform(const Interpreter& other) { - ChartToVHDL* c2c = new ChartToVHDL(other); - - return boost::shared_ptr(c2c); -} - -ChartToVHDL::ChartToVHDL(const Interpreter& other) : ChartToC(other), _eventTrie(".") { -} - -ChartToVHDL::~ChartToVHDL() { -} - -void ChartToVHDL::checkDocument() { - // filter unsupported stuff - Arabica::XPath::NodeSet unsupported; - - std::set elements; - elements.insert(_nsInfo.xmlNSPrefix + "datamodel"); - elements.insert(_nsInfo.xmlNSPrefix + "data"); - elements.insert(_nsInfo.xmlNSPrefix + "assign"); - elements.insert(_nsInfo.xmlNSPrefix + "donedata"); - elements.insert(_nsInfo.xmlNSPrefix + "content"); - elements.insert(_nsInfo.xmlNSPrefix + "param"); - elements.insert(_nsInfo.xmlNSPrefix + "script"); - - elements.insert(_nsInfo.xmlNSPrefix + "parallel"); - elements.insert(_nsInfo.xmlNSPrefix + "history"); - - elements.insert(_nsInfo.xmlNSPrefix + "if"); // implicit elseif und else - elements.insert(_nsInfo.xmlNSPrefix + "foreach"); - elements.insert(_nsInfo.xmlNSPrefix + "send"); - elements.insert(_nsInfo.xmlNSPrefix + "cancel"); - elements.insert(_nsInfo.xmlNSPrefix + "invoke"); - elements.insert(_nsInfo.xmlNSPrefix + "finalize"); - unsupported = DOMUtils::inDocumentOrder(elements, _scxml); - - std::stringstream ss; - if (unsupported.size() > 0) { - for (size_t i = 0; i < unsupported.size(); i++) { - ss << " " << DOMUtils::xPathForNode(unsupported[i]) << " unsupported" << std::endl; - } - throw std::runtime_error("Unsupported elements found:\n" + ss.str()); - } - - elements.clear(); - elements.insert(_nsInfo.xmlNSPrefix + "transition"); - unsupported = DOMUtils::inDocumentOrder(elements, _scxml); - - for (size_t i = 0; i < unsupported.size(); i++) { - Element transition(unsupported[i]); - 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 - NodeSet withEvent; - withEvent.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "raise", _scxml, true)); - withEvent.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "send", _scxml, true)); - withEvent.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true)); - - for (size_t i = 0; i < withEvent.size(); i++) { - if (HAS_ATTR_CAST(withEvent[i], "event")) { - // TODO: tokenize! - if (ATTR_CAST(withEvent[i], "event") != "*") - _eventTrie.addWord(ATTR_CAST(withEvent[i], "event")); - } - } -} - -void ChartToVHDL::writeTo(std::ostream& stream) { - // same preparations as the C transformation - prepare(); - - // 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) { - - // create hardware top level - stream << "-- FSM Logic" << std::endl; - writeIncludes(stream); - stream << "entity 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 fsm_scxml; " << std::endl; - - stream << std::endl; - stream << std::endl; - stream << "architecture behavioral of fsm_scxml is " << std::endl; - stream << std::endl; - - // Add signals and components - writeSignals(stream); - - stream << std::endl; - stream << "begin" << std::endl; - stream << std::endl; - // signal mapping - writeModuleInstantiation(stream); - - // write fsm architecture - writeNextStateLogic(stream); - - writeOptimalTransitionSetSelection(stream); - writeExitSet(stream); - writeEntrySet(stream); - writeDefaultCompletions(stream); - writeCompleteEntrySet(stream); - writeActiveStateNplusOne(stream); - - // writeOutputLogic(stream); - writeErrorHandler(stream); - - - stream << std::endl; - stream << "end behavioral; " << std::endl; - stream << "-- END FSM Logic" << std::endl; -} + using namespace Arabica::DOM; + using namespace Arabica::XPath; + + Transformer ChartToVHDL::transform(const Interpreter& other) { + ChartToVHDL* c2c = new ChartToVHDL(other); + + return boost::shared_ptr(c2c); + } + + ChartToVHDL::ChartToVHDL(const Interpreter& other) : ChartToC(other), _eventTrie(".") { + } + + ChartToVHDL::~ChartToVHDL() { + } + + void ChartToVHDL::checkDocument() { + // filter unsupported stuff + Arabica::XPath::NodeSet unsupported; + + std::set elements; + elements.insert(_nsInfo.xmlNSPrefix + "datamodel"); + elements.insert(_nsInfo.xmlNSPrefix + "data"); + elements.insert(_nsInfo.xmlNSPrefix + "assign"); + elements.insert(_nsInfo.xmlNSPrefix + "donedata"); + elements.insert(_nsInfo.xmlNSPrefix + "content"); + elements.insert(_nsInfo.xmlNSPrefix + "param"); + elements.insert(_nsInfo.xmlNSPrefix + "script"); + + elements.insert(_nsInfo.xmlNSPrefix + "parallel"); + elements.insert(_nsInfo.xmlNSPrefix + "history"); + + elements.insert(_nsInfo.xmlNSPrefix + "if"); // implicit elseif und else + elements.insert(_nsInfo.xmlNSPrefix + "foreach"); + elements.insert(_nsInfo.xmlNSPrefix + "send"); + elements.insert(_nsInfo.xmlNSPrefix + "cancel"); + elements.insert(_nsInfo.xmlNSPrefix + "invoke"); + elements.insert(_nsInfo.xmlNSPrefix + "finalize"); + unsupported = DOMUtils::inDocumentOrder(elements, _scxml); + + std::stringstream ss; + if (unsupported.size() > 0) { + for (size_t i = 0; i < unsupported.size(); i++) { + ss << " " << DOMUtils::xPathForNode(unsupported[i]) << " unsupported" << std::endl; + } + throw std::runtime_error("Unsupported elements found:\n" + ss.str()); + } + + elements.clear(); + elements.insert(_nsInfo.xmlNSPrefix + "transition"); + unsupported = DOMUtils::inDocumentOrder(elements, _scxml); + + for (size_t i = 0; i < unsupported.size(); i++) { + Element transition(unsupported[i]); + 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 + NodeSet withEvent; + withEvent.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "raise", _scxml, true)); + withEvent.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "send", _scxml, true)); + withEvent.push_back(DOMUtils::filterChildElements(_nsInfo.xmlNSPrefix + "transition", _scxml, true)); + + for (size_t i = 0; i < withEvent.size(); i++) { + if (HAS_ATTR_CAST(withEvent[i], "event")) { + // TODO: tokenize! + if (ATTR_CAST(withEvent[i], "event") != "*") + _eventTrie.addWord(ATTR_CAST(withEvent[i], "event")); + } + } + } + + void ChartToVHDL::writeTo(std::ostream& stream) { + // same preparations as the C transformation + prepare(); + + // 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 << " error_o :out std_logic;" << std::endl; + + for (size_t i = 0; i < _states.size(); i++) { + Element state(_states[i]); + 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 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 << " error_o => error_o," << std::endl; + + for (size_t i = 0; i < _states.size(); i++) { + Element state(_states[i]); + stream << " state_active_" << ATTR(state, "documentOrder") << "_o => open," << std::endl; + } + + stream << " completed_o => completed_o" << std::endl; + stream << " );" << std::endl; + stream << " " << std::endl; + stream << "end architecture;" << std::endl; + stream << "-- END TESTBENCH" << std::endl; + + } + + void ChartToVHDL::writeFSM(std::ostream & stream) { + + // create hardware top level + stream << "-- FSM Logic" << std::endl; + writeIncludes(stream); + stream << "entity 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 << " error_o :out std_logic;" << std::endl; + + for (size_t i = 0; i < _states.size(); i++) { + Element state(_states[i]); + 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 fsm_scxml; " << std::endl; + + stream << std::endl; + stream << std::endl; + stream << "architecture behavioral of fsm_scxml is " << std::endl; + stream << std::endl; + + // Add signals and components + writeSignals(stream); + + stream << std::endl; + stream << "begin" << std::endl; + stream << std::endl; + // signal mapping + writeModuleInstantiation(stream); + + // write fsm architecture + writeNextStateLogic(stream); + + writeOptimalTransitionSetSelection(stream); + writeExitSet(stream); + writeEntrySet(stream); + writeDefaultCompletions(stream); + writeCompleteEntrySet(stream); + writeActiveStateNplusOne(stream); + + writeErrorHandler(stream); + writeOutputLogic(stream); + + + stream << std::endl; + stream << "end behavioral; " << std::endl; + stream << "-- END FSM Logic" << std::endl; + } #if 0 -void ChartToVHDL::writeTopDown(std::ostream & stream) { - // create hardware top level - stream << "-- top level" << std::endl; - writeIncludes(stream); - stream << "entity top_scxml is" << std::endl; - stream << "port(" << std::endl; - stream << " --inputs" << std::endl; - stream << " clk\t:in std_logic;" << std::endl; - stream << " rst\t:in std_logic;" << std::endl; - stream << " --outputs" << std::endl; - stream << " completed_o\t:out std_logic;" << std::endl; - stream << " result_o\t:out std_logic;" << std::endl; - stream << " error_o\t:out std_logic" << std::endl; - stream << ");" << std::endl; - stream << "end top_scxml; " << std::endl; - stream << std::endl; - stream << std::endl; - stream << "architecture behavioral of top_scxml is " << std::endl; - stream << std::endl; - - // Add signals and components - writeSignals(stream); - - stream << std::endl; - stream << "begin" << std::endl; - stream << std::endl; - // signal mapping - writeModuleInstantiation(stream); - - // write fsm architecture - writeNextStateLogic(stream); - writeOutputLogic(stream); - - stream << std::endl; - stream << "end behavioral; " << std::endl; -} + void ChartToVHDL::writeTopDown(std::ostream & stream) { + // create hardware top level + stream << "-- top level" << std::endl; + writeIncludes(stream); + stream << "entity top_scxml is" << std::endl; + stream << "port(" << std::endl; + stream << " --inputs" << std::endl; + stream << " clk\t:in std_logic;" << std::endl; + stream << " rst\t:in std_logic;" << std::endl; + stream << " --outputs" << std::endl; + stream << " completed_o\t:out std_logic;" << std::endl; + stream << " result_o\t:out std_logic;" << std::endl; + stream << " error_o\t:out std_logic" << std::endl; + stream << ");" << std::endl; + stream << "end top_scxml; " << std::endl; + stream << std::endl; + stream << std::endl; + stream << "architecture behavioral of top_scxml is " << std::endl; + stream << std::endl; + + // Add signals and components + writeSignals(stream); + + stream << std::endl; + stream << "begin" << std::endl; + stream << std::endl; + // signal mapping + writeModuleInstantiation(stream); + + // write fsm architecture + writeNextStateLogic(stream); + writeOutputLogic(stream); + + stream << std::endl; + stream << "end behavioral; " << std::endl; + } #endif -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; - - //TODO complete - // create event type - stream << " type event_type is ("; - seperator = ""; - // for (size_t i = 0; i < _events.size(); i++) { - // stream << seperator; - // stream << _events[i]; - // seperator = ", "; - // } - if (seperator.size() == 0) { - stream << "NO_EVENTS"; - } - stream << ");" << std::endl; - - stream << "end machine" << _md5 << ";" << std::endl; - stream << std::endl; - stream << "-- END needed global types" << std::endl; -} - -void ChartToVHDL::writeIncludes(std::ostream & stream) { - // Add controler specific stuff here - stream << "library IEEE;" << std::endl; - stream << "use IEEE.std_logic_1164.all;" << std::endl; - stream << "use work.machine" << _md5 << ".all;" << std::endl; - stream << std::endl; -} - -void ChartToVHDL::writeFiFo(std::ostream & stream) { - // taken from: http://www.deathbylogic.com/2013/07/vhdl-standard-fifo/ - // alternativly take fifo logic for a ram device: http://www.eng.auburn.edu/~strouce/class/elec4200/vhdlmods.pdf - stream << "-- standard FIFO buffer" << std::endl; - writeIncludes(stream); - stream << "" << std::endl; - stream << "entity std_fifo is" << std::endl; - stream << "generic (" << std::endl; - stream << " constant FIFO_DEPTH : positive := 256" << std::endl; - stream << ");" << std::endl; - stream << "port ( " << std::endl; - stream << " clk : in std_logic;" << std::endl; - stream << " rst : in std_logic;" << std::endl; - stream << " write_en : in std_logic;" << std::endl; - stream << " read_en : in std_logic;" << std::endl; - stream << " data_in : in event_type;" << std::endl; - stream << " data_out : out event_type;" << std::endl; - stream << " empty : out std_logic;" << std::endl; - stream << " full : out std_logic" << std::endl; - stream << ");" << std::endl; - stream << "end std_fifo;" << std::endl; - stream << "" << std::endl; - stream << "architecture behavioral of std_fifo is" << std::endl; - stream << "begin" << std::endl; - stream << "-- Memory Pointer Process" << std::endl; - stream << "fifo_proc : process (clk)" << std::endl; - stream << " type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of event_type;" << std::endl; - stream << " variable Memory : FIFO_Memory;" << std::endl; - stream << "" << std::endl; - stream << " variable Head : natural range 0 to FIFO_DEPTH - 1;" << std::endl; - stream << " variable Tail : natural range 0 to FIFO_DEPTH - 1;" << std::endl; - stream << "" << std::endl; - stream << " variable Looped : boolean;" << std::endl; - stream << "begin" << std::endl; - stream << " if rising_edge(clk) then" << std::endl; - stream << " if rst = '1' then" << std::endl; - stream << " Head := 0;" << std::endl; - stream << " Tail := 0;" << std::endl; - stream << "" << std::endl; - stream << " Looped := false;" << std::endl; - stream << "" << std::endl; - stream << " full <= '0';" << std::endl; - stream << " empty <= '1';" << std::endl; - stream << " else" << std::endl; - stream << " if (read_en = '1') then" << std::endl; - stream << " if ((Looped = true) or (Head /= Tail)) then" << std::endl; - stream << " -- Update data output" << std::endl; - stream << " data_out <= Memory(Tail);" << std::endl; - stream << " " << std::endl; - stream << " -- Update Tail pointer as needed" << std::endl; - stream << " if (Tail = FIFO_DEPTH - 1) then" << std::endl; - stream << " Tail := 0;" << std::endl; - stream << " " << std::endl; - stream << " Looped := false;" << std::endl; - stream << " else" << std::endl; - stream << " Tail := Tail + 1;" << std::endl; - stream << " end if;" << std::endl; - stream << "" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << "" << std::endl; - stream << " if (write_en = '1') then" << std::endl; - stream << " if ((Looped = false) or (Head /= Tail)) then" << std::endl; - stream << " -- Write Data to Memory" << std::endl; - stream << " Memory(Head) := data_in;" << std::endl; - stream << " " << std::endl; - stream << " -- Increment Head pointer as needed" << std::endl; - stream << " if (Head = FIFO_DEPTH - 1) then" << std::endl; - stream << " Head := 0;" << std::endl; - stream << " " << std::endl; - stream << " Looped := true;" << std::endl; - stream << " else" << std::endl; - stream << " Head := Head + 1;" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << "" << std::endl; - stream << " -- Update empty and full flags" << std::endl; - stream << " if (Head = Tail) then" << std::endl; - stream << " if Looped then" << std::endl; - stream << " full <= '1';" << std::endl; - stream << " else" << std::endl; - stream << " empty <= '1';" << std::endl; - stream << " end if;" << std::endl; - stream << " else" << std::endl; - stream << " empty <= '0';" << std::endl; - stream << " full <= '0';" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << " end if;" << std::endl; - stream << "end process;" << std::endl; - stream << "" << std::endl; - stream << "end behavioral;" << std::endl; - stream << "-- END standard FIFO buffer" << std::endl; -} - -void ChartToVHDL::writeSignals(std::ostream & stream) { - // create needed internal signals - 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; - - for (size_t i = 0; i < _states.size(); i++) { - Element 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; - stream << "signal state_active_" << ATTR(state, "documentOrder") << "_sig : std_logic;" << std::endl; - stream << "signal default_completion_" << ATTR(state, "documentOrder") << "_sig : std_logic;" << std::endl; - } - - stream << "-- transition signals" << std::endl; - stream << "signal spontaneous_en : std_logic;" << std::endl; - - for (size_t i = 0; i < _transitions.size(); i++) { - Element transition(_transitions[i]); - stream << "signal in_optimal_transition_set_" << ATTR(transition, "postFixOrder") << "_sig : std_logic;" - << std::endl; - } - - stream << std::endl; - stream << "-- event signals" << std::endl; - stream << "signal int_event_write_en : std_logic;" << std::endl; - stream << "signal int_event_read_en : std_logic;" << std::endl; - stream << "signal int_event_empty : std_logic;" << std::endl; - stream << "signal int_event_input : event_type;" << std::endl; - stream << "signal int_event_output : event_type;" << std::endl; - stream << "signal next_event_re : std_logic;" << std::endl; - stream << "signal next_event : event_type;" << std::endl; - stream << "signal event_consumed : std_logic;" << std::endl; - stream << std::endl; - - std::list eventNames = _eventTrie.getWordsWithPrefix(""); - for (std::list::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - stream << "signal event_" << eventNameEscape((*eventIter)->value) << "_sig : std_logic;" << std::endl; - } - // _eventTrie.dump(); - - - stream << std::endl; - stream << "-- error signals" << std::endl; - stream << "signal reg_error_out : std_logic;" << std::endl; - stream << "signal error_full_int_event_fifo : std_logic;" << std::endl; - stream << std::endl; - - // add needed components - stream << "-- event FIFO" << std::endl; - stream << "component std_fifo is" << std::endl; - stream << "port ( " << std::endl; - stream << " clk : in std_logic;" << std::endl; - stream << " rst : in std_logic;" << std::endl; - stream << " write_en : in std_logic;" << std::endl; - stream << " read_en : in std_logic;" << std::endl; - stream << " data_in : in event_type;" << std::endl; - stream << " data_out : out event_type;" << std::endl; - stream << " empty : out std_logic;" << std::endl; - stream << " full : out std_logic" << std::endl; // we calculate how much we need - stream << ");" << std::endl; - stream << "end component;" << std::endl; - stream << std::endl; -} - -void ChartToVHDL::writeModuleInstantiation(std::ostream & stream) { - // tmp mapping for events - stream << "error_o <= reg_error_out; " << std::endl; - stream << "stall <= not en; " << std::endl; - stream << std::endl; - - stream << "next_event_re <= not int_event_empty and not stall; " << std::endl; - stream << "next_event <= int_event_output; " << std::endl; - stream << "int_event_write_en <= next_event_en_i; " << std::endl; - stream << "int_event_input <= next_event_i; " << std::endl; - stream << "int_event_read_en <= not spontaneous_en and not stall; " << std::endl; - stream << std::endl; - - // instantiate event fifo - stream << "int_event_fifo : component std_fifo " << std::endl; - stream << "port map ( " << std::endl; - stream << " clk => clk," << std::endl; - stream << " rst => rst," << std::endl; - stream << " write_en => int_event_write_en," << std::endl; - stream << " read_en => int_event_read_en," << std::endl; - stream << " data_in => int_event_input," << std::endl; - stream << " data_out => int_event_output," << std::endl; - stream << " empty => int_event_empty," << std::endl; - stream << " full => error_full_int_event_fifo" << std::endl; // we calculate how much we need - stream << ");" << std::endl; - stream << std::endl; -} - -void ChartToVHDL::writeErrorHandler(std::ostream & stream) { - // sets error output signal if an error occures somewhere - stream << "-- error handler" << std::endl; - stream << "-- sets error output signal if an error occures somewhere" << std::endl; - stream << "error_handler : process (clk, rst) " << std::endl; - stream << "begin" << std::endl; - stream << " if rst = '1' then" << std::endl; - stream << " reg_error_out <= '0';" << std::endl; - stream << " elsif rising_edge(clk) then" << std::endl; - stream << " reg_error_out <= error_full_int_event_fifo;" << std::endl; - stream << " end if;" << std::endl; - stream << "end process;" << std::endl; - stream << std::endl; -} - -std::string ChartToVHDL::eventNameEscape(const std::string& eventName) { - std::string escaped = escape(eventName); - boost::replace_all(escaped, ".", "_"); - 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++) { - Element transition(_transitions[i]); - std::string conflicts = ATTR(transition, "conflictBools"); - - - VContainer nameMatchers = VOR; - if (HAS_ATTR(transition, "event")) { - std::list eventDescs = tokenize(ATTR(transition, "event")); - for (std::list::iterator descIter = eventDescs.begin(); descIter != eventDescs.end(); descIter++) { - std::list eventNames = _eventTrie.getWordsWithPrefix((*descIter) == "*" ? "" : *descIter); - for (std::list::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { - *nameMatchers += VLINE("event_" + eventNameEscape((*eventIter)->value) + "_sig"); - } - } - } else { - *nameMatchers += VLINE("'1'"); - } - - VContainer conflicters = VOR; - for (size_t j = 0; j < i; j++) { - if (conflicts[j] == '1') { - *conflicters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig"); - } - } - - VBranch* tree = (VASSIGN, - VLINE("in_optimal_transition_set_" + ATTR(transition, "postFixOrder") + "_sig"), - (VAND, - (HAS_ATTR(transition, "event") - ? (VNOT, VLINE("spontaneous_en")) - : (VNOP, VLINE("spontaneous_en"))), - VLINE("state_active_" + ATTR(transition, "source") + "_sig"), - nameMatchers, - (VNOT, conflicters))); - - tree->print(stream); - stream << ";" << std::endl; - } -} - -void ChartToVHDL::writeExitSet(std::ostream & stream) { - stream << "-- exit set selection" << std::endl; - - for (size_t i = 0; i < _states.size(); i++) { - Element state(_states[i]); - std::string completion = ATTR(state, "completionBools"); - std::string ancestors = ATTR(state, "ancBools"); - std::string children = ATTR(state, "childBools"); - std::string parent = ATTR(state, "parent"); - - VContainer exitsetters = VOR; - for (size_t j = 0; j < _transitions.size(); j++) { - Element transition(_transitions[j]); - std::string exitSet = ATTR(transition, "exitSetBools"); - if (exitSet[i] == '1') { - *exitsetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig "); - } - } - - VBranch* tree = (VASSIGN, - VLINE("in_exit_set_" + toStr(i) + "_sig"), - (VAND, - VLINE("state_active_" + toStr(i) + "_sig"), - exitsetters)); - - tree->print(stream); - stream << ";" << std::endl; - } -} - -void ChartToVHDL::writeEntrySet(std::ostream & stream) { - stream << "-- entry set selection" << std::endl; - - 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, NodeSet > completions; - for (size_t i = 0; i < _states.size(); i++) { - Element 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(_states[j])].push_back(state); - } - } - } - - std::map, NodeSet >::const_iterator complIter = completions.begin(); - while(complIter != completions.end()) { - const Element& state(complIter->first); - const NodeSet& 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); - - tree->print(stream); - stream << ";" << std::endl; - - complIter++; - } - - -} - -void ChartToVHDL::writeCompleteEntrySet(std::ostream & stream) { - stream << "-- complete entry set selection" << std::endl; - - for (size_t i = 0; i < _states.size(); i++) { - Element state(_states[i]); - std::string completion = ATTR(state, "completionBools"); - std::string ancestors = ATTR(state, "ancBools"); - std::string children = ATTR(state, "childBools"); - std::string parent = ATTR(state, "parent"); - - VContainer optimalEntrysetters = VOR; - for (size_t j = 0; j < _transitions.size(); j++) { - Element transition(_transitions[j]); - std::string targetSet = ATTR(transition, "targetBools"); - if (targetSet[i] == '1') { - *optimalEntrysetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig"); - } - } - - VContainer completeEntrysetters = VOR; - if (isCompound(state)) { - for (size_t j = 0; j < _states.size(); j++) { - if (children[j] != '1') - continue; - *completeEntrysetters += VLINE("in_complete_entry_set_up_" + toStr(j) + "_sig"); - } - } - - VBranch* tree = (VASSIGN, - VLINE("in_complete_entry_set_up_" + toStr(i) + "_sig"), - optimalEntrysetters, - completeEntrysetters); - - tree->print(stream); - stream << ";" << std::endl; + 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; + + //TODO complete + // create event type + stream << " type event_type is ("; + seperator = ""; + // for (size_t i = 0; i < _events.size(); i++) { + // stream << seperator; + // stream << _events[i]; + // seperator = ", "; + // } + if (seperator.size() == 0) { + stream << "NO_EVENTS"; + } + stream << ");" << std::endl; + + stream << "end machine" << _md5 << ";" << std::endl; + stream << std::endl; + stream << "-- END needed global types" << std::endl; + } + + void ChartToVHDL::writeIncludes(std::ostream & stream) { + // Add controler specific stuff here + stream << "library IEEE;" << std::endl; + stream << "use IEEE.std_logic_1164.all;" << std::endl; + stream << "use work.machine" << _md5 << ".all;" << std::endl; + stream << std::endl; + } + + void ChartToVHDL::writeFiFo(std::ostream & stream) { + // taken from: http://www.deathbylogic.com/2013/07/vhdl-standard-fifo/ + // alternativly take fifo logic for a ram device: http://www.eng.auburn.edu/~strouce/class/elec4200/vhdlmods.pdf + stream << "-- standard FIFO buffer" << std::endl; + writeIncludes(stream); + stream << "" << std::endl; + stream << "entity std_fifo is" << std::endl; + stream << "generic (" << std::endl; + stream << " constant FIFO_DEPTH : positive := 256" << std::endl; + stream << ");" << std::endl; + stream << "port ( " << std::endl; + stream << " clk : in std_logic;" << std::endl; + stream << " rst : in std_logic;" << std::endl; + stream << " write_en : in std_logic;" << std::endl; + stream << " read_en : in std_logic;" << std::endl; + stream << " data_in : in event_type;" << std::endl; + stream << " data_out : out event_type;" << std::endl; + stream << " empty : out std_logic;" << std::endl; + stream << " full : out std_logic" << std::endl; + stream << ");" << std::endl; + stream << "end std_fifo;" << std::endl; + stream << "" << std::endl; + stream << "architecture behavioral of std_fifo is" << std::endl; + stream << "begin" << std::endl; + stream << "-- Memory Pointer Process" << std::endl; + stream << "fifo_proc : process (clk)" << std::endl; + stream << " type FIFO_Memory is array (0 to FIFO_DEPTH - 1) of event_type;" << std::endl; + stream << " variable Memory : FIFO_Memory;" << std::endl; + stream << "" << std::endl; + stream << " variable Head : natural range 0 to FIFO_DEPTH - 1;" << std::endl; + stream << " variable Tail : natural range 0 to FIFO_DEPTH - 1;" << std::endl; + stream << "" << std::endl; + stream << " variable Looped : boolean;" << std::endl; + stream << "begin" << std::endl; + stream << " if rising_edge(clk) then" << std::endl; + stream << " if rst = '1' then" << std::endl; + stream << " Head := 0;" << std::endl; + stream << " Tail := 0;" << std::endl; + stream << "" << std::endl; + stream << " Looped := false;" << std::endl; + stream << "" << std::endl; + stream << " full <= '0';" << std::endl; + stream << " empty <= '1';" << std::endl; + stream << " else" << std::endl; + stream << " if (read_en = '1') then" << std::endl; + stream << " if ((Looped = true) or (Head /= Tail)) then" << std::endl; + stream << " -- Update data output" << std::endl; + stream << " data_out <= Memory(Tail);" << std::endl; + stream << " " << std::endl; + stream << " -- Update Tail pointer as needed" << std::endl; + stream << " if (Tail = FIFO_DEPTH - 1) then" << std::endl; + stream << " Tail := 0;" << std::endl; + stream << " " << std::endl; + stream << " Looped := false;" << std::endl; + stream << " else" << std::endl; + stream << " Tail := Tail + 1;" << std::endl; + stream << " end if;" << std::endl; + stream << "" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << "" << std::endl; + stream << " if (write_en = '1') then" << std::endl; + stream << " if ((Looped = false) or (Head /= Tail)) then" << std::endl; + stream << " -- Write Data to Memory" << std::endl; + stream << " Memory(Head) := data_in;" << std::endl; + stream << " " << std::endl; + stream << " -- Increment Head pointer as needed" << std::endl; + stream << " if (Head = FIFO_DEPTH - 1) then" << std::endl; + stream << " Head := 0;" << std::endl; + stream << " " << std::endl; + stream << " Looped := true;" << std::endl; + stream << " else" << std::endl; + stream << " Head := Head + 1;" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << "" << std::endl; + stream << " -- Update empty and full flags" << std::endl; + stream << " if (Head = Tail) then" << std::endl; + stream << " if Looped then" << std::endl; + stream << " full <= '1';" << std::endl; + stream << " else" << std::endl; + stream << " empty <= '1';" << std::endl; + stream << " end if;" << std::endl; + stream << " else" << std::endl; + stream << " empty <= '0';" << std::endl; + stream << " full <= '0';" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << " end if;" << std::endl; + stream << "end process;" << std::endl; + stream << "" << std::endl; + stream << "end behavioral;" << std::endl; + stream << "-- END standard FIFO buffer" << std::endl; + } + + void ChartToVHDL::writeSignals(std::ostream & stream) { + // create needed internal signals + stream << "-- system signals" << std::endl; + stream << "signal stall : std_logic;" << std::endl; + stream << "signal completed_sig : 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; + + for (size_t i = 0; i < _states.size(); i++) { + Element state(_states[i]); + stream << "signal state_active_" << ATTR(state, "documentOrder") << "_sig : std_logic;" << std::endl; + stream << "signal state_next_" << ATTR(state, "documentOrder") << "_sig : std_logic;" << std::endl; + stream << "signal in_entry_set_" << ATTR(state, "documentOrder") << "_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; + stream << "signal default_completion_" << ATTR(state, "documentOrder") << "_sig : std_logic;" << std::endl; + } + + stream << "-- transition signals" << std::endl; + stream << "signal spontaneous_en : std_logic;" << std::endl; + + for (size_t i = 0; i < _transitions.size(); i++) { + Element transition(_transitions[i]); + stream << "signal in_optimal_transition_set_" << ATTR(transition, "postFixOrder") << "_sig : std_logic;" + << std::endl; + } + + stream << std::endl; + stream << "-- event signals" << std::endl; + stream << "signal int_event_write_en : std_logic;" << std::endl; + stream << "signal int_event_read_en : std_logic;" << std::endl; + stream << "signal int_event_empty : std_logic;" << std::endl; + stream << "signal int_event_input : event_type;" << std::endl; + stream << "signal int_event_output : event_type;" << std::endl; + stream << "signal next_event_re : std_logic;" << std::endl; + stream << "signal next_event : event_type;" << std::endl; + stream << "signal event_consumed : std_logic;" << std::endl; + stream << std::endl; + + std::list eventNames = _eventTrie.getWordsWithPrefix(""); + for (std::list::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { + stream << "signal event_" << eventNameEscape((*eventIter)->value) << "_sig : std_logic;" << std::endl; + } + // _eventTrie.dump(); + + + stream << std::endl; + stream << "-- error signals" << std::endl; + stream << "signal reg_error_out : std_logic;" << std::endl; + stream << "signal error_full_int_event_fifo : std_logic;" << std::endl; + stream << std::endl; + + // add needed components + stream << "-- event FIFO" << std::endl; + stream << "component std_fifo is" << std::endl; + stream << "port ( " << std::endl; + stream << " clk : in std_logic;" << std::endl; + stream << " rst : in std_logic;" << std::endl; + stream << " write_en : in std_logic;" << std::endl; + stream << " read_en : in std_logic;" << std::endl; + stream << " data_in : in event_type;" << std::endl; + stream << " data_out : out event_type;" << std::endl; + stream << " empty : out std_logic;" << std::endl; + stream << " full : out std_logic" << std::endl; // we calculate how much we need + stream << ");" << std::endl; + stream << "end component;" << std::endl; + stream << std::endl; + } + + void ChartToVHDL::writeModuleInstantiation(std::ostream & stream) { + // tmp mapping for events + stream << "error_o <= reg_error_out; " << std::endl; + stream << "stall <= not en or completed_sig; " << std::endl; + stream << std::endl; + + stream << "next_event_re <= not int_event_empty and not stall; " << std::endl; + stream << "next_event <= int_event_output; " << std::endl; + stream << "int_event_write_en <= next_event_en_i; " << std::endl; + stream << "int_event_input <= next_event_i; " << std::endl; + stream << "int_event_read_en <= not spontaneous_en and not stall; " << std::endl; + stream << std::endl; + + for (size_t i = 0; i < _states.size(); i++) { + Element state(_states[i]); + stream << " state_active_" << ATTR(state, "documentOrder") + << "_o <= state_active_" << ATTR(state, "documentOrder") + << "_sig;" << std::endl; + } + + stream << "completed_o <= completed_sig; " << std::endl; + + // instantiate event fifo + stream << "int_event_fifo : component std_fifo " << std::endl; + stream << "port map ( " << std::endl; + stream << " clk => clk," << std::endl; + stream << " rst => rst," << std::endl; + stream << " write_en => int_event_write_en," << std::endl; + stream << " read_en => int_event_read_en," << std::endl; + stream << " data_in => int_event_input," << std::endl; + stream << " data_out => int_event_output," << std::endl; + stream << " empty => int_event_empty," << std::endl; + stream << " full => error_full_int_event_fifo" << std::endl; // we calculate how much we need + stream << ");" << std::endl; + stream << std::endl; + } + + void ChartToVHDL::writeErrorHandler(std::ostream & stream) { + // sets error output signal if an error occures somewhere + stream << "-- error handler" << std::endl; + stream << "-- sets error output signal if an error occures somewhere" << std::endl; + stream << "error_handler : process (clk, rst) " << std::endl; + stream << "begin" << std::endl; + stream << " if rst = '1' then" << std::endl; + stream << " reg_error_out <= '0';" << std::endl; + stream << " elsif rising_edge(clk) then" << std::endl; + stream << " reg_error_out <= error_full_int_event_fifo;" << std::endl; + stream << " end if;" << std::endl; + stream << "end process;" << std::endl; + stream << std::endl; + } + + std::string ChartToVHDL::eventNameEscape(const std::string& eventName) { + std::string escaped = escape(eventName); + boost::replace_all(escaped, ".", "_"); + 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("state_next_" + toStr(i) + "_sig"), + (VAND, + VLINE("in_complete_entry_set_" + toStr(i) + "_sig"), + (VOR, VLINE("in_exit_set_" + toStr(i) + "_sig"), (VNOT, VLINE("state_active_" + toStr(i) + "_sig"))))); + + tree->print(stream); + stream << ";" << std::endl; + + } + } + + void ChartToVHDL::writeOptimalTransitionSetSelection(std::ostream & stream) { + stream << "-- optimal transition set selection" << std::endl; + for (size_t i = 0; i < _transitions.size(); i++) { + Element transition(_transitions[i]); + std::string conflicts = ATTR(transition, "conflictBools"); + + + VContainer nameMatchers = VOR; + if (HAS_ATTR(transition, "event")) { + std::list eventDescs = tokenize(ATTR(transition, "event")); + for (std::list::iterator descIter = eventDescs.begin(); descIter != eventDescs.end(); descIter++) { + std::list eventNames = _eventTrie.getWordsWithPrefix((*descIter) == "*" ? "" : *descIter); + for (std::list::iterator eventIter = eventNames.begin(); eventIter != eventNames.end(); eventIter++) { + *nameMatchers += VLINE("event_" + eventNameEscape((*eventIter)->value) + "_sig"); + } + } + } else { + *nameMatchers += VLINE("'1'"); + } + + VContainer conflicters = VOR; + for (size_t j = 0; j < i; j++) { + if (conflicts[j] == '1') { + *conflicters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig"); + } + } + + VBranch* tree = (VASSIGN, + VLINE("in_optimal_transition_set_" + ATTR(transition, "postFixOrder") + "_sig"), + (VAND, + (HAS_ATTR(transition, "event") + ? (VNOT, VLINE("spontaneous_en")) + : (VNOP, VLINE("spontaneous_en"))), + VLINE("state_active_" + ATTR(transition, "source") + "_sig"), + nameMatchers, + (VNOT, conflicters))); + + tree->print(stream); + stream << ";" << std::endl; + } + } + + void ChartToVHDL::writeExitSet(std::ostream & stream) { + stream << "-- exit set selection" << std::endl; + + for (size_t i = 0; i < _states.size(); i++) { + Element state(_states[i]); + std::string completion = ATTR(state, "completionBools"); + std::string ancestors = ATTR(state, "ancBools"); + std::string children = ATTR(state, "childBools"); + std::string parent = ATTR(state, "parent"); + + VContainer exitsetters = VOR; + for (size_t j = 0; j < _transitions.size(); j++) { + Element transition(_transitions[j]); + std::string exitSet = ATTR(transition, "exitSetBools"); + if (exitSet[i] == '1') { + *exitsetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig "); + } + } + + VBranch* tree = (VASSIGN, + VLINE("in_exit_set_" + toStr(i) + "_sig"), + (VAND, + VLINE("state_active_" + toStr(i) + "_sig"), + exitsetters)); + + tree->print(stream); + stream << ";" << std::endl; + } + } + + void ChartToVHDL::writeEntrySet(std::ostream & stream) { + stream << "-- entry set selection" << std::endl; + + 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("state_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, NodeSet > completions; + for (size_t i = 0; i < _states.size(); i++) { + Element 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(_states[j])].push_back(state); + } + } + } + + std::map, NodeSet >::const_iterator complIter = completions.begin(); + while (complIter != completions.end()) { + const Element& state(complIter->first); + const NodeSet& 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); + + tree->print(stream); + stream << ";" << std::endl; + + complIter++; + } + + + } + + void ChartToVHDL::writeCompleteEntrySet(std::ostream & stream) { + stream << "-- complete entry set selection" << std::endl; + + for (size_t i = 0; i < _states.size(); i++) { + Element state(_states[i]); + std::string completion = ATTR(state, "completionBools"); + std::string ancestors = ATTR(state, "ancBools"); + std::string children = ATTR(state, "childBools"); + std::string parent = ATTR(state, "parent"); + + VContainer optimalEntrysetters = VOR; + for (size_t j = 0; j < _transitions.size(); j++) { + Element transition(_transitions[j]); + std::string targetSet = ATTR(transition, "targetBools"); + if (targetSet[i] == '1') { + *optimalEntrysetters += VLINE("in_optimal_transition_set_" + toStr(j) + "_sig"); + } + } + + VContainer completeEntrysetters = VOR; + if (isCompound(state)) { + for (size_t j = 0; j < _states.size(); j++) { + if (children[j] != '1') + continue; + *completeEntrysetters += VLINE("in_complete_entry_set_up_" + toStr(j) + "_sig"); + } + } + + VBranch* tree = (VASSIGN, + VLINE("in_complete_entry_set_up_" + toStr(i) + "_sig"), + optimalEntrysetters, + completeEntrysetters); + + tree->print(stream); + stream << ";" << std::endl; #if 0 - stream << "in_complete_entry_set_up_" << toStr(i) << "_sig <= ('0'" << std::endl; - - for (size_t j = 0; j < _transitions.size(); j++) { - Element transition(_transitions[j]); - // std::cout << transition; - std::string targetSet = ATTR(transition, "targetBools"); - if (targetSet[i] == '1') { - stream << " or in_optimal_transition_set_" << toStr(j) << std::endl; - } - } - if (isCompound(state)) { - for (size_t j = 0; j < _states.size(); j++) { - if (children[j] != '1') - continue; - - stream << " or in_complete_entry_set_up_" << toStr(j) << "_sig" << std::endl; - } - - } - stream << ");" << std::endl; + stream << "in_complete_entry_set_up_" << toStr(i) << "_sig <= ('0'" << std::endl; + + for (size_t j = 0; j < _transitions.size(); j++) { + Element transition(_transitions[j]); + // std::cout << transition; + std::string targetSet = ATTR(transition, "targetBools"); + if (targetSet[i] == '1') { + stream << " or in_optimal_transition_set_" << toStr(j) << std::endl; + } + } + if (isCompound(state)) { + for (size_t j = 0; j < _states.size(); j++) { + if (children[j] != '1') + continue; + + stream << " or in_complete_entry_set_up_" << toStr(j) << "_sig" << std::endl; + } + + } + stream << ");" << std::endl; #endif - } + } - for (size_t i = 0; i < _states.size(); i++) { - Element state(_states[i]); - std::string completion = ATTR(state, "completionBools"); - std::string ancestors = ATTR(state, "ancBools"); - std::string children = ATTR(state, "childBools"); - std::string parent = ATTR(state, "parent"); + for (size_t i = 0; i < _states.size(); i++) { + Element state(_states[i]); + std::string completion = ATTR(state, "completionBools"); + std::string ancestors = ATTR(state, "ancBools"); + std::string children = ATTR(state, "childBools"); + std::string parent = ATTR(state, "parent"); - if (parent.size() == 0) { - continue; // TODO: FixMe - } + if (parent.size() == 0) { + continue; // TODO: FixMe + } - VContainer tmp1 = VAND; - if (isCompound(Element(_states[strTo(parent)]))) { - *tmp1 += VLINE("default_completion_" + toStr(parent) + "_sig"); + VContainer tmp1 = VAND; + if (isCompound(Element(_states[strTo(parent)]))) { + *tmp1 += VLINE("default_completion_" + toStr(parent) + "_sig"); - 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"))))); + for (size_t j = 0; j < _states.size(); j++) { + if (children[j] != '1') + continue; + *tmp1 += (VAND, + (VNOT, + (VAND, + VLINE("state_active" + toStr(j) + "_sig"), + (VNOT, + VLINE("in_exit_set_" + toStr(j) + "_sig"))))); - } + } - } + } - if (isParallel(Element(_states[strTo(parent)]))) { - *tmp1 += VLINE("in_complete_entry_set_" + toStr(parent) + "_sig"); - } + if (isParallel(Element(_states[strTo(parent)]))) { + *tmp1 += VLINE("in_complete_entry_set_" + toStr(parent) + "_sig"); + } - VBranch* tree = (VASSIGN, - VLINE("in_complete_entry_set_" + toStr(i) + "_sig"), tmp1); + VBranch* tree = (VASSIGN, + VLINE("in_complete_entry_set_" + toStr(i) + "_sig"), tmp1); - tree->print(stream); - stream << ";" << std::endl; + tree->print(stream); + stream << ";" << std::endl; #if 0 - stream << "in_complete_entry_set_" << toStr(i) << "_sig <= (in_complete_entry_set_up_" << toStr(i) << "_sig or (" << std::endl; + stream << "in_complete_entry_set_" << toStr(i) << "_sig <= (in_complete_entry_set_up_" << toStr(i) << "_sig or (" << std::endl; - if (isParallel(Element(_states[strTo(parent)]))) { - stream << " in_complete_entry_set_" << toStr(parent) << "_sig" << std::endl; - } else if (isCompound(Element(_states[strTo(parent)]))) { - stream << " default_completion_" << toStr(parent) << "_sig" << std::endl; + if (isParallel(Element(_states[strTo(parent)]))) { + stream << " in_complete_entry_set_" << toStr(parent) << "_sig" << std::endl; + } else if (isCompound(Element(_states[strTo(parent)]))) { + stream << " default_completion_" << toStr(parent) << "_sig" << std::endl; - for (size_t j = 0; j < _states.size(); j++) { - if (children[j] != '1') - continue; - stream << " and not (is_active" << toStr(j) << "_sig and not in_exit_set_" << toStr(j) << "_sig)" << std::endl; + for (size_t j = 0; j < _states.size(); j++) { + if (children[j] != '1') + continue; + stream << " and not (is_active" << toStr(j) << "_sig and not in_exit_set_" << toStr(j) << "_sig)" << std::endl; - } - } + } + } - stream << ");" << std::endl; + stream << ");" << std::endl; #endif - } -} - -//TODO write event generator -// wie die letzten beiden states erkennen -// 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 << "begin" << std::endl; - // - // std::stringstream nextStateBuffer; - // for (size_t i = 0; i < _states.size(); i++) { - // Element 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 > choices; - // std::string spntaneous_trans_sig = ""; - // for (size_t j = 0; j < _transitions.size(); j++) { - // Element 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 > incommingTransitions; - // for (size_t j = 0; j < _transitions.size(); j++) { - // Element 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 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 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 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 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 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; - - for (size_t i = 0; i < _states.size(); i++) { - Element state(_states[i]); - stream << " is_active_" << toStr(i) << "_sig <= " << "'0';" << std::endl; - } - - stream << " in_complete_entry_set_0_sig <= '1';" << std::endl; - stream << " elsif (rising_edge(clk) and stall = '0') then" << std::endl; - stream << " in_complete_entry_set_0_sig <= '0';" << std::endl; - - for (size_t i = 0; i < _states.size(); i++) { - Element state(_states[i]); - stream << " is_active_" << toStr(i) << "_sig <= " << "is_active_np1_" << toStr(i) << "_sig;" << std::endl; - } - - stream << " end if;" << std::endl; - stream << "end process;" << std::endl; - stream << std::endl; -} - -void ChartToVHDL::writeOutputLogic(std::ostream & stream) { - stream << "-- output logic" << std::endl; - stream << "output_proc: process(current_state)" << std::endl; - stream << "begin" << std::endl; - stream << " case current_state is" << std::endl; - - for (size_t i = 0; i < _states.size(); i++) { - //TODO - // if end state set completed and result - // on entry events generated here - } - - stream << " when others =>" << std::endl; - stream << " completed_o <= '0';" << std::endl; - stream << " result_o <= '0';" << std::endl; - - stream << "end case;" << std::endl; - stream << "end process;" << std::endl; - stream << std::endl; -} + } + } + + //TODO write event generator + // wie die letzten beiden states erkennen + // 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 << "begin" << std::endl; + // + // std::stringstream nextStateBuffer; + // for (size_t i = 0; i < _states.size(); i++) { + // Element 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 > choices; + // std::string spntaneous_trans_sig = ""; + // for (size_t j = 0; j < _transitions.size(); j++) { + // Element 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 > incommingTransitions; + // for (size_t j = 0; j < _transitions.size(); j++) { + // Element 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 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 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 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 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 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; + + for (size_t i = 0; i < _states.size(); i++) { + Element state(_states[i]); + stream << " state_active_" << toStr(i) << "_sig <= " << "'0';" << std::endl; + } + + stream << " in_complete_entry_set_0_sig <= '1';" << std::endl; + stream << " elsif (rising_edge(clk) and stall = '0') then" << std::endl; + stream << " in_complete_entry_set_0_sig <= '0';" << std::endl; + + for (size_t i = 0; i < _states.size(); i++) { + Element state(_states[i]); + stream << " state_active_" << toStr(i) << "_sig <= " << "state_next_" << toStr(i) << "_sig;" << std::endl; + } + + stream << " end if;" << std::endl; + stream << "end process;" << std::endl; + stream << std::endl; + } + + void ChartToVHDL::writeOutputLogic(std::ostream & stream) { + stream << "-- output logic" << std::endl; + // TODO find final states and add to or statement + stream << "completed_sig <= '0' or state_active_4_sig;" << std::endl; + stream << std::endl; + } } \ No newline at end of file -- cgit v0.12