Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / model / vendor / TLM-2006-11-29 / tlm / tlm_ports / tlm_initiator_port.h
CommitLineData
86530b38
AT
1/*****************************************************************************\r
2\r
3 The following code is derived, directly or indirectly, from the SystemC\r
4 source code Copyright (c) 1996-2004 by all Contributors.\r
5 All Rights reserved.\r
6\r
7 The contents of this file are subject to the restrictions and limitations\r
8 set forth in the SystemC Open Source License Version 2.4 (the "License");\r
9 You may not use this file except in compliance with such restrictions and\r
10 limitations. You may obtain instructions on how to receive a copy of the\r
11 License at http://www.systemc.org/. Software distributed by Contributors\r
12 under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF\r
13 ANY KIND, either express or implied. See the License for the specific\r
14 language governing rights and limitations under the License.\r
15\r
16*****************************************************************************/\r
17\r
18#ifndef _TLM_INITIATOR_PORT_H_\r
19#define _TLM_INITIATOR_PORT_H_\r
20\r
21/*------------------------------------------------------------------------------\r
22 * Includes\r
23 *----------------------------------------------------------------------------*/\r
24#include <vector>\r
25\r
26#include "systemc.h"\r
27\r
28#include "tlm_ports/tlm_initiator_port_base.h"\r
29#include "tlm_ports/tlm_target_port.h"\r
30\r
31\r
32//----------------------------------------------------------------------------\r
33/// Class tlm_initiator_port: port to be instantiated on the initiator side\r
34/**\r
35 * This class could be used as base class for user defined initiator ports (support of user convenience layer).\r
36 * \n It provides new binding methods definition: \r
37 * - sc_port to sc_export binding must be identified in order to create target_port_list\r
38 * used for port ID propagation through hierarchical binding. \r
39 * - sc_port to sc_port binding creates two initiator ports lists: one regular list (deep port "knows" other\r
40 * initiator ports through a hierarchy) and a reversed list (the port directly bound to the interface\r
41 * "knows" deeper ports through a hierarchy) used to convey target_port list to deeper ports for target port\r
42 * ID propagation.\r
43 * An error detection is also provided: When the same interface is bound two times to a sc_port, SystemC causes \r
44 * the simulation end. This case could append in test platform (dedicated debug and regular port of a target \r
45 * bound to the same router). The specific binding issues a warning message but let the simulation run.\r
46\r
47**/\r
48//----------------------------------------------------------------------------\r
49template<typename IF,int N = 1>\r
50class tlm_initiator_port : \r
51 public sc_port<IF,N>,\r
52 public tlm_initiator_port_base {\r
53\r
54 typedef IF interface_type;\r
55 typedef tlm_target_port<IF> target_port_type;\r
56 typedef tlm_initiator_port<IF,N> initiator_port_type;\r
57\r
58 typedef tlm_target_port_base target_port_base_type;\r
59 typedef tlm_initiator_port_base initiator_port_base_type;\r
60\r
61public:\r
62\r
63 //--------------\r
64 // Constructor\r
65 //--------------\r
66 tlm_initiator_port(const char * name);\r
67 \r
68\r
69 //--------------------------------------------------------------------\r
70 /// @name sc_port overridden methods\r
71 /// Need to specialize binding operation to support port propagation in transaction recorders. \r
72 /// Specialization is done for sc_port/sc_port and sc_port/sc_export \r
73 /// Other redefinitions of bindings are just calls to regular bind function\r
74 /// \n Note: This is due to non virtual definition of SystemC bind method\r
75 //--------------------------------------------------------------------\r
76 /// @{\r
77 ///\r
78 //-------------------------------------------------------------------------------\r
79 // Before end of elaboration\r
80 /**\r
81 * Called just before end of elaboration to propagate registered target ports to all the \r
82 * bound initiator ports (using the reversed initiator port list).\r
83 *\r
84 * Remark: sc_port_base::complete_binding should be the best place to do \r
85 * that but this method is private !!\r
86 **/\r
87 //-------------------------------------------------------------------------------\r
88 void before_end_of_elaboration();\r
89\r
90 //-------------------------------------------------------------------------------\r
91 // End of elaboration\r
92 /**\r
93 * Called at the end of elaboration. Checks target port list: empty target port\r
94 * list is a fatal error as initiator port should be bound at least to one target_port\r
95 **/\r
96 //-------------------------------------------------------------------------------\r
97 void end_of_elaboration();\r
98 \r
99 \r
100 //--------------------------------------------------------------------\r
101 // Special binding between initiator port and target port.\r
102 // (port registration added to the standard sc_port_base::bind())\r
103 //--------------------------------------------------------------------\r
104 \r
105 /// bind(sc_export) overridden with port registration \r
106 void bind(target_port_type& target_port_);\r
107\r
108 /// Case of the other port uses another interface as template: works only if OTHER_IF derives from IF\r
109 template<typename OTHER_IF>\r
110 void bind(tlm_target_port<OTHER_IF>& target_port_);\r
111\r
112\r
113 /// operator() (sc_export) overridden with port registration \r
114 void operator() (target_port_type& target_port_);\r
115\r
116 /// Case of the other port uses another interface as template: works only if OTHER_IF derives from IF\r
117 template<typename OTHER_IF>\r
118 void operator() (tlm_target_port<OTHER_IF>& target_port_) {\r
119 bind<OTHER_IF>(target_port_);\r
120 }\r
121\r
122\r
123 /// bind(sc_port) overridden with port registration \r
124 void bind(sc_port_b<interface_type>& port_);\r
125 \r
126 /// operator() (sc_port) overridden with port registration \r
127 void operator() (sc_port_b<interface_type>& port_);\r
128 \r
129 \r
130 //---------------------------------------------------------\r
131 // Normal binding between port and interface.\r
132 // To be redefined here (bind(port_) is overridden above\r
133 //---------------------------------------------------------\r
134 \r
135 /// bind(interface_type) overridden with port registration \r
136 void bind(interface_type& interface_);\r
137\r
138 /// operator () (interface_type) overridden with port registration\r
139 void operator () (interface_type& interface_);\r
140 \r
141 /// @}\r
142\r
143protected:\r
144\r
145/** Returns true and issues an error message and return true if the same interface is bound \r
146 two times throught 2 differents target port. \r
147**/\r
148 bool is_interface_bound_twice(sc_export_base& target_port_);\r
149\r
150};\r
151\r
152\r
153\r
154//--------------\r
155// Constructor\r
156//--------------\r
157template<typename IF,int N>\r
158tlm_initiator_port<IF,N>::tlm_initiator_port(const char * name) :\r
159 sc_port<interface_type,N>(name)\r
160{}\r
161\r
162 \r
163/** Returns true and issues an error message if the same interface is bound \r
164 two times throught 2 differents target port. \r
165**/\r
166template<typename IF,int N>\r
167bool tlm_initiator_port<IF,N>::is_interface_bound_twice(sc_export_base& target_port_) {\r
168 for(int i=0;i<this->size();i++) {\r
169 if ((*this)[i] == target_port_.get_interface()) {\r
170 sc_object * tmp = dynamic_cast<sc_object * >(target_port_.get_interface());\r
171 std::string if_name;\r
172 if (tmp) if_name = tmp->name();\r
173 else if_name = "unnamed interface/non sc_object";\r
174\r
175 std::string msg(sc_object::name());\r
176 msg += (std::string)(": tlm_initiator_port warning, while binding the interface \"");\r
177 msg += if_name + (std::string)("\" exported by target port ");\r
178 msg += (std::string)(target_port_.name()) + (std::string)(": the initiator port is already bound to this interface\n");\r
179 SC_REPORT_WARNING("binding warning",msg.c_str());\r
180 \r
181 return(true);\r
182 }\r
183 }\r
184 return(false);\r
185}\r
186\r
187//---------------------------\r
188// sc_port overridden methods\r
189//---------------------------\r
190 \r
191//-------------------------------------------------------------------------------\r
192// before_end_of_elaboration()\r
193// Called just before end of elaboration to propagate registered target ports to all the \r
194// bound initiator ports\r
195//-------------------------------------------------------------------------------\r
196template<typename IF,int N>\r
197void \r
198tlm_initiator_port<IF,N>::before_end_of_elaboration()\r
199{\r
200\r
201 // Registered target port list propagation (complete sharing of target_port_list between all initiator ports)\r
202 // If current port's target port list exist, share the list with all other port of the chain using the \r
203 // reversed initiator port list.\r
204 if (m_target_port_list.size()) {\r
205 for(typename std::vector<initiator_port_base_type *>::iterator port = get_reversed_initiator_port_list().begin();\r
206 port != get_reversed_initiator_port_list().end();\r
207 port++) { \r
208\r
209 // Copy the target port(s) to the target port list of the registered initiator (port info. propagation)\r
210 if ((*port) != this) {\r
211 for(typename std::vector<target_port_base_type *>::iterator target_port = m_target_port_list.begin();\r
212 target_port != m_target_port_list.end();\r
213 target_port++) {\r
214 (*port)->register_target_port((*target_port));\r
215 }\r
216 }\r
217 }\r
218 }\r
219\r
220 // Recreate the complete list of registered initiator_port, from deeper port to higher port (hierarchically speaking)\r
221 // Objective: deeper port is able to "see" all others but intermediate port cannot "see" deeper ports.\r
222 std::vector<initiator_port_base_type *> tmp_initiator_port_list; \r
223 tmp_initiator_port_list.push_back(this);\r
224 this->create_port_list(tmp_initiator_port_list);\r
225 // replace the regular initiator port list: this list is now complete\r
226 this->set_initiator_port_list(tmp_initiator_port_list);\r
227}\r
228\r
229//-------------------------------------------------------------------------------\r
230// end_of_elaboration()\r
231// Check the target port list: if empty, stops the simulation as initiator port should be bound at \r
232// least to one target_port\r
233//-------------------------------------------------------------------------------\r
234template<typename IF,int N>\r
235void \r
236tlm_initiator_port<IF,N>::end_of_elaboration() {\r
237\r
238#ifdef TLM_PORT_DEBUG\r
239 printf("DEBUG\t\t%s: Registered initiator port list :\n",sc_object::name());\r
240 for(typename std::vector<initiator_port_base_type *>::iterator port = get_initiator_port_list().begin();\r
241 port != get_initiator_port_list().end();\r
242 port++) {\r
243 printf("DEBUG\t\t%s: \t- %s\n",sc_object::name(),(static_cast<initiator_port_type * >(*port))->name());\r
244 \r
245 }\r
246 printf("DEBUG\t\t%s: Registered initiator reversed port list :\n",sc_object::name());\r
247 for(typename std::vector<initiator_port_base_type *>::iterator port = get_reversed_initiator_port_list().begin();\r
248 port != get_reversed_initiator_port_list().end();\r
249 port++) {\r
250 printf("DEBUG\t\t%s: \t- %s\n",sc_object::name(),(static_cast<initiator_port_type * >(*port))->name());\r
251 \r
252 }\r
253\r
254 printf("DEBUG\t\t%s: Registered target port list:\n",sc_object::name());\r
255 for(typename std::vector<target_port_base_type *>::iterator port = get_target_port_list().begin();\r
256 port != get_target_port_list().end();\r
257 port++) {\r
258 printf("DEBUG\t\t%s: \t- %s\n",sc_object::name(),(static_cast<target_port_type * >(*port))->name());\r
259 \r
260 }\r
261\r
262 printf("DEBUG\t\t%s: -------------------------------------------------------\n",sc_object::name());\r
263\r
264#endif\r
265 // Checks the target port list\r
266 if ((!get_target_port_list().size()) && this->size()) {\r
267 std::string msg(sc_object::name());\r
268 msg += (std::string)(": tlm_initiator_port error, target port list is empty. Initiator port should be bound at least to one target port\n");\r
269 SC_REPORT_ERROR("port end of elaboration",msg.c_str());\r
270 }\r
271}\r
272\r
273//--------------------------------------------------------------------\r
274// Special binding between initiator port and target port.\r
275// (port registration added to the standard sc_port_base::bind())\r
276//--------------------------------------------------------------------\r
277\r
278//---------------------------------------------------------\r
279// bind(sc_export)\r
280//---------------------------------------------------------\r
281template<typename IF,int N>\r
282void \r
283tlm_initiator_port<IF,N>::bind(target_port_type& target_port_) {\r
284 if (!is_interface_bound_twice(target_port_))\r
285 // Registers the target port\r
286 register_target_port(&target_port_);\r
287 \r
288 // Calls sc_port standard bind() method \r
289 sc_port_b<interface_type>::bind(target_port_);\r
290}\r
291\r
292\r
293template<typename IF,int N>\r
294template<typename OTHER_IF>\r
295void \r
296tlm_initiator_port<IF,N>::bind(tlm_target_port<OTHER_IF>& target_port_) {\r
297 // Test if OTHER_IF derives from IF\r
298 IF * other_if = dynamic_cast<IF*>(target_port_.get_interface());\r
299 if (other_if) {\r
300\r
301 if (!is_interface_bound_twice(target_port_)) \r
302 // Registers the target port\r
303 this->register_target_port(&target_port_);\r
304\r
305 // Calls sc_port standard bind() method \r
306 sc_port_b<interface_type>::bind(*other_if);\r
307 }\r
308 else { \r
309 std::string msg(sc_object::name());\r
310 msg += (std::string)(": tlm_initiator_port error, incompatible interface detected during the binding tlm_initiator_port \"") + (std::string)(this->name());\r
311 msg += (std::string)" to tlm_target_port \"" + (std::string)(target_port_.name()) +(std::string)("\"\n") ;\r
312 SC_REPORT_ERROR("bind export to export failed",msg.c_str());\r
313 }\r
314}\r
315\r
316 \r
317\r
318//---------------------------------------------------------\r
319// operator() (sc_export): just calls bind(sc_export)\r
320//---------------------------------------------------------\r
321template<typename IF,int N>\r
322void \r
323tlm_initiator_port<IF,N>::operator() (target_port_type& target_port_) {\r
324 bind(target_port_);\r
325}\r
326\r
327//---------------------------------------------------------\r
328// bind(sc_port) \r
329//---------------------------------------------------------\r
330template<typename IF,int N>\r
331void \r
332tlm_initiator_port<IF,N>::bind(sc_port_b<interface_type>& port_) {\r
333 // Register the bound port in the regular list\r
334 this->register_initiator_port(static_cast<initiator_port_type *>(&port_));\r
335\r
336 // Bound port registers the current port. Used to share the target port list between all port before the end of elaboration\r
337 for(typename std::vector<initiator_port_base_type *>::iterator initiator_port = get_reversed_initiator_port_list().begin();\r
338 initiator_port != get_reversed_initiator_port_list().end();\r
339 initiator_port++) {\r
340 static_cast<initiator_port_type *>(&port_)->reversed_register_initiator_port(*initiator_port);\r
341 }\r
342\r
343 // Calls sc_port standard bind() method \r
344 sc_port_b<interface_type>::bind(port_);\r
345}\r
346 \r
347//---------------------------------------------------------\r
348// operator() (sc_port): just calls bind(sc_port)\r
349//---------------------------------------------------------\r
350template<typename IF,int N>\r
351void \r
352tlm_initiator_port<IF,N>::operator() (sc_port_b<interface_type>& port_) {\r
353 bind(port_);\r
354}\r
355\r
356//--------------------------------------------------------------------\r
357// Normal binding between port and interface\r
358// To be redefined here (bind(port_) is overridden above\r
359//--------------------------------------------------------------------\r
360\r
361//---------------------------------------------------------\r
362// bind(interface_type) \r
363//---------------------------------------------------------\r
364template<typename IF,int N>\r
365void \r
366tlm_initiator_port<IF,N>::bind(interface_type& interface_) {\r
367 // Calls sc_port standard bind method\r
368 sc_port_b<interface_type>::bind(interface_); \r
369}\r
370\r
371//---------------------------------------------------------\r
372// operator() (interface_type) \r
373//---------------------------------------------------------\r
374template<typename IF,int N>\r
375void \r
376tlm_initiator_port<IF,N>::operator() (interface_type& interface_) {\r
377 sc_port_b<interface_type>::bind(interface_); \r
378}\r
379\r
380#endif /* _TLM_INITIATOR_PORT_H_ */\r