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
21  test07.cpp -- Test handling of process objects with living descendants
22
23  Original Author: Philipp A. Hartmann, OFFIS
24
25 *****************************************************************************/
26/*****************************************************************************
27  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
28  changes you are making here.
29
30      Name, Affiliation, Date:
31  Description of Modification:
32
33 *****************************************************************************/
34// $Log: test07.cpp,v $
35// Revision 1.2  2011/02/14 17:00:00  acg
36//  Andy Goodrich: updated copyright and added cvs logging information inline.
37//
38
39#define SC_INCLUDE_DYNAMIC_PROCESSES
40#include <systemc.h>
41
42void
43dump_hierarchy(
44    std::vector< sc_object* > const & objs = sc_get_top_level_objects()
45  , unsigned level = 0
46)
47{
48  if (!level)
49    std::cout << "------ " << "(" << sc_time_stamp() << ")" << " ------"
50      << std::endl;
51
52  std::vector<sc_object*>::const_iterator it = objs.begin();
53  for( ; it != objs.end(); it++ )
54  {
55    std::cout << std::string( level + 1, ' ' )
56              << (*it)->name() << " (" << (*it)->kind() << ")";
57
58    sc_process_handle h(*it);
59
60    std::cout << ( h.valid() // is it a process? -> print state
61                 ? (! h.terminated() ? " (running)" : " (terminated)"  )
62                 : "" )
63              << std::endl;
64
65    dump_hierarchy( (*it)->get_child_objects(), level+1 );
66  }
67
68  if (!level)
69    std::cout << "---------------------- " << std::endl;
70}
71
72struct my_object : sc_object {
73  my_object( const char* name ) : sc_object( name ) {}
74  ~my_object()
75  {
76    std::cout << "+++ " << this->name() << " deleted" << std::endl;
77  }
78};
79
80SC_MODULE(DUT)
81{
82  SC_CTOR(DUT)
83    : leaf_(0)
84  {
85    SC_THREAD(parent);
86  }
87
88  enum start_options
89  {
90    no_children      = 0,
91    start_child_proc = 1,
92    create_child_obj = 2,
93    both_children    = 3
94  };
95
96  void child( start_options opt ){
97    start();
98
99    my_object local( "local" );
100
101    if( opt & create_child_obj )
102      leaf_=new my_object("dyn_obj");
103
104    wait( 100, SC_NS );
105
106    if( opt & start_child_proc )
107      sc_spawn( sc_bind( &DUT::child, this, no_children )
108              , "grandchild" );
109
110    wait( 100, SC_NS );
111    end();
112  }
113
114  void parent()
115  {
116    // only parent alive
117    wait( 50, SC_NS );
118    dump_hierarchy();
119
120    sc_spawn( sc_bind( &DUT::child, this, start_child_proc ), "child0" );
121    sc_spawn( sc_bind( &DUT::child, this, both_children ), "child1" );
122
123    // direct children up and running
124    wait( 50, SC_NS );
125    dump_hierarchy();
126
127    // grandchildren started, child object created
128    wait( 100, SC_NS );
129    dump_hierarchy();
130
131    // direct children ended (zombies kept)
132    wait( 100, SC_NS );
133    dump_hierarchy();
134
135    // grandhildren ended (zombie with child object kept)
136    wait( 100, SC_NS );
137    dump_hierarchy();
138
139    // child object removed, zombies deleted
140    delete leaf_; leaf_ = 0;
141    wait( 100, SC_NS );
142    dump_hierarchy();
143
144    {
145      // create another pair of children
146      sc_process_handle
147        h0 = sc_spawn( sc_bind( &DUT::child, this, start_child_proc ), "child0" ),
148        h1 = sc_spawn( sc_bind( &DUT::child, this, start_child_proc ), "child1" );
149
150      wait( 100, SC_NS );
151      dump_hierarchy();
152
153      // and kill them, after it has spawned its grandchild
154      wait( 50, SC_NS );
155      h0.kill();
156      h1.kill( SC_INCLUDE_DESCENDANTS );
157
158      std::cout << "+++ kills sent ... "
159                << "(" << sc_time_stamp() << ")"
160                << std::endl;
161
162      // needed to avoid segfault
163      //wait(SC_ZERO_TIME);
164
165    } // drop handles
166
167    wait( 50, SC_NS );
168    dump_hierarchy();
169
170    end();
171  }
172
173  void start()
174  {
175    std::cout
176      << "+++ "
177      << sc_get_current_process_handle().name()
178      << " starting "
179      << "(" << sc_time_stamp() << ")"
180      << std::endl;
181  }
182  void end()
183  {
184    std::cout
185      << "+++ "
186      << sc_get_current_process_handle().name()
187      << " exiting "
188      << "(" << sc_time_stamp() << ")"
189      << std::endl;
190  }
191
192  my_object* leaf_;
193};
194
195
196int sc_main( int, char*[] )
197{
198  DUT dut("dut");
199  sc_start(900, SC_NS );
200  // everything cleaned up (only module still alive)
201  dump_hierarchy();
202
203  return 0;
204}
205