1
2// General tests combining features of SystemC 2.1 and 1666
3
4
5#define SC_INCLUDE_DYNAMIC_PROCESSES
6
7#include <systemc>
8using sc_core::sc_interface;
9using sc_core::sc_object;
10using sc_core::sc_port;
11using sc_core::sc_export;
12using sc_core::sc_module;
13using sc_core::sc_module_name;
14using sc_core::sc_in;
15using sc_core::sc_in_clk;
16using sc_core::sc_signal;
17using sc_core::sc_prim_channel;
18using sc_core::sc_event;
19using sc_core::sc_delta_count;
20using sc_core::sc_is_running;
21using sc_core::sc_get_top_level_objects;
22using sc_core::sc_find_object;
23using sc_core::sc_report;
24using sc_core::sc_report_handler;
25using sc_core::sc_actions;
26using sc_core::SC_INFO;
27using sc_core::SC_UNSPECIFIED;
28using sc_core::SC_THROW;
29using sc_core::sc_spawn;
30using sc_core::sc_process_handle;
31using sc_core::sc_get_current_process_handle;
32using sc_core::sc_time;
33using sc_core::sc_time_stamp;
34using sc_core::SC_ZERO_TIME;
35using sc_core::SC_PS;
36using sc_core::SC_NS;
37using sc_core::SC_US;
38using sc_core::sc_start_of_simulation_invoked;
39using sc_core::sc_end_of_simulation_invoked;
40using sc_core::sc_start;
41using sc_core::sc_stop;
42using sc_core::sc_copyright;
43using sc_core::sc_version;
44using sc_core::sc_release;
45using sc_dt::sc_abs;
46using sc_dt::sc_max;
47using sc_dt::sc_min;
48using sc_dt::sc_int;
49using sc_dt::sc_bigint;
50using std::cout;
51using std::endl;
52
53#if defined(IEEE_1666_CPLUSPLUS) && IEEE_1666_CPLUSPLUS >= 201103L
54// dynamic process macros have been moved to functions on C++11
55using sc_core::sc_bind;
56using sc_core::sc_ref;
57using sc_core::sc_cref;
58#endif // IEEE_1666_CPLUSPLUS
59
60struct i_f: virtual sc_interface
61{
62  virtual void write() = 0;
63};
64
65void check_form_of_suffix(std::string s)
66{
67  std::string charset = "0123456789";
68  while (!s.empty())
69  {
70    sc_assert(s[0] == '_');
71  s = s.substr(1);
72  sc_assert(!s.empty());
73  do
74  {
75    sc_assert(charset.find(s[0]) < charset.size());
76    s = s.substr(1);
77  } while (!s.empty() && (s[0] != '_'));
78  }
79}
80
81struct Chan: i_f, sc_object
82{
83  virtual void write()
84  {
85    sc_assert(std::string(name()).substr(0,17) == "top.m_dest.object");
86    check_form_of_suffix(std::string(name()).substr(17));
87  }
88};
89
90struct M_src: sc_core::sc_behavior
91{
92  sc_port<i_f>* p;
93  SC_HAS_PROCESS(M_src);
94
95  M_src(sc_module_name _name)
96  {
97    p = new sc_port<i_f>;
98
99    SC_THREAD(T);
100  }
101  void T()
102  {
103    (*p)->write();
104  }
105};
106
107struct M_dest: sc_core::sc_channel
108{
109  sc_export<i_f>* xp;
110  SC_HAS_PROCESS(M_dest);
111
112  M_dest(sc_module_name _name)
113  {
114    xp = new sc_export<i_f>;
115    Chan* ch = new Chan;
116    xp->bind(*ch);
117  }
118};
119
120void f()
121{
122  ::sc_core::wait(33, SC_PS);
123}
124
125struct Prim: sc_prim_channel
126{
127  Prim() : cref_arg(1) {}
128
129  void write() { request_update(); }
130
131  void update()
132  {
133    sc_spawn(sc_bind(&Prim::proc, this));
134  }
135
136  void proc()
137  {
138    ev.notify(SC_ZERO_TIME);
139    wait(ev);
140    cout << "Prim::Proc spawned and resumed" << endl;
141    SC_FORK
142      sc_spawn(sc_bind(&Prim::Th, this, 1)),
143      sc_spawn(sc_bind(&Prim::Th, this, 2))
144    SC_JOIN
145    sc_spawn(sc_bind(&Prim::Th_ref, this, sc_ref(ref_arg)));
146    sc_spawn(sc_bind(&Prim::Th_cref, this, sc_cref(cref_arg)));
147    wait(1, SC_NS);
148    sc_assert(ref_arg == 99);
149  }
150  sc_event ev;
151  void Th(int i)
152  {
153    cout << "Th::i=" << i << endl;
154  }
155  void Th_ref(int& arg)
156  {
157    arg = 99;
158    sc_time t(sc_time_stamp());
159    sc_process_handle h = sc_spawn(&f);
160    wait(h.terminated_event());
161    sc_assert(sc_time_stamp() == t + sc_time(33, SC_PS));
162  }
163  void Th_cref(const int& arg)
164  {
165  }
166  int ref_arg;
167  const int cref_arg;
168};
169
170SC_MODULE(M)
171{
172  Prim prim;
173  SC_CTOR(M)
174  {
175    SC_THREAD(T);
176  }
177
178  void T()
179  {
180    wait(10, SC_NS);
181    try {
182      sc_report_handler::set_actions("msg_type", SC_INFO, SC_THROW);
183      SC_REPORT_INFO("msg_type", "msg");
184    }
185    catch (sc_report& rpt) {
186      cout << "Caught rpt " << rpt.what() << endl;
187      sc_assert(rpt.get_severity() == SC_INFO);
188      sc_assert(std::string(rpt.get_msg_type()) == "msg_type");
189      sc_assert(std::string(rpt.get_msg()) == "msg");
190      sc_assert(rpt.get_time() == sc_time(10, SC_NS));
191      sc_assert(std::string(rpt.get_process_name()) == "top.m.T");
192
193      sc_assert(sc_report_handler::get_count(SC_INFO) == 1);
194      sc_report rpt2 = rpt; // Copy constructor
195
196      prim.write();
197
198      sc_spawn(sc_bind(&M::proc, this, &rpt2));
199      wait(100, SC_NS);
200    }
201  }
202  void proc(sc_report* rpt)
203  {
204    sc_assert(rpt->get_severity() == SC_INFO);
205    sc_assert(std::string(rpt->get_msg_type()) == "msg_type");
206    sc_assert(std::string(rpt->get_msg()) == "msg");
207    sc_assert(rpt->get_time() == sc_time(10, SC_NS));
208    sc_assert(std::string(rpt->get_process_name()) == "top.m.T");
209    rpt->get_file_name();
210    rpt->get_line_number();
211  }
212};
213
214struct CM: sc_module
215{
216  sc_in_clk clk;
217  sc_in<bool> reset;
218
219  SC_HAS_PROCESS(CM);
220
221  CM(sc_module_name _name)
222  : first(true)
223  {
224    SC_CTHREAD(CT, clk.pos());
225      reset_signal_is(reset, true);
226
227    sc_assert(sc_start_of_simulation_invoked() == false);
228    sc_assert(sc_end_of_simulation_invoked() == false);
229    sc_assert(sc_is_running() == false);
230  }
231
232  bool first;
233
234  void CT()
235  {
236    if (first)
237      sc_assert(sc_time_stamp() == sc_time(5, SC_US));
238    else
239      sc_assert(sc_time_stamp() == sc_time(30, SC_US));
240    first = false;
241
242    sc_assert(sc_start_of_simulation_invoked() == true);
243    sc_assert(sc_end_of_simulation_invoked() == false);
244    sc_assert(sc_is_running() == true);
245
246    while(1)
247    {
248      wait();
249      sc_assert(sc_time_stamp() == sc_time(15, SC_US));
250      wait();
251      sc_assert(sc_time_stamp() == sc_time(25, SC_US));
252      wait();
253      sc_assert(false);
254    }
255  }
256
257  void start_of_simulation()
258  {
259    sc_assert(sc_start_of_simulation_invoked() == false);
260    sc_assert(sc_end_of_simulation_invoked() == false);
261    sc_assert(sc_is_running() == false);
262  }
263
264  void end_of_simulation()
265  {
266    sc_assert(sc_start_of_simulation_invoked() == true);
267    sc_assert(sc_end_of_simulation_invoked() == false);
268    sc_assert(sc_is_running() == false);
269  }
270};
271
272SC_MODULE(Top)
273{
274  M *m;
275  CM *cm;
276
277  M_src m_src;
278  M_dest m_dest;
279
280  sc_signal<bool> clk, reset;
281
282  SC_CTOR(Top)
283  : m_src("m_src"), m_dest("m_dest")
284  {
285    m = new M("m");
286    cm = new CM("cm");
287    cm->clk(clk);
288    cm->reset(reset);
289
290    m_src.p->bind( *(m_dest.xp) );  // Port-export binding
291
292    SC_THREAD(T);
293    SC_THREAD(T2);
294  }
295  void T()
296  {
297    clk = false;
298    reset = true;
299    wait(5, SC_US);
300    clk = true;
301    wait(5, SC_US);
302    clk = false;
303    reset = false;
304    wait(5, SC_US);
305    clk = true;
306    wait(5, SC_US);
307    clk = false;
308    wait(5, SC_US);
309    clk = true;
310    wait(5, SC_US);
311    clk = false;
312    reset = true;
313    wait(10, SC_US);
314  }
315  void T2()
316  {
317    sc_assert(sc_min(-1,1) == -1);
318    sc_assert(sc_max(-1,1) == 1);
319    sc_assert(sc_abs(-1) == 1);
320
321    sc_assert(sc_min(sc_int<8>(-1),sc_int<8>(1)) == sc_int<8>(-1));
322    sc_assert(sc_max(sc_int<8>(-1),sc_int<8>(1)) == sc_int<8>(1));
323    sc_assert(sc_abs(sc_int<8>(-1)) == sc_int<8>(1));
324
325    sc_assert(sc_min(sc_bigint<256>(-1),sc_bigint<256>(1)) == sc_bigint<256>(-1));
326    sc_assert(sc_max(sc_bigint<256>(-1),sc_bigint<256>(1)) == sc_bigint<256>(1));
327    sc_assert(sc_abs(sc_bigint<256>(-1)) == sc_bigint<256>(1));
328  }
329};
330
331int sc_main(int argc, char* argv[])
332{
333  sc_assert(sc_delta_count() == 0);
334  sc_assert(sc_is_running() == 0);
335  sc_assert(sc_time_stamp() == sc_time(SC_ZERO_TIME));
336  sc_assert(sc_report_handler::get_count(SC_INFO) == 0);
337  sc_assert(sc_report_handler::get_count("foo") == 0);
338
339  sc_actions act1 = sc_report_handler::get_new_action_id();
340  sc_actions act2 = sc_report_handler::get_new_action_id();
341  while (act2 != SC_UNSPECIFIED)
342  {
343    sc_assert(act2 != act1);
344    act2 = sc_report_handler::get_new_action_id();
345  }
346  sc_assert(sc_report_handler::get_log_file_name() == 0);
347  sc_assert(sc_get_top_level_objects().size() == 0);
348  sc_assert(sc_find_object("foo") == 0);
349  sc_assert(!sc_get_current_process_handle().valid());
350
351  sc_copyright();
352  sc_version();
353  std::string release = sc_release();
354  int n = release.find('.');
355  std::string major = release.substr(0,n);
356  release = release.substr(n+1,release.size()-1);
357  n = release.find('.');
358  std::string minor = release.substr(0,n);
359  release = release.substr(n+1,release.size()-1);
360  n = release.find('-');
361  std::string patch = release.substr(0,n);
362  std::string originator = release.substr(n+1,release.size());
363
364  std::string charset =
365  "abcdefghijklmnopqrstuvwxyzABSCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
366
367  for (unsigned int i = 0; i < major.size(); i++)
368    sc_assert(charset.find(major[i]) < charset.size());
369  for (unsigned int i = 0; i < minor.size(); i++)
370    sc_assert(charset.find(minor[i]) < charset.size());
371  for (unsigned int i = 0; i < patch.size(); i++)
372    sc_assert(charset.find(patch[i]) < charset.size());
373  for (unsigned int i = 0; i < originator.size(); i++)
374    sc_assert(charset.find(originator[i]) < charset.size());
375
376  Top top("top");
377  sc_start();
378
379  sc_stop();
380  sc_assert(sc_end_of_simulation_invoked() == true);
381
382  cout << endl << "Success" << endl;
383  return 0;
384}
385