aboutsummaryrefslogtreecommitdiff
path: root/Circuit.cpp
blob: 731e79fa64df2b9e6e7de00632154c1ae65ba2fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <format>

#include "Circuit.h"
#include "Exception.h"
#include "NodeFactory.h"

#include "NodeOutputVisitor.h"
#include "prut.h"

using std::format;

void Circuit::create(string label, vector<string> nodes) {
	if (nodes.size() == 1 && NodeFactory::has_type(nodes[0]))
		return new_node(label, nodes[0]);

	new_net(label, nodes);
	ld->add_connection(label, nodes);
}

void Circuit::new_node(string label, string type) {
	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)
		throw CircuitException("unknown type \"%s\"", type.c_str());

	nodes[label] = node;

	prutprintf("[%s] (%s)", label.c_str(), type.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);
		prutprintf("%s -> %s", src.c_str(), dest.c_str());
	}
}

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 & n : nodes)
		delete n.second;
	for (auto & n : nets)
		delete n;
}

string Circuit::result() {
	string output;

	for (auto & n : nodes) {
		NodeOutputVisitor visitor;
		n.second->accept(visitor);
		if (!visitor.output_node) continue;

		output += std::format("{}: {}\n", n.first, std::to_string(visitor.level));
	}

	return output;
}