diff --git a/Makefile b/Makefile index d79fa8e..29e1327 100644 --- a/Makefile +++ b/Makefile @@ -25,8 +25,16 @@ SRC = $(SRC_DIR)/Parser.cpp \ $(SRC_DIR)/specialComponents/Undefined.cpp \ $(SRC_DIR)/elementaryComponents/ANDComponent.cpp \ $(SRC_DIR)/elementaryComponents/NOTComponent.cpp \ - $(SRC_DIR)/elementaryComponents/ORComponent.cpp \ + $(SRC_DIR)/elementaryComponents/ORComponent.cpp \ $(SRC_DIR)/elementaryComponents/XORComponent.cpp \ + $(SRC_DIR)/elementaryComponents/NANDComponent.cpp \ + $(SRC_DIR)/elementaryComponents/NORComponent.cpp \ + $(SRC_DIR)/gateComponents/4001Component.cpp \ + $(SRC_DIR)/gateComponents/4011Component.cpp \ + $(SRC_DIR)/gateComponents/4030Component.cpp \ + $(SRC_DIR)/gateComponents/4069Component.cpp \ + $(SRC_DIR)/gateComponents/4071Component.cpp \ + $(SRC_DIR)/gateComponents/4081Component.cpp \ $(SRC_DIR)/ShellLoop.cpp \ $(SRC_DIR)/AComponent.cpp \ $(SRC_DIR)/Circuit.cpp diff --git a/include/Factory.hpp b/include/Factory.hpp index 7f5b6a1..54b0b17 100644 --- a/include/Factory.hpp +++ b/include/Factory.hpp @@ -26,13 +26,15 @@ namespace nts std::shared_ptr createOR(const std::string &name) const; std::shared_ptr createNOT(const std::string &name) const; std::shared_ptr createXOR(const std::string &name) const; - - std::shared_ptr create4001() const; - std::shared_ptr create4011() const; - std::shared_ptr create4030() const; - std::shared_ptr create4069() const; - std::shared_ptr create4071() const; - std::shared_ptr create4081() const; + std::shared_ptr createNOR(const std::string &name) const; + std::shared_ptr createNAND(const std::string &name) const; + + std::shared_ptr create4001(const std::string &name) const; + std::shared_ptr create4011(const std::string &name) const; + std::shared_ptr create4030(const std::string &name) const; + std::shared_ptr create4069(const std::string &name) const; + std::shared_ptr create4071(const std::string &name) const; + std::shared_ptr create4081(const std::string &name) const; std::shared_ptr create4008() const; std::shared_ptr create4013() const; diff --git a/src/Circuit.cpp b/src/Circuit.cpp index b7e878d..5e56131 100644 --- a/src/Circuit.cpp +++ b/src/Circuit.cpp @@ -121,8 +121,6 @@ void nts::Circuit::linkComponents(const std::string &name1, const std::string &n void nts::Circuit::setInputState(nts::InputComponent &input, nts::Tristate state) const { - std::shared_ptr tempComponent; - if (state == nts::UNDEFINED) input.setLink(1, _components.at("undefined"), 1); else if (state == nts::TRUE) diff --git a/src/Factory.cpp b/src/Factory.cpp index 013ea25..ef65746 100644 --- a/src/Factory.cpp +++ b/src/Factory.cpp @@ -10,6 +10,14 @@ #include "./elementaryComponents/NOTComponent.hpp" #include "./elementaryComponents/ORComponent.hpp" #include "./elementaryComponents/XORComponent.hpp" +#include "./elementaryComponents/NANDComponent.hpp" +#include "./elementaryComponents/NORComponent.hpp" +#include "./gateComponents/4001Component.hpp" +#include "./gateComponents/4011Component.hpp" +#include "./gateComponents/4030Component.hpp" +#include "./gateComponents/4069Component.hpp" +#include "./gateComponents/4071Component.hpp" +#include "./gateComponents/4081Component.hpp" #include "../include/specialComponents/Clock.hpp" #include "../include/specialComponents/Input.hpp" #include "../include/specialComponents/Output.hpp" @@ -39,10 +47,61 @@ std::shared_ptr nts::Factory::createComponent(const std::string return createXOR(name); else if (type == "not") return createNOT(name); + else if (type == "nand") + return createNAND(name); + else if (type == "nor") + return createNOR(name); + else if (type == "4001") + return create4001(name); + else if (type == "4011") + return create4011(name); + else if (type == "4030") + return create4030(name); + else if (type == "4069") + return create4069(name); + else if (type == "4071") + return create4071(name); + else if (type == "4081") + return create4081(name); else return nullptr; } +std::shared_ptr nts::Factory::create4081(const std::string &name) const +{ + return std::make_shared(name); +} + +std::shared_ptr nts::Factory::create4071(const std::string &name) const +{ + return std::make_shared(name); +} + +std::shared_ptr nts::Factory::create4069(const std::string &name) const +{ + return std::make_shared(name); +} + +std::shared_ptr nts::Factory::create4011(const std::string &name) const +{ + return std::make_shared(name); +} + +std::shared_ptr nts::Factory::create4001(const std::string &name) const +{ + return std::make_shared(name); +} + +std::shared_ptr nts::Factory::createNAND(const std::string &name) const +{ + return std::make_shared(name); +} + +std::shared_ptr nts::Factory::createNOR(const std::string &name) const +{ + return std::make_shared(name); +} + std::shared_ptr nts::Factory::createUndefined(const std::string &name) const { return std::make_shared(name); @@ -91,4 +150,9 @@ std::shared_ptr nts::Factory::createXOR(const std::string &name std::shared_ptr nts::Factory::createNOT(const std::string &name) const { return std::make_shared(name); +} + +std::shared_ptr nts::Factory::create4030(const std::string &name) const +{ + return std::make_shared(name); } \ No newline at end of file diff --git a/src/elementaryComponents/ANDComponent.cpp b/src/elementaryComponents/ANDComponent.cpp index c16402e..7aba0df 100644 --- a/src/elementaryComponents/ANDComponent.cpp +++ b/src/elementaryComponents/ANDComponent.cpp @@ -21,28 +21,29 @@ namespace nts throw std::invalid_argument("Pin does not exist"); } + Tristate ANDComponent::calculateState(nts::Tristate first, nts::Tristate second) + { + if (first == nts::FALSE || second == nts::FALSE) + return nts::FALSE; + else if (first == nts::UNDEFINED || second == nts::UNDEFINED) + return nts::UNDEFINED; + else + return nts::TRUE; + } + void ANDComponent::simulate(std::size_t tick) { - nts::Tristate first; - nts::Tristate second; + nts::Tristate first = UNDEFINED; + nts::Tristate second = UNDEFINED; if (tick == this->_lastTick) return; this->_lastTick = tick; - if (this->_pins[0].lock() == nullptr) - first = nts::UNDEFINED; - else + if (this->_pins[0].lock() != nullptr) first = this->_pins[0].lock()->compute(tick); - if (this->_pins[1].lock() == nullptr) - second = nts::UNDEFINED; - else + if (this->_pins[1].lock() != nullptr) second = this->_pins[1].lock()->compute(tick); - if (first == nts::FALSE || second == nts::FALSE) - this->setState(nts::FALSE); - else if (first == nts::UNDEFINED || second == nts::UNDEFINED) - this->setState(nts::UNDEFINED); - else - this->setState(nts::TRUE); + this->setState(calculateState(first, second)); } nts::Tristate ANDComponent::compute(std::size_t tick) diff --git a/src/elementaryComponents/ANDComponent.hpp b/src/elementaryComponents/ANDComponent.hpp index fe7424b..7614c9f 100644 --- a/src/elementaryComponents/ANDComponent.hpp +++ b/src/elementaryComponents/ANDComponent.hpp @@ -15,6 +15,7 @@ namespace nts void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin); void simulate(std::size_t tick) override; nts::Tristate compute(std::size_t tick) override; + static nts::Tristate calculateState(nts::Tristate first, nts::Tristate second); }; } diff --git a/src/elementaryComponents/NANDComponent.cpp b/src/elementaryComponents/NANDComponent.cpp new file mode 100644 index 0000000..a3d9e64 --- /dev/null +++ b/src/elementaryComponents/NANDComponent.cpp @@ -0,0 +1,54 @@ +#include "NANDComponent.hpp" +#include + +namespace nts +{ + NANDComponent::NANDComponent(const std::string &name) : AComponent(name, 3) + { + this->setState(nts::UNDEFINED); + } + + NANDComponent::~NANDComponent() + { + } + + void NANDComponent::setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) + { + (void)otherPin; + if (pin >= 1 && pin <= 3) + this->_pins[pin - 1] = other; + else + throw std::invalid_argument("Pin does not exist"); + } + + Tristate NANDComponent::calculateState(nts::Tristate first, nts::Tristate second) + { + if (first == nts::FALSE || second == nts::FALSE) + return nts::TRUE; + else if (first == nts::UNDEFINED || second == nts::UNDEFINED) + return nts::UNDEFINED; + else + return nts::FALSE; + } + + void NANDComponent::simulate(std::size_t tick) + { + nts::Tristate first = UNDEFINED; + nts::Tristate second = UNDEFINED; + + if (tick == this->_lastTick) + return; + this->_lastTick = tick; + if (this->_pins[0].lock() != nullptr) + first = this->_pins[0].lock()->compute(tick); + if (this->_pins[1].lock() != nullptr) + second = this->_pins[1].lock()->compute(tick); + this->setState(calculateState(first, second)); + } + + nts::Tristate NANDComponent::compute(std::size_t tick) + { + this->simulate(tick); + return this->getState(); + } +} \ No newline at end of file diff --git a/src/elementaryComponents/NANDComponent.hpp b/src/elementaryComponents/NANDComponent.hpp new file mode 100644 index 0000000..76551a8 --- /dev/null +++ b/src/elementaryComponents/NANDComponent.hpp @@ -0,0 +1,22 @@ +#ifndef NANDCOMPONENT_HPP +#define NANDCOMPONENT_HPP + +#include +#include +#include "../include/AComponent.hpp" + +namespace nts +{ + class NANDComponent : public AComponent + { + public: + NANDComponent(const std::string &name = "nand"); + ~NANDComponent(); + void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin); + void simulate(std::size_t tick) override; + nts::Tristate compute(std::size_t tick) override; + static nts::Tristate calculateState(nts::Tristate first, nts::Tristate second); + }; +} + +#endif // NANDCOMPONENT_HPP diff --git a/src/elementaryComponents/NORComponent.cpp b/src/elementaryComponents/NORComponent.cpp new file mode 100644 index 0000000..e3bb575 --- /dev/null +++ b/src/elementaryComponents/NORComponent.cpp @@ -0,0 +1,54 @@ +#include "NORComponent.hpp" +#include + +namespace nts +{ + NORComponent::NORComponent(const std::string &name) : AComponent(name, 3) + { + this->setState(nts::UNDEFINED); + } + + NORComponent::~NORComponent() + { + } + + void NORComponent::setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) + { + (void)otherPin; + if (pin >= 1 && pin <= 3) + this->_pins[pin - 1] = other; + else + throw std::invalid_argument("Pin does not exist"); + } + + Tristate NORComponent::calculateState(nts::Tristate first, nts::Tristate second) + { + if (first == nts::TRUE || second == nts::TRUE) + return nts::FALSE; + else if (first == nts::UNDEFINED || second == nts::UNDEFINED) + return nts::UNDEFINED; + else + return nts::TRUE; + } + + void NORComponent::simulate(std::size_t tick) + { + nts::Tristate first = UNDEFINED; + nts::Tristate second = UNDEFINED; + + if (tick == this->_lastTick) + return; + this->_lastTick = tick; + if (this->_pins[0].lock() != nullptr) + first = this->_pins[0].lock()->compute(tick); + if (this->_pins[1].lock() != nullptr) + second = this->_pins[1].lock()->compute(tick); + this->setState(calculateState(first, second)); + } + + nts::Tristate NORComponent::compute(std::size_t tick) + { + this->simulate(tick); + return this->getState(); + } +} \ No newline at end of file diff --git a/src/elementaryComponents/NORComponent.hpp b/src/elementaryComponents/NORComponent.hpp new file mode 100644 index 0000000..0911b29 --- /dev/null +++ b/src/elementaryComponents/NORComponent.hpp @@ -0,0 +1,22 @@ +#ifndef NORCOMPONENT_HPP +#define NORCOMPONENT_HPP + +#include +#include +#include "../include/AComponent.hpp" + +namespace nts +{ + class NORComponent : public AComponent + { + public: + NORComponent(const std::string &name = "nor"); + ~NORComponent(); + void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin); + void simulate(std::size_t tick) override; + nts::Tristate compute(std::size_t tick) override; + static nts::Tristate calculateState(nts::Tristate first, nts::Tristate second); + }; +} + +#endif // NORCOMPONENT_HPP diff --git a/src/elementaryComponents/NOTComponent.cpp b/src/elementaryComponents/NOTComponent.cpp index c477b63..339c53d 100644 --- a/src/elementaryComponents/NOTComponent.cpp +++ b/src/elementaryComponents/NOTComponent.cpp @@ -21,14 +21,26 @@ namespace nts throw std::invalid_argument("Pin does not exist"); } + nts::Tristate NOTComponent::calculateState(nts::Tristate state) + { + if (state == nts::TRUE) + return nts::FALSE; + else if (state == nts::FALSE) + return nts::TRUE; + else + return nts::UNDEFINED; + } + void NOTComponent::simulate(std::size_t tick) { + Tristate state = UNDEFINED; + if (tick == this->_lastTick) return; this->_lastTick = tick; - if (this->_pins[0].lock() == nullptr || this->_pins[0].lock()->compute(tick) == nts::UNDEFINED) - return; - this->setState(this->_pins[0].lock()->compute(tick) == nts::TRUE ? nts::FALSE : nts::TRUE); + if (this->_pins[0].lock() != nullptr) + state = this->_pins[0].lock()->compute(tick); + this->setState(calculateState(state)); } nts::Tristate NOTComponent::compute(std::size_t tick) diff --git a/src/elementaryComponents/NOTComponent.hpp b/src/elementaryComponents/NOTComponent.hpp index e1ec329..170c652 100644 --- a/src/elementaryComponents/NOTComponent.hpp +++ b/src/elementaryComponents/NOTComponent.hpp @@ -15,6 +15,7 @@ namespace nts void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin); void simulate(std::size_t tick) override; nts::Tristate compute(std::size_t tick) override; + static nts::Tristate calculateState(nts::Tristate state); }; } diff --git a/src/elementaryComponents/ORComponent.cpp b/src/elementaryComponents/ORComponent.cpp index b67a148..901c8f7 100644 --- a/src/elementaryComponents/ORComponent.cpp +++ b/src/elementaryComponents/ORComponent.cpp @@ -21,28 +21,30 @@ namespace nts throw std::invalid_argument("Pin does not exist"); } + nts::Tristate ORComponent::calculateState(nts::Tristate first, nts::Tristate second) + { + if (first == nts::TRUE || second == nts::TRUE) + return nts::TRUE; + else if (first == nts::UNDEFINED || second == nts::UNDEFINED) + return nts::UNDEFINED; + else + return nts::FALSE; + } + void ORComponent::simulate(std::size_t tick) { - nts::Tristate first; - nts::Tristate second; + nts::Tristate first = UNDEFINED; + nts::Tristate second = UNDEFINED; if (tick == this->_lastTick) return; this->_lastTick = tick; - if (this->_pins[0].lock() == nullptr) - first = nts::UNDEFINED; - else + + if (this->_pins[0].lock() != nullptr) first = this->_pins[0].lock()->compute(tick); - if (this->_pins[1].lock() == nullptr) - second = nts::UNDEFINED; - else + if (this->_pins[1].lock() != nullptr) second = this->_pins[1].lock()->compute(tick); - if (first == nts::TRUE || second == nts::TRUE) - this->setState(nts::TRUE); - else if (first == nts::UNDEFINED || second == nts::UNDEFINED) - this->setState(nts::UNDEFINED); - else - this->setState(nts::FALSE); + this->setState(calculateState(first, second)); } nts::Tristate ORComponent::compute(std::size_t tick) diff --git a/src/elementaryComponents/ORComponent.hpp b/src/elementaryComponents/ORComponent.hpp index 9a54b8f..5bf622d 100644 --- a/src/elementaryComponents/ORComponent.hpp +++ b/src/elementaryComponents/ORComponent.hpp @@ -15,6 +15,7 @@ namespace nts void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin); void simulate(std::size_t tick) override; nts::Tristate compute(std::size_t tick) override; + static nts::Tristate calculateState(nts::Tristate first, nts::Tristate second); }; } diff --git a/src/elementaryComponents/XORComponent.cpp b/src/elementaryComponents/XORComponent.cpp index c271ef0..def56c8 100644 --- a/src/elementaryComponents/XORComponent.cpp +++ b/src/elementaryComponents/XORComponent.cpp @@ -21,28 +21,30 @@ namespace nts throw std::invalid_argument("Pin does not exist"); } + nts::Tristate XORComponent::calculateState(nts::Tristate first, nts::Tristate second) + { + if (first == nts::UNDEFINED || second == nts::UNDEFINED) + return nts::UNDEFINED; + else if (first == second) + return nts::FALSE; + else + return nts::TRUE; + } + void XORComponent::simulate(std::size_t tick) { - nts::Tristate first; - nts::Tristate second; + nts::Tristate first = UNDEFINED; + nts::Tristate second = UNDEFINED; if (tick == this->_lastTick) return; this->_lastTick = tick; - if (this->_pins[0].lock() == nullptr) - first = nts::UNDEFINED; - else + + if (this->_pins[0].lock() != nullptr) first = this->_pins[0].lock()->compute(tick); - if (this->_pins[1].lock() == nullptr) - second = nts::UNDEFINED; - else + if (this->_pins[1].lock() != nullptr) second = this->_pins[1].lock()->compute(tick); - if (first == nts::UNDEFINED || second == nts::UNDEFINED) - this->setState(nts::UNDEFINED); - else if (first == second) - this->setState(nts::FALSE); - else - this->setState(nts::TRUE); + this->setState(calculateState(first, second)); } nts::Tristate XORComponent::compute(std::size_t tick) diff --git a/src/elementaryComponents/XORComponent.hpp b/src/elementaryComponents/XORComponent.hpp index cc5e6c2..0a9c902 100644 --- a/src/elementaryComponents/XORComponent.hpp +++ b/src/elementaryComponents/XORComponent.hpp @@ -10,11 +10,12 @@ namespace nts class XORComponent : public AComponent { public: - XORComponent(const std::string &name = "or"); + XORComponent(const std::string &name = "xor"); ~XORComponent(); void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin); void simulate(std::size_t tick) override; nts::Tristate compute(std::size_t tick) override; + static nts::Tristate calculateState(nts::Tristate first, nts::Tristate second); }; } diff --git a/src/gateComponents/4001Component.cpp b/src/gateComponents/4001Component.cpp new file mode 100644 index 0000000..290d781 --- /dev/null +++ b/src/gateComponents/4001Component.cpp @@ -0,0 +1,72 @@ +#include "./4001Component.hpp" +#include "../elementaryComponents/NORComponent.hpp" +#include + +namespace nts +{ + Component4001::Component4001(const std::string &name) : AGate(name, 14) + { + this->setState(UNDEFINED); + } + + Component4001::~Component4001() + { + } + + void Component4001::setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) + { + (void)otherPin; + if (pin < 1 || pin > 13 || pin == 7) { + return; + } else { + this->_pins[pin - 1] = other; + } + } + + void Component4001::simulate(std::size_t tick) + { + if (tick == this->_lastTick) + return; + this->_lastTick = tick; + + for (size_t i = 0; i < 4; i++) { + size_t input1Pin; + size_t input2Pin; + size_t outputPin; + switch (i) { + case 0: + input1Pin = 1; + input2Pin = 2; + outputPin = 3; + break; + case 1: + input1Pin = 5; + input2Pin = 6; + outputPin = 4; + break; + case 2: + input1Pin = 8; + input2Pin = 9; + outputPin = 10; + break; + case 3: + input1Pin = 12; + input2Pin = 13; + outputPin = 11; + break; + } + Tristate input1 = this->_pins[input1Pin - 1].lock() ? this->_pins[input1Pin - 1].lock()->compute(tick) : UNDEFINED; + Tristate input2 = this->_pins[input2Pin - 1].lock() ? this->_pins[input2Pin - 1].lock()->compute(tick) : UNDEFINED; + Tristate output = NORComponent::calculateState(input1, input2); + if (auto outputPinComponent = this->_pins[outputPin - 1].lock()) { + outputPinComponent->setState(output); + } + } + } + + Tristate Component4001::compute(std::size_t tick) + { + this->simulate(tick); + return UNDEFINED; + } +} diff --git a/src/gateComponents/4001Component.hpp b/src/gateComponents/4001Component.hpp new file mode 100644 index 0000000..d09922c --- /dev/null +++ b/src/gateComponents/4001Component.hpp @@ -0,0 +1,22 @@ +#ifndef COMPONENT4001_HPP +#define COMPONENT4001_HPP + +#include +#include +#include "AGate.hpp" + +namespace nts +{ + class Component4001 : public AGate + { + public: + Component4001(const std::string &name = "4001"); + ~Component4001(); + + void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) override; + void simulate(std::size_t tick) override; + nts::Tristate compute(std::size_t tick) override; + }; +} + +#endif // COMPONENT4001_HPP diff --git a/src/gateComponents/4011Component.cpp b/src/gateComponents/4011Component.cpp new file mode 100644 index 0000000..ed260c5 --- /dev/null +++ b/src/gateComponents/4011Component.cpp @@ -0,0 +1,72 @@ +#include "./4011Component.hpp" +#include "../elementaryComponents/NANDComponent.hpp" +#include + +namespace nts +{ + Component4011::Component4011(const std::string &name) : AGate(name, 14) + { + this->setState(UNDEFINED); + } + + Component4011::~Component4011() + { + } + + void Component4011::setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) + { + (void)otherPin; + if (pin < 1 || pin > 13 || pin == 7) { + return; + } else { + this->_pins[pin - 1] = other; + } + } + + void Component4011::simulate(std::size_t tick) + { + if (tick == this->_lastTick) + return; + this->_lastTick = tick; + + for (size_t i = 0; i < 4; i++) { + size_t input1Pin; + size_t input2Pin; + size_t outputPin; + switch (i) { + case 0: + input1Pin = 1; + input2Pin = 2; + outputPin = 3; + break; + case 1: + input1Pin = 5; + input2Pin = 6; + outputPin = 4; + break; + case 2: + input1Pin = 8; + input2Pin = 9; + outputPin = 10; + break; + case 3: + input1Pin = 12; + input2Pin = 13; + outputPin = 11; + break; + } + Tristate input1 = this->_pins[input1Pin - 1].lock() ? this->_pins[input1Pin - 1].lock()->compute(tick) : UNDEFINED; + Tristate input2 = this->_pins[input2Pin - 1].lock() ? this->_pins[input2Pin - 1].lock()->compute(tick) : UNDEFINED; + Tristate output = NANDComponent::calculateState(input1, input2); + if (auto outputPinComponent = this->_pins[outputPin - 1].lock()) { + outputPinComponent->setState(output); + } + } + } + + Tristate Component4011::compute(std::size_t tick) + { + this->simulate(tick); + return UNDEFINED; + } +} diff --git a/src/gateComponents/4011Component.hpp b/src/gateComponents/4011Component.hpp new file mode 100644 index 0000000..0ded475 --- /dev/null +++ b/src/gateComponents/4011Component.hpp @@ -0,0 +1,22 @@ +#ifndef COMPONENT4011_HPP +#define COMPONENT4011_HPP + +#include +#include +#include "AGate.hpp" + +namespace nts +{ + class Component4011 : public AGate + { + public: + Component4011(const std::string &name = "4011"); + ~Component4011(); + + void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) override; + void simulate(std::size_t tick) override; + nts::Tristate compute(std::size_t tick) override; + }; +} + +#endif // COMPONENT4011_HPP diff --git a/src/gateComponents/4030Component.cpp b/src/gateComponents/4030Component.cpp new file mode 100644 index 0000000..9ee3257 --- /dev/null +++ b/src/gateComponents/4030Component.cpp @@ -0,0 +1,72 @@ +#include "./4030Component.hpp" +#include "../elementaryComponents/XORComponent.hpp" +#include + +namespace nts +{ + Component4030::Component4030(const std::string &name) : AGate(name, 14) + { + this->setState(UNDEFINED); + } + + Component4030::~Component4030() + { + } + + void Component4030::setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) + { + (void)otherPin; + if (pin < 1 || pin > 13 || pin == 7) { + return; + } else { + this->_pins[pin - 1] = other; + } + } + + void Component4030::simulate(std::size_t tick) + { + if (tick == this->_lastTick) + return; + this->_lastTick = tick; + + for (size_t i = 0; i < 4; i++) { + size_t input1Pin; + size_t input2Pin; + size_t outputPin; + switch (i) { + case 0: + input1Pin = 1; + input2Pin = 2; + outputPin = 3; + break; + case 1: + input1Pin = 5; + input2Pin = 6; + outputPin = 4; + break; + case 2: + input1Pin = 8; + input2Pin = 9; + outputPin = 10; + break; + case 3: + input1Pin = 12; + input2Pin = 13; + outputPin = 11; + break; + } + Tristate input1 = this->_pins[input1Pin - 1].lock() ? this->_pins[input1Pin - 1].lock()->compute(tick) : UNDEFINED; + Tristate input2 = this->_pins[input2Pin - 1].lock() ? this->_pins[input2Pin - 1].lock()->compute(tick) : UNDEFINED; + Tristate output = XORComponent::calculateState(input1, input2); + if (auto outputPinComponent = this->_pins[outputPin - 1].lock()) { + outputPinComponent->setState(output); + } + } + } + + Tristate Component4030::compute(std::size_t tick) + { + this->simulate(tick); + return UNDEFINED; + } +} diff --git a/src/gateComponents/4030Component.hpp b/src/gateComponents/4030Component.hpp new file mode 100644 index 0000000..58b176c --- /dev/null +++ b/src/gateComponents/4030Component.hpp @@ -0,0 +1,22 @@ +#ifndef COMPONENT4030_HPP +#define COMPONENT4030_HPP + +#include +#include +#include "AGate.hpp" + +namespace nts +{ + class Component4030 : public AGate + { + public: + Component4030(const std::string &name = "4030"); + ~Component4030(); + + void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) override; + void simulate(std::size_t tick) override; + nts::Tristate compute(std::size_t tick) override; + }; +} + +#endif // COMPONENT4030_HPP diff --git a/src/gateComponents/4069Component.cpp b/src/gateComponents/4069Component.cpp new file mode 100644 index 0000000..e3d0dd7 --- /dev/null +++ b/src/gateComponents/4069Component.cpp @@ -0,0 +1,74 @@ +#include "./4069Component.hpp" +#include "../elementaryComponents/NOTComponent.hpp" +#include + +namespace nts +{ + Component4069::Component4069(const std::string &name) : AGate(name, 14) + { + this->setState(UNDEFINED); + } + + Component4069::~Component4069() + { + } + + void Component4069::setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) + { + (void)otherPin; + if (pin < 1 || pin > 13 || pin == 7) { + return; + } else { + this->_pins[pin - 1] = other; + } + } + + void Component4069::simulate(std::size_t tick) + { + if (tick == this->_lastTick) + return; + this->_lastTick = tick; + + for (size_t i = 0; i < 6; i++) { + size_t inputPin; + size_t outputPin; + switch (i) { + case 0: + inputPin = 1; + outputPin = 2; + break; + case 1: + inputPin = 3; + outputPin = 4; + break; + case 2: + inputPin = 5; + outputPin = 6; + break; + case 3: + inputPin = 9; + outputPin = 8; + break; + case 4: + inputPin = 11; + outputPin = 10; + break; + case 5: + inputPin = 13; + outputPin = 12; + break; + } + Tristate input = this->_pins[inputPin - 1].lock() ? this->_pins[inputPin - 1].lock()->compute(tick) : UNDEFINED; + Tristate output = NOTComponent::calculateState(input); + if (auto outputPinComponent = this->_pins[outputPin - 1].lock()) { + outputPinComponent->setState(output); + } + } + } + + Tristate Component4069::compute(std::size_t tick) + { + this->simulate(tick); + return UNDEFINED; + } +} diff --git a/src/gateComponents/4069Component.hpp b/src/gateComponents/4069Component.hpp new file mode 100644 index 0000000..6328b61 --- /dev/null +++ b/src/gateComponents/4069Component.hpp @@ -0,0 +1,22 @@ +#ifndef COMPONENT4069_HPP +#define COMPONENT4069_HPP + +#include +#include +#include "AGate.hpp" + +namespace nts +{ + class Component4069 : public AGate + { + public: + Component4069(const std::string &name = "4069"); + ~Component4069(); + + void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) override; + void simulate(std::size_t tick) override; + nts::Tristate compute(std::size_t tick) override; + }; +} + +#endif // COMPONENT4069_HPP diff --git a/src/gateComponents/4071Component.cpp b/src/gateComponents/4071Component.cpp new file mode 100644 index 0000000..83de826 --- /dev/null +++ b/src/gateComponents/4071Component.cpp @@ -0,0 +1,72 @@ +#include "./4071Component.hpp" +#include "../elementaryComponents/ORComponent.hpp" +#include + +namespace nts +{ + Component4071::Component4071(const std::string &name) : AGate(name, 14) + { + this->setState(UNDEFINED); + } + + Component4071::~Component4071() + { + } + + void Component4071::setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) + { + (void)otherPin; + if (pin < 1 || pin > 13 || pin == 7) { + return; + } else { + this->_pins[pin - 1] = other; + } + } + + void Component4071::simulate(std::size_t tick) + { + if (tick == this->_lastTick) + return; + this->_lastTick = tick; + + for (size_t i = 0; i < 4; i++) { + size_t input1Pin; + size_t input2Pin; + size_t outputPin; + switch (i) { + case 0: + input1Pin = 1; + input2Pin = 2; + outputPin = 3; + break; + case 1: + input1Pin = 5; + input2Pin = 6; + outputPin = 4; + break; + case 2: + input1Pin = 8; + input2Pin = 9; + outputPin = 10; + break; + case 3: + input1Pin = 12; + input2Pin = 13; + outputPin = 11; + break; + } + Tristate input1 = this->_pins[input1Pin - 1].lock() ? this->_pins[input1Pin - 1].lock()->compute(tick) : UNDEFINED; + Tristate input2 = this->_pins[input2Pin - 1].lock() ? this->_pins[input2Pin - 1].lock()->compute(tick) : UNDEFINED; + Tristate output = ORComponent::calculateState(input1, input2); + if (auto outputPinComponent = this->_pins[outputPin - 1].lock()) { + outputPinComponent->setState(output); + } + } + } + + Tristate Component4071::compute(std::size_t tick) + { + this->simulate(tick); + return UNDEFINED; + } +} diff --git a/src/gateComponents/4071Component.hpp b/src/gateComponents/4071Component.hpp new file mode 100644 index 0000000..08c2f77 --- /dev/null +++ b/src/gateComponents/4071Component.hpp @@ -0,0 +1,22 @@ +#ifndef COMPONENT4071_HPP +#define COMPONENT4071_HPP + +#include +#include +#include "AGate.hpp" + +namespace nts +{ + class Component4071 : public AGate + { + public: + Component4071(const std::string &name = "4071"); + ~Component4071(); + + void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) override; + void simulate(std::size_t tick) override; + nts::Tristate compute(std::size_t tick) override; + }; +} + +#endif // COMPONENT4071_HPP diff --git a/src/gateComponents/4081Component.cpp b/src/gateComponents/4081Component.cpp new file mode 100644 index 0000000..8597be7 --- /dev/null +++ b/src/gateComponents/4081Component.cpp @@ -0,0 +1,72 @@ +#include "./4081Component.hpp" +#include "../elementaryComponents/ANDComponent.hpp" +#include + +namespace nts +{ + Component4081::Component4081(const std::string &name) : AGate(name, 14) + { + this->setState(UNDEFINED); + } + + Component4081::~Component4081() + { + } + + void Component4081::setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) + { + (void)otherPin; + if (pin < 1 || pin > 14 || pin == 7) { + return; + } else { + this->_pins[pin - 1] = other; + } + } + + void Component4081::simulate(std::size_t tick) + { + if (tick == this->_lastTick) + return; + this->_lastTick = tick; + + for (size_t i = 0; i < 4; i++) { + size_t input1Pin; + size_t input2Pin; + size_t outputPin; + switch (i) { + case 0: + input1Pin = 1; + input2Pin = 2; + outputPin = 3; + break; + case 1: + input1Pin = 5; + input2Pin = 6; + outputPin = 4; + break; + case 2: + input1Pin = 8; + input2Pin = 9; + outputPin = 10; + break; + case 3: + input1Pin = 12; + input2Pin = 13; + outputPin = 11; + break; + } + Tristate input1 = this->_pins[input1Pin - 1].lock() ? this->_pins[input1Pin - 1].lock()->compute(tick) : UNDEFINED; + Tristate input2 = this->_pins[input2Pin - 1].lock() ? this->_pins[input2Pin - 1].lock()->compute(tick) : UNDEFINED; + Tristate output = ANDComponent::calculateState(input1, input2); + if (auto outputPinComponent = this->_pins[outputPin - 1].lock()) { + outputPinComponent->setState(output); + } + } + } + + Tristate Component4081::compute(std::size_t tick) + { + this->simulate(tick); + return UNDEFINED; + } +} diff --git a/src/gateComponents/4081Component.hpp b/src/gateComponents/4081Component.hpp new file mode 100644 index 0000000..9082545 --- /dev/null +++ b/src/gateComponents/4081Component.hpp @@ -0,0 +1,22 @@ +#ifndef COMPONENT4081_HPP +#define COMPONENT4081_HPP + +#include +#include +#include "AGate.hpp" + +namespace nts +{ + class Component4081 : public AGate + { + public: + Component4081(const std::string &name = "4081"); + ~Component4081(); + + void setLink(std::size_t pin, std::shared_ptr other, std::size_t otherPin) override; + void simulate(std::size_t tick) override; + nts::Tristate compute(std::size_t tick) override; + }; +} + +#endif // COMPONENT4081_HPP diff --git a/src/gateComponents/AGate.hpp b/src/gateComponents/AGate.hpp new file mode 100644 index 0000000..c13fbd1 --- /dev/null +++ b/src/gateComponents/AGate.hpp @@ -0,0 +1,15 @@ +#ifndef AGATE_HPP +#define AGATE_HPP + +#include "../include/AComponent.hpp" + +namespace nts +{ +class AGate : public AComponent { + public: + AGate(const std::string &name, size_t nbPins) : AComponent(name, nbPins) {} + virtual ~AGate() = default; +}; +} + +#endif // AGATE_HPP \ No newline at end of file diff --git a/src/specialComponents/Output.cpp b/src/specialComponents/Output.cpp index 54988f4..68e5048 100644 --- a/src/specialComponents/Output.cpp +++ b/src/specialComponents/Output.cpp @@ -6,6 +6,7 @@ */ #include "../../include/specialComponents/Output.hpp" +#include "../gateComponents/4001Component.hpp" nts::OutputComponent::OutputComponent(const std::string &name) : AComponent(name, 1) { @@ -18,6 +19,8 @@ void nts::OutputComponent::simulate(std::size_t tick) auto pin = this->_pins[0].lock(); if (!pin) this->setState(nts::UNDEFINED); + else if (auto component4001 = std::dynamic_pointer_cast(pin)) + pin->compute(tick); else this->setState(pin->compute(tick)); } diff --git a/tests/test_elementaryComponents.cpp b/tests/test_elementaryComponents.cpp index 6a33190..e81a15e 100644 --- a/tests/test_elementaryComponents.cpp +++ b/tests/test_elementaryComponents.cpp @@ -198,4 +198,48 @@ Test(Circuit, xor_gate_behavior) { circuit.simulate(2); state = circuit.compute("Out1"); cr_assert_eq(state, nts::FALSE, "Output should be FALSE when inputs are the same"); +} + +Test(Circuit, nand_gate_behavior) { + nts::Circuit circuit; + circuit.addComponent("input", "In1"); + circuit.addComponent("input", "In2"); + circuit.addComponent("nand", "Nand1"); + circuit.addComponent("output", "Out1"); + + circuit.linkComponents("In1", "Nand1", 1, 1); + circuit.linkComponents("In2", "Nand1", 1, 2); + circuit.linkComponents("Nand1", "Out1", 3, 1); + + circuit.setInputState(*dynamic_cast(circuit.getComponent("In1").get()), nts::TRUE); + circuit.setInputState(*dynamic_cast(circuit.getComponent("In2").get()), nts::TRUE); + circuit.simulate(1); + nts::Tristate state = circuit.compute("Out1"); + + circuit.setInputState(*dynamic_cast(circuit.getComponent("In2").get()), nts::FALSE); + circuit.simulate(2); + state = circuit.compute("Out1"); + cr_assert_eq(state, nts::TRUE, "Output should be TRUE when one input is FALSE"); +} + +Test(Circuit, nor_gate_behavior) { + nts::Circuit circuit; + circuit.addComponent("input", "In1"); + circuit.addComponent("input", "In2"); + circuit.addComponent("nor", "Nor1"); + circuit.addComponent("output", "Out1"); + + circuit.linkComponents("In1", "Nor1", 1, 1); + circuit.linkComponents("In2", "Nor1", 1, 2); + circuit.linkComponents("Nor1", "Out1", 3, 1); + + circuit.setInputState(*dynamic_cast(circuit.getComponent("In1").get()), nts::FALSE); + circuit.setInputState(*dynamic_cast(circuit.getComponent("In2").get()), nts::FALSE); + circuit.simulate(1); + nts::Tristate state = circuit.compute("Out1"); + + circuit.setInputState(*dynamic_cast(circuit.getComponent("In1").get()), nts::TRUE); + circuit.simulate(2); + state = circuit.compute("Out1"); + cr_assert_eq(state, nts::FALSE, "Output should be FALSE when one input is TRUE"); } \ No newline at end of file