The Sparta Modeling Framework
Loading...
Searching...
No Matches
SpartaTLMTargetGasket.cpp
1
2#include "SpartaTLMTargetGasket.hpp"
3#include "MemoryRequest.hpp"
4#include "SpartaMemory.hpp"
5#include "reporting.h"
7
8//#define DIRECT_MEMORY_OPERATION 1
9
10namespace sparta_target
11{
12
13 static const char *filename = "SpartaTLMTargetGasket.cpp";
14
15 int SpartaTLMTargetGasket::nextID = 0;
16
17 tlm::tlm_sync_enum SpartaTLMTargetGasket::nb_transport_fw(tlm::tlm_generic_payload &gp,
18 tlm::tlm_phase &phase,
19 sc_core::sc_time &delay_time)
20 {
21 std::ostringstream msg; // log message
22
23 tlm::tlm_sync_enum return_val = tlm::TLM_COMPLETED;
24 switch (phase)
25 {
26 case tlm::BEGIN_REQ:
27 {
28 std::cout << "Info: Gasket: BEGIN_REQ" << std::endl;
29
30 //-----------------------------------------------------------------------------
31 // Force synchronization multiple timing points by returning TLM_ACCEPTED
32 // use a payload event queue to schedule BEGIN_RESP timing point
33 //-----------------------------------------------------------------------------
34 target_memory_.get_delay(gp, delay_time); // get memory operation delay
35
36 MemoryRequest request = {
37 (gp.get_command() == tlm::TLM_READ_COMMAND ?
38 MemoryRequest::Command::READ :
39 MemoryRequest::Command::WRITE),
40 gp.get_address(),
41 gp.get_data_length(),
42 // Always scary pointing to memory owned by someone else...
43 gp.get_data_ptr(),
44 (void *)&gp};
45
47 {
48 info_logger_ << " sending to memory model: " << request;
49 }
50
51 event_end_req_.preparePayload(request)->
52 schedule(sparta::sparta_sysc_utils::calculateSpartaOffset
53 (getClock(), accept_delay_.value() + delay_time.value()));
54 return_val = tlm::TLM_ACCEPTED;
55 break;
56 }
57 case tlm::END_RESP:
58 // std::ostringstream msg; // log message
59 //m_end_resp_rcvd_event.notify (sc_core::SC_ZERO_TIME);
60 std::cout << "Info: Gasket: END_RESP" << std::endl;
61 return_val = tlm::TLM_COMPLETED;
62 break;
63 //=============================================================================
64 case tlm::END_REQ:
65 case tlm::BEGIN_RESP:
66 {
67 msg << "Target: " << ID_
68 << " Illegal phase received by target -- END_REQ or BEGIN_RESP";
69 REPORT_FATAL(filename, __FUNCTION__, msg.str());
70 return_val = tlm::TLM_ACCEPTED;
71 break;
72 }
73
74 //=============================================================================
75 default:
76 {
77 return_val = tlm::TLM_ACCEPTED;
78 if (!nb_trans_fw_prev_warning_)
79 {
80 msg << "Target: " << ID_
81 << " unknown phase " << phase << " encountered";
82 REPORT_WARNING(filename, __FUNCTION__, msg.str());
83 nb_trans_fw_prev_warning_ = true;
84 }
85 break;
86 }
87 }
88 return return_val;
89 }
90
91 void SpartaTLMTargetGasket::send_end_request_(const MemoryRequest &req)
92 {
93 std::ostringstream msg; // log message
94 msg.str("");
95 tlm::tlm_sync_enum status = tlm::TLM_COMPLETED;
96
97 msg.str("");
98 msg << "Target: " << ID_
99 << " starting end-request method";
100
101 sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
102
103 // target_memory_.get_delay(gp, delay); // get memory operation delay
104
105#ifdef DIRECT_MEMORY_OPERATION
106 delay_time += accept_delay_;
107 response_PEQ_.notify(gp, delay_time);
108#else
109 // target_memory_.operation(gp, delay_time); // perform memory operation now
110
112 {
113 info_logger_ << " sending to memory model: " << req;
114 }
115
116 out_memory_request_.send(req, getClock()->getCycle
117 (sparta::sparta_sysc_utils::calculateSpartaOffset(getClock(), 0)));
118#endif
119 tlm::tlm_phase phase = tlm::END_REQ;
120 delay = sc_core::SC_ZERO_TIME;
121
122 msg << endl
123 << " "
124 << "Target: " << ID_
125 << " transaction moved to send-response PEQ "
126 << endl
127 << " ";
128 msg << "Target: " << ID_
129 << " nb_transport_bw (GP, "
130 << report::print(phase) << ", "
131 << delay << ")";
132 REPORT_INFO(filename, __FUNCTION__, msg.str());
133
134 auto &gp = *((tlm::tlm_generic_payload *)req.meta_data);
135 gp.set_response_status(tlm::TLM_OK_RESPONSE);
136 //-----------------------------------------------------------------------------
137 // Call nb_transport_bw with phase END_REQ check the returned status
138 //-----------------------------------------------------------------------------
139 status = memory_socket_->nb_transport_bw(gp, phase, delay);
140
141 msg.str("");
142 msg << "Target: " << ID_
143 << " " << report::print(status) << " (GP, "
144 << report::print(phase) << ", "
145 << delay << ")";
146 REPORT_INFO(filename, __FUNCTION__, msg.str());
147
148 switch (status)
149 {
150 //=============================================================================
151 case tlm::TLM_ACCEPTED:
152 {
153 // more phases will follow
154
155 break;
156 }
157
158 //=============================================================================
159 case tlm::TLM_COMPLETED:
160 {
161 msg << "Target: " << ID_
162 << " TLM_COMPLETED invalid response to END_REQ" << endl
163 << " Initiator must receive data before ending transaction";
164 REPORT_FATAL(filename, __FUNCTION__, msg.str());
165 break;
166 }
167
168 //=============================================================================
169 case tlm::TLM_UPDATED:
170 {
171 msg << "Target: " << ID_
172 << " TLM_UPDATED invalid response to END_REQ" << endl
173 << " Initiator must receive data before updating transaction";
174 REPORT_FATAL(filename, __FUNCTION__, msg.str());
175
176 break;
177 }
178
179 //=============================================================================
180 default:
181 {
182 msg << "Target: " << ID_
183 << " Illegal return status";
184 REPORT_FATAL(filename, __FUNCTION__, msg.str());
185
186 break;
187 }
188 } // end switch
189 }
190
191 void SpartaTLMTargetGasket::forwardMemoryResponse_(const MemoryRequest &req)
192 {
193 std::ostringstream msg; // log message
194 msg.str("");
195
196 // non-const lvalues
197 tlm::tlm_phase resp = tlm::BEGIN_RESP;
198 sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
199
201 {
202 info_logger_ << " sending back to transactor: " << req;
203 }
204
205 auto &gp = *((tlm::tlm_generic_payload *)req.meta_data);
206 gp.set_response_status(tlm::TLM_OK_RESPONSE);
207
208 //m_response_PEQ.notify(gp, delay); // put transaction in the PEQ
209
210 // Send back the response to the initiator
211 auto status = memory_socket_->nb_transport_bw(*((tlm::tlm_generic_payload *)req.meta_data),
212 resp, delay);
213 switch (status)
214 {
215
216 //=============================================================================
217 case tlm::TLM_COMPLETED:
218 {
219 return;
220 break;
221 }
222
223 //=============================================================================
224 case tlm::TLM_ACCEPTED:
225 {
226 return;
227 break;
228 }
229
230 //=============================================================================
231 case tlm::TLM_UPDATED:
232 {
233 if (!begin_resp_method_prev_warning_)
234 {
235 msg << "Target: " << ID_
236 << " TLM_UPDATED invalid response to BEGIN_RESP";
237 REPORT_WARNING(filename, __FUNCTION__, msg.str());
238 }
239 else
240 begin_resp_method_prev_warning_ = true;
241 break;
242 }
243
244 //=============================================================================
245 default:
246 {
247 if (!begin_resp_method_prev_warning_)
248 {
249 msg << "Target: " << ID_
250 << " undefined return status ";
251 REPORT_WARNING(filename, __FUNCTION__, msg.str());
252 }
253 else
254 begin_resp_method_prev_warning_ = true;
255 break;
256 }
257 } // end switch
258 }
259
260} // namespace sparta_target
#define SPARTA_EXPECT_FALSE(x)
A macro for hinting to the compiler a particular condition should be considered most likely false.
Glue code that connect the Sparta scheduler to SystemC.
const Clock * getClock() const
log::MessageSource info_logger_
Default info logger.
Definition Unit.hpp:161