1
2#include <systemc.h>
3
4// Tests for 2.0.1 extended coding styles, illustrating that SystemC is a class library, not a syntax
5
6static int global_count = 0;
7
8SC_MODULE(Mod)
9{
10  SC_CTOR(Mod)
11  {
12    sc_assert(std::string(this->kind()) == "sc_module");
13  }
14};
15
16
17
18SC_MODULE(Mod0)
19{
20  SC_CTOR(Mod0)
21  {
22    sc_assert(std::string(basename()) == "mod0");
23    SC_METHOD(method);
24    dont_initialize();
25    method();             //// Calling an SC_METHOD member function directly DOULOS009
26
27    for (int i = 0; i < 3; i++)
28    {
29      SC_THREAD(thread);  //// Registering the same function multiple times DOULOS046
30                          //// Get warnings re-defining sc_object names, multiple threads created
31    }
32    SC_THREAD(thread);
33    SC_THREAD(thread);  //// Compile-time error - 'threadhandle' redefinition
34
35    f();
36  }
37  void method(void) {
38    sc_assert(sc_get_current_process_handle().proc_kind() == SC_METHOD_PROC_);
39  ++ global_count;
40  }
41  void thread(void) {
42  sc_assert(sc_get_current_process_handle().proc_kind() == SC_THREAD_PROC_);
43  ++ global_count;
44  }
45
46  void f() { SC_THREAD(g); } //// Process registered in member function called from constructor DOULOS007
47  void g()
48  {
49    sc_assert(std::string(sc_get_current_process_handle().name()) == "top.mod0.g");
50  ++ global_count;
51  }
52};
53
54
55struct Chan               //// Pseudo-channel used for port-less interprocess communication
56                          //// but not derived from sc_module, sc_prim_channel or sc_interface DOULOS048
57{
58  void write(int i) { wait(10, SC_NS); data = i; e.notify(); }
59  void read(int& i) { wait(e); i = data; }
60  int data;
61  bool wr, re;
62  sc_event e;
63};
64
65struct MyMod: Mod         //// Class derived from an SC_MODULE DOULOS050
66{
67  sc_in<bool> p;
68
69  MyMod(sc_module_name n)
70  : Mod(n)
71  {
72    SC_THREAD(p1);
73    SC_THREAD(p2);
74  }
75
76  Chan ch;                //// Instance of pseudo-channel DOULOS048
77  void p1() { ch.write(333); }
78  void p2() { int i; ch.read(i); sc_assert(i == 333); }
79
80  SC_HAS_PROCESS(MyMod);
81};
82
83
84
85struct C0: sc_module, virtual sc_interface //// Combining channel and interface in one class DOULOS015
86{
87  void write(int i) { data = i; }
88  void read(int& i) { i = data; }
89  int data;
90
91  SC_CTOR(C0)
92  {
93    SC_THREAD(action);
94  }
95  void action() {
96  sc_assert(std::string(sc_get_current_process_handle().get_process_object()->basename()) == "action");
97  }
98};
99
100
101struct C1: virtual public sc_interface //// Combining channel and interface in one class DOULOS015
102{
103  void write(int i) { data = i; }
104  void read(int& i) { i = data; }
105  int data;
106};
107
108
109struct I_F: virtual public sc_interface
110{
111  virtual void method() = 0;
112};
113
114struct C2: I_F            //// Channel derived from neither sc_module nor sc_prim_channel DOULOS049
115{
116  void method() {}
117};
118
119struct C3: sc_object, I_F //// Channel derived from sc_object only
120                          //// (and derived from neither sc_module nor sc_prim_channel) DOULOS049
121{
122  void method() {}
123};
124
125
126void check_form_of_suffix(std::string s)
127{
128  std::string charset = "0123456789";
129  while (!s.empty())
130  {
131    sc_assert(s[0] == '_');
132    s = s.substr(1);
133    sc_assert(!s.empty());
134    do
135    {
136      sc_assert(charset.find(s[0]) < charset.size());
137      s = s.substr(1);
138    } while (!s.empty() && (s[0] != '_'));
139  }
140}
141
142struct Modtype: sc_module
143{
144  Modtype(sc_module_name n = sc_gen_unique_name("Modtype"))
145  {
146    if (global_count == 0)
147      sc_assert(std::string(basename()) == "mt");
148    else
149    {
150      std::string s = std::string(basename());
151      sc_assert(s.substr(0,7) == "Modtype");
152      sc_assert(s.size() > 7);
153      check_form_of_suffix(s.substr(7));
154    }
155    ++ global_count;
156  }
157  void dump() {
158    sc_assert(std::string(sc_get_current_process_handle().get_process_object()->basename()) == "thread");
159    ++ global_count;
160  }
161};
162
163typedef sc_signal<Modtype*> MS; //// Pointer-to-module used as the type of a signal DOULOS051
164
165
166
167template<class T>
168struct S
169{
170  T t;
171};
172
173
174
175SC_MODULE(Moda)
176{
177  sc_port<C0> p0;
178  sc_port<C1> p1;
179  sc_port<C2> p2;
180  sc_port<C3> p3;
181  sc_port<MS> p4;
182
183  Modtype mt;
184
185  SC_CTOR(Moda): mt("mt")
186  {
187  sc_assert(std::string(name()) == "top.moda");
188    SC_THREAD(thread);
189  }
190  void thread();
191};
192
193SC_MODULE(Modb)
194{
195  sc_port<C0> p0;
196  sc_port<C1> p1;
197  sc_port<C2> p2;
198  sc_port<C3> p3;
199  sc_port<MS> p4;
200
201  SC_CTOR(Modb)
202  {
203  sc_assert(std::string(name()) == "top.modb");
204    SC_THREAD(thread);
205    SC_THREAD(funny);
206  }
207  void thread();
208  void funny();
209};
210
211void Moda::thread()
212{
213  p1->write(999);
214  p2->method();
215  p3->method();
216  p4->write(&mt);
217}
218void Modb::thread()
219{
220  wait(SC_ZERO_TIME);
221  int i; p1->read(i);
222  sc_assert(i == 999);
223  p2->method();
224  p3->method();
225  wait(SC_ZERO_TIME);
226  (p4->read())->dump();
227}
228
229void Modb::funny()  { C1 c1; C2 c2; C3 c3; }
230
231
232
233
234struct Link
235{
236  Link *link;
237  sc_module      *m;       //// Pointer-to-module DOULOS006
238  sc_signal<int> *s;       //// Pointer-to-signal
239  sc_in<int>     *p;       //// Pointer-to-port DOULOS008
240};
241
242SC_MODULE(Top)
243{
244
245  SC_MODULE(Nested)        //// Nested modules DOULOS005
246  {
247    sc_in<int> *pp;        //// Pointer-to-port DOULOS008
248
249    SC_CTOR(Nested)
250    {
251      SC_METHOD(action);
252
253      pp = new sc_in<int>; //// Dynamic port instantiation DOULOS008
254
255      sensitive << *pp;    //// Sensitivity separated from SC_METHOD DOULOS011
256    }
257
258  void action() { op = sc_min(3, (*pp).read() + 1); }
259
260    sc_out<int> op;        //// Out-of-order declaration DOULOS052
261  };
262
263
264  Nested n;
265  Link* link;
266  sc_signal<bool> b;
267  sc_signal<int> *sig;      //// Pointer-to-signal
268
269  MyMod mymod;
270  Moda moda;
271  Modb modb;
272  C0 c0;
273  C1 c1;
274  C2 c2;
275  C3 c3;
276
277  S<Modtype> Sm;            //// Using sc_module as a template parameter DOULOS051
278  MS ms;                    //// Pointer-to-module used as the type of a signal DOULOS051
279
280  Mod0 mod0;
281
282  SC_CTOR(Top)
283  : n("n"), mymod("mymod"), moda("moda"), modb("modb"), c0("c0"), mod0("mod0")
284  {
285    link = new Link;
286    link->m = new Mod("mod_1");
287    link->p = new sc_in<int>;
288    link->link = new Link;
289    link->link->m = new Mod("mod_2");  //// Buried dynamic module instantiation DOULOS002
290    link->link->s = new sc_signal<int>;//// Buried dynamic channel instantiation
291    link->link->p = new sc_in<int>;    //// Buried dynamic port instantiation DOULOS008
292
293    sig = new sc_signal<int>;          //// Dynamic channel instantiation
294    n.op(*sig);
295    (*(n.pp)).bind(*sig);              //// Binding dynamically allocated port DOULOS008
296
297    mymod.p(b);
298
299    moda.p0(c0);
300    moda.p1(c1);
301    moda.p2(c2);
302    moda.p3(c3);
303    moda.p4(ms);
304
305    modb.p0(c0);
306    modb.p1(c1);
307    modb.p2(c2);
308    modb.p3(c3);
309    modb.p4(ms);
310  }
311
312};
313
314
315int sc_main(int argc, char* argv[])
316{
317  cout << "Should be silent except for some renaming warnings..." << endl;
318
319  sc_signal<int> s;
320  Top top("top");
321  top.link->p->bind(s);
322  top.link->link->p->bind(s);         //// Binding dynamically allocated port DOULOS008
323
324  sc_start();
325  sc_assert(global_count == 10);
326  sc_assert(top.sig->read() == 3);
327
328  cout << endl << "Success" << endl;
329  return 0;
330}
331