misc: Merge branch hotfix v20.1.0.2 branch into develop
[gem5.git] / src / systemc / sc_port_wrapper.hh
1 /*
2 * Copyright 2019 Google LLC.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met: redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer;
8 * redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution;
11 * neither the name of the copyright holders nor the names of its
12 * contributors may be used to endorse or promote products derived from
13 * this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #ifndef __SYSTEMC_SC_PORT_WRAPPER_HH__
29 #define __SYSTEMC_SC_PORT_WRAPPER_HH__
30
31 #include <string>
32 #include <type_traits>
33
34 #include "base/logging.hh"
35 #include "sim/port.hh"
36 #include "systemc/ext/core/sc_export.hh"
37 #include "systemc/ext/core/sc_interface.hh"
38 #include "systemc/ext/core/sc_port.hh"
39
40 namespace sc_gem5
41 {
42
43 // Forward declaration
44 template <typename IF>
45 class ScPortWrapper;
46 template <typename IF>
47 class ScInterfaceWrapper;
48 template <typename IF>
49 class ScExportWrapper;
50
51 template <typename IF>
52 class ScPortWrapper : public ::Port
53 {
54 public:
55 using ScPort = sc_core::sc_port_b<IF>;
56
57 ScPortWrapper(ScPort& p, const std::string& name, PortID id)
58 : Port(name, id), port_(p)
59 {}
60
61 ScPort&
62 port()
63 {
64 return port_;
65 }
66
67 void
68 unbind() override
69 {
70 panic("sc_port can't be unbound.");
71 }
72
73 void
74 bind(::Port& peer) override
75 {
76 // Try ScPortWrapper or ScInterfaceWrapper
77 if (auto* beer = dynamic_cast<ScPortWrapper<IF>*>(&peer)) {
78 port_.bind(beer->port());
79 } else if (auto* iface =
80 dynamic_cast<ScInterfaceWrapper<IF>*>(&peer)) {
81 port_.bind(iface->interface());
82 } else {
83 fatal("Attempt to bind sc_port %s to incompatible port %s.",
84 name(), peer.name());
85 }
86 Port::bind(peer);
87 }
88
89 private:
90 ScPort& port_;
91 };
92
93 template <typename IF>
94 class ScInterfaceWrapper : public ::Port
95 {
96 public:
97 ScInterfaceWrapper(IF& i, const std::string name, PortID id)
98 : Port(name, id), iface_(i)
99 {}
100
101 IF&
102 interface()
103 {
104 return iface_;
105 }
106
107 void
108 unbind() override
109 {
110 panic("sc_interface can't be unbound.");
111 }
112
113 void
114 bind(::Port& peer) override
115 {
116 // fatal error if peer is neither ScPortWrapper nor ScExportWrapper
117 fatal_if(!dynamic_cast<ScPortWrapper<IF>*>(&peer) &&
118 !dynamic_cast<ScExportWrapper<IF>*>(&peer),
119 "Attempt to bind sc_interface %s to incompatible port %s.",
120 name(), peer.name());
121
122 // Don't bind to peer otherwise we may have error messages saying that
123 // this interface has already be bound since the peer may already did
124 // that. Just let sc_port or sc_export do the binding
125 Port::bind(peer);
126 }
127
128 private:
129 IF& iface_;
130 };
131
132 template <typename IF>
133 class ScExportWrapper : public ::Port
134 {
135 public:
136 using ScExport = sc_core::sc_export<IF>;
137
138 ScExportWrapper(ScExport& p, const std::string& name, PortID id)
139 : Port(name, id), port_(p)
140 {}
141
142 ScExport&
143 port()
144 {
145 return port_;
146 }
147
148 void
149 unbind() override
150 {
151 panic("sc_export cannot be unbound.");
152 }
153
154 void
155 bind(::Port& peer) override
156 {
157 auto* iface = dynamic_cast<ScInterfaceWrapper<IF>*>(&peer);
158 fatal_if(!iface,
159 "Attempt to bind sc_export %s to incompatible port %s.",
160 name(), peer.name());
161
162 port_.bind(iface->interface());
163 Port::bind(peer);
164 }
165
166 private:
167 ScExport& port_;
168 };
169
170 } // namespace sc_gem5
171
172 #endif // __SYSTEMC_SC_PORT_WRAPPER_HH__