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