Logikai szimulátor
 Összes Osztályok Fájl Függvények Változók
logic_vm.hpp
Ugrás a fájl dokumentációjához.
1 #ifndef __LOGIC_VM_HPP__
2 #define __LOGIC_VM_HPP__
3 
4 #include <iostream>
5 #include <fstream>
6 #include <list>
7 #include <vector>
8 #include <functional>
9 #include <utility>
10 
16 class logic_vm {
17  public:
21  class block {
22  public:
29  class port {
30  private:
32  std::string name;
34  bool state;
36  std::vector<port*> driven;
41  bool uninit;
42  public:
43  port(std::string const &name = "port default", bool state = false, block *owner = nullptr, bool uninit=true) : name(name), state(state), owner(owner), uninit(uninit) {
44  }
50  void set_state(bool new_state) {
51  if ((state != new_state) || uninit) {
52  uninit=false;
53  if(owner!=nullptr) {
54  if(owner->parent!=nullptr) {
55  std::cout << owner->parent->get_name() << ".";
56  }
57  std::cout << owner->get_id() << ".";
58  }
59  std::cout << name << ": " << state << " -> " << new_state << std::endl;
60  state = new_state;
61  if(owner!=nullptr && driven.size()==0) {
62  if (owner->parent != nullptr) {
63  owner->parent->queue.push_back(std::make_pair(owner->parent->get_time() + owner->get_delay(), [&] () {owner->eval(); } ));
64  }
65  else {
66  throw "";
67  }
68  }
69  if(driven.size()>0) {
70  for(auto &drive: driven) {
71  drive->set_state(state);
72  }
73  }
74  }
75  }
77  void set_name(std::string const &new_name) {
78  name = new_name;
79  }
81  block* get_owner() { return owner; }
87  bool get_state() { return state; }
93  std::string get_name() { return name; }
99  void add_driven(port &p) {
100  driven.push_back(&p);
101  owner->parent->dot_file << owner->id << name << "->" << p.owner->id << p.name << "\n";
102  }
104  void print() {
105  std::cout << "\t" << name << " -> " << state;
106  // if(owner!=nullptr)
107  // std::cout << "\t Owner: " << owner->id ;
108  // std::cout << std::endl;
109  }
110  ~port() {}
111  };
112  protected:
114  std::string id;
116  std::vector<port> input;
118  std::vector<port> output;
120  std::vector<std::function<void()> > events;
122  unsigned delay;
125  public:
126  block(std::string const &id = "block default", unsigned delay=1, logic_vm *parent=nullptr) : id(id), delay(delay), parent(parent) {};
132  void set_id(std::string const &tag) {
133  id = tag;
134  }
140  std::string get_id() { return id; }
147  void add_port(std::string const &name, std::string type) {
148  parent->dot_file << id << name << " [label=\"" << name << "\" shape=\"circle\"]\n";
149  if(type=="input") {
150  input.push_back(port(name,false,this));
151  parent->dot_file << id << name << "->" << id << "\n";
152  }
153  else {
154  output.push_back(port(name,false,this));
155  parent->dot_file << id << "->" << id << name << "\n";
156  }
157  }
163  unsigned get_delay() { return delay; }
170  void set_port(std::string const &name, bool value) {
171  for(auto &p: input) {
172  if(p.get_name() == name) {
173  p.set_state(value);
174  }
175  }
176  }
183  port & get_port(std::string const& name){
184  for(auto &in: input)
185  if(in.get_name() == name)
186  return in;
187  for(auto &out: output)
188  if(out.get_name() == name)
189  return out;
190  throw "";
191  }
199  void connect(std::string const &out, block &b, std::string const &in) {
200  this->get_port(out).add_driven(b.get_port(in));
201 
202  std::cout << "Connect ";
203  if(this->parent != nullptr)
204  std::cout << this->parent->get_name() << ".";
205  std::cout << this->id << "." << get_port(out).get_name() << " -> ";
206  if(b.parent != nullptr)
207  std::cout << b.parent->get_name() << ".";
208  std::cout << b.id << "." << b.get_port(in).get_name() << std::endl;
209  }
214  void eval() {
215  for(auto gyi: events) {
216  gyi();
217  }
218  }
222  void print() {
223  std::cout << "ID: " << id << std::endl;
224  std::cout << "Delay: " << delay << std::endl;
225  std::cout << "Input(s): ";
226  for(auto &in: input) in.print();
227  std::cout << std::endl;
228  std::cout << "Output(s): ";
229  for(auto &out: output) out.print();
230  std::cout << std::endl;
231  if (parent != nullptr)
232  std::cout << "Parent: " << parent->get_name() << std::endl;
233  }
239  void set_parent(logic_vm *p) { parent = p; }
240  virtual ~block() { }
241 
242  };
243  private:
245  unsigned time_stamp=0;
247  std::string vm_name;
248  protected:
253  std::list<std::pair<unsigned, std::function<void()> > > queue;
255  std::ofstream dot_file;
256  public:
258  std::list<block*> elements;
259  logic_vm(std::string const &vm_name="Default-VM") : vm_name(vm_name) {
260  std::cout << "Logic VM " << vm_name << " has been created." << std::endl;
261  dot_file.open(vm_name+".dot");
262  dot_file << "digraph " << vm_name << " {\n";
263  }
269  void add(block *element) {
270  element->set_parent(this);
271  elements.push_back(element);
272  dot_file << element->get_id() << " [label=\"" << element->get_id() << "\" shape=\"box\"]" << "\n";
273  }
274 
281  block& element(std::string const &id) {
282  for( auto &element: elements)
283  if (element->get_id() == id)
284  return *element;
285  throw "";
286  }
287 
289  std::string get_name() { return vm_name; }
291  unsigned get_time() { return time_stamp; }
293  void info() {
294  std::cout << " VM informations:" << std::endl;
295  std::cout << "\t vm_name: \t\t" << vm_name << std::endl;
296  std::cout << "\t time_stamp: \t\t" << time_stamp << std::endl;
297  std::cout << "\t Elements in the VM: \t" << elements.size() << std::endl;
298  std::cout << "\t Events in the queue: \t" << queue.size() << std::endl;
299  }
300 
306  void run(unsigned end) {
307  unsigned until = time_stamp+end;
308  for(; time_stamp<until; ++time_stamp) {
309  while(queue.front().first == time_stamp) {
310  std::cout << "Event at " << time_stamp << std::endl;
311  (queue.front().second)();
312  queue.pop_front();
313  }
314  }
315  }
316 
320  void list_queue() {
321  for(auto instance: queue) {
322  std::cout << "Time: " << instance.first << std::endl;
323  }
324  }
325 
327  dot_file << "}\n";
328  dot_file.close();
329  std::cout << "Logic VM " << vm_name << " has been destructed." << std::endl;
330  }
331 };
332 
333 #endif // __LOGIC_VM_HPP__