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