15#ifndef SIMICS_SYSTEMC_COMPOSITE_PCI_MAPPING_INTERCONNECT_H
16#define SIMICS_SYSTEMC_COMPOSITE_PCI_MAPPING_INTERCONNECT_H
18#if defined SIMICS_5_API || defined SIMICS_6_API
22#include <tlm_utils/multi_passthrough_target_socket.h>
23#include <tlm_utils/simple_target_socket.h>
24#include <tlm_utils/simple_initiator_socket.h>
41const char *
const PCI_MAPPING_INTERCONNECT_TAG =
"intel/PciMappingInterconnect";
50template<
typename TSocket>
51class PciMappingInterconnectExtensionSender
52 :
public iface::ExtensionSender<TSocket> {
54 virtual ~PciMappingInterconnectExtensionSender() {}
55 virtual void send_extension(iface::Transaction *transaction) {
56 failed_transaction_ = iface::Transaction(NULL);
57 iface::ExtensionSender<TSocket>::send_extension(transaction);
59 virtual void send_failed(iface::Transaction *transaction) {
60 failed_transaction_ = *transaction;
61 iface::ExtensionSender<TSocket>::send_failed(transaction);
63 iface::Transaction failed_transaction_;
84template <
unsigned int BUSWIDTH,
typename TYPES>
85class PciMappingInterconnect :
public sc_core::sc_module {
88 typedef tlm_utils::simple_target_socket<
89 PciMappingInterconnect, BUSWIDTH, TYPES> target_socket_t;
90 typedef tlm_utils::multi_passthrough_target_socket<
91 PciMappingInterconnect, BUSWIDTH, TYPES> multi_target_socket_t;
92 typedef tlm_utils::simple_initiator_socket<
93 PciMappingInterconnect, BUSWIDTH, TYPES> initiator_socket_t;
95 tlm::tlm_target_socket<BUSWIDTH, TYPES> *tlm;
96 tlm_utils::multi_target_base<BUSWIDTH, TYPES> *multi;
97 } supported_target_socket_t;
100 SC_HAS_PROCESS(PciMappingInterconnect);
101 explicit PciMappingInterconnect(
102 sc_core::sc_module_name =
"PciMappingInterconnect")
103 : target_socket(
"target_socket"),
104 simics_target_socket(
"simics_target_socket"),
105 pci_bus_initiator_socket(
"pci_bus_initiator_socket"),
106 initiator_sockets_(
"initiator_socket"),
107 pci_target_socket_(),
108 pci_device_target_socket_(),
109 pci_bus_target_socket_(
"pci_bus_target_socket"),
110 number_of_functions_(1),
111 mapping_id_offset_(0x10100) {
112 target_socket.register_b_transport(
113 this, &PciMappingInterconnect::b_transport);
114 target_socket.register_transport_dbg(
115 this, &PciMappingInterconnect::transport_dbg);
116 simics_target_socket.register_b_transport(
117 this, &PciMappingInterconnect::simics_b_transport);
118 pci_bus_target_socket_.register_b_transport(
119 this, &PciMappingInterconnect::pci_bus_b_transport);
120 pci_bus_target_socket_.register_transport_dbg(
121 this, &PciMappingInterconnect::pci_bus_transport_dbg);
122 pci_bus_target_socket_.register_get_direct_mem_ptr(
123 this, &PciMappingInterconnect::pci_bus_get_direct_mem_ptr);
124 pci_bus_initiator_socket.register_invalidate_direct_mem_ptr(
125 this, &PciMappingInterconnect::pci_bus_invalidate_direct_mem_ptr);
126 sender_.init(&pci_bus_initiator_socket);
127 extension_.init(&sender_);
130 virtual void before_end_of_elaboration();
132 void retrieveFunctionData(
int id,
int bar);
134 void connect(iface::PciDeviceQueryInterface *pci, ConfObjectRef o);
136 void connectConfig(iface::BaseAddressRegisterQueryInterface *bar,
137 simics2tlm::IoMemory *gasket,
140 void connectMmio(iface::BaseAddressRegisterQueryInterface *bar,
141 simics2tlm::IoMemory *gasket,
148 multi_target_socket_t target_socket;
149 multi_target_socket_t simics_target_socket;
151 initiator_socket_t pci_bus_initiator_socket;
155 void b_transport(
int id, tlm::tlm_generic_payload &trans,
156 sc_core::sc_time &t);
157 unsigned int transport_dbg(
int id, tlm::tlm_generic_payload &trans);
158 void simics_b_transport(
int id, tlm::tlm_generic_payload &trans,
159 sc_core::sc_time &t);
160 void pci_bus_b_transport(tlm::tlm_generic_payload &trans,
161 sc_core::sc_time &t);
162 unsigned int pci_bus_transport_dbg(tlm::tlm_generic_payload &trans);
163 bool pci_bus_get_direct_mem_ptr(tlm::tlm_generic_payload &trans,
164 tlm::tlm_dmi &dmi_data);
165 void pci_bus_invalidate_direct_mem_ptr(sc_dt::uint64 start_range,
166 sc_dt::uint64 end_range);
169 void castToTarget(sc_core::sc_object *
object,
170 supported_target_socket_t *target);
171 template <
typename TGasket>
172 void bindToGasket(supported_target_socket_t target,
173 TGasket *gasket, ConfObjectRef o,
int id);
174 void updateCommand(
int id, uint16_t old_command);
175 void updateBaseAddress(
int id,
int bar);
176 void updateMemoryMapping(
bool enable, types::addr_space_t space,
177 uint64_t base_address,
int bar_size_bits,
179 void interceptBarAccess(
int id, tlm::tlm_generic_payload &trans,
180 sc_core::sc_time &t);
184 sc_core::sc_vector<initiator_socket_t> initiator_sockets_;
185 supported_target_socket_t pci_target_socket_;
186 initiator_socket_t pci_device_initiator_socket_;
187 supported_target_socket_t pci_device_target_socket_;
189 target_socket_t pci_bus_target_socket_;
191 struct function_data_t {
194 uint32_t base_address[6];
196 std::vector<function_data_t> function_data_;
197 int number_of_functions_;
198 int mapping_id_offset_;
199 iface::BaseAddressRegisterQueryInterface::BarInfo bar_info_;
201 PciMappingInterconnectExtensionSender<
202 initiator_socket_t> sender_;
203 iface::PciBusExtension extension_;
206template <
unsigned int BUSWIDTH,
typename TYPES>
207void PciMappingInterconnect<BUSWIDTH, TYPES>::before_end_of_elaboration() {
213 initiator_sockets_.init(number_of_functions_);
214 for (std::size_t i = 0; i < initiator_sockets_.size(); ++i) {
215 if (pci_target_socket_.tlm) {
216 initiator_sockets_[i].bind(*pci_target_socket_.tlm);
218 initiator_sockets_[i].bind(*pci_target_socket_.multi);
223 function_data_ = std::vector<function_data_t>(number_of_functions_);
224 int prev_function = -1;
226 for (iface::BaseAddressRegisterQueryInterface::BarInfo::const_iterator it
227 = bar_info_.begin(); it != bar_info_.end(); ++it) {
228 int current_function = (*it).function;
229 if (current_function != prev_function) {
230 function_data_[++id].function = current_function;
231 prev_function = current_function;
235 if (pci_device_target_socket_.tlm) {
236 pci_device_initiator_socket_.bind(*pci_device_target_socket_.tlm);
237 }
else if (pci_device_target_socket_.multi) {
238 pci_device_initiator_socket_.bind(*pci_device_target_socket_.multi);
248template <
unsigned int BUSWIDTH,
typename TYPES>
249void PciMappingInterconnect<BUSWIDTH, TYPES>::retrieveFunctionData(
251 tlm::tlm_generic_payload trans;
252 trans.set_command(tlm::TLM_READ_COMMAND);
253 trans.set_data_length(4);
254 trans.set_streaming_width(4);
257 trans.set_data_ptr(
reinterpret_cast<unsigned char *
>(&value));
258 trans.set_address(0x4);
259 initiator_sockets_[id]->transport_dbg(trans);
260 function_data_[id].command = value;
263 bool all_bars = (bar == -1) ?
true :
false;
267 int function = function_data_[id].function;
268 for (iface::BaseAddressRegisterQueryInterface::BarInfo::const_iterator
269 it = bar_info_.begin(); it != bar_info_.end(); ++it) {
273 if ((*it).function != function) {
277 bar = ((*it).offset - 0x10) / 4;
278 }
else if (bar != ((*it).offset - 0x10) / 4) {
281 uint32_t base_address = 0;
282 trans.set_address((*it).offset);
284 reinterpret_cast<unsigned char *
>(&base_address));
285 trans.set_data_length(
sizeof base_address);
286 trans.set_streaming_width(trans.get_data_length());
287 initiator_sockets_[id]->transport_dbg(trans);
288 function_data_[id].base_address[bar] = base_address;
289 if ((*it).is_64bit) {
291 trans.set_address((*it).offset + 4);
293 reinterpret_cast<unsigned char *
>(&base_address));
294 trans.set_data_length(
sizeof base_address);
295 trans.set_streaming_width(trans.get_data_length());
296 initiator_sockets_[id]->transport_dbg(trans);
297 function_data_[id].base_address[bar + 1] = base_address;
310template <
unsigned int BUSWIDTH,
typename TYPES>
311void PciMappingInterconnect<BUSWIDTH, TYPES>::connect(
312 iface::PciDeviceQueryInterface *pci, ConfObjectRef o) {
313 castToTarget(pci->getPciDeviceTargetSocket(),
314 &pci_device_target_socket_);
315 castToTarget(pci->getConfigTargetSocket(), &pci_target_socket_);
316 tlm::tlm_initiator_socket<BUSWIDTH, TYPES> *initiator
317 =
dynamic_cast<tlm::tlm_initiator_socket<BUSWIDTH, TYPES> *
>(
318 pci->getPciBusInitiatorSocket());
320 pci_bus_target_socket_.bind(*initiator);
322 SIM_LOG_ERROR(o, Log_Configuration,
323 "object returned by getPciBusInitiatorSocket was not"
324 " a tlm::tlm_initiator_socket.");
334template <
unsigned int BUSWIDTH,
typename TYPES>
335void PciMappingInterconnect<BUSWIDTH, TYPES>::connectConfig(
336 iface::BaseAddressRegisterQueryInterface *bar,
337 simics2tlm::IoMemory *gasket, ConfObjectRef o) {
341 255, simics2tlm::createGasket(&target_socket, o));
344 bar_info_ = bar->getBarInfo();
345 int prev_function = 0;
346 for (iface::BaseAddressRegisterQueryInterface::BarInfo::const_iterator it
347 = bar_info_.begin(); it != bar_info_.end(); ++it) {
348 int current_function = (*it).function;
349 if (current_function != prev_function) {
350 ++number_of_functions_;
351 prev_function = current_function;
352 gasket->addGasket(255 + current_function,
353 simics2tlm::createGasket(&target_socket, o));
355 FATAL_ERROR_IF(current_function < prev_function,
356 "BarInfo must be sorted on function number"
357 " in ascending order");
366template <
unsigned int BUSWIDTH,
typename TYPES>
367void PciMappingInterconnect<BUSWIDTH, TYPES>::connectMmio(
368 iface::BaseAddressRegisterQueryInterface *bar,
369 simics2tlm::IoMemory *gasket, ConfObjectRef o) {
370 iface::BaseAddressRegisterQueryInterface::BarSockets bar_sockets
371 = bar->getBarTargetSockets();
372 iface::BaseAddressRegisterQueryInterface::BarSockets::const_iterator it;
373 for (iface::BaseAddressRegisterQueryInterface::BarSockets::const_iterator it
374 = bar_sockets.begin(); it != bar_sockets.end(); ++it) {
375 supported_target_socket_t target = {};
376 castToTarget((*it).second, &target);
377 bindToGasket(target, gasket, o,
378 (*it).first.mapping_id + mapping_id_offset_);
383template <
unsigned int BUSWIDTH,
typename TYPES>
384void PciMappingInterconnect<BUSWIDTH, TYPES>::busReset() {
385 for (iface::BaseAddressRegisterQueryInterface::BarInfo::const_iterator it
386 = bar_info_.begin(); it != bar_info_.end(); ++it) {
387 int mapping_id = (*it).mapping_id + mapping_id_offset_;
388 types::addr_space_t space = types::Sim_Addr_Space_IO;
389 if ((*it).is_memory) {
390 space = types::Sim_Addr_Space_Memory;
392 extension_.remove_map(space, mapping_id);
393 if (sender_.failed_transaction_.payload()) {
394 SC_REPORT_INFO(PCI_MAPPING_INTERCONNECT_TAG,
395 "Failure to unmap device on bus_reset");
406template <
unsigned int BUSWIDTH,
typename TYPES>
407void PciMappingInterconnect<BUSWIDTH, TYPES>::b_transport(
409 tlm::tlm_generic_payload &trans,
410 sc_core::sc_time &t) {
411 interceptBarAccess(
id, trans, t);
412 initiator_sockets_[id]->b_transport(trans, t);
418template <
unsigned int BUSWIDTH,
typename TYPES>
419unsigned int PciMappingInterconnect<BUSWIDTH, TYPES>::transport_dbg(
421 tlm::tlm_generic_payload &trans) {
422 return initiator_sockets_[id]->transport_dbg(trans);
428template <
unsigned int BUSWIDTH,
typename TYPES>
429void PciMappingInterconnect<BUSWIDTH, TYPES>::simics_b_transport(
430 int id, tlm::tlm_generic_payload &trans,
431 sc_core::sc_time &t) {
432 pci_device_initiator_socket_->b_transport(trans, t);
438template <
unsigned int BUSWIDTH,
typename TYPES>
439void PciMappingInterconnect<BUSWIDTH, TYPES>::pci_bus_b_transport(
440 tlm::tlm_generic_payload &trans,
441 sc_core::sc_time &t) {
442 pci_bus_initiator_socket->b_transport(trans, t);
448template <
unsigned int BUSWIDTH,
typename TYPES>
449unsigned int PciMappingInterconnect<BUSWIDTH, TYPES>::pci_bus_transport_dbg(
450 tlm::tlm_generic_payload &trans) {
451 return pci_bus_initiator_socket->transport_dbg(trans);
457template <
unsigned int BUSWIDTH,
typename TYPES>
458bool PciMappingInterconnect<BUSWIDTH, TYPES>::pci_bus_get_direct_mem_ptr(
459 tlm::tlm_generic_payload &trans,
460 tlm::tlm_dmi &dmi_data) {
461 return pci_bus_initiator_socket->get_direct_mem_ptr(trans, dmi_data);
467template <
unsigned int BUSWIDTH,
typename TYPES>
468void PciMappingInterconnect<BUSWIDTH, TYPES>::pci_bus_invalidate_direct_mem_ptr(
469 sc_dt::uint64 start_range,
470 sc_dt::uint64 end_range) {
471 pci_bus_target_socket_->invalidate_direct_mem_ptr(start_range,
477template <
unsigned int BUSWIDTH,
typename TYPES>
478void PciMappingInterconnect<BUSWIDTH, TYPES>::castToTarget(
479 sc_core::sc_object *
object, supported_target_socket_t *target) {
480 tlm::tlm_target_socket<BUSWIDTH, TYPES> *tlm_target
481 =
dynamic_cast<tlm::tlm_target_socket<BUSWIDTH, TYPES> *
>(object);
483 target->tlm = tlm_target;
487 tlm_utils::multi_target_base<BUSWIDTH, TYPES> *multi_target
488 =
dynamic_cast<tlm_utils::multi_target_base<BUSWIDTH, TYPES> *
>(object);
490 target->multi = multi_target;
494 SC_REPORT_ERROR(PCI_MAPPING_INTERCONNECT_TAG,
495 "Unable to dynamic-cast PCI target socket");
498template <
unsigned int BUSWIDTH,
typename TYPES>
499template <
typename TGasket>
500void PciMappingInterconnect<BUSWIDTH, TYPES>::bindToGasket(
501 supported_target_socket_t target,
502 TGasket *gasket, ConfObjectRef o,
int id) {
504 gasket->addGasket(
id, simics2tlm::createGasket(target.tlm, o));
505 }
else if (target.multi) {
507 gasket->addGasket(
id, simics2tlm::createGasket(target.multi, o));
519template <
unsigned int BUSWIDTH,
typename TYPES>
520void PciMappingInterconnect<BUSWIDTH, TYPES>::updateCommand(
521 int id, uint16_t old_command) {
522 int command = function_data_[id].command;
523 if (command == old_command) {
526 int function = function_data_[id].function;
527 bool mem_enable = (command >> 1) & 1;
528 bool io_enable = command & 1;
530 for (iface::BaseAddressRegisterQueryInterface::BarInfo::const_iterator it
531 = bar_info_.begin(); it != bar_info_.end(); ++it) {
532 if ((*it).function == function) {
534 = (*it).is_memory ? mem_enable : io_enable;
535 types::addr_space_t space
536 = (*it).is_memory ? types::Sim_Addr_Space_Memory
537 : types::Sim_Addr_Space_IO;
538 int bar = ((*it).offset - 0x10) / 4;
539 uint64_t base_address = function_data_[id].base_address[bar];
540 if ((*it).is_64bit) {
541 base_address |=
static_cast<uint64_t
>(
542 function_data_[id].base_address[bar + 1]) << 32;
544 updateMemoryMapping(enable, space, base_address,
546 (*it).mapping_id + mapping_id_offset_);
559template <
unsigned int BUSWIDTH,
typename TYPES>
560void PciMappingInterconnect<BUSWIDTH, TYPES>::updateBaseAddress(
int id,
562 int command = function_data_[id].command;
563 int function = function_data_[id].function;
564 bool mem_enable = (command >> 1) & 1;
565 bool io_enable = command & 1;
566 for (iface::BaseAddressRegisterQueryInterface::BarInfo::const_iterator it
567 = bar_info_.begin(); it != bar_info_.end(); ++it) {
568 if ((*it).function == function && (*it).offset == 0x10 + 4 * bar) {
569 bool enable = (*it).is_memory ? mem_enable : io_enable;
574 types::addr_space_t space
575 = (*it).is_memory ? types::Sim_Addr_Space_Memory
576 : types::Sim_Addr_Space_IO;
577 uint64_t base_address = function_data_[id].base_address[bar];
578 if ((*it).is_64bit) {
579 base_address |=
static_cast<uint64_t
>(
580 function_data_[id].base_address[bar + 1]) << 32;
582 updateMemoryMapping(enable, space, base_address,
584 (*it).mapping_id + mapping_id_offset_);
590template <
unsigned int BUSWIDTH,
typename TYPES>
591void PciMappingInterconnect<BUSWIDTH, TYPES>::updateMemoryMapping(
593 types::addr_space_t space,
594 uint64_t base_address,
597 extension_.remove_map(space, mapping_id);
598 if (sender_.failed_transaction_.payload()) {
599 SC_REPORT_INFO(PCI_MAPPING_INTERCONNECT_TAG,
"Failure to unmap device");
604 types::map_info_t info(base_address & ~((1 << bar_size_bits) - 1),
605 0, 1 << bar_size_bits,
607 extension_.add_map(space, info);
609 if (sender_.failed_transaction_.payload()) {
610 SC_REPORT_INFO(PCI_MAPPING_INTERCONNECT_TAG,
611 "Failure to map device");
617template <
unsigned int BUSWIDTH,
typename TYPES>
618void PciMappingInterconnect<BUSWIDTH, TYPES>::interceptBarAccess(
620 tlm::tlm_generic_payload &trans,
621 sc_core::sc_time &t) {
623 sc_dt::uint64 offset = trans.get_address();
624 unsigned int size = trans.get_data_length();
625 uint64_t *data =
reinterpret_cast<uint64_t *
>(trans.get_data_ptr());
628 if (trans.get_byte_enable_ptr()) {
631 if (trans.get_streaming_width() != size) {
638 if (trans.is_write()) {
639 uint16_t old_command = function_data_[id].command;
643 retrieveFunctionData(
id, -1);
644 function_data_[id].command = (*data) & 0xffff;
645 updateCommand(
id, old_command);
654 int bar = (offset - 0x10) / 4;
655 retrieveFunctionData(
id, bar);
662 function_data_[id].base_address[bar] = *data & 0xffffffff;
663 if (size == 8 && !(offset % 8)) {
664 function_data_[id].base_address[bar + 1] = *data >> 32;
666 updateBaseAddress(
id, bar);
Definition: pci_bus_interface.h:24