aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Circuit.cpp47
-rw-r--r--Circuit.h11
-rw-r--r--Exception.cpp45
-rw-r--r--Exception.h27
-rw-r--r--GateAnd.cpp2
-rw-r--r--GateAnd.h6
-rw-r--r--Net.cpp4
-rw-r--r--Net.h12
-rw-r--r--Node.cpp11
-rw-r--r--Node.h2
-rw-r--r--NodeInput.cpp6
-rw-r--r--NodeInput.h2
-rw-r--r--NodeOutput.cpp11
-rw-r--r--NodeOutput.h2
-rw-r--r--Observer.cpp8
-rw-r--r--Parser.cpp28
-rw-r--r--Parser.h11
-rw-r--r--circuits/and-test.txt13
-rw-r--r--docs/class-diag.puml112
-rw-r--r--main.cpp14
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;
}
diff --git a/Circuit.h b/Circuit.h
index 5fd8d23..0cc08c6 100644
--- a/Circuit.h
+++ b/Circuit.h
@@ -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;
diff --git a/GateAnd.h b/GateAnd.h
index 187f7b8..142c628 100644
--- a/GateAnd.h
+++ b/GateAnd.h
@@ -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:
diff --git a/Net.cpp b/Net.cpp
index 5b3f5e3..249b6bb 100644
--- a/Net.cpp
+++ b/Net.cpp
@@ -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;
diff --git a/Net.h b/Net.h
index 150c9b6..7168186 100644
--- a/Net.h
+++ b/Net.h
@@ -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();
};
diff --git a/Node.cpp b/Node.cpp
index a0fc27b..d3564da 100644
--- a/Node.cpp
+++ b/Node.cpp
@@ -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();
}
diff --git a/Node.h b/Node.h
index 43cfc6c..b7f6681 100644
--- a/Node.h
+++ b/Node.h
@@ -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 *){
}
diff --git a/Parser.cpp b/Parser.cpp
index 84c3217..08ff2b0 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -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;
diff --git a/Parser.h b/Parser.h
index 3a86eec..b6d7bd5 100644
--- a/Parser.h
+++ b/Parser.h
@@ -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
diff --git a/main.cpp b/main.cpp
index 0ff11b2..5fcfb3e 100644
--- a/main.cpp
+++ b/main.cpp
@@ -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;