Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | /***************************************************************************** |
2 | ||
3 | The following code is derived, directly or indirectly, from the SystemC | |
4 | source code Copyright (c) 1996-2004 by all Contributors. | |
5 | All Rights reserved. | |
6 | ||
7 | The contents of this file are subject to the restrictions and limitations | |
8 | set forth in the SystemC Open Source License Version 2.4 (the "License"); | |
9 | You may not use this file except in compliance with such restrictions and | |
10 | limitations. You may obtain instructions on how to receive a copy of the | |
11 | License at http://www.systemc.org/. Software distributed by Contributors | |
12 | under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF | |
13 | ANY KIND, either express or implied. See the License for the specific | |
14 | language governing rights and limitations under the License. | |
15 | ||
16 | *****************************************************************************/ | |
17 | ||
18 | #ifndef _TLM_TARGET_PORT_H_ | |
19 | #define _TLM_TARGET_PORT_H_ | |
20 | ||
21 | /*------------------------------------------------------------------------------ | |
22 | * Includes | |
23 | *----------------------------------------------------------------------------*/ | |
24 | #include <vector> | |
25 | ||
26 | #include "systemc.h" | |
27 | ||
28 | #include "tlm_ports/tlm_target_port_base.h" | |
29 | ||
30 | //---------------------------------------------------------------------------- | |
31 | /// Class tlm_target_port: port to be instantiated on the target side | |
32 | /** | |
33 | * This class could be used as base class for user defined target ports (support of user convenience layer). | |
34 | * \n It provides new binding methods definition: sc_export to sc_export binding must be identified in order | |
35 | * create tlm_target_port_base::target_port_list used target port ID propagation through hierarchical | |
36 | * binding; the only port ID that makes sense is the port ID of the port directly bound to the interface. | |
37 | * An error detection is also provided: multiple interface bind declarations are not detected by | |
38 | * sc_export (the interface is just replaced), the new binding definition issues an error message in this | |
39 | * case. | |
40 | **/ | |
41 | //---------------------------------------------------------------------------- | |
42 | template<typename IF> | |
43 | class tlm_target_port : | |
44 | public sc_export<IF>, | |
45 | public tlm_target_port_base { | |
46 | ||
47 | typedef IF interface_type; | |
48 | typedef tlm_target_port<IF> target_port_type; | |
49 | typedef tlm_target_port_base target_port_base_type; | |
50 | ||
51 | public: | |
52 | ||
53 | //-------------- | |
54 | // Constructor | |
55 | //-------------- | |
56 | tlm_target_port(const char * name); | |
57 | ||
58 | //-------------------------------------------------------------------- | |
59 | /// @name sc_export overridden methods | |
60 | /// Need to specialize binding operation to support port propagation in transaction recorders. | |
61 | /// Specialization is done for sc_export/sc_export. | |
62 | /// Other redefinitions of bindings are just calls to regular bind function | |
63 | /// \n Note: This is due to non virtual definition of SystemC bind | |
64 | //-------------------------------------------------------------------- | |
65 | /// @{ | |
66 | /// | |
67 | //------------------------------------------------------------------------------- | |
68 | // Before end of elaboration | |
69 | /** | |
70 | * Called just before end of elaboration to propagate the significant target port id: | |
71 | * the only valid port id is the one set by the module which implements the tlm core interface. | |
72 | * | |
73 | * Remark: sc_port_base::complete_binding should be the best place to do | |
74 | * that but this method is private !! | |
75 | **/ | |
76 | //------------------------------------------------------------------------------- | |
77 | void before_end_of_elaboration(); | |
78 | ||
79 | //------------------------------------------------------------------------------- | |
80 | // End of elaboration | |
81 | /** | |
82 | * Called at the end of elaboration. Used to print debug message: content opf the target port list | |
83 | **/ | |
84 | //------------------------------------------------------------------------------- | |
85 | void end_of_elaboration(); | |
86 | ||
87 | //--------------------------------------------------------- | |
88 | // Special binding between two target ports | |
89 | //--------------------------------------------------------- | |
90 | ||
91 | /// bind(sc_export) with target ports propagation | |
92 | void bind(target_port_type& target_port_); | |
93 | ||
94 | /// Case of the other port uses another interface as template: works only if OTHER_IF derives from IF | |
95 | template<typename OTHER_IF> | |
96 | void bind(tlm_target_port<OTHER_IF>& target_port_); | |
97 | ||
98 | /// operator() (sc_export) overridden: just calls bind(sc_export) | |
99 | void operator() (target_port_type& target_port_) { | |
100 | bind(target_port_); | |
101 | } | |
102 | ||
103 | /// Case of the other port uses another interface as template: works only if OTHER_IF derives from IF | |
104 | template<typename OTHER_IF> | |
105 | void operator() (tlm_target_port<OTHER_IF>& target_port_) { | |
106 | bind<OTHER_IF>(target_port_); | |
107 | } | |
108 | ||
109 | ||
110 | //--------------------------------------------------------- | |
111 | // Normal binding between port and interface. | |
112 | // To be redefined here (bind(port_) is overridden above | |
113 | //--------------------------------------------------------- | |
114 | ||
115 | /// bind(interface_type) overridden | |
116 | void bind(interface_type& interface_); | |
117 | ||
118 | /// operator() (interface_type) overridden | |
119 | void operator() (interface_type& interface_); | |
120 | ||
121 | /// @} | |
122 | ||
123 | protected: | |
124 | ||
125 | /** Returns true and issues an error message if the port is already bound to an interface during the | |
126 | binding of other_if (called by bind(sc_export)) | |
127 | **/ | |
128 | bool is_already_bound(sc_interface * other_if); | |
129 | ||
130 | }; | |
131 | ||
132 | ||
133 | //-------------- | |
134 | // Constructor | |
135 | //-------------- | |
136 | ||
137 | template<typename IF> | |
138 | tlm_target_port<IF>::tlm_target_port(const char * name) : | |
139 | sc_export<interface_type>(name) | |
140 | {} | |
141 | ||
142 | ||
143 | ||
144 | /* Return true and issue an error message if the port is already bound to an interface during the | |
145 | binding of other_if (called by bind(sc_export)) | |
146 | */ | |
147 | template<typename IF> | |
148 | bool tlm_target_port<IF>::is_already_bound(sc_interface * other_if) { | |
149 | if (dynamic_cast<sc_interface * >(this->get_interface()) == NULL) return(false); | |
150 | else { | |
151 | std::string if_name1,if_name2 ; | |
152 | sc_object * tmp = dynamic_cast<sc_object * >(other_if); | |
153 | if (tmp) if_name1 = tmp->name(); | |
154 | else if_name1 = "unnamed interface (non sc_object)"; | |
155 | tmp = dynamic_cast<sc_object * >(this->get_interface()); | |
156 | if (tmp) if_name2 = tmp->name(); | |
157 | else if_name2 = "unnamed interface (non sc_object)"; | |
158 | ||
159 | std::string msg(sc_object::name()); | |
160 | msg += (std::string)(": tlm_target_port warning, Can't bind to \"") + if_name1; | |
161 | msg += (std::string)("\" interface,the target port is already bound to this interface: \""); | |
162 | msg += if_name2 + (std::string)("\"\n"); | |
163 | SC_REPORT_WARNING("binding warning",msg.c_str()); | |
164 | ||
165 | return(true); | |
166 | } | |
167 | } | |
168 | ||
169 | //--------------------------- | |
170 | // sc_export overridden methods | |
171 | //--------------------------- | |
172 | ||
173 | //------------------------------------------------------------------------------- | |
174 | // before_end_of_elaboration() | |
175 | // Called just before end of elaboration to propagate the significant target port id | |
176 | // The only significant target port id is the one set by the module which implements the | |
177 | // tlm core interface | |
178 | //------------------------------------------------------------------------------- | |
179 | template<typename IF> | |
180 | void | |
181 | tlm_target_port<IF>::before_end_of_elaboration() | |
182 | { | |
183 | // if this target port is not directly connected to the core interface | |
184 | if (get_target_port_list().size() > 1) { | |
185 | ||
186 | for(typename std::vector<target_port_base_type *>::iterator target_port = get_target_port_list().begin(); | |
187 | target_port != get_target_port_list().end(); | |
188 | target_port++) { | |
189 | set_tlm_export_id((*target_port)->get_tlm_export_id()); // Propagate the target port id | |
190 | } | |
191 | } | |
192 | } | |
193 | ||
194 | //------------------------------------------------------------------------------- | |
195 | // end_of_elaboration(). Debug message concerning target port list centent | |
196 | //------------------------------------------------------------------------------- | |
197 | template<typename IF> | |
198 | void | |
199 | tlm_target_port<IF>::end_of_elaboration() { | |
200 | ||
201 | #ifdef TLM_PORT_DEBUG | |
202 | printf("DEBUG\t\t%s: Registered target port list :\n",sc_object::name()); | |
203 | for(typename std::vector<target_port_base_type *>::iterator port = get_target_port_list().begin(); | |
204 | port != get_target_port_list().end(); | |
205 | port++) { | |
206 | printf("DEBUG\t\t%s: \t- %s\n",sc_object::name(),(static_cast<target_port_type * >(*port))->name()); | |
207 | } | |
208 | printf("DEBUG\t\t%s: -------------------------------------------------------\n",sc_object::name()); | |
209 | #endif | |
210 | ||
211 | } | |
212 | //--------------------------------------------------------- | |
213 | // Special binding between two target ports | |
214 | //--------------------------------------------------------- | |
215 | ||
216 | // bind(sc_export) | |
217 | template<typename IF> | |
218 | void | |
219 | tlm_target_port<IF>::bind(target_port_type& target_port_) | |
220 | { | |
221 | // If the target port is still not bound | |
222 | if (!is_already_bound(target_port_.get_interface())) { | |
223 | // Copy the list of registered target ports to the current bound port (port propagation) | |
224 | for(typename std::vector<target_port_base_type *>::iterator target_port = target_port_.get_target_port_list().begin(); | |
225 | target_port != target_port_.get_target_port_list().end(); | |
226 | target_port++) { | |
227 | this->register_target_port(*target_port); | |
228 | } | |
229 | ||
230 | // Calls sc_export standard bind method | |
231 | sc_export<interface_type>::bind(target_port_); | |
232 | } | |
233 | } | |
234 | ||
235 | // Specific case: if the bound export is based on a different interface. Requirement, the interface of | |
236 | // the bound export MUST derive from the interface the export is based on. | |
237 | template<typename IF> | |
238 | template<typename OTHER_IF> | |
239 | void | |
240 | tlm_target_port<IF>::bind(tlm_target_port<OTHER_IF>& target_port_) { | |
241 | // Test if OTHER_IF derives from IF | |
242 | IF * other_if = dynamic_cast<IF*>(target_port_.get_interface()); | |
243 | if (other_if) { | |
244 | // If the target port is still not bound | |
245 | if (!is_already_bound(target_port_.get_interface())) { | |
246 | // Copy the list of registered target ports to the current bound port (port propagation) | |
247 | for(typename std::vector<target_port_base_type *>::iterator target_port = target_port_.get_target_port_list().begin(); | |
248 | target_port != target_port_.get_target_port_list().end(); | |
249 | target_port++) { | |
250 | this->register_target_port(*target_port); | |
251 | } | |
252 | ||
253 | // Calls sc_export standard bind method | |
254 | sc_export<interface_type>::bind(*other_if); | |
255 | } | |
256 | } | |
257 | else { | |
258 | std::string msg(sc_object::name()); | |
259 | msg += (std::string)(": tlm_target_port error, incompatible interface detected during the binding tlm_target_port \"") + (std::string)(this->name()); | |
260 | msg += (std::string)" to tlm_target_port \"" + (std::string)(target_port_.name()) +(std::string)("\"\n") ; | |
261 | SC_REPORT_ERROR("bind export to export failed",msg.c_str()); | |
262 | } | |
263 | ||
264 | } | |
265 | ||
266 | ||
267 | //--------------------------------------------------------- | |
268 | // Normal binding between port and interface. | |
269 | // To be redefined here (bind(port_) is overridden above | |
270 | //--------------------------------------------------------- | |
271 | ||
272 | // bind(interface_type) | |
273 | template<typename IF> | |
274 | void | |
275 | tlm_target_port<IF>::bind(interface_type& interface_) { | |
276 | // Calls sc_export standard bind method | |
277 | sc_export<interface_type>::bind(interface_); | |
278 | } | |
279 | ||
280 | // operator() (interface_type): just calls bind(interface_type) | |
281 | template<typename IF> | |
282 | void | |
283 | tlm_target_port<IF>::operator() (interface_type& interface_) { | |
284 | sc_export<interface_type>::bind(interface_); | |
285 | } | |
286 | ||
287 | #endif /* _TLM_TARGET_PORT_H_ */ |