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