SystemC Library API Reference Manual
Reference documentation for the Simics SystemC Library.
 
Loading...
Searching...
No Matches
gasket.h
Go to the documentation of this file.
1// -*- mode: C++; c-file-style: "virtutech-c++" -*-
2
3/*
4 © 2012 Intel Corporation
5
6 This software and the related documents are Intel copyrighted materials, and
7 your use of them is governed by the express license under which they were
8 provided to you ("License"). Unless the License provides otherwise, you may
9 not use, modify, copy, publish, distribute, disclose or transmit this software
10 or the related documents without Intel's prior written permission.
11
12 This software and the related documents are provided as is, with no express or
13 implied warranties, other than those that are expressly stated in the License.
14*/
15
16#ifndef SIMICS_SYSTEMC_TLM2SIMICS_GASKET_H
17#define SIMICS_SYSTEMC_TLM2SIMICS_GASKET_H
18
19#include <systemc>
20#include <tlm>
21#include <tlm_utils/simple_target_socket.h>
22
31
32#include <string>
33
34namespace simics {
35namespace systemc {
36namespace tlm2simics {
37
40 public:
42 pstack_ = internal->process_stack();
43 pstack_->push();
44 }
48 pstack_->pop();
49 }
50
51 private:
52 ProcessStackInterface *pstack_;
53};
54
61template<unsigned int BUSWIDTH = 32,
62 typename TYPES = tlm::tlm_base_protocol_types>
63class Gasket : public sc_core::sc_module, public GasketInterface {
64 public:
65 Gasket(sc_core::sc_module_name,
66 const simics::ConfObjectRef &obj)
67 : simics_obj_(obj), socket_("target_socket"),
68 transaction_handler_(new NullTransactionHandler),
69 internal_(NULL),
70 initiator_socket_(NULL) {
71 FATAL_ERROR_IF(!obj, "Must provide a valid Simics object");
72 // only registers a b_transport callback with the
73 // simple target socket since it will automatically
74 // convert non-blocking call to blocking call
75 socket_.register_b_transport(this, &Gasket::b_transport);
76 socket_.register_get_direct_mem_ptr(this, &Gasket::get_direct_mem_ptr);
77 socket_.register_transport_dbg(this, &Gasket::transport_dbg);
78 }
79 void init(InternalInterface *internal) {
80 internal_ = internal;
81 }
82 virtual ~Gasket() {
83 if (dynamic_cast<NullTransactionHandler *>(transaction_handler_))
84 delete transaction_handler_;
85 }
86
87 // Used by createGasket() to bind with initiator socket
88 template <typename Socket>
89 void bind(Socket &sock) { // NOLINT
90 sock(socket_);
91 initiator_socket_ = &sock;
92 }
93
94 // GasketInterface
97 if (dynamic_cast<NullTransactionHandler *>(transaction_handler_))
98 delete transaction_handler_;
99 transaction_handler_ = transaction_handler ? transaction_handler
101 }
102 virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_range,
103 sc_dt::uint64 end_range) {
104 socket_->invalidate_direct_mem_ptr(start_range, end_range);
105 }
106 sc_core::sc_object *get_initiator_socket() const override {
107 return initiator_socket_;
108 }
109 std::string gasket_name() const override {
110 return name();
111 }
113 return transaction_handler_;
114 }
115 // By registering nb_transport_fw, it no longer uses simple target
116 // socket's auto b – nb conversion
118 socket_.register_nb_transport_fw(this, &Gasket::nb_transport_fw);
119 }
120
121 private:
122 void execute_transaction(tlm::tlm_generic_payload &trans, // NOLINT
123 bool non_blocking) {
124 ProcessStackHandler pstack(internal());
125 trans.set_response_status(tlm::TLM_OK_RESPONSE);
126 tlm::tlm_response_status status = tlm::TLM_INCOMPLETE_RESPONSE;
127 {
128 if (non_blocking) {
129 trans.set_extension(&nb_ext_);
130 }
131
132 // Switching context to detect re-entry without setting context.
133 Context c(&null_simulation_);
134 status = transaction_handler_->simics_transaction(simics_obj_,
135 &trans);
136
137 if (non_blocking) {
138 trans.clear_extension(&nb_ext_);
139 }
140 }
141
142 // When execute_transaction successfully returns, the response on
143 // the trans should be same with the status
144 if (trans.get_response_status() != status &&
145 status != tlm::TLM_OK_RESPONSE) {
146 const char *msg = "Gasket transaction error";
147 switch (status) {
148 case tlm::TLM_INCOMPLETE_RESPONSE: {
149 msg = "Gasket did not attempt to execute the command";
150 break;
151 }
152 case tlm::TLM_ADDRESS_ERROR_RESPONSE: {
153 msg = "Gasket was unable to act on the address attribute, "
154 "or address out-of-range";
155 break;
156 }
157 case tlm::TLM_COMMAND_ERROR_RESPONSE: {
158 msg = "Gasket was unable to execute the command";
159 break;
160 }
161 case tlm::TLM_BURST_ERROR_RESPONSE: {
162 msg = "Gasket was unable to act on the data length or "
163 "streaming width";
164 break;
165 }
166 case tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE: {
167 msg = "Gasket was unable to act on the byte enable";
168 break;
169 }
170 case tlm::TLM_GENERIC_ERROR_RESPONSE: {
171 break;
172 }
173 default: {
174 }
175 }
176 SIM_LOG_SPEC_VIOLATION(1, simics_obj_, 0, "%s", msg);
177 }
178 trans.set_response_status(status);
179 transaction_handler_->update_dmi_allowed(simics_obj_, &trans);
180 }
181
182 void b_transport(tlm::tlm_generic_payload &trans, // NOLINT
183 sc_core::sc_time &local_time_offset) { // NOLINT
184 if (trans.get_byte_enable_ptr() != NULL &&
185 !transaction_handler_->byte_enable_supported(simics_obj_, &trans)) {
186 return;
187 }
188
189 // Before we send the transaction to simics we need to synchronize
190 // local time.
191 if (local_time_offset.value() > 0) {
192#ifndef RISC_SIMICS
193 wait(local_time_offset);
194#endif
195 local_time_offset = sc_core::SC_ZERO_TIME;
196 }
197
198 execute_transaction(trans, false);
199 }
200
201 unsigned int transport_dbg(tlm::tlm_generic_payload &trans) { // NOLINT
202 ProcessStackHandler pstack(internal());
203 return transaction_handler_->debug_transaction(simics_obj_, &trans);
204 }
205
206 bool get_direct_mem_ptr(tlm::tlm_generic_payload &trans, // NOLINT
207 tlm::tlm_dmi &dmi_data) { // NOLINT
208 ProcessStackHandler pstack(internal());
209 return transaction_handler_->get_direct_mem_ptr(simics_obj_,
210 trans, dmi_data);
211 }
212
213 // Non-blocking transport interface
214 virtual tlm::tlm_sync_enum nb_transport_fw(
215 tlm::tlm_generic_payload &trans, // NOLINT
216 tlm::tlm_phase &phase, // NOLINT
217 sc_core::sc_time &local_time_offset) { // NOLINT
218 if (phase == tlm::END_RESP) {
219 trans.set_response_status(tlm::TLM_OK_RESPONSE);
220 return tlm::TLM_COMPLETED;
221 }
222
223 if (phase != tlm::BEGIN_REQ) {
224 SIM_LOG_SPEC_VIOLATION(
225 1, simics_obj_, 0,
226 "Gasket was unable to execute the command (invalid phase)");
227 trans.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
228 // Return early completion when failure to process
229 return tlm::TLM_COMPLETED;
230 }
231
232 if (trans.get_byte_enable_ptr() != NULL &&
233 !transaction_handler_->byte_enable_supported(simics_obj_, &trans)) {
234 SIM_LOG_SPEC_VIOLATION(
235 1, simics_obj_, 0,
236 "Gasket was unable to execute the command (byte enable)");
237 trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
238 // Return early completion when failure to process
239 return tlm::TLM_COMPLETED;
240 }
241
242 execute_transaction(trans, true);
243 if (trans.get_response_status() == tlm::TLM_INCOMPLETE_RESPONSE) {
244 SIM_LOG_INFO(3, simics_obj_, 0, "Gasket deferred the transaction");
245 return tlm::TLM_ACCEPTED;
246 }
247 return tlm::TLM_COMPLETED;
248 }
249
250 InternalInterface *internal() {
251 if (!internal_) {
252 Adapter *adapter = static_cast<Adapter *>(
253 SIM_object_data(simics_obj_));
254 assert(adapter);
255 internal_ = adapter->internal();
256 }
257
258 return internal_;
259 }
260
261 simics::ConfObjectRef simics_obj_;
262 tlm_utils::simple_target_socket<Gasket, BUSWIDTH, TYPES> socket_;
263
264 // Target object in Simics side receiving the TLM transaction
265 TransactionHandlerInterface *transaction_handler_;
266 NullSimulation null_simulation_;
267 InternalInterface *internal_;
268 sc_core::sc_object *initiator_socket_;
269
270 NonBlockingTlmExtension nb_ext_;
271};
272
273} // namespace tlm2simics
274} // namespace systemc
275} // namespace simics
276
277#endif
Utility class that handles the context switching, using RAII methodology.
Definition: context.h:33
Definition: internal_interface.h:25
virtual ProcessStackInterface * process_stack()=0
The process stack helps maintain a LIFO order of function calls that cross the SystemC/Simics border,...
Definition: process_stack_interface.h:27
Interface used by tlm2simics gaskets, implemented by Gasket base class.
Definition: gasket_interface.h:30
Implements core functionality for receiving a TLM2 transaction over a socket.
Definition: gasket.h:63
Gasket(sc_core::sc_module_name, const simics::ConfObjectRef &obj)
Definition: gasket.h:65
virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_range, sc_dt::uint64 end_range)
Calling this method will end up calling the same method on the target socket, that will forward the c...
Definition: gasket.h:102
std::string gasket_name() const override
Definition: gasket.h:109
virtual ~Gasket()
Definition: gasket.h:82
sc_core::sc_object * get_initiator_socket() const override
Definition: gasket.h:106
void bind(Socket &sock)
Definition: gasket.h:89
virtual void set_transaction_handler(TransactionHandlerInterface *transaction_handler)
Target object in Simics side receiving the TLM transaction.
Definition: gasket.h:95
void register_nb_transport_fw()
For gaskets support non-blocking transport, call this function to register the non-blocking transport...
Definition: gasket.h:117
void init(InternalInterface *internal)
Definition: gasket.h:79
TransactionHandlerInterface * transaction_handler() override
Definition: gasket.h:112
Utility class that counts the number of instances.
Definition: null_transaction_handler.h:33
ProcessStackHandler(const ProcessStackHandler &)=delete
ProcessStackHandler(InternalInterface *internal)
Definition: gasket.h:41
ProcessStackHandler & operator=(const ProcessStackHandler &)=delete
virtual ~ProcessStackHandler()
Definition: gasket.h:47
Interface used by Gasket, implemented by protocol specific transaction handlers.
Definition: transaction_handler_interface.h:36
virtual unsigned int debug_transaction(ConfObjectRef &simics_obj, tlm::tlm_generic_payload *trans)=0
virtual void update_dmi_allowed(ConfObjectRef &simics_obj, tlm::tlm_generic_payload *trans)=0
virtual bool byte_enable_supported(ConfObjectRef &simics_obj, tlm::tlm_generic_payload *trans)=0
virtual bool get_direct_mem_ptr(ConfObjectRef &simics_obj, tlm::tlm_generic_payload &trans, tlm::tlm_dmi &dmi_data)=0
virtual tlm::tlm_response_status simics_transaction(ConfObjectRef &simics_obj, tlm::tlm_generic_payload *trans)=0
AdapterNonCheckpointable Adapter
Definition: adapter.h:340
Definition: adapter.h:80