dt_process_constructors.hpp
Go to the documentation of this file.
1 /**********************************************************************
2  * dt_process_constructors.hpp -- Process constructors in the DT *
3  * MOC *
4  * *
5  * Author: Hosein Attarzadeh (shan2@kth.se) *
6  * *
7  * Purpose: Providing basic process constructors for modeling *
8  * discrete-time systems in ForSyDe-SystemC *
9  * *
10  * Usage: This file is included automatically *
11  * *
12  * License: BSD3 *
13  *******************************************************************/
14 
15 #ifndef DT_PROCESS_CONSTRUCTORS_HPP
16 #define DT_PROCESS_CONSTRUCTORS_HPP
17 
25 #include <functional>
26 #include <tuple>
27 
28 #include "abst_ext.hpp"
29 #include "dt_process.hpp"
30 
31 namespace ForSyDe
32 {
33 
34 namespace DT
35 {
36 
37 using namespace sc_core;
38 
40 
44 template <typename T0, typename T1>
45 class comb : public dt_process
46 {
47 public:
50 
52  typedef std::function<void(T0&,const T1&)> functype;
53 
55 
59  comb(sc_module_name _name,
60  functype _func
61  ) : dt_process(_name), iport1("iport1"), oport1("oport1"),
62  _func(_func), invoke(false)
63  {
64 #ifdef FORSYDE_INTROSPECTION
65  std::string func_name = std::string(basename());
66  func_name = func_name.substr(0, func_name.find_last_not_of("0123456789")+1);
67  arg_vec.push_back(std::make_tuple("_func",func_name+std::string("_func")));
68 #endif
69  }
70 
72  std::string forsyde_kind() const {return "DT::comb";}
73 
74 private:
75  // Inputs and output variables
76  abst_ext<T0>* oval;
77  abst_ext<T1>* ival1;
78 
80  functype _func;
81 
82  // whether the function should be invoked in this iteration
83  bool invoke;
84 
85  //Implementing the abstract semantics
86  void init()
87  {
88  oval = new abst_ext<T0>;
89  ival1 = new abst_ext<T1>;
90  }
91 
92  void prep()
93  {
94  auto tval1 = iport1.read();
95  if (is_present(tval1))
96  {
97  *ival1 = tval1;
98  invoke = true;
99  }
100  }
101 
102  void exec()
103  {
104  if (invoke)
105  {
106  auto tval = new T0;
107  _func(*tval, unsafe_from_abst_ext(*ival1));
108  set_val(*oval, *tval);
109  invoke = false;
110  }
111  else
112  set_abst(*oval);
113  }
114 
115  void prod()
116  {
117  WRITE_MULTIPORT(oport1, *oval)
118  }
119 
120  void clean()
121  {
122  delete ival1;
123  delete oval;
124  }
125 
126 #ifdef FORSYDE_INTROSPECTION
127  void bindInfo()
128  {
129  boundInChans.resize(1); // only one input port
130  boundInChans[0].port = &iport1;
131  boundOutChans.resize(1); // only one output port
132  boundOutChans[0].port = &oport1;
133  }
134 #endif
135 };
136 
138 
140 template <typename T0, typename T1, typename T2>
141 class comb2 : public dt_process
142 {
143 public:
147 
149  typedef std::function<void(T0&, const T1&, const T2&)> functype;
150 
152 
156  comb2(sc_module_name _name,
157  functype _func
158  ) : dt_process(_name), iport1("iport1"), iport2("iport2"), oport1("oport1"),
159  _func(_func)
160  {
161 #ifdef FORSYDE_INTROSPECTION
162  std::string func_name = std::string(basename());
163  func_name = func_name.substr(0, func_name.find_last_not_of("0123456789")+1);
164  arg_vec.push_back(std::make_tuple("_func",func_name+std::string("_func")));
165 #endif
166  }
167 
169  std::string forsyde_kind() const {return "DT::comb2";}
170 private:
171  // Inputs and output variables
172  abst_ext<T0>* oval;
173  abst_ext<T1>* ival1;
174  abst_ext<T2>* ival2;
175 
177  functype _func;
178 
179  // whether the function should be invoked in this iteration
180  bool invoke;
181 
182  //Implementing the abstract semantics
183  void init()
184  {
185  oval = new abst_ext<T0>;
186  ival1 = new abst_ext<T1>;
187  ival2 = new abst_ext<T2>;
188  invoke = false;
189  }
190 
191  void prep()
192  {
193  auto tval1 = iport1.read();
194  if (is_present(tval1))
195  {
196  *ival1 = tval1;
197  invoke = true;
198  }
199  auto tval2 = iport2.read();
200  if (is_present(tval2))
201  {
202  *ival2 = tval2;
203  invoke = true;
204  }
205  }
206 
207  void exec()
208  {
209  if (invoke)
210  {
211  auto tval = new T0;
212  _func(*tval, unsafe_from_abst_ext(*ival1), unsafe_from_abst_ext(*ival2));
213  set_val(*oval, *tval);
214  invoke = false;
215  }
216  else
217  set_abst(*oval);
218  }
219 
220  void prod()
221  {
222  WRITE_MULTIPORT(oport1, *oval)
223  }
224 
225  void clean()
226  {
227  delete ival2;
228  delete ival1;
229  delete oval;
230  }
231 
232 #ifdef FORSYDE_INTROSPECTION
233  void bindInfo()
234  {
235  boundInChans.resize(2); // only one input port
236  boundInChans[0].port = &iport1;
237  boundInChans[1].port = &iport2;
238  boundOutChans.resize(1); // only one output port
239  boundOutChans[0].port = &oport1;
240  }
241 #endif
242 };
243 
245 
247 template <typename T0, typename T1, typename T2, typename T3>
248 class comb3 : public dt_process
249 {
250 public:
255 
257  typedef std::function<void(T0&, const T1&, const T2&, const T3&)> functype;
258 
259 
261 
265  comb3(sc_module_name _name,
266  functype _func
267  ) : dt_process(_name), iport1("iport1"), iport2("iport2"), iport3("iport3"),
268  oport1("oport1"), _func(_func)
269  {
270 #ifdef FORSYDE_INTROSPECTION
271  std::string func_name = std::string(basename());
272  func_name = func_name.substr(0, func_name.find_last_not_of("0123456789")+1);
273  arg_vec.push_back(std::make_tuple("_func",func_name+std::string("_func")));
274 #endif
275  }
276 
278  std::string forsyde_kind() const {return "DT::comb3";}
279 
280 private:
281  // Inputs and output variables
282  abst_ext<T0>* oval;
283  abst_ext<T1>* ival1;
284  abst_ext<T2>* ival2;
285  abst_ext<T3>* ival3;
286 
288  functype _func;
289 
290  bool invoke;
291 
292  //Implementing the abstract semantics
293  void init()
294  {
295  oval = new abst_ext<T0>;
296  ival1 = new abst_ext<T1>;
297  ival2 = new abst_ext<T2>;
298  ival3 = new abst_ext<T3>;
299  invoke = false;
300  }
301 
302  void prep()
303  {
304  auto tval1 = iport1.read();
305  if (is_present(tval1))
306  {
307  *ival1 = tval1;
308  invoke = true;
309  }
310  auto tval2 = iport2.read();
311  if (is_present(tval2))
312  {
313  *ival2 = tval2;
314  invoke = true;
315  }
316  auto tval3 = iport3.read();
317  if (is_present(tval3))
318  {
319  *ival3 = tval3;
320  invoke = true;
321  }
322  }
323 
324  void exec()
325  {
326  if (invoke)
327  {
328  auto tval = new T0;
329  _func(*tval, unsafe_from_abst_ext(*ival1), unsafe_from_abst_ext(*ival2),
330  unsafe_from_abst_ext(*ival3));
331  set_val(*oval, *tval);
332  invoke = false;
333  }
334  else
335  set_abst(*oval);
336  }
337 
338  void prod()
339  {
340  WRITE_MULTIPORT(oport1, *oval)
341  }
342 
343  void clean()
344  {
345  delete ival3;
346  delete ival2;
347  delete ival1;
348  delete oval;
349  }
350 
351 #ifdef FORSYDE_INTROSPECTION
352  void bindInfo()
353  {
354  boundInChans.resize(3); // only one input port
355  boundInChans[0].port = &iport1;
356  boundInChans[1].port = &iport2;
357  boundInChans[2].port = &iport3;
358  boundOutChans.resize(1); // only one output port
359  boundOutChans[0].port = &oport1;
360  }
361 #endif
362 };
363 
365 
367 template <typename T0, typename T1, typename T2, typename T3, typename T4>
368 class comb4 : public dt_process
369 {
370 public:
376 
378  typedef std::function<void(T0&, const T1&, const T2&, const T3&, const T4&)> functype;
380 
384  comb4(sc_module_name _name,
385  functype _func
386  ) : dt_process(_name), iport1("iport1"), iport2("iport2"),
387  iport3("iport3"), iport4("iport4"), _func(_func)
388  {
389 #ifdef FORSYDE_INTROSPECTION
390  std::string func_name = std::string(basename());
391  func_name = func_name.substr(0, func_name.find_last_not_of("0123456789")+1);
392  arg_vec.push_back(std::make_tuple("_func",func_name+std::string("_func")));
393 #endif
394  }
395 
397  std::string forsyde_kind() const{return "DT::comb4";}
398 
399 private:
400  // Inputs and output variables
401  abst_ext<T0>* oval;
402  abst_ext<T1>* ival1;
403  abst_ext<T2>* ival2;
404  abst_ext<T3>* ival3;
405  abst_ext<T4>* ival4;
406 
408  functype _func;
409 
410  bool invoke;
411 
412  //Implementing the abstract semantics
413  void init()
414  {
415  oval = new abst_ext<T0>;
416  ival1 = new abst_ext<T1>;
417  ival2 = new abst_ext<T2>;
418  ival3 = new abst_ext<T3>;
419  ival4 = new abst_ext<T4>;
420  invoke = false;
421  }
422 
423  void prep()
424  {
425  auto tval1 = iport1.read();
426  if (is_present(tval1))
427  {
428  *ival1 = tval1;
429  invoke = true;
430  }
431  auto tval2 = iport2.read();
432  if (is_present(tval2))
433  {
434  *ival2 = tval2;
435  invoke = true;
436  }
437  auto tval3 = iport3.read();
438  if (is_present(tval3))
439  {
440  *ival3 = tval3;
441  invoke = true;
442  }
443  auto tval4 = iport4.read();
444  if (is_present(tval4))
445  {
446  *ival4 = tval4;
447  invoke = true;
448  }
449  }
450 
451  void exec()
452  {
453  if (invoke)
454  {
455  auto tval = new T0;
456  _func(*tval, unsafe_from_abst_ext(*ival1), unsafe_from_abst_ext(*ival2),
457  unsafe_from_abst_ext(*ival3), unsafe_from_abst_ext(*ival4));
458  set_val(*oval, *tval);
459  invoke = false;
460  }
461  else
462  set_abst(*oval);
463  }
464 
465  void prod()
466  {
467  WRITE_MULTIPORT(oport1, *oval)
468  }
469 
470  void clean()
471  {
472  delete ival4;
473  delete ival3;
474  delete ival2;
475  delete ival1;
476  delete oval;
477  }
478 
479 #ifdef FORSYDE_INTROSPECTION
480  void bindInfo()
481  {
482  boundInChans.resize(4); // only one input port
483  boundInChans[0].port = &iport1;
484  boundInChans[1].port = &iport2;
485  boundInChans[2].port = &iport3;
486  boundInChans[3].port = &iport4;
487  boundOutChans.resize(1); // only one output port
488  boundOutChans[0].port = &oport1;
489  }
490 #endif
491 };
492 
494 
503 template <class T>
504 class delay : public dt_process
505 {
506 public:
509 
511 
515  delay(sc_module_name _name,
516  abst_ext<T> init_val
517  ) : dt_process(_name), iport1("iport1"), oport1("oport1"),
518  init_val(init_val)
519  {
520 #ifdef FORSYDE_INTROSPECTION
521  std::stringstream ss;
522  ss << init_val;
523  arg_vec.push_back(std::make_tuple("init_val", ss.str()));
524 #endif
525  }
526 
528  std::string forsyde_kind() const {return "DT::delay";}
529 
530 private:
531  // Initial value
532  abst_ext<T> init_val;
533 
534  // Inputs and output variables
535  abst_ext<T>* val;
536 
537  //Implementing the abstract semantics
538  void init()
539  {
540  val = new abst_ext<T>;
541  WRITE_MULTIPORT(oport1, init_val)
542  }
543 
544  void prep()
545  {
546  *val = iport1.read();
547  }
548 
549  void exec() {}
550 
551  void prod()
552  {
553  WRITE_MULTIPORT(oport1, *val)
554  }
555 
556  void clean()
557  {
558  delete val;
559  }
560 #ifdef FORSYDE_INTROSPECTION
561  void bindInfo()
562  {
563  boundInChans.resize(1); // only one input port
564  boundInChans[0].port = &iport1;
565  boundOutChans.resize(1); // only one output port
566  boundOutChans[0].port = &oport1;
567  }
568 #endif
569 };
570 
572 
579 template <class T>
580 class delayn : public dt_process
581 {
582 public:
585 
587 
591  delayn(sc_module_name _name,
592  abst_ext<T> init_val,
593  unsigned int ns
594  ) : dt_process(_name), iport1("iport1"), oport1("oport1"),
595  init_val(init_val), ns(ns)
596  {
597 #ifdef FORSYDE_INTROSPECTION
598  std::stringstream ss;
599  ss << init_val;
600  arg_vec.push_back(std::make_tuple("init_val", ss.str()));
601  arg_vec.push_back(std::make_tuple("ns", std::to_string(ns)));
602 #endif
603  }
604 
606  std::string forsyde_kind() const {return "DT::delayn";}
607 
608 private:
609  // Initial value
610  abst_ext<T> init_val;
611  unsigned int ns;
612 
613  // Inputs and output variables
614  abst_ext<T>* val;
615 
616  //Implementing the abstract semantics
617  void init()
618  {
619  val = new abst_ext<T>;
620  for (unsigned int i=0; i<ns; i++)
621  WRITE_MULTIPORT(oport1, abst_ext<T>())
622  }
623 
624  void prep()
625  {
626  *val = iport1.read();
627  }
628 
629  void exec() {}
630 
631  void prod()
632  {
633  WRITE_MULTIPORT(oport1, *val)
634  }
635 
636  void clean()
637  {
638  delete val;
639  }
640 #ifdef FORSYDE_INTROSPECTION
641  void bindInfo()
642  {
643  boundInChans.resize(1); // only one input port
644  boundInChans[0].port = &iport1;
645  boundOutChans.resize(1); // only one output port
646  boundOutChans[0].port = &oport1;
647  }
648 #endif
649 };
650 
652 
656 template <class IT, class ST, class OT>
657 class mealyT : public dt_process
658 {
659 public:
662 
664  typedef std::function<void(unsigned int&, const ST&)> p_functype;
665 
667  typedef std::function<void(ST&,
668  const ST&,
669  const std::vector<abst_ext<IT>>&)> ns_functype;
670 
672  typedef std::function<void(std::vector<abst_ext<OT>>&,
673  const ST&,
674  const std::vector<abst_ext<IT>>&)> od_functype;
675 
677 
681  mealyT(sc_module_name _name,
682  p_functype gamma,
683  ns_functype _ns_func,
684  od_functype _od_func,
685  ST init_st
686  ) : dt_process(_name), gamma(gamma), _ns_func(_ns_func),
687  _od_func(_od_func), init_st(init_st)
688  {
689 #ifdef FORSYDE_INTROSPECTION
690  std::string func_name = std::string(basename());
691  func_name = func_name.substr(0, func_name.find_last_not_of("0123456789")+1);
692  arg_vec.push_back(std::make_tuple("gamma",func_name+std::string("_gamma")));
693  arg_vec.push_back(std::make_tuple("_ns_func",func_name+std::string("_ns_func")));
694  arg_vec.push_back(std::make_tuple("_od_func",func_name+std::string("_od_func")));
695  std::stringstream ss;
696  ss << init_st;
697  arg_vec.push_back(std::make_tuple("init_st",ss.str()));
698 #endif
699  }
700 
702  std::string forsyde_kind() const{return "DT::mealyT";}
703 
704 private:
706  p_functype gamma;
707  ns_functype _ns_func;
708  od_functype _od_func;
709 
710  // Initial value
711  ST init_st;
712 
713  // Input, output, current state, and next state variables
714  std::vector<abst_ext<IT>> ivals;
715  ST* stval;
716  ST* nsval;
717  std::vector<abst_ext<OT>> ovals;
718 
719  unsigned int itoks;
720 
721  // Whether the function should be invoked in this iteration
722  bool invoke;
723 
724  // The current input/output time
725  unsigned long ti1, to1;
726 
727  //Implementing the abstract semantics
728  void init()
729  {
730  ti1 = to1 = 0;
731  stval = new ST;
732  *stval = init_st;
733  nsval = new ST;
734  }
735 
736  void prep()
737  {
738  gamma(itoks, *stval);
739  for (unsigned int i=0; i<itoks; i++)
740  ivals.push_back(iport1.read());
741  ti1 += itoks;
742  }
743 
744  void exec()
745  {
746  _ns_func(*nsval, *stval, ivals);
747  _od_func(ovals, *stval, ivals);
748  *stval = *nsval;
749  }
750 
751  void prod()
752  {
753  // First write the required absent events to ensure casaulity
754  for (unsigned int i=0; i<ti1-to1-1; i++)
755  WRITE_MULTIPORT(oport1, abst_ext<OT>())
756  to1 += ti1-to1-1;
757  //Then write out the result
758  WRITE_VEC_MULTIPORT(oport1, ovals)
759  to1 += itoks;
760  // clean up the input and output vectors
761  ivals.clear();
762  ovals.clear();
763  }
764 
765  void clean()
766  {
767  delete stval;
768  delete nsval;
769  }
770 #ifdef FORSYDE_INTROSPECTION
771  void bindInfo()
772  {
773  boundInChans.resize(1); // only one input port
774  boundInChans[0].port = &iport1;
775  boundOutChans.resize(1); // only one output port
776  boundOutChans[0].port = &oport1;
777  }
778 #endif
779 };
780 
782 
787 template <class T>
788 class constant : public dt_process
789 {
790 public:
792 
794 
797  constant(sc_module_name _name,
798  abst_ext<T> init_val,
799  unsigned long long take=0
800  ) : dt_process(_name), oport1("oport1"),
801  init_val(init_val), take(take)
802 
803  {
804 #ifdef FORSYDE_INTROSPECTION
805  std::stringstream ss;
806  ss << init_val;
807  arg_vec.push_back(std::make_tuple("init_val", ss.str()));
808  ss.str("");
809  ss << take;
810  arg_vec.push_back(std::make_tuple("take", ss.str()));
811 #endif
812  }
813 
815  std::string forsyde_kind() const {return "DT::constant";}
816 
817 private:
818  abst_ext<T> init_val;
819  unsigned long long take; // Number of tokens produced
820 
821  unsigned long long tok_cnt;
822  bool infinite;
823 
824  //Implementing the abstract semantics
825  void init()
826  {
827  if (take==0) infinite = true;
828  tok_cnt = 0;
829  }
830 
831  void prep() {}
832 
833  void exec() {}
834 
835  void prod()
836  {
837  if (tok_cnt++ < take || infinite)
838  WRITE_MULTIPORT(oport1, init_val)
839  else wait();
840  }
841 
842  void clean() {}
843 
844 #ifdef FORSYDE_INTROSPECTION
845  void bindInfo()
846  {
847  boundOutChans.resize(1); // only one output port
848  boundOutChans[0].port = &oport1;
849  boundOutChans[0].portType = typeid(T).name();
850  }
851 #endif
852 };
853 
855 
860 template <class T>
861 class source : public dt_process
862 {
863 public:
865 
867  typedef std::function<void(abst_ext<T>&, const abst_ext<T>&)> functype;
868 
870 
873  source(sc_module_name _name,
874  functype _func,
875  abst_ext<T> init_val,
876  unsigned long long take=0
877  ) : dt_process(_name), oport1("oport1"),
878  init_st(init_val), take(take), _func(_func)
879  {
880 #ifdef FORSYDE_INTROSPECTION
881  std::string func_name = std::string(basename());
882  func_name = func_name.substr(0, func_name.find_last_not_of("0123456789")+1);
883  arg_vec.push_back(std::make_tuple("_func",func_name+std::string("_func")));
884  std::stringstream ss;
885  ss << init_val;
886  arg_vec.push_back(std::make_tuple("init_val", ss.str()));
887  ss.str("");
888  ss << take;
889  arg_vec.push_back(std::make_tuple("take", ss.str()));
890 #endif
891  }
892 
894  std::string forsyde_kind() const {return "DT::source";}
895 
896 private:
897  abst_ext<T> init_st; // The current state
898  unsigned long long take; // Number of tokens produced
899 
900  abst_ext<T>* cur_st; // The current state of the process
901  unsigned long long tok_cnt;
902  bool infinite;
903 
905  functype _func;
906 
907  //Implementing the abstract semantics
908  void init()
909  {
910  cur_st = new abst_ext<T>;
911  *cur_st = init_st;
912  WRITE_MULTIPORT(oport1, *cur_st)
913  if (take==0) infinite = true;
914  tok_cnt = 1;
915  }
916 
917  void prep() {}
918 
919  void exec()
920  {
921  _func(*cur_st, *cur_st);
922  }
923 
924  void prod()
925  {
926  if (tok_cnt++ < take || infinite)
927  WRITE_MULTIPORT(oport1, *cur_st)
928  else wait();
929  }
930 
931  void clean()
932  {
933  delete cur_st;
934  }
935 
936 #ifdef FORSYDE_INTROSPECTION
937  void bindInfo()
938  {
939  boundOutChans.resize(1); // only one output port
940  boundOutChans[0].port = &oport1;
941  boundOutChans[0].portType = typeid(T).name();
942  }
943 #endif
944 };
945 
947 
952 template <class T>
953 class vsource : public dt_process
954 {
955 public:
957 
959 
962  vsource(sc_module_name _name,
963  const std::vector<std::tuple<unsigned int,T>>& in_vec
964  ) : dt_process(_name), in_vec(in_vec)
965  {
966 #ifdef FORSYDE_INTROSPECTION
967  std::stringstream ss;
968  ss << in_vec;
969  arg_vec.push_back(std::make_tuple("in_vec", ss.str()));
970 #endif
971  }
972 
974  std::string forsyde_kind() const {return "DT::vsource";}
975 
976 private:
977  std::vector<std::tuple<unsigned int,T>> in_vec;
978 
979  typename std::vector<std::tuple<unsigned int,T>>::iterator it;
980  unsigned int local_time;
981 
982  //Implementing the abstract semantics
983  void init()
984  {
985  it = in_vec.begin();
986  local_time = 0;
987  }
988 
989  void prep() {}
990 
991  void exec() {}
992 
993  void prod()
994  {
995  if (std::get<0>(*it) > local_time)
996  WRITE_MULTIPORT(oport1, abst_ext<T>())
997  else
998  {
999  WRITE_MULTIPORT(oport1, std::get<1>(*it))
1000  if (it != in_vec.end()-1) it++; else wait();
1001  }
1002 
1003  local_time++;
1004  }
1005 
1006  void clean() {}
1007 
1008 #ifdef FORSYDE_INTROSPECTION
1009  void bindInfo()
1010  {
1011  boundOutChans.resize(1); // only one output port
1012  boundOutChans[0].port = &oport1;
1013  }
1014 #endif
1015 };
1016 
1018 
1022 template <class T>
1023 class sink : public dt_process
1024 {
1025 public:
1027 
1029  typedef std::function<void(const abst_ext<T>&)> functype;
1030 
1032 
1035  sink(sc_module_name _name,
1036  functype _func
1037  ) : dt_process(_name), iport1("iport1"), _func(_func)
1038 
1039  {
1040 #ifdef FORSYDE_INTROSPECTION
1041  std::string func_name = std::string(basename());
1042  func_name = func_name.substr(0, func_name.find_last_not_of("0123456789")+1);
1043  arg_vec.push_back(std::make_tuple("_func",func_name+std::string("_func")));
1044 #endif
1045  }
1046 
1048  std::string forsyde_kind() const {return "DT::sink";}
1049 
1050 private:
1051  abst_ext<T>* val; // The current state of the process
1052 
1054  functype _func;
1055 
1056  //Implementing the abstract semantics
1057  void init()
1058  {
1059  val = new abst_ext<T>;
1060  }
1061 
1062  void prep()
1063  {
1064  *val = iport1.read();
1065  }
1066 
1067  void exec()
1068  {
1069  _func(*val);
1070  }
1071 
1072  void prod() {}
1073 
1074  void clean()
1075  {
1076  delete val;
1077  }
1078 
1079 #ifdef FORSYDE_INTROSPECTION
1080  void bindInfo()
1081  {
1082  boundInChans.resize(1); // only one output port
1083  boundInChans[0].port = &iport1;
1084  boundInChans[0].portType = typeid(T).name();
1085  }
1086 #endif
1087 };
1088 
1090 
1096 template <class ITYP>
1097 class printSigs : public sc_module
1098 {
1099 public:
1100  sc_fifo_in<ITYP> iport;
1101 
1103 
1106  printSigs(sc_module_name _name
1107  ):sc_module(_name)
1108  {
1109  SC_THREAD(worker);
1110  }
1111 
1112 private:
1113  SC_HAS_PROCESS(printSigs);
1114 
1116  void worker()
1117  {
1118  // write the header
1119  for (int i=0;i<iport.size();i++)
1120  std::cout << " " << name() << "(" << i << ")";
1121  std::cout << std::endl;
1122  // start reading from the ports
1123  ITYP in_val[iport.size()];
1124  while (1)
1125  {
1126  for (int i=0;i<iport.size();i++)
1127  in_val[i] = iport[i]->read();
1128  // print one line
1129  for (int i=0;i<iport.size();i++)
1130  std::cout << " " << in_val[i];
1131  std::cout << std::endl;
1132  }
1133  }
1134 };
1135 
1137 
1139 template <class T1, class T2>
1140 class zip : public dt_process
1141 {
1142 public:
1146 
1148 
1151  zip(sc_module_name _name)
1152  :dt_process(_name), iport1("iport1"), iport2("iport2"), oport1("oport1")
1153  { }
1154 
1156  std::string forsyde_kind() const {return "DT::zip";}
1157 
1158 private:
1159  // intermediate values
1160  abst_ext<T1>* ival1;
1161  abst_ext<T1>* ival2;
1162 
1163  void init()
1164  {
1165  ival1 = new abst_ext<T1>;
1166  ival2 = new abst_ext<T2>;
1167  }
1168 
1169  void prep()
1170  {
1171  *ival1 = iport1.read();
1172  *ival2 = iport2.read();
1173  }
1174 
1175  void exec() {}
1176 
1177  void prod()
1178  {
1179  if (ival1->is_absent() && ival2->is_absent())
1180  {
1181  typedef std::tuple<abst_ext<T1>,abst_ext<T2>> TT;
1182  WRITE_MULTIPORT(oport1,abst_ext<TT>()) // write to the output 1
1183  }
1184  else
1185  {
1186  WRITE_MULTIPORT(oport1,std::make_tuple(ival1,ival2)) // write to the output
1187  }
1188  }
1189 
1190  void clean()
1191  {
1192  delete ival1;
1193  delete ival2;
1194  }
1195 
1196 #ifdef FORSYDE_INTROSPECTION
1197  void bindInfo()
1198  {
1199  boundInChans.resize(2); // two input ports
1200  boundInChans[0].port = &iport1;
1201  boundInChans[0].portType = typeid(T1).name();
1202  boundInChans[1].port = &iport2;
1203  boundInChans[1].portType = typeid(T2).name();
1204  boundOutChans.resize(1); // only one output port
1205  boundOutChans[0].port = &oport1;
1206  boundOutChans[0].portType = typeid(std::tuple<T1,T2>).name();
1207  }
1208 #endif
1209 };
1210 
1212 
1214 template <class... ITYPs>
1215 class zipN : public sc_module
1216 {
1217 public:
1218  std::tuple <sc_fifo_in<ITYPs>...> iport;
1219  sc_fifo_out<std::tuple<ITYPs...> > oport1;
1220 
1222 
1225  zipN(sc_module_name _name)
1226  :sc_module(_name)
1227  {
1228  SC_THREAD(worker);
1229  }
1230 private:
1231  SC_HAS_PROCESS(zipN);
1232 
1234  void worker()
1235  {
1236  std::tuple<ITYPs...> in_vals;
1237  while (1)
1238  {
1239  in_vals = sc_fifo_tuple_read<ITYPs...>(iport);
1240  WRITE_MULTIPORT(oport1,in_vals) // write to the output
1241  }
1242  }
1243 
1244  template<size_t N,class R, class T>
1245  struct fifo_read_helper
1246  {
1247  static void read(R& ret, T& t)
1248  {
1249  fifo_read_helper<N-1,R,T>::read(ret,t);
1250  std::get<N>(ret) = std::get<N>(t).read();
1251  }
1252  };
1253 
1254  template<class R, class T>
1255  struct fifo_read_helper<0,R,T>
1256  {
1257  static void read(R& ret, T& t)
1258  {
1259  std::get<0>(ret) = std::get<0>(t).read();
1260  }
1261  };
1262 
1263  template<class... T>
1264  std::tuple<T...> sc_fifo_tuple_read(std::tuple<sc_fifo_in<T>...>& ports)
1265  {
1266  std::tuple<T...> ret;
1267  fifo_read_helper<sizeof...(T)-1,
1268  std::tuple<T...>,
1269  std::tuple<sc_fifo_in<T>...>>::read(ret,ports);
1270  return ret;
1271  }
1272 
1273 };
1274 
1276 
1278 template <class T1, class T2>
1279 class unzip : public dt_process
1280 {
1281 public:
1285 
1287 
1290  unzip(sc_module_name _name)
1291  :dt_process(_name), iport1("iport1"), oport1("oport1"), oport2("oport2")
1292  {}
1293 
1295  std::string forsyde_kind() const {return "DT::unzip";}
1296 private:
1297  // intermediate values
1299 
1300  void init()
1301  {
1303  }
1304 
1305  void prep()
1306  {
1307  *in_val = iport1.read();
1308  }
1309 
1310  void exec() {}
1311 
1312  void prod()
1313  {
1314  if (in_val->is_absent())
1315  {
1316  WRITE_MULTIPORT(oport1,abst_ext<T1>()) // write to the output 1
1317  WRITE_MULTIPORT(oport2,abst_ext<T2>()) // write to the output 2
1318  }
1319  else
1320  {
1321  WRITE_MULTIPORT(oport1,std::get<0>(in_val->unsafe_from_abst_ext())) // write to the output 1
1322  WRITE_MULTIPORT(oport2,std::get<1>(in_val->unsafe_from_abst_ext())) // write to the output 2
1323  }
1324  }
1325 
1326  void clean()
1327  {
1328  delete in_val;
1329  }
1330 
1331 #ifdef FORSYDE_INTROSPECTION
1332  void bindInfo()
1333  {
1334  boundInChans.resize(1); // only one input port
1335  boundInChans[0].port = &iport1;
1336  boundInChans[0].portType = typeid(std::tuple<T1,T2>).name();
1337  boundOutChans.resize(2); // two output ports
1338  boundOutChans[0].port = &oport1;
1339  boundOutChans[0].portType = typeid(T1).name();
1340  boundOutChans[1].port = &oport2;
1341  boundOutChans[1].portType = typeid(T2).name();
1342  }
1343 #endif
1344 };
1345 
1347 
1349 template <class... Ts>
1350 class unzipN : public dt_process
1351 {
1352 public:
1354  std::tuple<DT_out<Ts>...> oport;
1355 
1357 
1360  unzipN(sc_module_name _name)
1361  :dt_process(_name), iport1("iport1")
1362  { }
1363 
1365  std::string forsyde_kind() const {return "DT::unzipN";}
1366 private:
1367  // intermediate values
1368  abst_ext<std::tuple<abst_ext<Ts>...>>* in_val;
1369 
1370  void init()
1371  {
1372  in_val = new abst_ext<std::tuple<abst_ext<Ts>...>>;
1373  }
1374 
1375  void prep()
1376  {
1377  *in_val = iport1.read();
1378  }
1379 
1380  void exec() {}
1381 
1382  void prod()
1383  {
1384  if (in_val->is_absent())
1385  {
1386  std::tuple<abst_ext<Ts>...> all_abs;
1387  fifo_tuple_write<Ts...>(all_abs, oport);
1388  }
1389  else
1390  {
1391  fifo_tuple_write<Ts...>(in_val->unsafe_from_abst_ext(), oport);
1392  }
1393  }
1394 
1395  void clean()
1396  {
1397  delete in_val;
1398  }
1399 
1400  template<size_t N,class R, class T>
1401  struct fifo_write_helper
1402  {
1403  static void write(const R& vals, T& t)
1404  {
1405  fifo_write_helper<N-1,R,T>::write(vals,t);
1406  std::get<N>(t).write(std::get<N>(vals));
1407  }
1408  };
1409 
1410  template<class R, class T>
1411  struct fifo_write_helper<0,R,T>
1412  {
1413  static void write(const R& vals, T& t)
1414  {
1415  std::get<0>(t).write(std::get<0>(vals));
1416  }
1417  };
1418 
1419  template<class... T>
1420  void fifo_tuple_write(const std::tuple<abst_ext<T>...>& vals,
1421  std::tuple<DT_out<T>...>& ports)
1422  {
1423  fifo_write_helper<sizeof...(T)-1,
1424  std::tuple<abst_ext<T>...>,
1425  std::tuple<DT_out<T>...>>::write(vals,ports);
1426  }
1427 
1428 #ifdef FORSYDE_INTROSPECTION
1429  void bindInfo()
1430  {
1431  boundInChans.resize(1); // only one input port
1432  boundInChans[0].port = &iport1;
1433  boundInChans[0].portType = typeid(int).name();
1434  boundOutChans.resize(sizeof...(Ts)); // two output ports
1435  register_ports(boundOutChans, oport);
1436  }
1437 
1438  template<size_t N, class T>
1439  struct register_ports_helper
1440  {
1441  static void reg_port(std::vector<PortInfo>& boundChans, T& t)
1442  {
1443  register_ports_helper<N-1,T>::reg_port(boundChans,t);
1444  boundChans[N].port = &std::get<N>(t);
1445  }
1446  };
1447 
1448  template<class T>
1449  struct register_ports_helper<0,T>
1450  {
1451  static void reg_port(std::vector<PortInfo>& boundChans, T& t)
1452  {
1453  boundChans[0].port = &std::get<0>(t);
1454  }
1455  };
1456 
1457  template<class... T>
1458  void register_ports(std::vector<PortInfo>& boundChans,
1459  std::tuple<DT_out<T>...>& ports)
1460  {
1461  register_ports_helper<sizeof...(T)-1,
1462  std::tuple<DT_out<T>...>&>::reg_port(boundChans,ports);
1463  }
1464 #endif
1465 
1466 };
1467 
1469 
1478 template <class T>
1479 class fanout : public dt_process
1480 {
1481 public:
1484 
1486 
1489  fanout(sc_module_name _name) // module name
1490  : dt_process(_name) { }
1491 
1493  std::string forsyde_kind() const {return "DT::fanout";}
1494 
1495 private:
1496  // Inputs and output variables
1497  abst_ext<T>* val;
1498 
1499  //Implementing the abstract semantics
1500  void init()
1501  {
1502  val = new abst_ext<T>;
1503  }
1504 
1505  void prep()
1506  {
1507  *val = iport1.read();
1508  }
1509 
1510  void exec() {}
1511 
1512  void prod()
1513  {
1514  WRITE_MULTIPORT(oport1, *val)
1515  }
1516 
1517  void clean()
1518  {
1519  delete val;
1520  }
1521 #ifdef FORSYDE_INTROSPECTION
1522  void bindInfo()
1523  {
1524  boundInChans.resize(1); // only one input port
1525  boundInChans[0].port = &iport1;
1526  boundInChans[0].portType = typeid(T).name();
1527  boundOutChans.resize(1); // only one output port
1528  boundOutChans[0].port = &oport1;
1529  boundOutChans[0].portType = typeid(T).name();
1530  }
1531 #endif
1532 };
1533 
1534 }
1535 }
1536 
1537 #endif
DT_in< T2 > iport2
port for the input channel 2
Definition: dt_process_constructors.hpp:252
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:1156
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:278
DT_in< T1 > iport1
port for the input channel 1
Definition: dt_process_constructors.hpp:144
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:702
unzip(sc_module_name _name)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:1290
mealyT(sc_module_name _name, p_functype gamma, ns_functype _ns_func, od_functype _od_func, ST init_st)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:681
T unsafe_from_abst_ext() const
Unsafely converts a value from an extended value assuming it is present.
Definition: abst_ext.hpp:54
DT_out< T > oport1
port for the output channel
Definition: dt_process_constructors.hpp:508
The zip process with two inputs and one output.
Definition: dt_process_constructors.hpp:1140
std::function< void(T0 &, const T1 &, const T2 &, const T3 &, const T4 &)> functype
Type of the function to be passed to the process constructor.
Definition: dt_process_constructors.hpp:378
DT_in< T1 > iport1
port for the input channel 1
Definition: dt_process_constructors.hpp:1143
DT_in< T3 > iport3
port for the input channel 3
Definition: dt_process_constructors.hpp:253
std::function< void(T0 &, const T1 &, const T2 &, const T3 &)> functype
Type of the function to be passed to the process constructor.
Definition: dt_process_constructors.hpp:257
std::function< void(const abst_ext< T > &)> functype
Type of the function to be passed to the process constructor.
Definition: dt_process_constructors.hpp:1029
DT_in< T1 > iport1
port for the input channel 1
Definition: dt_process_constructors.hpp:371
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:1365
Process constructor for a combinational process with four inputs and one output.
Definition: dt_process_constructors.hpp:368
The namespace for ForSyDe.
Definition: abssemantics.hpp:30
Process constructor for a sink process.
Definition: dt_process_constructors.hpp:1023
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:1295
printSigs(sc_module_name _name)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:1106
Process constructor for a source process.
Definition: dt_process_constructors.hpp:861
DT_out< T > oport1
port for the output channel
Definition: dt_process_constructors.hpp:956
Implements the Absent-extended values.
Process constructor for a n-delay element.
Definition: dt_process_constructors.hpp:580
Process constructor for a combinational process with one input and one output.
Definition: dt_process_constructors.hpp:45
zip(sc_module_name _name)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:1151
DT_in< T1 > iport1
port for the input channel
Definition: dt_process_constructors.hpp:48
std::function< void(T0 &, const T1 &, const T2 &)> functype
Type of the function to be passed to the process constructor.
Definition: dt_process_constructors.hpp:149
Process constructor for a multi-input print process.
Definition: dt_process_constructors.hpp:1097
DT_out< T0 > oport1
port for the output channel
Definition: dt_process_constructors.hpp:375
comb2(sc_module_name _name, functype _func)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:156
Process constructor for a constant source process.
Definition: dt_process_constructors.hpp:788
DT_out< T0 > oport1
port for the output channel
Definition: dt_process_constructors.hpp:146
std::function< void(abst_ext< T > &, const abst_ext< T > &)> functype
Type of the function to be passed to the process constructor.
Definition: dt_process_constructors.hpp:867
Process constructor for a fan-out process with one input and one output.
Definition: dt_process_constructors.hpp:1479
DT_in< T4 > iport4
port for the input channel 4
Definition: dt_process_constructors.hpp:374
DT_out< T > oport1
port for the output channel
Definition: dt_process_constructors.hpp:584
zipN(sc_module_name _name)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:1225
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:528
Process constructor for a combinational process with three inputs and one output. ...
Definition: dt_process_constructors.hpp:248
DT_in< std::tuple< abst_ext< Ts >... > > iport1
port for the input channel
Definition: dt_process_constructors.hpp:1353
comb(sc_module_name _name, functype _func)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:59
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:815
DT_in< T2 > iport2
port for the input channel 2
Definition: dt_process_constructors.hpp:372
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:974
DT_in< std::tuple< abst_ext< T1 >, abst_ext< T2 > > > iport1
port for the input channel
Definition: dt_process_constructors.hpp:1282
DT_out< T2 > oport2
port for the output channel 2
Definition: dt_process_constructors.hpp:1284
Process constructor for a combinational process with two inputs and one output.
Definition: dt_process_constructors.hpp:141
std::function< void(std::vector< abst_ext< OT >> &, const ST &, const std::vector< abst_ext< IT >> &)> od_functype
Type of the output-decoding function to be passed to the process constructor.
Definition: dt_process_constructors.hpp:674
sink(sc_module_name _name, functype _func)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:1035
DT_out< OT > oport1
port for the output channel
Definition: dt_process_constructors.hpp:661
DT_in< T > iport1
port for the input channel
Definition: dt_process_constructors.hpp:507
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:894
source(sc_module_name _name, functype _func, abst_ext< T > init_val, unsigned long long take=0)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:873
DT_in< T > iport1
port for the input channel
Definition: dt_process_constructors.hpp:1026
delay(sc_module_name _name, abst_ext< T > init_val)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:515
bool is_absent() const
Checks for the absence of a value.
Definition: abst_ext.hpp:79
DT_out< T > oport1
port for the output channel
Definition: dt_process_constructors.hpp:1483
DT_out< T0 > oport1
port for the output channel
Definition: dt_process_constructors.hpp:254
Implements the abstract process in the DT Model of Computation.
DT_out< T > oport1
port for the output channel
Definition: dt_process_constructors.hpp:864
The zip process with variable number of inputs and one output.
Definition: dt_process_constructors.hpp:1215
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:397
Process constructor for a source process with vector input.
Definition: dt_process_constructors.hpp:953
The process constructor which defines the abstract semantics of execution.
Definition: abssemantics.hpp:212
std::function< void(unsigned int &, const ST &)> p_functype
Type of the partitioning function to be passed to the process constructor.
Definition: dt_process_constructors.hpp:664
std::tuple< sc_fifo_in< ITYPs >... > iport
tuple of ports for the input channels
Definition: dt_process_constructors.hpp:1218
Process constructor for a MealyT machine.
Definition: dt_process_constructors.hpp:657
DT_out< T0 > oport1
port for the output channel
Definition: dt_process_constructors.hpp:49
std::tuple< DT_out< Ts >... > oport
tuple of ports for the output channels
Definition: dt_process_constructors.hpp:1354
DT_in< T1 > iport1
port for the input channel 1
Definition: dt_process_constructors.hpp:251
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:72
comb4(sc_module_name _name, functype _func)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:384
DT_out< T1 > oport1
port for the output channel 1
Definition: dt_process_constructors.hpp:1283
Process constructor for a delay element.
Definition: dt_process_constructors.hpp:504
DT_in< IT > iport1
port for the input channel
Definition: dt_process_constructors.hpp:660
vsource(sc_module_name _name, const std::vector< std::tuple< unsigned int, T >> &in_vec)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:962
DT_in< T2 > iport2
port for the input channel 2
Definition: dt_process_constructors.hpp:145
The unzip process with one input and two outputs.
Definition: dt_process_constructors.hpp:1279
DT_in< T > iport1
port for the input channel
Definition: dt_process_constructors.hpp:583
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:169
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:1048
DT_in< T3 > iport3
port for the input channel 3
Definition: dt_process_constructors.hpp:373
DT_out< T > oport1
port for the output channel
Definition: dt_process_constructors.hpp:791
DT_in< T2 > iport2
port for the input channel 2
Definition: dt_process_constructors.hpp:1144
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:1493
unzipN(sc_module_name _name)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:1360
std::function< void(T0 &, const T1 &)> functype
Type of the function to be passed to the process constructor.
Definition: dt_process_constructors.hpp:52
DT_out< std::tuple< abst_ext< T1 >, abst_ext< T2 > > > oport1
port for the output channel
Definition: dt_process_constructors.hpp:1145
The unzip process with one input and variable number of outputs.
Definition: dt_process_constructors.hpp:1350
DT_in< T > iport1
port for the input channel
Definition: dt_process_constructors.hpp:1482
fanout(sc_module_name _name)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:1489
sc_fifo_in< ITYP > iport
multi-port for the input channel
Definition: dt_process_constructors.hpp:1100
sc_fifo_out< std::tuple< ITYPs... > > oport1
port for the output channel
Definition: dt_process_constructors.hpp:1219
delayn(sc_module_name _name, abst_ext< T > init_val, unsigned int ns)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:591
constant(sc_module_name _name, abst_ext< T > init_val, unsigned long long take=0)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:797
std::string forsyde_kind() const
Specifying from which process constructor is the module built.
Definition: dt_process_constructors.hpp:606
comb3(sc_module_name _name, functype _func)
The constructor requires the module name.
Definition: dt_process_constructors.hpp:265
std::function< void(ST &, const ST &, const std::vector< abst_ext< IT >> &)> ns_functype
Type of the next-state function to be passed to the process constructor.
Definition: dt_process_constructors.hpp:669