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 /// @file at_initiator_explicit.cpp
22 /// @Details Implements a AT non-blocking initiator
23 //
24 //=============================================================================
25 // Original Authors:
26 // Bill Bunton, ESLX
27 // Charles Wilson, ESLX
28 // Anna Keist, ESLX
29 //=============================================================================
30
31 #include "reporting.h" // Reporting convenience macros
32 #include "at_initiator_explicit.h" // Our header
33 #include "tlm.h" // TLM headers
34
35 using namespace sc_core;
36
37 static const char *filename = "at_initiator_explicit.cpp"; /// filename for reporting
38
39 //=============================================================================
40 ///Constructor
41
at_initiator_explicit(sc_module_name name,const unsigned int ID,sc_core::sc_time end_rsp_delay)42 at_initiator_explicit::at_initiator_explicit // constructor
43 ( sc_module_name name // module name
44 , const unsigned int ID // initiator ID
45 , sc_core::sc_time end_rsp_delay // delay
46 )
47 : sc_module (name) /// init module name
48 , initiator_socket ("initiator_socket") /// init socket name
49 , m_send_end_rsp_PEQ ("send_end_rsp_PEQ") /// init PEQ name
50 , m_ID (ID) /// init initiator ID
51 , m_end_rsp_delay (end_rsp_delay) /// init end response delay
52
53 {
54 // bind initiator to the export
55 initiator_socket (*this);
56
57 // register thread process
58 SC_THREAD(initiator_thread);
59
60 // register method process
61 SC_METHOD(send_end_rsp_method);
62
63 sensitive << m_send_end_rsp_PEQ.get_event();
64 dont_initialize();
65 }
66
67 //=============================================================================
68 //
69 // Initiator thread
70 //
71 //=============================================================================
initiator_thread(void)72 void at_initiator_explicit::initiator_thread(void) // initiator thread
73 {
74 tlm::tlm_generic_payload *transaction_ptr; // transaction pointer
75 std::ostringstream msg; // log message
76
77 while (true)
78 {
79 //=============================================================================
80 // Read FIFO to Get new transaction GP from the traffic generator
81 //=============================================================================
82 transaction_ptr = request_in_port->read(); // get request from input fifo
83
84 tlm::tlm_phase phase = tlm::BEGIN_REQ; // Create phase objects
85 sc_time delay = SC_ZERO_TIME; // Create delay objects
86
87 msg.str("");
88 msg << "Initiator: " << m_ID
89 << " starting new transaction"
90 << endl << " "
91 << "Initiator: " << m_ID
92 << " nb_transport_fw (GP, "
93 << report::print(phase) << ", "
94 << delay << ")";
95 REPORT_INFO(filename, __FUNCTION__, msg.str());
96
97
98 //-----------------------------------------------------------------------------
99 // Make the non-blocking call and decode returned status (tlm_sync_enum)
100 //-----------------------------------------------------------------------------
101 tlm::tlm_sync_enum
102 return_value = initiator_socket->nb_transport_fw(*transaction_ptr, phase, delay);
103
104 msg.str("");
105 msg << "Initiator: " << m_ID
106 << " " << report::print(return_value) << " (GP, "
107 << report::print(phase) << ", "
108 << delay << ")" << endl;
109
110 switch (return_value) {
111 //-----------------------------------------------------------------------------
112 // The target returned COMPLETED this is a 1 phase transaction
113 // Wait the annotated delay
114 // Return the transaction to the traffic generator
115 // Make the next request
116 //-----------------------------------------------------------------------------
117 case tlm::TLM_COMPLETED:
118 {
119 wait(delay + m_end_rsp_delay); // wait the annotated delay
120
121 msg << " "
122 << "Initiator: " << m_ID
123 << " target returned COMPLETED with annotated time ";
124 REPORT_INFO (filename, __FUNCTION__, msg.str() );
125
126 response_out_port->write(transaction_ptr); // return txn to traffic gen
127
128 break;
129 }// end case TLM_COMPLETED
130
131 //-----------------------------------------------------------------------------
132 // Target returned UPDATED
133 //-----------------------------------------------------------------------------
134 case tlm::TLM_UPDATED:
135 {
136 //-----------------------------------------------------------------------------
137 // Put poiter in waiting backware path map
138 // Wait the annotated delay
139 // Make the next request
140 //-----------------------------------------------------------------------------
141 if( phase == tlm::END_REQ) {
142
143 m_waiting_bw_path_map.insert(make_pair(transaction_ptr
144 ,Rcved_END_REQ_enum
145 ));
146
147 wait(delay); // wait the annotated delay
148
149 msg << " "
150 << "Initiator: " << m_ID
151 << " transaction waiting begin-response on backward path";
152 REPORT_INFO (filename, __FUNCTION__, msg.str() );
153 }
154
155 //-----------------------------------------------------------------------------
156 // Wait the annotated delay
157 // Use payload event queue to schedule sending end response
158 // Make the next request
159 //-----------------------------------------------------------------------------
160
161 else if( phase == tlm::BEGIN_RESP) {
162 msg << " "
163 << "Initiator: " << m_ID
164 << " transaction moved to send-end-response PEQ "
165 << endl;
166
167 wait(delay); // wait the annotated delay
168
169 m_send_end_rsp_PEQ.notify (*transaction_ptr, m_end_rsp_delay);
170
171 msg << " "
172 << "Initiator: " << m_ID
173 << " " << " (GP, "
174 << report::print(phase) << ", "
175 << delay << ")" ;
176 REPORT_INFO (filename, __FUNCTION__, msg.str() )
177 }
178 //-----------------------------------------------------------------------------
179 //-----------------------------------------------------------------------------
180 else {
181 msg << " "
182 << "Initiator: " << m_ID
183 << " Unexpected phase for UPDATED return from target ";
184 REPORT_FATAL (filename, __FUNCTION__, msg.str() );
185 }
186 break;
187 } // end case TLM_UPDATED
188
189
190 //-----------------------------------------------------------------------------
191 // Target returned ACCEPTED this an explicit response
192 // Add the transaction pointer to the waiting backward path map
193 // END REQUEST RULE wait for the target to response
194 //-----------------------------------------------------------------------------
195 case tlm::TLM_ACCEPTED:
196 {
197 msg << " "
198 << "Initiator: " << m_ID
199 << " transaction waiting end-request on backward-path ";
200 REPORT_INFO (filename, __FUNCTION__, msg.str() );
201
202 // use map to track transaction including current state information
203 m_waiting_bw_path_map.insert (make_pair (transaction_ptr
204 ,Rcved_ACCEPTED_enum
205 ));
206
207 wait (m_enable_next_request_event); // wait for the target to response
208
209 break;
210 } // end case TLM_ACCEPTED
211
212
213 //-----------------------------------------------------------------------------
214 // All case covered default
215 //-----------------------------------------------------------------------------
216 default:
217 {
218 msg << " "
219 << "Initiator: " << m_ID
220 << " Unexpected response to BEGIN_REQ ";
221 REPORT_FATAL (filename, __FUNCTION__, msg.str() );
222 break;
223 }
224 } // end case
225 } // end while true
226 } // end initiator_thread
227
228
229
230 //=============================================================================
231 /// @fn at_initiator_explicit::nb_transport_bw
232 //
233 /// @brief non-blocking transport from targets
234 //
235 //=============================================================================
236 tlm::tlm_sync_enum
nb_transport_bw(tlm::tlm_generic_payload & transaction_ref,tlm::tlm_phase & phase,sc_time & delay)237 at_initiator_explicit::nb_transport_bw // inbound nb_transport_bw
238 ( tlm::tlm_generic_payload& transaction_ref // generic payload
239 , tlm::tlm_phase& phase // tlm phase
240 , sc_time& delay // delay
241 )
242
243 {
244 tlm::tlm_sync_enum status = tlm::TLM_COMPLETED; // return status reject by default
245 std::ostringstream msg; // log message
246
247 //=============================================================================
248 // Check waiting backward path map of valid transaction
249 //=============================================================================
250 waiting_bw_path_map::iterator transaction_inter; // create interator for map
251
252 transaction_inter = m_waiting_bw_path_map.find(&transaction_ref);
253
254 if (transaction_inter == m_waiting_bw_path_map.end() ) {
255
256 //=============================================================================
257 // The transaction pointer used by the backward path call does not belong
258 // to this initiator, this is a major error
259 //=============================================================================
260 msg << " "
261 << "Initiator: " << m_ID
262 << " Received invalid transaction pointer";
263 REPORT_FATAL (filename, __FUNCTION__, msg.str() );
264 }
265
266 //=============================================================================
267 // Normal operation
268 // Decode backward path phase
269 //=============================================================================
270 else {
271 msg.str ("");
272 msg << "Initiator: " << m_ID
273 << " nb_transport_bw (GP, "
274 << report::print(phase) << ", "
275 << delay << ")"
276 << endl;
277
278 switch (phase) {
279 //-----------------------------------------------------------------------------
280 // Target has responded with END_REQ
281 // notify enable next request event
282 //-----------------------------------------------------------------------------
283 case tlm::END_REQ: {
284 msg << " "
285 << "Initiator: " << m_ID
286 << " transaction waiting begin-response on backward path"
287 << endl;
288
289 m_enable_next_request_event.notify(SC_ZERO_TIME);
290
291 transaction_inter->second = Rcved_END_REQ_enum;
292 status = tlm::TLM_ACCEPTED;
293
294 msg << " "
295 << "Initiator: " << m_ID
296 << " " << report::print(status) << " (GP, "
297 << report::print(phase) << ", "
298 << delay << ")";
299 REPORT_INFO (filename, __FUNCTION__, msg.str() );
300
301 break;
302 }
303
304 //-----------------------------------------------------------------------------
305 // Target has responded with BEGIN_RESP
306 // Use payload event queue to schedule sending end response
307 // If there was no END REQUEST this ends the request phase notify
308 // enable next request event
309 //-----------------------------------------------------------------------------
310 case tlm::BEGIN_RESP: {
311
312 msg << " "
313 << "Initiator: " << m_ID
314 << " transaction moved to send-end-response PEQ "
315 << endl;
316
317 m_send_end_rsp_PEQ.notify (transaction_ref, m_end_rsp_delay);
318
319 // check for a synthetic 3-phase transaction (BEGIN_RESP without END_REQ)
320 if (transaction_inter->second == Rcved_ACCEPTED_enum) {
321 m_enable_next_request_event.notify(SC_ZERO_TIME);
322 }
323
324 m_waiting_bw_path_map.erase(&transaction_ref); // erase from map
325
326 status = tlm::TLM_ACCEPTED;
327
328 msg << " "
329 << "Initiator: " << m_ID
330 << " " << report::print(status) << " (GP, "
331 << report::print(phase) << ", "
332 << delay << ")" ;
333 REPORT_INFO (filename, __FUNCTION__, msg.str() );
334
335 break;
336 } // end case BEGIN_RESP
337
338
339 //-----------------------------------------------------------------------------
340 // Invalid phase for backward path
341 //-----------------------------------------------------------------------------
342 case tlm::BEGIN_REQ:
343 case tlm::END_RESP:
344 {
345 msg.str ("");
346 msg << m_ID << " Illegal phase on backward path ";
347 REPORT_FATAL(filename, __FUNCTION__, msg.str() );
348 break;
349 }
350 //-----------------------------------------------------------------------------
351 // Unknown phase on backward path
352 //-----------------------------------------------------------------------------
353 default:
354 {
355 msg.str ("");
356 msg << m_ID << " Unknown phase on the backward path ";
357 REPORT_WARNING (filename, __FUNCTION__, msg.str() );
358 break;
359 }
360 } // end switch (phase)
361 }
362 return status;
363 } // end backward nb transport
364
365
366
367 //=============================================================================
368 /// @fn at_initiator_explicit::send_end_rsp_method
369 //
370 /// @brief send end response method
371 //
372 /// @details This method is scheduled to send the end-response timing point.
373 /// It is sensitive to the m_send_end_rsp_PEQ.get_event() event.
374 //
375 //=============================================================================
send_end_rsp_method(void)376 void at_initiator_explicit::send_end_rsp_method(void) // send end response method
377 {
378 tlm::tlm_generic_payload* transaction_ptr;
379 std::ostringstream msg; // log message
380
381 //-----------------------------------------------------------------------------
382 // Process all transactions scheduled for current time a return value of NULL
383 // indicates that the PEQ is empty at this time
384 //-----------------------------------------------------------------------------
385 while ((transaction_ptr = m_send_end_rsp_PEQ.get_next_transaction()) != NULL)
386 {
387 tlm::tlm_phase phase = tlm::END_RESP; // set the appropriate phase
388 sc_time delay = SC_ZERO_TIME;
389
390 msg.str("");
391 msg << "Initiator: " << m_ID
392 << " starting send-end-response method"
393 << endl << " "
394 << "Initiator: " << m_ID
395 << " nb_transport_fw (GP, "
396 << report::print(phase) << ", "
397 << delay << ")";
398 REPORT_INFO(filename, __FUNCTION__, msg.str());
399
400 // call begin response and then decode return status
401 tlm::tlm_sync_enum
402 return_value = initiator_socket->nb_transport_fw(*transaction_ptr, phase, delay);
403
404 msg.str("");
405 msg << "Initiator: " << m_ID
406 << " " << report::print(return_value) << " (GP, "
407 << report::print(phase) << ", "
408 << delay << ")";
409
410 switch (return_value)
411 {
412 case tlm::TLM_COMPLETED: // transaction complete
413 {
414 response_out_port->write(transaction_ptr); // send GP to output rsp fifo
415
416 REPORT_INFO (filename, __FUNCTION__, msg.str() );
417 break;
418 }
419
420 case tlm::TLM_ACCEPTED:
421 case tlm::TLM_UPDATED:
422 {
423 msg << " "
424 << "Initiator: " << m_ID
425 << report::print(return_value) << " Invalid return value for END_RESP ";
426 REPORT_FATAL(filename, __FUNCTION__, msg.str());
427 break;
428 }
429
430 default:
431 {
432 msg << " "
433 << "Initiator: " << m_ID
434 << report::print(return_value) << " Unknown return value for END_RESP ";
435 REPORT_FATAL(filename, __FUNCTION__, msg.str());
436 break;
437 }
438 } // end switch
439 } // end while
440
441 return;
442 } // end send_end_rsp_method
443
444
445 //=============================================================================
446 /// @fn at_initiator_explicit::invalidate_direct_mem_ptr
447 //
448 /// @brief invalidate direct memory pointer Not implemented
449 //=============================================================================
450
invalidate_direct_mem_ptr(sc_dt::uint64 start_range,sc_dt::uint64 end_range)451 void at_initiator_explicit::invalidate_direct_mem_ptr // invalidate_direct_mem_ptr
452 ( sc_dt::uint64 start_range // start range
453 , sc_dt::uint64 end_range // end range
454 )
455 {
456 std::ostringstream msg; // log message
457
458 msg.str ("");
459 msg << m_ID << " invalidate_direct_mem_ptr: not implemented";
460 REPORT_INFO(filename, __FUNCTION__, msg.str());
461 }
462
463