1/*****************************************************************************
2
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements.  See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License.  You may obtain a copy of the License at
9
10    http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied.  See the License for the specific language governing
16  permissions and limitations under the License.
17
18 *****************************************************************************/
19
20// sc_pause.cpp -- test for
21//
22//  Original Author: John Aynsley, Doulos, Inc.
23//
24// MODIFICATION LOG - modifiers, enter your name, affiliation, date and
25//
26// $Log: sc_pause.cpp,v $
27// Revision 1.2  2011/05/08 19:18:46  acg
28//  Andy Goodrich: remove extraneous + prefixes from git diff.
29//
30
31// sc_pause, sc_get_status, sc_is_running
32
33#define SC_INCLUDE_DYNAMIC_PROCESSES
34
35#include <systemc>
36using namespace sc_core;
37using std::cout;
38using std::endl;
39using std::hex;
40
41struct my_interface: virtual sc_interface
42{
43  virtual void schedule_events_while_paused() = 0;
44};
45
46struct M: sc_module, private my_interface
47{
48  sc_export<my_interface> xport;
49
50  SC_CTOR(M)
51  {
52    cout << "sc_get_status() == " << hex << sc_get_status() << " CTOR in " << name() << endl;
53    sc_assert( sc_get_status() == SC_BEFORE_END_OF_ELABORATION );
54    sc_assert( sc_is_running() == false );
55
56    xport.bind(*this);
57
58    sc_spawn(sc_bind(&M::T, this));
59
60    SC_THREAD(on_immed_event);
61    SC_THREAD(on_delta_event);
62    SC_THREAD(on_timed_event);
63  }
64
65  sc_signal<int> sig1, sig2, sig3, sig4;
66  sc_event immed_event;
67  sc_event delta_event;
68  sc_event timed_event;
69
70  void before_end_of_elaboration()
71  {
72    cout << "sc_get_status() == " << hex << sc_get_status() << " before_end_of_elaboration in " << name() << endl;
73    sc_assert( sc_get_status() == SC_BEFORE_END_OF_ELABORATION );
74    sc_assert( sc_is_running() == false );
75    sig1.write(1);
76    timed_event.notify(1234, SC_NS);
77    sc_pause();  // Should be ignored
78  }
79
80  void end_of_elaboration()
81  {
82    cout << "sc_get_status() == " << hex << sc_get_status() << " end_of_elaboration in " << name() << endl;
83    sc_assert( sc_get_status() == SC_END_OF_ELABORATION );
84    sc_assert( sc_is_running() == false );
85    sig2.write(2);
86    sc_pause();  // Should be ignored
87  }
88
89  void start_of_simulation()
90  {
91    cout << "sc_get_status() == " << hex << sc_get_status() << " start_of_simulation in " << name() << endl;
92    sc_assert( sc_get_status() == SC_START_OF_SIMULATION );
93    sc_assert( sc_is_running() == false );
94    sig3.write(3);
95    sig4.write(0);
96    sc_pause();  // Should be ignored
97  }
98
99  void end_of_simulation()
100  {
101    cout << "sc_get_status() == " << hex << sc_get_status() << " end_of_simulation in " << name() << endl;;
102    sc_assert( sc_get_status() == SC_END_OF_SIMULATION );
103    sc_assert( sc_is_running() == false );
104  }
105
106  void T()
107  {
108    sc_assert( sig1.read() == 1 );
109    sc_assert( sig2.read() == 2 );
110    sc_assert( sig3.read() == 3 );
111  }
112
113  void on_immed_event()
114  {
115    wait(immed_event);
116    cout << "on_immed_event() awoke\n";
117
118    // Should run in 1st eval phase after pause
119    sc_assert( sig4.read() == 0 );
120  }
121
122  void on_delta_event()
123  {
124    wait(delta_event);
125    cout << "on_delta_event() awoke\n";
126
127    // Should run in 2nd eval phase after pause
128    sc_assert( sig4.read() == 4 );
129  }
130
131  void on_timed_event()
132  {
133    wait(timed_event);
134    cout << "on_timed_event() awoke\n";
135
136    sc_assert( sig1.read() == 1 );
137    sc_assert( sig2.read() == 2 );
138    sc_assert( sig3.read() == 3 );
139    sc_assert( sig4.read() == 0 );
140    sc_assert( sc_time_stamp() == sc_time(1234, SC_NS) );
141  }
142
143private:
144
145  void schedule_events_while_paused()
146  {
147    sig4.write(4);
148    immed_event.notify();
149    delta_event.notify(SC_ZERO_TIME);
150
151    // Should be able to instantiate an sc_object while paused
152    mut = new sc_mutex("mut");
153    sem = new sc_semaphore("sem", 1);
154  }
155
156  sc_mutex* mut;
157  sc_semaphore* sem;
158};
159
160SC_MODULE(Top)
161{
162  SC_CTOR(Top)
163  {
164    cout << "sc_get_status() == " << hex << sc_get_status() << " CTOR in " << name() << endl;
165    sc_assert( sc_get_status() == SC_ELABORATION );
166    sc_assert( sc_is_running() == false );
167    SC_THREAD(T);
168
169    sc_spawn_options opt;
170      opt.spawn_method();
171      opt.set_sensitivity( &timed_ev );
172      opt.set_sensitivity( &delta_ev );
173      opt.dont_initialize();
174    sc_spawn(sc_bind(&Top::ev_handler, this), "ev_handler", &opt);
175
176    SC_METHOD(immed_ev_handler);
177      sensitive << immed_ev;
178      dont_initialize();
179
180    immed_ev_delta = 0;
181    sc_assert( sc_delta_count() == 0 );
182  }
183
184  ~Top()
185  {
186    sc_assert( sc_get_status() == SC_STOPPED );
187    sc_assert( sc_is_running() == false );
188  }
189
190  M* m;
191  sc_event timed_ev;
192  sc_event delta_ev;
193  sc_event immed_ev;
194  unsigned immed_ev_delta;
195  sc_signal<int> sig;
196
197  void before_end_of_elaboration()
198  {
199    cout << "sc_get_status() == " << hex << sc_get_status() << " before_end_of_elaboration in " << name() << endl;
200    sc_assert( sc_get_status() == SC_BEFORE_END_OF_ELABORATION );
201    sc_assert( sc_is_running() == false );
202
203    m = new M("m");
204  }
205
206  void end_of_elaboration()
207  {
208    cout << "sc_get_status() == " << hex << sc_get_status() << " end_of_elaboration in " << name() << endl;
209    sc_assert( sc_get_status() == SC_END_OF_ELABORATION );
210    sc_assert( sc_is_running() == false );
211  }
212
213  void start_of_simulation()
214  {
215    cout << "sc_get_status() == " << hex << sc_get_status() << " start_of_simulation in " << name() << endl;
216    sc_assert( sc_get_status() == SC_START_OF_SIMULATION );
217    sc_assert( sc_is_running() == false );
218  }
219
220  void end_of_simulation()
221  {
222    cout << "sc_get_status() == " << hex << sc_get_status() << " end_of_simulation in " << name() << endl;
223    sc_assert( sc_get_status() == SC_END_OF_SIMULATION );
224    sc_assert( sc_is_running() == false );
225    sc_assert( immed_ev_delta == 999 );
226  }
227
228  void T()
229  {
230    cout << "sc_get_status() == " << hex << sc_get_status() << " PROCESS in " << name() << endl;
231    sc_assert( sc_delta_count() == 0 );
232    sc_assert( sig.read()      == 42 );
233    sc_assert( sc_get_status() == SC_RUNNING );
234    sc_assert( sc_is_running() == true );
235    wait(timed_ev);
236    sc_assert( sc_time_stamp() == sc_time(42, SC_US) );
237    sc_assert( sc_get_status() == SC_RUNNING );
238    sc_assert( sc_is_running() == true );
239
240    sc_pause();
241    cout << "sc_get_status() == " << hex << sc_get_status() << " PROCESS after sc_pause in " << name() << endl;
242    sc_assert( sc_time_stamp() == sc_time(42, SC_US) );
243    sc_assert( sc_get_status() == SC_RUNNING );
244    sc_assert( sc_is_running() == true );
245    wait(SC_ZERO_TIME);
246    sc_assert( sc_get_status() == SC_RUNNING );
247    sc_assert( sc_is_running() == true );
248
249    sc_pause();
250    cout << "sc_get_status() == " << hex << sc_get_status() << " PROCESS after sc_pause in " << name() << endl;
251    sc_assert( sc_time_stamp() == sc_time(42, SC_US) );
252    sc_assert( sc_get_status() == SC_RUNNING );
253    sc_assert( sc_is_running() == true );
254    wait(2, SC_US);
255    sc_assert( sc_time_stamp() == sc_time(44, SC_US) );
256    sc_assert( sc_get_status() == SC_RUNNING );
257    sc_assert( sc_is_running() == true );
258
259    sc_stop();
260    cout << "sc_get_status() == " << hex << sc_get_status() << " PROCESS after sc_stop() in " << name() << endl;;
261    sc_assert( sc_time_stamp() == sc_time(44, SC_US) );
262    sc_assert( sc_get_status() == SC_RUNNING );
263    sc_assert( sc_is_running() == true );
264
265    sc_pause();
266    sc_assert( sc_get_status() == SC_RUNNING );
267  }
268
269  void ev_handler()
270  {
271    cout << "sc_get_status() == " << hex << sc_get_status() << " METHOD in " << name() << endl;
272    sc_assert( sc_get_status() == SC_RUNNING );
273    sc_assert( sig.read()      == 42 );
274
275    static bool first = true;
276    if (first)
277    {
278      sc_assert( sc_time_stamp() == SC_ZERO_TIME );
279      first = false;
280    }
281    else
282      sc_assert( sc_time_stamp() == sc_time(42, SC_US) );
283  }
284
285  void immed_ev_handler()
286  {
287    sc_assert( sc_time_stamp() == sc_time(42, SC_US) );
288    sc_assert( sc_delta_count() == immed_ev_delta );
289    immed_ev_delta = 999;
290  }
291};
292
293void spawned_while_paused()
294{
295  cout << "spawned_while_paused() awoke" << endl;
296  sc_assert( sc_time_stamp() == sc_time(42, SC_US) );
297  sc_assert( sc_get_status() == SC_RUNNING );
298  sc_assert( sc_pending_activity() == true );
299}
300
301int sc_main(int argc, char* argv[])
302{
303  sc_assert( sc_delta_count() == 0 );
304  cout << "sc_get_status() == " << hex << sc_get_status() << " ELAB" << endl;
305  sc_assert( sc_get_status() == SC_ELABORATION );
306  sc_assert( sc_is_running() == false );
307  Top top("top");
308
309  sc_pause();  // Should be ignored
310
311  // Schedule some update requests and events
312  top.sig.write(42);
313  top.timed_ev.notify(42, SC_US);
314  top.delta_ev.notify(SC_ZERO_TIME);
315  sc_assert( sc_get_status() == SC_ELABORATION );
316  sc_assert( sc_delta_count() == 0 );
317
318  sc_start();
319  cout << "sc_get_status() == " << hex << sc_get_status() << " PAUSED" << endl;
320  sc_assert( sc_get_status() == SC_PAUSED );
321  sc_assert( sc_is_running() == true );
322  sc_assert( sc_time_stamp() == sc_time(42, SC_US) );
323
324  sc_start(1, SC_US);
325  cout << "sc_get_status() == " << hex << sc_get_status() << " PAUSED" << endl;
326  sc_assert( sc_get_status() == SC_PAUSED );
327  sc_assert( sc_is_running() == true );
328  sc_assert( sc_time_stamp() == sc_time(42, SC_US) );
329
330  // Schedule an immediate notification
331  top.immed_ev.notify();
332  top.immed_ev_delta = sc_delta_count();
333
334  // IMC while paused
335  top.m->xport->schedule_events_while_paused();
336
337  sc_process_handle h = sc_spawn(&spawned_while_paused);
338  sc_assert( h.valid() );
339
340  sc_start();
341  cout << "sc_get_status() == " << hex << sc_get_status() << " STOPPED" << endl;
342  sc_assert( sc_get_status() == SC_STOPPED );
343  sc_assert( sc_is_running() == false );
344  sc_assert( sc_time_stamp() == sc_time(44, SC_US) );
345
346  cout << endl << "Success" << endl;
347  return 0;
348}
349