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:
66 Gasket(sc_core::sc_module_name,
67 const simics::ConfObjectRef &obj)
68 : simics_obj_(obj), socket_("target_socket"),
69 transaction_handler_(new NullTransactionHandler),
70 internal_(NULL),
71 initiator_socket_(NULL) {
72 FATAL_ERROR_IF(!obj, "Must provide a valid Simics object");
73 // only registers a b_transport callback with the
74 // simple target socket since it will automatically
75 // convert non-blocking call to blocking call
76 socket_.register_b_transport(this, &Gasket::b_transport);
77 socket_.register_get_direct_mem_ptr(this, &Gasket::get_direct_mem_ptr);
78 socket_.register_transport_dbg(this, &Gasket::transport_dbg);
79 }
80 void init(InternalInterface *internal) {
81 internal_ = internal;
82 }
83 virtual ~Gasket() {
84 if (dynamic_cast<NullTransactionHandler *>(transaction_handler_))
85 delete transaction_handler_;
86 }
87
88 // Used by createGasket() to bind with initiator socket
89 template <typename Socket>
90 void bind(Socket &sock) { // NOLINT
91 sock(socket_);
92 initiator_socket_ = &sock;
93 }
94
95 // GasketInterface
98 if (dynamic_cast<NullTransactionHandler *>(transaction_handler_))
99 delete transaction_handler_;
100 transaction_handler_ = transaction_handler ? transaction_handler
102 }
103 virtual void invalidate_direct_mem_ptr(sc_dt::uint64 start_range,
104 sc_dt::uint64 end_range) {
105 socket_->invalidate_direct_mem_ptr(start_range, end_range);
106 }
107 sc_core::sc_object *get_initiator_socket() const override {
108 return initiator_socket_;
109 }
110 std::string gasket_name() const override {
111 return name();
112 }
114 return transaction_handler_;
115 }
116 // By registering nb_transport_fw, it no longer uses simple target
117 // socket's auto b – nb conversion
119 socket_.register_nb_transport_fw(this, &Gasket::nb_transport_fw);
120 }
121
122 private:
123 void execute_transaction(tlm::tlm_generic_payload &trans, // NOLINT
124 bool non_blocking) {
125 ProcessStackHandler pstack(internal());
126 trans.set_response_status(tlm::TLM_OK_RESPONSE);
127 tlm::tlm_response_status status = tlm::TLM_INCOMPLETE_RESPONSE;
128 {
129 if (non_blocking) {
130 trans.set_extension(&nb_ext_);
131 }
132
133 // Switching context to detect re-entry without setting context.
134 Context c(&null_simulation_);
135 status = transaction_handler_->simics_transaction(simics_obj_,
136 &trans);
137
138 if (non_blocking) {
139 trans.clear_extension(&nb_ext_);
140 }
141 }
142
143 // When execute_transaction successfully returns, the response on
144 // the trans should be same with the status
145 if (trans.get_response_status() != status &&
146 status != tlm::TLM_OK_RESPONSE) {
147 const char *msg = "Gasket transaction error";
148 switch (status) {
149 case tlm::TLM_INCOMPLETE_RESPONSE: {
150 msg = "Gasket did not attempt to execute the command";
151 break;
152 }
153 case tlm::TLM_ADDRESS_ERROR_RESPONSE: {
154 msg = "Gasket was unable to act on the address attribute, "
155 "or address out-of-range";
156 break;
157 }
158 case tlm::TLM_COMMAND_ERROR_RESPONSE: {
159 msg = "Gasket was unable to execute the command";
160 break;
161 }
162 case tlm::TLM_BURST_ERROR_RESPONSE: {
163 msg = "Gasket was unable to act on the data length or "
164 "streaming width";
165 break;
166 }
167 case tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE: {
168 msg = "Gasket was unable to act on the byte enable";
169 break;
170 }
171 case tlm::TLM_GENERIC_ERROR_RESPONSE: {
172 break;
173 }
174 default: {
175 }
176 }
177 SIM_LOG_SPEC_VIOLATION(1, simics_obj_, 0, "%s", msg);
178 }
179 trans.set_response_status(status);
180 transaction_handler_->update_dmi_allowed(simics_obj_, &trans);
181 }
182
183 void b_transport(tlm::tlm_generic_payload &trans, // NOLINT
184 sc_core::sc_time &local_time_offset) { // NOLINT
185 if (trans.get_byte_enable_ptr() != NULL &&
186 !transaction_handler_->byte_enable_supported(simics_obj_, &trans)) {
187 return;
188 }
189
190 // Before we send the transaction to simics we need to synchronize
191 // local time.
192 if (local_time_offset.value() > 0) {
193#ifndef RISC_SIMICS
194 wait(local_time_offset);
195#endif
196 local_time_offset = sc_core::SC_ZERO_TIME;
197 }
198
199 execute_transaction(trans, false);
200 }
201
202 unsigned int transport_dbg(tlm::tlm_generic_payload &trans) { // NOLINT
203 ProcessStackHandler pstack(internal());
204 return transaction_handler_->debug_transaction(simics_obj_, &trans);
205 }
206
207 bool get_direct_mem_ptr(tlm::tlm_generic_payload &trans, // NOLINT
208 tlm::tlm_dmi &dmi_data) { // NOLINT
209 ProcessStackHandler pstack(internal());
210 return transaction_handler_->get_direct_mem_ptr(simics_obj_,
211 trans, dmi_data);
212 }
213
214 // Non-blocking transport interface
215 virtual tlm::tlm_sync_enum nb_transport_fw(
216 tlm::tlm_generic_payload &trans, // NOLINT
217 tlm::tlm_phase &phase, // NOLINT
218 sc_core::sc_time &local_time_offset) { // NOLINT
219 if (phase == tlm::END_RESP) {
220 trans.set_response_status(tlm::TLM_OK_RESPONSE);
221 return tlm::TLM_COMPLETED;
222 }
223
224 if (phase != tlm::BEGIN_REQ) {
225 SIM_LOG_SPEC_VIOLATION(
226 1, simics_obj_, 0,
227 "Gasket was unable to execute the command (invalid phase)");
228 trans.set_response_status(tlm::TLM_COMMAND_ERROR_RESPONSE);
229 // Return early completion when failure to process
230 return tlm::TLM_COMPLETED;
231 }
232
233 if (trans.get_byte_enable_ptr() != NULL &&
234 !transaction_handler_->byte_enable_supported(simics_obj_, &trans)) {
235 SIM_LOG_SPEC_VIOLATION(
236 1, simics_obj_, 0,
237 "Gasket was unable to execute the command (byte enable)");
238 trans.set_response_status(tlm::TLM_BYTE_ENABLE_ERROR_RESPONSE);
239 // Return early completion when failure to process
240 return tlm::TLM_COMPLETED;
241 }
242
243 execute_transaction(trans, true);
244 if (trans.get_response_status() == tlm::TLM_INCOMPLETE_RESPONSE) {
245 SIM_LOG_INFO(3, simics_obj_, 0, "Gasket deferred the transaction");
246 return tlm::TLM_ACCEPTED;
247 }
248 return tlm::TLM_COMPLETED;
249 }
250
251 InternalInterface *internal() {
252 if (!internal_) {
253 Adapter *adapter = static_cast<Adapter *>(
254 SIM_object_data(simics_obj_));
255 assert(adapter);
256 internal_ = adapter->internal();
257 }
258
259 return internal_;
260 }
261
262 simics::ConfObjectRef simics_obj_;
263 tlm_utils::simple_target_socket<Gasket, BUSWIDTH, TYPES> socket_;
264
265 // Target object in Simics side receiving the TLM transaction
266 TransactionHandlerInterface *transaction_handler_;
267 NullSimulation null_simulation_;
268 InternalInterface *internal_;
269 sc_core::sc_object *initiator_socket_;
270
271 NonBlockingTlmExtension nb_ext_;
272};
273
274} // namespace tlm2simics
275} // namespace systemc
276} // namespace simics
277
278#endif
Utility class that handles the context switching, using RAII methodology.
Definition: context.h:31
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:66
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:103
std::string gasket_name() const override
Definition: gasket.h:110
virtual ~Gasket()
Definition: gasket.h:83
sc_core::sc_object * get_initiator_socket() const override
Definition: gasket.h:107
void bind(Socket &sock)
Definition: gasket.h:90
virtual void set_transaction_handler(TransactionHandlerInterface *transaction_handler)
Target object in Simics side receiving the TLM transaction.
Definition: gasket.h:96
void register_nb_transport_fw()
For gaskets support non-blocking transport, call this function to register the non-blocking transport...
Definition: gasket.h:118
void init(InternalInterface *internal)
Definition: gasket.h:80
TransactionHandlerInterface * transaction_handler() override
Definition: gasket.h:113
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
Definition: pci_bus_interface.h:24