test15.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  test15.cpp -- sc_writer_policy: check conflicts within an evaluation phase
23
24  Original Author: Philipp A. Hartmann, Intel, 2017-05-12
25
26 *****************************************************************************/
27
28// see https://github.com/OSCI-WG/systemc/issues/222
29
30#define SC_INCLUDE_DYNAMIC_PROCESSES
31#include <systemc>
32#include <iomanip>
33#include <sstream>
34
35using sc_core::SC_NS;
36using sc_core::SC_ZERO_TIME;
37
38SC_MODULE(dut)
39{
40    static const int num_drivers = 4;
41
42    SC_CTOR(dut)
43      : sig("sig")
44    {
45        SC_THREAD(run);
46        for(int id=1; id <= num_drivers; ++id) {
47          // first and last driver write the same values
48          spawn_driver( id, (id-1) % (num_drivers-1) + 1 );
49        }
50    }
51
52private:
53    void spawn_driver(int id, int value) {
54      sc_assert( id > 0 && id <= num_drivers );
55      sc_core::sc_spawn_options sp;
56      sp.set_sensitivity(&ev[id-1]);
57      sp.spawn_method();
58      sp.dont_initialize();
59
60      std::stringstream nm;
61      nm << "p" << id;
62      sc_spawn( sc_bind(&dut::driver, this, value), nm.str().c_str(), &sp );
63    }
64
65    void run() {
66      wait(1, SC_NS);
67
68      std::cout << "\n*** trigger each driver in individual delta cycles" << std::endl;
69      for(int id=1; id <= num_drivers; ++id) {
70        trigger(id);
71        wait(SC_ZERO_TIME);
72        log();
73      }
74
75      wait(1, SC_NS);
76      std::cout << "\n*** trigger 1-2-3 in the same delta cycle" << std::endl;
77      trigger(1);
78      trigger(2); // error expected
79      trigger(3); // error expected
80      wait(SC_ZERO_TIME);
81      log();
82
83      wait(1, SC_NS);
84      std::cout << "\n*** trigger 2-3-1 in the same delta cycle" << std::endl;
85      trigger(2);
86      trigger(3); // error expected
87      trigger(1); // error expected
88      wait(SC_ZERO_TIME);
89      log();
90
91      wait(1, SC_NS);
92      std::cout << "\n*** trigger 3-1-2 in the same delta cycle" << std::endl;
93      trigger(3);
94      trigger(1); // error expected
95      trigger(2); // error expected
96      wait(SC_ZERO_TIME);
97      log();
98
99      wait(1, SC_NS);
100      std::cout << "\n*** trigger 1-2-1-2 in the same delta cycle" << std::endl;
101      trigger(1);
102      trigger(2); // error expected
103      trigger(1); // NO error expected (original process)
104      trigger(2); // error expected
105      wait(SC_ZERO_TIME);
106      log();
107
108      wait(1, SC_NS);
109      std::cout << "\n*** trigger 2-1 in the same delta cycle" << std::endl;
110      trigger(2);
111      trigger(1); // error expected
112      wait(SC_ZERO_TIME);
113      log();
114
115      wait(1, SC_NS);
116      std::cout << "\n*** trigger 1-3 in the same delta cycle" << std::endl;
117      trigger(1);
118      trigger(3); // error expected
119      wait(SC_ZERO_TIME);
120      log();
121
122      wait(1, SC_NS);
123      std::cout << "\n*** trigger 1-4-1 in the same delta cycle" << std::endl;
124      trigger(1);
125      trigger(4); // error expected? (same value)
126      trigger(1); // NO error expected (original process)
127      wait(SC_ZERO_TIME);
128      log();
129
130      wait(1, SC_NS);
131      std::cout << "\n*** trigger 4-1 in the same delta cycle" << std::endl;
132      trigger(4);
133      trigger(1); // error expected? (same value)
134      wait(SC_ZERO_TIME);
135      log();
136    }
137
138    void trigger(int id) {
139      sc_assert( id > 0 && id <= num_drivers );
140      ev[id-1].notify();
141      wait(ev_schedule);
142    }
143
144    void driver(int value) {
145        log(value);
146        try {
147            sig.write(value);
148        } catch (const sc_core::sc_report& msg ) {
149            std::cout << "\n" << msg.what() << "\n" << std::endl;
150        }
151        ev_schedule.notify();
152    }
153
154    void log(int value = -1) {
155        std::cout
156          << std::setw(8) << sc_core::sc_get_current_process_handle().name() << ": "
157          << std::setw(5) << sc_core::sc_time_stamp()
158          << " @ " << std::setw(2) << sc_core::sc_delta_count() << ": "
159          << ( (value!=-1) ? "writing " : "reading " )
160          << sig.name() << " = "
161          << ( (value!=-1) ? value : sig.read() )
162          << std::endl;
163    }
164
165    sc_core::sc_signal<int, sc_core::SC_MANY_WRITERS> sig;
166    sc_core::sc_event ev_schedule, ev[num_drivers];
167};
168
169int sc_main( int, char*[] )
170{
171    dut top("dut");
172    sc_core::sc_start();
173    std::cout << "\nProgram completed" << std::endl;
174    return 0;
175}
176