stepwise_simulation.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/*****************************************************************************
21
22  stepwise_simulation.cpp -- Test step-wise simulation
23
24  Original Author: Philipp A. Hartmann, OFFIS, 2011-01-21
25
26 *****************************************************************************/
27
28/*****************************************************************************
29
30  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
31  changes you are making here.
32
33      Name, Affiliation, Date:
34  Description of Modification:
35
36 *****************************************************************************/
37
38#include <systemc.h>
39
40const int num_events = 2;
41const sc_time delay( 10, SC_NS );
42
43//#define EXPLICIT_DELTA // should not modify the trace
44#define DELAYED_EVENTS
45
46SC_MODULE(echo)
47{
48  sc_event ev[num_events];
49  SC_CTOR(echo)
50    : self_trigger(3)
51  {
52    SC_METHOD(do_print);
53#   ifdef DELAYED_EVENTS
54      dont_initialize();
55#   endif
56      for( int i=0; i<num_events; ++i )
57        sensitive << ev[i];
58  }
59
60  void do_print()
61  {
62    std::cout << "`" << sc_get_current_process_handle().name()
63              << "' triggered at " << sc_time_stamp()
64              << " - delta: " << sc_delta_count()
65              << std::endl;
66
67    if( --self_trigger > 1 )
68      next_trigger( delay/2 );
69    else if( self_trigger == 1 )
70      next_trigger( SC_ZERO_TIME );
71    else
72      self_trigger = 3;
73
74  }
75  int self_trigger;
76};
77
78void do_step( sc_time const & step )
79{
80    sc_dt::uint64 delta       = sc_delta_count();
81    static bool   start_delta = ( delta == 0 ) && ( step == SC_ZERO_TIME );
82    std::cout
83       << " ----- running for "
84       << ( ( step == SC_ZERO_TIME ) ? "delta" : step.to_string() )
85       << std::endl;
86
87    sc_time start = sc_time_stamp();
88    if( step > SC_ZERO_TIME )
89    {
90      std::cout << "   --- No-op start (warning) - ";
91      sc_start( step / 2, SC_EXIT_ON_STARVATION );
92      sc_assert( start == sc_time_stamp() );
93
94      sc_start( step / 2, SC_RUN_TO_TIME );
95      sc_assert( start + step / 2 == sc_time_stamp() );
96
97      sc_start( step / 2 ); // complete step
98    }
99    else
100    {
101      sc_start( SC_ZERO_TIME );
102    }
103    sc_assert( start + step == sc_time_stamp() );
104
105    std::cout
106       << "    -- stopped at - "
107       << sc_time_stamp() << " - delta: " << sc_delta_count()
108       << std::endl;
109
110    // delta has only increased, when a delta has been run
111    sc_assert( sc_delta_count()
112                 == delta + ( !start_delta && step == SC_ZERO_TIME ) );
113    start_delta = false;
114}
115
116int sc_main(int, char*[])
117{
118  sc_assert( !sc_pending_activity() );
119  sc_assert( sc_time_to_pending_activity()
120             == sc_max_time() - sc_time_stamp() );
121
122  sc_signal<bool> toggle("toggle");
123  echo dut("echo");
124
125  // notify future events
126  for( int i=0; i<num_events; ++i )
127    dut.ev[i].notify( (i+1) * delay );
128
129  sc_assert( sc_pending_activity_at_future_time() );
130  sc_assert( sc_time_to_pending_activity() == delay );
131
132  do_step( SC_ZERO_TIME ); // elaborate
133
134  while( sc_pending_activity() )
135  {
136    sc_assert( sc_pending_activity_at_current_time()
137               || sc_time_to_pending_activity() > SC_ZERO_TIME );
138
139    sc_assert( sc_pending_activity_at_future_time()
140               || sc_time_to_pending_activity() == SC_ZERO_TIME );
141
142    // run single (time) step
143    do_step( sc_time_to_pending_activity() );
144
145#   ifdef EXPLICIT_DELTA
146      // run remaining current deltas (optional)
147      while( sc_pending_activity_at_current_time() ) {
148        sc_assert( sc_time_to_pending_activity() == SC_ZERO_TIME );
149        do_step( SC_ZERO_TIME );
150      }
151#   endif // EXPLICIT_DELTA
152  }
153
154  // force one empty evaluate (w/ non-empty update)
155  toggle.write( !toggle.read() );
156  sc_assert(  sc_pending_activity_at_current_time() );
157  sc_start( SC_ZERO_TIME );
158
159  sc_assert( !sc_pending_activity() );
160  sc_assert( sc_time_to_pending_activity()
161             == sc_max_time() - sc_time_stamp() );
162
163  std::cout << "Success" << std::endl;
164  return 0;
165}
166