diff options
-rw-r--r-- | Circuit.cpp | 47 | ||||
-rw-r--r-- | Circuit.h | 11 | ||||
-rw-r--r-- | Exception.cpp | 45 | ||||
-rw-r--r-- | Exception.h | 27 | ||||
-rw-r--r-- | GateAnd.cpp | 2 | ||||
-rw-r--r-- | GateAnd.h | 6 | ||||
-rw-r--r-- | Net.cpp | 4 | ||||
-rw-r--r-- | Net.h | 12 | ||||
-rw-r--r-- | Node.cpp | 11 | ||||
-rw-r--r-- | Node.h | 2 | ||||
-rw-r--r-- | NodeInput.cpp | 6 | ||||
-rw-r--r-- | NodeInput.h | 2 | ||||
-rw-r--r-- | NodeOutput.cpp | 11 | ||||
-rw-r--r-- | NodeOutput.h | 2 | ||||
-rw-r--r-- | Observer.cpp | 8 | ||||
-rw-r--r-- | Parser.cpp | 28 | ||||
-rw-r--r-- | Parser.h | 11 | ||||
-rw-r--r-- | circuits/and-test.txt | 13 | ||||
-rw-r--r-- | docs/class-diag.puml | 112 | ||||
-rw-r--r-- | main.cpp | 14 |
20 files changed, 263 insertions, 111 deletions
diff --git a/Circuit.cpp b/Circuit.cpp index cf6312e..8137939 100644 --- a/Circuit.cpp +++ b/Circuit.cpp @@ -1,35 +1,60 @@ #include "Circuit.h" +#include "Exception.h" #include "NodeFactory.h" void Circuit::create(string label, vector<string> nodes) { if (nodes.size() == 1 && NodeFactory::has_type(nodes[0])) return new_node(label, nodes[0]); - for (string node : nodes) - new_net(label, node); + new_net(label, nodes); } void Circuit::new_node(string label, string type) { - if (nodes.find(label) != nodes.end()) return; // TODO: exception! + if (nodes.find(label) != nodes.end()) + throw CircuitException("node with label \"%s\" already exists!", label.c_str()); Node * node = NodeFactory::create(type); - if (node == nullptr) return; // TODO: exception? + if (node == nullptr) + throw CircuitException("unknown type \"%s\"", type.c_str()); nodes[label] = node; printf("[%s] (%s)\n", label.c_str(), type.c_str()); } -void Circuit::new_net(string label, string connection) { - // TODO: instance Net - // TODO: connect Net to connection - printf("[%s] -> %s\n", label.c_str(), connection.c_str()); +void Circuit::new_net(string src, vector<string> dests) { + Net * net = new Net(); + nets.push_back(net); + + Node * node = find_node(src); + if (node == nullptr) + throw CircuitException("unknown source node \"%s\"", src.c_str()); + node->setOutput(net); + + for (auto dest : dests) { + Node * node = find_node(dest); + if (node == nullptr) + throw CircuitException("unknown destination node \"%s\"", dest.c_str()); + node->addInput(net); + } +} + +void Circuit::sim() { + for (auto & node : nodes) { + node.second->sim(); + } +} + +Node * Circuit::find_node(string label) { + auto map_index = this->nodes.find(label); + if (map_index == nodes.end()) return nullptr; + return map_index->second; } Circuit::~Circuit() { - for (auto const & n : nodes) - delete n.second; - for (auto const & n : nets) + for (auto & n : nodes) delete n.second; + for (auto & n : nets) + delete n; } @@ -16,12 +16,15 @@ public: virtual ~Circuit(); public: - void create(string label, vector<string> nodes); - void new_node(string label, string type); - void new_net(string label, string node); + virtual void create(string label, vector<string> nodes); + virtual void new_node(string label, string type); + virtual void new_net(string src, vector<string> dests); + virtual void sim(); private: std::map<string, Node *> nodes = {}; - std::map<string, Net *> nets = {}; + vector<Net *> nets = {}; + + virtual Node * find_node(string label); }; diff --git a/Exception.cpp b/Exception.cpp new file mode 100644 index 0000000..371aaa7 --- /dev/null +++ b/Exception.cpp @@ -0,0 +1,45 @@ +#include "Exception.h" + +#include <cstdarg> +#include <cstdio> +#include <cstdlib> + +Exception::~Exception() { + if (error != NULL) + free(error); +} + +const char * Exception::what() { + return error; +} + +void Exception::va_format(va_list args, const char * fmt) { + va_list args_copy; + va_copy(args_copy, args); + + size_t sz = vsnprintf(NULL, 0, fmt, args_copy) + 1; + if (error != NULL) free(error); + error = (char *) malloc(sz); + va_end(args_copy); + + vsnprintf(error, sz, fmt, args); +} + +Exception::Exception(const char * fmt, ...) { + va_list args; + va_start(args, fmt); + va_format(args, fmt); + va_end(args); +} +CircuitException::CircuitException(const char * fmt, ...) { + va_list args; + va_start(args, fmt); + va_format(args, fmt); + va_end(args); +} +ParserException::ParserException(const char * fmt, ...) { + va_list args; + va_start(args, fmt); + va_format(args, fmt); + va_end(args); +} diff --git a/Exception.h b/Exception.h new file mode 100644 index 0000000..8f4ba4f --- /dev/null +++ b/Exception.h @@ -0,0 +1,27 @@ +#pragma once + +#include <cstdarg> +#include <exception> + +class Exception : public std::exception { +public: + Exception(const char * fmt, ...); + virtual ~Exception(); + virtual const char * what(); + +protected: + Exception() = default; + void va_format(va_list args, const char * fmt); + char * error = NULL; +}; + +class ParserException : public Exception { +public: + ParserException(const char * fmt, ...); +}; + +class CircuitException : public Exception { +public: + CircuitException(const char * fmt, ...); +}; + diff --git a/GateAnd.cpp b/GateAnd.cpp index 5760117..d14d7f6 100644 --- a/GateAnd.cpp +++ b/GateAnd.cpp @@ -18,7 +18,7 @@ SignalLevel GateAnd::level() { } // Concrete Nodes: -void GateAnd::compare() { +void GateAnd::sim() { SignalLevel new_out = this->level(); if (new_out == UNDEFINED) return; @@ -4,10 +4,10 @@ class GateAnd : public Node { public: - GateAnd() {}; + GateAnd() = default; GateAnd(const GateAnd * prototype); - virtual ~GateAnd() = default; - virtual void compare(); + ~GateAnd() = default; + virtual void sim(); virtual GateAnd * clone() const; private: @@ -1,10 +1,6 @@ #include "Net.h" #include <iostream> -Net::Net(){} - -Net::~Net(){} - void Net::setLevel(SignalLevel level){ this->level = level; std::cout << this->size() << std::endl; @@ -2,14 +2,18 @@ #include "Observer.h" -enum SignalLevel {LOW, HIGH, UNDEFINED}; +enum SignalLevel { + LOW, + HIGH, + UNDEFINED +}; -class Net: public Subject { +class Net : public Subject { private: SignalLevel level = UNDEFINED; public: - Net(/* args */); - ~Net(); + Net() = default; + virtual ~Net() = default; virtual void setLevel(SignalLevel); virtual SignalLevel getLevel(); }; @@ -1,22 +1,23 @@ +#include <iostream> + #include "Node.h" #include "NodeFactory.h" - -#include <iostream> +#include "Net.h" Node::Node(const char * type) { NodeFactory::assign(type, this); } -void Node::addInput(Net* net) { +void Node::addInput(Net * net) { net->attach(this); } -void Node::setOutput(Net* net){ +void Node::setOutput(Net * net){ this->output = net; } void Node::update(){ std::cout << "updated" << std::endl; - this->compare(); + this->sim(); } @@ -19,7 +19,7 @@ public: void update(); virtual void addInput(Net *); virtual void setOutput(Net *); - virtual void compare() = 0; + virtual void sim() = 0; protected: Node(const char * type); diff --git a/NodeInput.cpp b/NodeInput.cpp index 046cd72..17f9ed5 100644 --- a/NodeInput.cpp +++ b/NodeInput.cpp @@ -1,10 +1,12 @@ #include "NodeInput.h" +#include <iostream> + NodeInput::NodeInput(const char * type) : Node(type) { } -void NodeInput::compare() { +void NodeInput::sim() { if (this->output == nullptr) return; - + std::cout << this->level << " bar\n"; this->output->setLevel(this->level); } diff --git a/NodeInput.h b/NodeInput.h index 73ef6e1..bcca8f4 100644 --- a/NodeInput.h +++ b/NodeInput.h @@ -7,7 +7,7 @@ public: NodeInput() = default; NodeInput(const NodeInput * prototype); ~NodeInput() = default; - virtual void compare(); + virtual void sim(); virtual NodeInput * clone() const; private: diff --git a/NodeOutput.cpp b/NodeOutput.cpp index cff66c0..00ca006 100644 --- a/NodeOutput.cpp +++ b/NodeOutput.cpp @@ -1,14 +1,17 @@ #include "NodeOutput.h" +#include "Exception.h" + #include <iostream> NodeOutput NodeOutput::instance(NodeOutput::type); NodeOutput::NodeOutput(const char * type) : Node(type) { } -void NodeOutput::compare() { - if (this->inputs.size() > 0) { - std::cout << this->inputs[0]->getLevel() << std::endl; - } +void NodeOutput::sim() { + if (this->inputs.size() == 0) + throw CircuitException("No inputs on probe"); + + std::cout << this->inputs[0]->getLevel() << "foo" << std::endl; } NodeOutput::NodeOutput(const NodeOutput * prototype) : Node() { } diff --git a/NodeOutput.h b/NodeOutput.h index 4e7f742..2e92bf0 100644 --- a/NodeOutput.h +++ b/NodeOutput.h @@ -6,7 +6,7 @@ class NodeOutput : public Node { public: NodeOutput(const NodeOutput * prototype); ~NodeOutput() = default; - virtual void compare(); + virtual void sim(); virtual NodeOutput * clone() const; private: diff --git a/Observer.cpp b/Observer.cpp index d2a1062..ff523b8 100644 --- a/Observer.cpp +++ b/Observer.cpp @@ -1,17 +1,17 @@ -#include "Observer.h" #include <iostream> +#include "Observer.h" + void Observer::update(){ std::cout << 'a' << std::endl; } - -void Subject::attach(Observer* obs){ +void Subject::attach(Observer * obs){ std::cout << "added" << std::endl; this->observers.push_back(obs); } -void Subject::detach(Observer*){ +void Subject::detach(Observer *){ } @@ -1,30 +1,10 @@ #include <cstring> #include <sstream> -#include <cstdarg> #include "Parser.h" using std::getline; -ParserException::ParserException(const char * fmt, ...) { - va_list args; - va_start(args, fmt); - size_t sz = vsnprintf(NULL, 0, fmt, args) + 1; - if (error != NULL) free(error); - error = (char *) malloc(sz); - vsnprintf(error, sz, fmt, args); - va_end(args); -} - -ParserException::~ParserException() { - if (error != NULL) - free(error); -} - -const char * ParserException::what() { - return error; -} - size_t Parser::filter(char * input) { size_t len = strlen(input), @@ -79,11 +59,15 @@ void Parser::parse(istream & input) { } if (circuit == nullptr) throw ParserException("circuit is not initialized!"); - circuit->create(label, nodes); + + try { + circuit->create(label, nodes); + } catch(CircuitException & c) { + throw ParserException("line %u: %s", linenum, c.what()); + } } } - istream & operator >> (istream & s, Parser & parser) { parser.parse(s); return s; @@ -2,22 +2,15 @@ #include <iostream> #include <istream> -#include <exception> + #include "Circuit.h" +#include "Exception.h" using std::istream; using std::string; -class ParserException : public std::exception { -public: - ParserException(const char * fmt, ...); - virtual ~ParserException(); - virtual const char * what(); -private: - char * error = NULL; -}; class Parser { public: diff --git a/circuits/and-test.txt b/circuits/and-test.txt new file mode 100644 index 0000000..7ab3d78 --- /dev/null +++ b/circuits/and-test.txt @@ -0,0 +1,13 @@ +# full adder circuit +# vim:ft=cfg +A: INPUT_LOW; +OUT: PROBE; +# OUT: A; +A: OUT; +# B: INPUT_LOW; +# OUT: PROBE; +# TEST: AND; +# A: TEST; +# B: TEST; +# OUT: TEST; + diff --git a/docs/class-diag.puml b/docs/class-diag.puml index 5efda1b..4d9f489 100644 --- a/docs/class-diag.puml +++ b/docs/class-diag.puml @@ -1,31 +1,49 @@ @startuml -abstract class Node { /' (also ConcreteObserver) '/ - + setOutput(Net*) - + addInput(Net*) - - inputs: Net*[] - - output: Net* - - type: static const char * string - - minInputs: constexpr unsigned int - - maxInputs: constexpr int +skinparam linetype ortho + +class Node <<Template>> { /' (also ConcreteObserver) '/ + +Node() + #Node(const char* type) + +~Node() + #output : Net* + +{abstract} clone() : Node* {query} + #label : string + #inputs : vector<Net*> + +addInput(Net*) : void + +{abstract} compare() : void + +setOutput(Net*) : void + +update() : void + } class Net { /' (also ConcreteSubject) '/ - - level: SignalLevel - + setLevel(SignalLevel) - ' only call notify when setLevel actually changes the level!!!!!!! + +Net() + +~Net() + -level : SignalLevel + +getLevel() : int + +setLevel(SignalLevel) : void } class Subject { - - observers: Observer*[] - + attach(Observer*) - + detach(Observer*) - + notify() + +size() : int + -observers : std::vector<Observer*> + +attach(Observer* obs) : void + +detach(Observer*) : void + +notify() : void } interface Observer { - + update() + +update() : void } -class GateAnd +class GateAnd { + -GateAnd(const char* type) + +GateAnd(const GateAnd* prototype) + +~GateAnd() + +clone() : GateAnd* {query} + -{static} type : constexpr static const char* + -{static} instance : static GateAnd + +compare() : void +} class GateNand class GateNor class GateNot @@ -39,6 +57,8 @@ enum SignalLevel { HIGH UNDEFINED } +Net -- SignalLevel +Node -- SignalLevel Node <|-[dashed]-- GateAnd Node <|-[dashed]-- GateNand @@ -49,30 +69,66 @@ Node <|-[dashed]-- GateXor Node <|-[dashed]-- NodeOutput Node <|-[dashed]-- NodeInput +class NodeInputLow +class NodeInputHigh +NodeInput <|-- NodeInputLow +NodeInput <|-- NodeInputHigh + Subject <|-- Net Observer <|-[dashed]- Node Node -> "owner" Net Observer "*" - Subject +class ParserException { + +ParserException(const char* fmt, ...) + +~ParserException() + -error : char* + +what() : char* +} + class Parser { - + loadFromFile() + +Parser() + +~Parser() + -circuit : Circuit* + -operator<<(Parser& parser, istream s) : istream& + -operator>>(istream s, Parser& parser) : istream& + +{static} filter(char* input) : size_t + +parse(string input) : void + +parse(istream input) : void + +set_circuit(Circuit& circuit) : void } +ParserException - Parser -class CircuitFactory { - + run() - + configure() +class NodeFactory { + +NodeFactory() + +~NodeFactory() + +{static} create(string type) : Node* + -{static} find_type(string type) : Node* + -{static} get_map() : NodeFactoryMap& + +{static} has_type(const char* type) : bool + +{static} has_type(string type) : bool + -{static} normalize_type(string type) : string + -{static} assign(const char* type, const Node* node) : void } class Circuit { - + createNode(string type, string label) - + createLink(string labelA, string labelB) - - - nets: Map<string label, Net*> - - nodes: Map<string label, Node*> + +Circuit() + +~Circuit() + -find_node(string label) : Node* + -nodes : std::map<string, Node*> + -nets : vector<Net*> + +create(string label, vector<string> nodes) : void + +new_net(string src, vector<string> dests) : void + +new_node(string label, string type) : void } -CircuitFactory -[dashed]> Node -CircuitFactory <-[dashed]- Node +Circuit ---> Net +Circuit ---> Node + +Parser -[dashed]> Circuit + +NodeFactory -[dashed]> Node +NodeFactory <-[dashed]- Node @enduml @@ -35,7 +35,7 @@ int main(int argc, char** argv) { main_parser.set_circuit(circuit); - ifstream file("circuits/full-adder.txt"); + ifstream file("circuits/and-test.txt"); try { file >> main_parser; @@ -45,12 +45,12 @@ int main(int argc, char** argv) { return EXIT_FAILURE; } - // try { - // circuit.run(); - // } catch (exception& e) { - // cout << "Circuit error: " << e.what() << endl; - // return EXIT_FAILURE; - // } + try { + circuit.sim(); + } catch (CircuitException & e) { + cout << "Circuit error: " << e.what() << endl; + return EXIT_FAILURE; + } // cout << "Circuit output: " << circuit.getOutput() << endl; |