democ.hpp
1 /**********************************************************************
2  * de.hpp -- The discrete-event model of computation *
3  * *
4  * Authors: Mikkel Koefoed Jakobsen (mkoe@imm.dtu.dk) *
5  * *
6  * Purpose: Providing promitive element required for modeling *
7  * discrete-evnent systems in ForSyDe-SystemC *
8  * *
9  * Usage: This file is included automatically *
10  * *
11  * License: BSD3 *
12  *******************************************************************/
13 
14 #ifndef DEMOC_HPP
15 #define DEMOC_HPP
16 
17 
18 #include <vector>
19 
20 using namespace sc_core;
21 
22 namespace ForSyDe {
23 namespace DiscreteEvent {
24 
25 
26 template <class T> class Event;
27 template <class T> class Signal;
28 
29 template <class T>
30 std::string toString(const Event<T> & e) {
31  std::stringstream s;
32  s << "(" << e.time << "," << e.value << ")";
33  return s.str();
34 }
35 
36 template <class T>
37 std::string toString(const std::vector<Event<T> > & es) {
38  std::stringstream s;
39  typename std::vector<Event<T> >::iterator i;
40  if (es.empty()) {
41  s << "[]";
42  } else {
43  s << "[" << toString<T>(es.front());
44  i = ++(es.begin());
45  for (; i != es.end(); ++i) {
46  s << "," << toString<T>(*i);
47  }
48  s << "]";
49  }
50  return s.str();
51 }
52 
53 template <class T>
54 std::string toString(Signal<T> & signal) {
55  return toString<T>(signal.events);
56 }
57 
58 } /* namespace DiscreteEvent */
59 } /* namespace ForSyDe */
60 
61 
62 #include <deque>
63 
64 namespace ForSyDe {
65 namespace DiscreteEvent {
66 
67 template <typename O>
68 struct tuple {
69  tuple(const sc_core::sc_time & time, const O value) : time(time), value(value) {}
70 
71  sc_core::sc_time time;
72  O value;
73 };
74 
75 template <class O1>
76 class Out1 : public sc_core::sc_module {
77 public:
78  sc_core::sc_out<O1> o1;
79 
80  Out1(const sc_core::sc_module_name & name, const sc_core::sc_time & delay1) : sc_core::sc_module(name) , delay1(delay1) {
81  SC_METHOD(delay1_method);
82  dont_initialize();
83  sensitive << action1;
84  }
85 
86 protected:
87  void delayOutput(const O1 & o1) {
88  this->f1.push_back(tuple<O1>(sc_core::sc_time_stamp() + this->delay1,o1));
89  this->next_event();
90  }
91 
92 private:
93  std::deque<tuple<O1> > f1;
94  sc_core::sc_event action1;
95  sc_core::sc_time delay1;
96 
97  SC_HAS_PROCESS(Out1);
98 
99  void delay1_method() {
100  if (!f1.empty()) {
101  o1 = f1.front().value;
102  f1.pop_front();
103  this->next_event();
104  }
105  }
106 
107  void next_event() {
108  if (!f1.empty()) {
109  const sc_core::sc_time t1 = f1.front().time;
110  this->action1.notify(t1 - sc_core::sc_time_stamp());
111  }
112  }
113 };
114 
115 template <class O1,class O2>
116 class Out2 : public sc_core::sc_module {
117 public:
118  sc_core::sc_out<O1> o1;
119  sc_core::sc_out<O2> o2;
120 
121  Out2(const sc_core::sc_module_name & name, const sc_core::sc_time & delay1, const sc_core::sc_time & delay2) : sc_core::sc_module(name) , delay1(delay1) , delay2(delay2) {
122  SC_METHOD(delay1_method);
123  dont_initialize();
124  sensitive << action1;
125  SC_METHOD(delay2_method);
126  dont_initialize();
127  sensitive << action2;
128  }
129 
130 protected:
131  void delayOutput(const O1 & o1, const O2 & o2) {
132  this->f1.push_back(tuple<O1>(sc_core::sc_time_stamp() + this->delay1,o1));
133  this->next_event1();
134  this->f2.push_back(tuple<O2>(sc_core::sc_time_stamp() + this->delay2,o2));
135  this->next_event2();
136  }
137 
138 private:
139  std::deque<tuple<O1> > f1;
140  std::deque<tuple<O2> > f2;
141  sc_core::sc_event action1, action2;
142  sc_core::sc_time delay1, delay2;
143 
144  SC_HAS_PROCESS(Out2);
145 
146  void delay1_method() {
147  if (!f1.empty()) {
148  o1 = f1.front().value;
149  f1.pop_front();
150  this->next_event1();
151  }
152  }
153 
154  void delay2_method() {
155  if (!f2.empty()) {
156  o2 = f2.front().value;
157  f2.pop_front();
158  this->next_event2();
159  }
160  }
161 
162  void next_event1() {
163  if (!f1.empty()) {
164  const sc_core::sc_time t1 = f1.front().time;
165  this->action1.notify(t1 - sc_core::sc_time_stamp());
166  }
167  }
168 
169  void next_event2() {
170  if (!f2.empty()) {
171  const sc_core::sc_time t2 = f2.front().time;
172  this->action2.notify(t2 - sc_core::sc_time_stamp());
173  }
174  }
175 };
176 
177 template <class O1,class O2, class O3>
178 class Out3 : public sc_core::sc_module {
179 public:
180  sc_core::sc_out<O1> o1;
181  sc_core::sc_out<O2> o2;
182  sc_core::sc_out<O3> o3;
183 
184  Out3(const sc_core::sc_module_name & name, const sc_core::sc_time & delay1, const sc_core::sc_time & delay2, const sc_core::sc_time & delay3) : sc_core::sc_module(name) , delay1(delay1) , delay2(delay2) , delay3(delay3) {
185  SC_METHOD(delay1_method);
186  dont_initialize();
187  sensitive << action1;
188  SC_METHOD(delay2_method);
189  dont_initialize();
190  sensitive << action2;
191  SC_METHOD(delay3_method);
192  dont_initialize();
193  sensitive << action3;
194  }
195 
196 protected:
197  void delayOutput(const O1 & o1, const O2 & o2, const O3 & o3) {
198  this->f1.push_back(tuple<O1>(sc_core::sc_time_stamp() + this->delay1,o1));
199  this->next_event1();
200  this->f2.push_back(tuple<O2>(sc_core::sc_time_stamp() + this->delay2,o2));
201  this->next_event2();
202  this->f3.push_back(tuple<O3>(sc_core::sc_time_stamp() + this->delay3,o3));
203  this->next_event3();
204  }
205 
206 private:
207  std::deque<tuple<O1> > f1;
208  std::deque<tuple<O2> > f2;
209  std::deque<tuple<O3> > f3;
210  sc_core::sc_event action1, action2, action3;
211  sc_core::sc_time delay1, delay2, delay3;
212 
213  SC_HAS_PROCESS(Out3);
214 
215  void delay1_method() {
216  if (!f1.empty()) {
217  o1 = f1.front().value;
218  f1.pop_front();
219  this->next_event1();
220  }
221  }
222 
223  void delay2_method() {
224  if (!f2.empty()) {
225  o2 = f2.front().value;
226  f2.pop_front();
227  this->next_event2();
228  }
229  }
230 
231  void delay3_method() {
232  if (!f3.empty()) {
233  o3 = f3.front().value;
234  f3.pop_front();
235  this->next_event3();
236  }
237  }
238 
239  void next_event1() {
240  if (!f1.empty()) {
241  const sc_core::sc_time t1 = f1.front().time;
242  this->action1.notify(t1 - sc_core::sc_time_stamp());
243  }
244  }
245 
246  void next_event2() {
247  if (!f2.empty()) {
248  const sc_core::sc_time t2 = f2.front().time;
249  this->action2.notify(t2 - sc_core::sc_time_stamp());
250  }
251  }
252 
253  void next_event3() {
254  if (!f3.empty()) {
255  const sc_core::sc_time t3 = f3.front().time;
256  this->action3.notify(t3 - sc_core::sc_time_stamp());
257  }
258  }
259 };
260 
261 template <class I1,class O1>
262 class Map : public Out1<O1> {
263 public:
264  sc_core::sc_in<I1> i1;
265 
266  Map(const sc_core::sc_module_name & name, const sc_core::sc_time & delay) : Out1<O1>::Out1(name,delay) {
267  SC_METHOD(method);
268  sc_core::sc_module::dont_initialize();
269  sc_core::sc_module::sensitive << i1 << start;
270  this->start.notify(SC_ZERO_TIME);
271  }
272 
273 private:
274  sc_core::sc_event start;
275 
276  SC_HAS_PROCESS(Map);
277 
278  void method() {
279  this->delayOutput(this->func(i1));
280  }
281 
282  virtual O1 func(const I1) const = 0;
283 };
284 
285 template <class I1,class I2,class O1>
286 class Zip : public Out1<O1> {
287 public:
288  sc_core::sc_in<I1> i1;
289  sc_core::sc_in<I2> i2;
290 
291  Zip(const sc_core::sc_module_name & name, const sc_core::sc_time & delay) : Out1<O1>::Out1(name,delay) {
292  SC_METHOD(method);
293  sc_core::sc_module::dont_initialize();
294  sc_core::sc_module::sensitive << i1 << i2 << start;
295  this->start.notify(SC_ZERO_TIME);
296  }
297 
298 private:
299  sc_core::sc_event start;
300 
301  SC_HAS_PROCESS(Zip);
302 
303  void method() {
304  this->delayOutput(this->func(i1,i2));
305  }
306 
307  virtual O1 func(const I1, const I2) const = 0;
308 };
309 
310 template <class I1,class I2,class I3,class O1>
311 class Zip3 : public Out1<O1> {
312 public:
313  sc_core::sc_in<I1> i1;
314  sc_core::sc_in<I2> i2;
315  sc_core::sc_in<I3> i3;
316 
317  Zip3(const sc_core::sc_module_name & name, const sc_core::sc_time & delay) : Out1<O1>::Out1(name,delay) {
318  SC_METHOD(method);
319  sc_core::sc_module::dont_initialize();
320  sc_core::sc_module::sensitive << i1 << i2 << i3 << start;
321  this->start.notify(SC_ZERO_TIME);
322  }
323 
324 private:
325  sc_core::sc_event start;
326 
327  SC_HAS_PROCESS(Zip3);
328 
329  void method() {
330  this->delayOutput(this->func(i1,i2,i3));
331  }
332 
333  virtual O1 func(const I1, const I2, const I3) const = 0;
334 };
335 
336 template <class I1,class I2,class I3,class I4,class O1>
337 class Zip4 : public Out1<O1> {
338 public:
339  sc_core::sc_in<I1> i1;
340  sc_core::sc_in<I2> i2;
341  sc_core::sc_in<I3> i3;
342  sc_core::sc_in<I4> i4;
343 
344  Zip4(const sc_core::sc_module_name & name, const sc_core::sc_time & delay) : Out1<O1>::Out1(name,delay) {
345  SC_METHOD(method);
346  sc_core::sc_module::dont_initialize();
347  sc_core::sc_module::sensitive << i1 << i2 << i3 << i4 << start;
348  this->start.notify(SC_ZERO_TIME);
349  }
350 
351 private:
352  sc_core::sc_event start;
353 
354  SC_HAS_PROCESS(Zip4);
355 
356  void method() {
357  this->delayOutput(this->func(i1,i2,i3,i4));
358  }
359 
360  virtual O1 func(const I1, const I2, const I3, const I4) const = 0;
361 };
362 
363 template <class T1>
364 class FanOut : public Out2<T1,T1> {
365  sc_core::sc_in<T1> i1;
366 
367  FanOut(const sc_core::sc_module_name & name) : Out2<T1,T1>::Out2(name,SC_ZERO_TIME,SC_ZERO_TIME) {
368  SC_METHOD(method);
369  sc_core::sc_module::dont_initialize();
370  sc_core::sc_module::sensitive << i1 << start;
371  this->start.notify(SC_ZERO_TIME);
372  }
373 
374 private:
375  sc_core::sc_event start;
376 
377  SC_HAS_PROCESS(FanOut);
378 
379  void method() {
380  T1 tmp = i1;
381  this->delayOutput(tmp,tmp);
382  }
383 };
384 
385 template <class T1>
386 class FanOut3 : public Out3<T1,T1,T1> {
387  sc_core::sc_in<T1> i1;
388 
389  FanOut3(const sc_core::sc_module_name & name) : Out3<T1,T1,T1>::Out3(name,SC_ZERO_TIME,SC_ZERO_TIME,SC_ZERO_TIME) {
390  SC_METHOD(method);
391  sc_core::sc_module::dont_initialize();
392  sc_core::sc_module::sensitive << i1 << start;
393  this->start.notify(SC_ZERO_TIME);
394  }
395 
396 private:
397  sc_core::sc_event start;
398 
399  SC_HAS_PROCESS(FanOut3);
400 
401  void method() {
402  T1 tmp = i1;
403  this->delayOutput(tmp,tmp,tmp);
404  }
405 };
406 
407 } /* namespace DiscreteEvent */
408 } /* namespace ForSyDe */
409 
410 
411 #include <deque>
412 #include <vector>
413 
414 namespace ForSyDe {
415 namespace DiscreteEvent {
416 
417 template <class T>
418 class Event {
419 public:
420  Event() : time(sc_core::sc_time(0,SC_SEC)) , value() {};
421  Event(const sc_core::sc_time & time, const T & value) : time(time), value(value) {}
422 
423  sc_core::sc_time time;
424  T value;
425 };
426 
427 template <class T>
428 class Signal {
429  friend std::string toString<T>(Signal<T> &);
430 public:
431  typedef std::vector<Event<T> > EventList_t;
432 
433  Signal() : events(), now(0,SC_SEC), last(), index(0) {}
434 
435  Signal(const EventList_t & events) : events(events), now(0,SC_SEC), last(), index(0) {}
436 
437  void append(const sc_core::sc_time & time, const T & value) {
438  this->events.push_back(Event<T>(time,value));
439  }
440 
441  const Event<T> next() {
442  if (this->index != this->events.size()) {
443  Event<T> head = this->events[this->index];
444  ++this->index;
445  Event<T> result(head.time - now,head.value);
446  now = head.time;
447  last = head;
448  return result;
449  } else {
450  return last;
451  }
452  }
453 
454  bool has_next() const {
455  return (this->index != this->events.size());
456  }
457 private:
458  EventList_t events;
459  sc_core::sc_time now;
460  Event<T> last;
461  typename EventList_t::size_type index;
462 };
463 
464 } /* namespace DiscreteEvent */
465 } /* namespace ForSyDe */
466 
467 
468 
469 namespace ForSyDe {
470 namespace DiscreteEvent {
471 
472 template <class T>
473 class Driver : public sc_core::sc_module {
474 public:
475  sc_core::sc_out<T> out;
476 
477  Driver(const sc_core::sc_module_name & name, const Signal<T> & signal) : sc_core::sc_module(name), signal(signal) {
478  SC_THREAD(driver);
479  }
480 private:
481  SC_HAS_PROCESS(Driver);
482 
484 
485  void driver() {
486  while (this->signal.has_next()) {
487  Event<T> event = this->signal.next();
488  wait(event.time);
489  out = event.value;
490  }
491  }
492 };
493 
494 } /* namespace DiscreteEvent */
495 } /* namespace ForSyDe */
496 
497 #endif /* DEMOC_H */
498 
Definition: democ.hpp:76
Definition: democ.hpp:473
Definition: democ.hpp:386
Definition: democ.hpp:364
The namespace for ForSyDe.
Definition: abssemantics.hpp:30
Definition: democ.hpp:286
CT2CT signal
The CT::signal is an alias for CT::CT2CT.
Definition: ct_process.hpp:50
Definition: democ.hpp:178
Definition: democ.hpp:337
Definition: democ.hpp:26
Definition: democ.hpp:27
Definition: democ.hpp:116
Definition: democ.hpp:262
Definition: democ.hpp:311
Definition: democ.hpp:68
A ForSyDe signal is used to inter-connect processes.
Definition: abssemantics.hpp:70