From c5d2856619ea6360a39c65cde08a7bfc3c680c8d Mon Sep 17 00:00:00 2001 From: maelemiel Date: Sat, 8 Mar 2025 14:22:04 +0100 Subject: [PATCH 1/4] [FIX] Stack overflow in inputcomponent --- src/specialComponents/Input.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/specialComponents/Input.cpp b/src/specialComponents/Input.cpp index 53f97f6..a5aec26 100644 --- a/src/specialComponents/Input.cpp +++ b/src/specialComponents/Input.cpp @@ -21,18 +21,23 @@ nts::InputComponent::~InputComponent() void nts::InputComponent::simulate(std::size_t tick) { - (void)tick; - if (_pins[0].lock() == nullptr) { + if (_lastTick == tick) + return; + _lastTick = tick; + + if (_pins[0].lock() == nullptr) this->setState(nts::UNDEFINED); - } else { - this->setState(_pins[0].lock()->compute(tick)); + auto linkedComponent = _pins[0].lock(); + linkedComponent->simulate(tick); + this->setState(linkedComponent->getState()); } } nts::Tristate nts::InputComponent::compute(std::size_t tick) { - this->simulate(tick); + if (_lastTick != tick) + this->simulate(tick); return this->getState(); } From b33209398e6fb9d0f441c412df92390f4fc46828 Mon Sep 17 00:00:00 2001 From: maelemiel Date: Sat, 8 Mar 2025 20:51:59 +0100 Subject: [PATCH 2/4] [FIX] input output test with removing one simulate because compute do simulate --- tests/test_elementaryComponents.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_elementaryComponents.cpp b/tests/test_elementaryComponents.cpp index fbcd6ef..6a33190 100644 --- a/tests/test_elementaryComponents.cpp +++ b/tests/test_elementaryComponents.cpp @@ -30,7 +30,7 @@ Test(Circuit, link_input_to_output) { circuit.addComponent("output", "Out1"); circuit.linkComponents("In1", "Out1", 1, 1); circuit.setInputState(*dynamic_cast(circuit.getComponent("In1").get()), nts::TRUE); - circuit.simulate(1); + //circuit.simulate(1); nts::Tristate state = circuit.compute("Out1"); cr_assert_eq(state, nts::TRUE, "Output should be TRUE when input is TRUE"); } From 0b2059edc2468b983877b8898333713cd26fce54 Mon Sep 17 00:00:00 2001 From: maelemiel Date: Sun, 9 Mar 2025 02:35:34 +0100 Subject: [PATCH 3/4] [FEATURE] add signal handling and improve user input processing in ShellLoop --- include/ShellLoop.hpp | 6 ++++ src/ShellLoop.cpp | 82 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/include/ShellLoop.hpp b/include/ShellLoop.hpp index 1e202e9..ef4775c 100644 --- a/include/ShellLoop.hpp +++ b/include/ShellLoop.hpp @@ -8,6 +8,7 @@ #include #include #include "Circuit.hpp" +#include namespace nts { @@ -17,6 +18,8 @@ class ShellLoop { ~ShellLoop(); void run(); + static bool signalReceived; + static void signalHandler(int signal); private: protected: Circuit &_circuit; @@ -26,6 +29,9 @@ class ShellLoop { void display(Circuit &circuit); void simulate(Circuit &circuit); void loop(Circuit &circuit); + bool getUserInput(std::string &input); + bool executeCommand(const std::string &input); + void handleException(const std::exception &e); bool _running; }; diff --git a/src/ShellLoop.cpp b/src/ShellLoop.cpp index 4965e46..42d0e0f 100644 --- a/src/ShellLoop.cpp +++ b/src/ShellLoop.cpp @@ -7,14 +7,29 @@ #include "ShellLoop.hpp" + +bool nts::ShellLoop::signalReceived = false; + +void nts::ShellLoop::signalHandler(int signal) { + if (signal == SIGINT) { + signalReceived = true; + dup2(0, 0); + } +} + nts::ShellLoop::ShellLoop(Circuit &circuit) : _circuit(circuit) { + struct sigaction sa; + _commands.emplace("exit", &ShellLoop::exit); _commands.emplace("simulate", &ShellLoop::simulate); _commands.emplace("display", &ShellLoop::display); _commands.emplace("loop", &ShellLoop::loop); _running = true; -} + sa.sa_handler = signalHandler; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, NULL);} nts::ShellLoop::~ShellLoop() { @@ -38,7 +53,7 @@ void nts::ShellLoop::simulate(Circuit &circuit) void nts::ShellLoop::loop(Circuit &circuit) { - while (_running) { + while (_running && !signalReceived) { circuit.simulate(circuit.getTick() + 1); circuit.display(); } @@ -78,25 +93,60 @@ bool nts::ShellLoop::setComponentValue(const std::string &input, Circuit &circui return false; } +bool nts::ShellLoop::getUserInput(std::string &input) +{ + if (!std::getline(std::cin, input)) { + if (signalReceived || std::cin.eof()) { + std::cout << std::endl; + return false; + } + if (std::cin.fail()) { + std::cin.clear(); + return true; + } + } + return !signalReceived; +} + +bool nts::ShellLoop::executeCommand(const std::string &input) +{ + if (input.empty()) + return true; + if (_commands.find(input) != _commands.end()) { + (this->*_commands[input])(_circuit); + } else if (input == "exit") { + exit(_circuit); + return false; + } else if (!setComponentValue(input, _circuit)) { + std::cerr << "Invalid command: " << input << std::endl; + } + return !signalReceived; +} + +void nts::ShellLoop::handleException(const std::exception &e) +{ + if (!signalReceived) { + std::cerr << "Error: " << e.what() << std::endl; + } +} + void nts::ShellLoop::run() { std::string input; _circuit.simulate(0); - while (_running) { - std::cout << "> "; - if (!std::getline(std::cin, input)) { - std::cout << std::endl; - break; - } - if (input.empty()) - continue; - if (_commands.find(input) != _commands.end()) - (this->*_commands[input])(_circuit); - else if (input == "exit") - exit(_circuit); - else if (!setComponentValue(input, _circuit)) { - std::cerr << "Invalid command: " << input << std::endl; + while (_running && !signalReceived) { + std::cout << "> " << std::flush; + try { + if (!getUserInput(input)) + break; + if (!executeCommand(input)) + break; + } catch (const std::exception &e) { + handleException(e); } + if (signalReceived) + break; } + _running = false; } \ No newline at end of file From 6f8b4548f29e6a9f9b7d528cb72bc63fbe948a8f Mon Sep 17 00:00:00 2001 From: maelemiel Date: Sun, 9 Mar 2025 18:39:44 +0100 Subject: [PATCH 4/4] [FEATURE] enhance input display by sorting inputs before output --- include/Circuit.hpp | 1 + src/Circuit.cpp | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/Circuit.hpp b/include/Circuit.hpp index b63a01e..273af9e 100644 --- a/include/Circuit.hpp +++ b/include/Circuit.hpp @@ -14,6 +14,7 @@ #include #include +#include #include "./specialComponents/Input.hpp" namespace nts diff --git a/src/Circuit.cpp b/src/Circuit.cpp index 5179f07..b7e878d 100644 --- a/src/Circuit.cpp +++ b/src/Circuit.cpp @@ -8,6 +8,7 @@ #include "../include/Circuit.hpp" #include "../include/specialComponents/Input.hpp" #include "../include/IComponent.hpp" +#include nts::Circuit::Circuit() : _factory(nts::Factory()), _tick(0) @@ -53,42 +54,47 @@ void nts::Circuit::displayComponentState(const std::string& name, nts::Tristate void nts::Circuit::displayInputs() const { + std::cout << "input(s):" << std::endl; + std::map sortedInputs; + for (const auto &component : _components) { - //check if it is true/false or if it is an actual input/clock if (isTrueFalseComponent(*component.second)) continue; - if (component.first == "true" || component.first == "false" || component.first == "undefined") continue; auto clock = dynamic_cast(component.second.get()); if (clock != nullptr) { - displayComponentState(clock->getName(), clock->getState()); + sortedInputs[clock->getName()] = clock->getState(); continue; } auto input = dynamic_cast(component.second.get()); if (input != nullptr) { - displayComponentState(input->getName(), input->getState()); + sortedInputs[input->getName()] = input->getState(); + continue; } auto trueComponent = dynamic_cast(component.second.get()); if (trueComponent != nullptr) { - displayComponentState(trueComponent->getName(), trueComponent->getState()); + sortedInputs[trueComponent->getName()] = trueComponent->getState(); + continue; } auto falseComponent = dynamic_cast(component.second.get()); if (falseComponent != nullptr) { - displayComponentState(falseComponent->getName(), falseComponent->getState()); + sortedInputs[falseComponent->getName()] = falseComponent->getState(); } } + for (const auto &[name, state] : sortedInputs) { + displayComponentState(name, state); + } } void nts::Circuit::display() const { std::cout << "tick: " << _tick << std::endl; - std::cout << "input(s):" << std::endl; displayInputs(); std::cout << "output(s):" << std::endl; for (const auto &output : _outputs) {