mixed_child_procs.cpp revision 12855:588919e0e4aa
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// mixed_child_procs.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: mixed_child_procs.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// Process control methods applied where child process tree contains
32// a mixture of method and thread processes
33
34#define SC_INCLUDE_DYNAMIC_PROCESSES
35
36#include <systemc>
37
38using namespace sc_core;
39using std::cout;
40using std::endl;
41
42#include <string>
43using std::string;
44
45struct Top: sc_module
46{
47  Top(sc_module_name _name)
48  : count(0)
49  , index(0)
50  , n(30)
51  {
52    SC_THREAD(ctrl);
53
54    opt.spawn_method();
55    opt.set_sensitivity( &ev );
56
57    given_birth = new bool[n];
58
59    f0 = new int[n];
60    f1 = new int[n];
61    f2 = new int[n];
62    f3 = new int[n];
63    f4 = new int[n];
64    f5 = new int[n];
65
66    for (int i = 0; i < n; i++)
67    {
68      given_birth[i] = false;
69
70      f0[i] = 0;
71      f1[i] = 0;
72      f2[i] = 0;
73      f3[i] = 0;
74      f4[i] = 0;
75      f5[i] = 0;
76    }
77
78    t = sc_spawn(sc_bind(&Top::child_thread, this, index++, 3));
79    m = sc_spawn(sc_bind(&Top::child_method, this, index++, 3), "m", &opt);
80  }
81
82  sc_spawn_options opt;
83  sc_process_handle t, m;
84  std::exception ex;
85  int count;
86  int index;
87  const int n;
88  int *f0, *f1, *f2, *f3, *f4, *f5;
89  bool *given_birth;
90
91  sc_event ev;
92
93  void ctrl()
94  {
95    wait(10, SC_NS);
96
97    count = 1;
98    ev.notify();
99    wait(10, SC_NS);
100
101    count = 2;
102    t.throw_it(ex, SC_INCLUDE_DESCENDANTS);
103    m.throw_it(ex, SC_INCLUDE_DESCENDANTS);
104    wait(10, SC_NS);
105
106    count = 3;
107    t.sync_reset_on(SC_INCLUDE_DESCENDANTS);
108    m.sync_reset_on(SC_INCLUDE_DESCENDANTS);
109    wait(10, SC_NS);
110
111    count = 4;
112    ev.notify();
113    wait(10, SC_NS);
114
115    count = 5;
116    t.sync_reset_off(SC_INCLUDE_DESCENDANTS);
117    m.sync_reset_off(SC_INCLUDE_DESCENDANTS);
118    wait(10, SC_NS);
119
120    count = 6;
121    ev.notify();
122    wait(10, SC_NS);
123   }
124
125  void child_thread(int i, int level)
126  {
127    //cout << "child_thread " << i << " at level " << level << " called at " << sc_time_stamp() << endl;
128    if (level > 0 && !given_birth[i])
129    {
130      sc_spawn(sc_bind(&Top::child_thread, this, index++, level-1));
131      sc_spawn(sc_bind(&Top::child_method, this, index++, level-1), "h", &opt);
132      given_birth[i] = true;
133    }
134    switch(count)
135    {
136      case  0: f0[i]=1; break;
137      case  4: f4[i]=1; break;
138      default: sc_assert(false); break;
139    }
140    while(true)
141    {
142      try {
143        wait(ev);
144        //cout << "child_thread " << i << " at level " << level << " awoke at " << sc_time_stamp() << endl;
145        switch(count)
146        {
147          case  1: f1[i]=1; break;
148          case  6: f5[i]=1; break;
149          default: sc_assert(false); break;
150        }
151      }
152      catch (const std::exception& e) {
153        //cout << "child_thread " << i << " at level " << level << " caught at " << sc_time_stamp() << endl;
154        switch(count)
155        {
156          case  2: f2[i]=1; break;
157          case  4: f3[i]=1; throw static_cast<const sc_unwind_exception&>(e);
158          default: sc_assert(false); break;
159        }
160      }
161    }
162  }
163
164  void child_method(int i, int level)
165  {
166    //cout << "child_method " << i << " at level " << level << " at " << sc_time_stamp() << endl;
167    if (level > 0 && !given_birth[i])
168    {
169      sc_spawn(sc_bind(&Top::child_thread, this, index++, level-1));
170      sc_spawn(sc_bind(&Top::child_method, this, index++, level-1), "m", &opt);
171      given_birth[i] = true;
172    }
173    switch(count)
174    {
175      case  0: f0[i]=2; break;
176      case  1: sc_assert(sc_time_stamp() == sc_time(10, SC_NS)); f1[i]=1; break;
177      case  4: f4[i]=1; break;
178      case  6: f5[i]=1; break;
179      default: sc_assert(false); break;
180    }
181    next_trigger(ev);
182  }
183
184  SC_HAS_PROCESS(Top);
185};
186
187int sc_main(int argc, char* argv[])
188{
189  sc_report_handler::set_actions(SC_WARNING, SC_DO_NOTHING);
190
191  Top top("top");
192
193  sc_start();
194
195  sc_assert( top.index == top.n );
196
197  for (int i = 0; i < top.n; i++)
198  {
199    sc_assert( top.f0[i] );
200    sc_assert( top.f1[i] );
201
202    if (top.f0[i] == 1)  // i.e. a thread process
203    {
204      sc_assert( top.f2[i] );
205      sc_assert( top.f3[i] );
206    }
207    sc_assert( top.f4[i] );
208    sc_assert( top.f5[i] );
209  }
210
211  cout << endl << "Success" << endl;
212  return 0;
213}
214
215