15#ifndef SIMICS_SYSTEMC_COMPOSITE_PCIE_MAPPING_INTERCONNECT_H
16#define SIMICS_SYSTEMC_COMPOSITE_PCIE_MAPPING_INTERCONNECT_H
20#include <tlm_utils/multi_socket_bases.h>
21#include <tlm_utils/simple_initiator_socket.h>
22#include <tlm_utils/simple_target_socket.h>
24#include <simics/cc-api.h>
42const char *
const PCIE_MAPPING_INTERCONNECT_TAG = \
43 "intel/PcieMappingInterconnect";
65std::string pcieDeviceIdStr(uint16_t device_id) {
66 std::ostringstream os;
67 os <<
"device id 0x" << std::hex << device_id
68 <<
" (" << std::dec << (device_id >> 8)
69 <<
":" << ((device_id >> 3) & 0x1f)
70 <<
"." << (device_id & 7) <<
")";
81template<
typename TSocket>
106template <
unsigned int BUSWIDTH,
typename TYPES>
109 typedef tlm_utils::simple_target_socket<
111 typedef tlm_utils::simple_initiator_socket<
114 tlm::tlm_target_socket<BUSWIDTH, TYPES> *tlm;
115 tlm_utils::multi_target_base<BUSWIDTH, TYPES> *multi;
116 } supported_target_socket_t;
123 sc_core::sc_module_name =
"PcieMappingInterconnect")
127 initiator_sockets_(
"initiator_socket"),
128 config_target_socket_(),
129 msg_target_socket_(),
130 pcie_map_target_socket_(
"pcie_map_target_socket") {
132 this, &PcieMappingInterconnect::transaction_b_transport);
134 this, &PcieMappingInterconnect::transaction_transport_dbg);
136 this, &PcieMappingInterconnect::pcie_map_invalidate_direct_mem_ptr);
137 pcie_map_target_socket_.register_b_transport(
138 this, &PcieMappingInterconnect::pcie_map_b_transport);
139 pcie_map_target_socket_.register_transport_dbg(
140 this, &PcieMappingInterconnect::pcie_map_transport_dbg);
141 pcie_map_target_socket_.register_get_direct_mem_ptr(
142 this, &PcieMappingInterconnect::pcie_map_get_direct_mem_ptr);
145 pcie_map_extension_.
init(&sender_);
150 SC_METHOD(warmReset);
154 config_target_socket_.tlm =
nullptr;
155 config_target_socket_.multi =
nullptr;
156 msg_target_socket_.tlm =
nullptr;
157 msg_target_socket_.multi =
nullptr;
225 void addFunction(uint16_t device_id);
228 void delFunction(uint16_t device_id);
231 void castToTarget(sc_core::sc_object *
object,
232 supported_target_socket_t *target);
239 void updateMappings(
int function_id = -1,
int bar_id = -1);
249 void updateCommand(uint16_t function_id, uint16_t old_command);
257 void retrieveFunctionData(
size_t socket_id,
int bar_id);
260 void interceptCfgHeaderAccess(
size_t socket_id,
261 tlm::tlm_generic_payload &trans);
266 tlm::tlm_generic_payload &trans)
const;
269 conf_object_t *getCfgMapHelper(uint16_t device_id);
273 size_t validateTransaction(tlm::tlm_generic_payload &trans);
280 void transaction_b_transport(tlm::tlm_generic_payload &trans,
281 sc_core::sc_time &t);
282 unsigned int transaction_transport_dbg(
283 tlm::tlm_generic_payload &trans);
285 void pcie_map_invalidate_direct_mem_ptr(sc_dt::uint64 start_range,
286 sc_dt::uint64 end_range);
287 void pcie_map_b_transport(
288 tlm::tlm_generic_payload &trans,
289 sc_core::sc_time &t);
290 unsigned int pcie_map_transport_dbg(
291 tlm::tlm_generic_payload &trans);
292 bool pcie_map_get_direct_mem_ptr(
293 tlm::tlm_generic_payload &trans,
294 tlm::tlm_dmi &dmi_data);
298 sc_core::sc_vector<initiator_socket_t> initiator_sockets_;
299 supported_target_socket_t config_target_socket_;
300 supported_target_socket_t msg_target_socket_;
302 target_socket_t pcie_map_target_socket_;
304 struct cfg_header_t {
306 uint32_t base_address[7];
309 std::map<uint16_t, cfg_header_t> function_data_;
310 std::vector<iface::PcieBaseAddressRegisterQueryInterface::PCIeBar>
314 PcieMappingInterconnectExtensionSender<initiator_socket_t> sender_;
321 std::map<std::pair<size_t, size_t>,
size_t> address_id_mem_map_;
323 std::map<std::pair<size_t, size_t>,
size_t> address_id_io_map_;
325 std::map<std::pair<size_t, size_t>,
size_t> fn_bar_id_map_;
327 ConfObjectRef simulation_obj_ {
nullptr};
331 ConfObjectRef gasket_obj_ {
nullptr};
336 bool function_number_has_8bits_ {
false};
340 iface::PcieSriovQueryInterface *sriov_query_ {
nullptr};
347 uint16_t cap_offset = 0;
350 int first_vf_function = 0;
366 uint32_t vf_bar[6] = {};
369 uint16_t control = 0;
370 uint16_t num_vfs = 0;
372 std::vector<SriovState> sriov_states_;
379 void setupSriovStates();
384 void updateVfCfgMappings(SriovState &state,
bool enable);
389 void updateVfBarMappings(SriovState &state,
bool enable);
392template <
unsigned int BUSWIDTH,
typename TYPES>
400 initiator_sockets_.init(function_data_.size() + bar_info_.size() + 1);
402 size_t socket_id = 0;
404 for (; socket_id < function_data_.size(); ++socket_id) {
405 if (config_target_socket_.tlm) {
406 initiator_sockets_[socket_id].bind(*config_target_socket_.tlm);
408 initiator_sockets_[socket_id].bind(*config_target_socket_.multi);
412 for (
const auto &bar : bar_info_) {
413 supported_target_socket_t target = {};
414 castToTarget(bar.target_socket, &target);
416 initiator_sockets_[socket_id].bind(*target.tlm);
417 }
else if (target.multi) {
418 initiator_sockets_[socket_id].bind(*target.multi);
421 PCIE_MAPPING_INTERCONNECT_TAG,
422 "BAR target_socket type is not supported");
424 fn_bar_id_map_[std::make_pair(bar.function, bar.offset)] = socket_id;
428 if (msg_target_socket_.tlm) {
429 initiator_sockets_[socket_id].bind(*msg_target_socket_.tlm);
431 initiator_sockets_[socket_id].bind(*msg_target_socket_.multi);
435template <
unsigned int BUSWIDTH,
typename TYPES>
440 pcie_map_extension_.get_device_id(gasket_obj_);
447 for (
const auto &fd : function_data_) {
448 delFunction(device_id | fd.first);
449 addFunction(device_id | fd.first);
459 for (
const auto &state : sriov_states_) {
460 for (
int i = 0; i < state.total_vfs; ++i) {
461 const uint16_t fn =
static_cast<uint16_t
>(
462 state.first_vf_function
463 + i * state.vf_stride);
464 pcie_map_extension_.disable_function(fn);
469template <
unsigned int BUSWIDTH,
typename TYPES>
472 for (
auto &fd : function_data_) {
473 delFunction(device_id | fd.first);
475 fd.second.command = 0;
476 updateMappings(fd.first);
480template <
unsigned int BUSWIDTH,
typename TYPES>
484 for (
auto &fd : function_data_) {
486 fd.second.command = 0;
487 updateMappings(fd.first);
495 for (
auto &state : sriov_states_) {
496 if (state.control & 0x1u) {
497 updateVfCfgMappings(state,
false);
501 std::fill(std::begin(state.vf_bar), std::end(state.vf_bar), 0u);
506template <
unsigned int BUSWIDTH,
typename TYPES>
510 for (
auto &fd : function_data_) {
512 fd.second.command = 0;
513 updateMappings(fd.first);
518template <
unsigned int BUSWIDTH,
typename TYPES>
519void PcieMappingInterconnect<BUSWIDTH, TYPES>::
520addFunction(uint16_t device_id) {
521 std::ostringstream os;
522 os <<
"Adding function for device_id: "
524 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
525 auto *map_helper = getCfgMapHelper(device_id);
526 if (map_helper ==
nullptr) {
527 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG,
528 "Failure to get map helper");
531 pcie_map_extension_.add_function(map_helper, device_id);
532 if (sender_.failed_transaction_.payload()) {
533 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG,
534 "Failure to add function");
539template <
unsigned int BUSWIDTH,
typename TYPES>
540void PcieMappingInterconnect<BUSWIDTH, TYPES>::
541delFunction(uint16_t device_id) {
542 std::ostringstream os;
543 os <<
"Deleting function for device_id: "
545 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
546 auto *map_helper = getCfgMapHelper(device_id);
547 if (map_helper ==
nullptr) {
548 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG,
549 "Failure to get map helper");
552 pcie_map_extension_.del_function(map_helper, device_id);
553 if (sender_.failed_transaction_.payload()) {
554 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG,
555 "Failure to delete function");
560template <
unsigned int BUSWIDTH,
typename TYPES>
566 if (pci ==
nullptr) {
569 "PcieDeviceQueryInterface not implemented on the device");
573 if (bar ==
nullptr) {
576 "PcieBaseAddressRegisterQueryInterface not implemented on"
581 if (reset ==
nullptr) {
583 "PcieResetInterface not implemented on the device");
600 for (
const auto &bar : bar_info_) {
601 if (function_data_.find(bar.function) == function_data_.end()) {
602 function_data_[bar.function];
603 if (bar.function > 7) {
604 function_number_has_8bits_ =
true;
610 auto *initiator =
dynamic_cast<
611 tlm::tlm_initiator_socket<BUSWIDTH, TYPES> *
>(
614 pcie_map_target_socket_.bind(*initiator);
617 "object returned by getPcieMapInitiatorSocket was not"
618 " a tlm::tlm_initiator_socket.");
622 sriov_query_ = sriov;
624 createCfgMapHelper();
627template <
unsigned int BUSWIDTH,
typename TYPES>
628std::map<std::pair<size_t, size_t>,
size_t>
630 return address_id_mem_map_;
633template <
unsigned int BUSWIDTH,
typename TYPES>
634std::map<std::pair<size_t, size_t>,
size_t>
636 return address_id_io_map_;
639template <
unsigned int BUSWIDTH,
typename TYPES>
642 sriov_states_.clear();
643 if (sriov_query_ !=
nullptr) {
644 for (
const auto &info : sriov_query_->getSriovInfo()) {
645 SriovState state = {};
646 state.cap_offset = info.cap_offset;
647 state.pf_function = info.pf_function;
648 state.total_vfs = info.total_vfs;
649 state.first_vf_function = info.first_vf_function;
650 state.vf_stride = (info.vf_stride <= 0) ? 1 : info.vf_stride;
653 for (
const auto &bi : bar_info_) {
654 const int fn = bi.function;
656 (fn >= state.first_vf_function)
657 && ((fn - state.first_vf_function) % state.vf_stride == 0)
658 && ((fn - state.first_vf_function) / state.vf_stride
660 if (is_vf && !bi.is_memory) {
661 std::ostringstream oss;
662 oss <<
"SR-IOV: VF BAR (function=" << fn
663 <<
" offset=0x" << std::hex << bi.offset
664 <<
") has is_memory=false; VF BARs must be"
665 " Memory Space only per PCIe SR-IOV spec";
667 "%s", oss.str().c_str());
671 sriov_states_.push_back(state);
678template <
unsigned int BUSWIDTH,
typename TYPES>
679void PcieMappingInterconnect<BUSWIDTH, TYPES>::
680updateVfCfgMappings(SriovState &state,
bool enable) {
681 const int num_vfs =
static_cast<int>(state.num_vfs);
683 std::ostringstream os;
684 os <<
"SR-IOV PF" << state.pf_function <<
": "
685 << (enable ?
"enabling " :
"disabling ") << num_vfs
686 <<
" VF config space(s)";
687 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
689 for (
int i = 0; i < num_vfs; ++i) {
690 const uint16_t fn =
static_cast<uint16_t
>(
691 state.first_vf_function + i * state.vf_stride);
693 pcie_map_extension_.enable_function(fn);
695 pcie_map_extension_.disable_function(fn);
703template <
unsigned int BUSWIDTH,
typename TYPES>
704void PcieMappingInterconnect<BUSWIDTH, TYPES>::
705updateVfBarMappings(SriovState &state,
bool enable) {
706 const int num_vfs =
static_cast<int>(state.num_vfs);
710 if (num_vfs > state.total_vfs) {
711 std::ostringstream os;
712 os <<
"SR-IOV: NumVFs (" << num_vfs
713 <<
") exceeds TotalVFs (" << state.total_vfs
714 <<
") for PF" << state.pf_function
715 <<
" — refusing to update VF BAR mappings";
716 SC_REPORT_WARNING(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
724 for (
const auto &bi : bar_info_) {
725 if (bi.function != state.first_vf_function || !bi.is_memory)
728 const int ba_idx = (bi.offset - 0x10) / 4;
729 if (ba_idx < 0 || ba_idx >= 6)
732 const int sz = bi.size_bits;
738 const uint32_t lo = state.vf_bar[ba_idx];
739 const uint32_t hi = (bi.is_64bit && ba_idx + 1 < 6)
740 ? state.vf_bar[ba_idx + 1] : 0u;
741 const uint64_t vf_bar_raw = (
static_cast<uint64_t
>(hi) << 32) | lo;
742 const uint64_t align_mask = ~((1ULL << sz) - 1ULL);
743 const uint64_t vf_base = vf_bar_raw & align_mask;
746 std::ostringstream os;
747 os <<
"SR-IOV PF" << state.pf_function
748 <<
" VF BAR (cfg 0x" << std::hex << bi.offset <<
"): "
749 << (enable ?
"enabling " :
"disabling ")
750 << std::dec << num_vfs <<
" VF BAR(s)";
751 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
755 for (
int i = 0; i < num_vfs; ++i) {
756 const uint16_t fn =
static_cast<uint16_t
>(
757 state.first_vf_function + i * state.vf_stride);
758 auto it = function_data_.find(fn);
759 if (it == function_data_.end()) {
760 std::ostringstream os;
761 os <<
"SR-IOV PF" << state.pf_function
762 <<
": VF function " << fn
763 <<
" not found in function_data_ — inconsistent SR-IOV"
764 " configuration (getSriovInfo() and getBarInfo()"
766 SC_REPORT_ERROR(PCIE_MAPPING_INTERCONNECT_TAG,
770 auto &fd = it->second;
775 const size_t socket_id = fn_bar_id_map_.at(
776 std::make_pair(
static_cast<size_t>(fn),
777 static_cast<size_t>(bi.offset)));
780 const uint64_t vf_addr =
781 vf_base +
static_cast<uint64_t
>(i) * (1ULL << sz);
782 fd.base_address[ba_idx] =
static_cast<uint32_t
>(vf_addr);
783 if (bi.is_64bit && ba_idx + 1 < 7)
784 fd.base_address[ba_idx + 1] =
785 static_cast<uint32_t
>(vf_addr >> 32);
786 const types::map_info_t info(
787 vf_addr, vf_addr, 1ULL << sz,
788 static_cast<int>(fn));
789 address_id_mem_map_[std::make_pair(
790 vf_addr, vf_addr + (1ULL << sz))] = socket_id;
793 fd.base_address[ba_idx] = 0;
794 if (bi.is_64bit && ba_idx + 1 < 7)
795 fd.base_address[ba_idx + 1] = 0;
801template <
unsigned int BUSWIDTH,
typename TYPES>
802void PcieMappingInterconnect<BUSWIDTH, TYPES>::
803retrieveFunctionData(
size_t socket_id,
int bar_id) {
804 if (initiator_sockets_.size() <= socket_id) {
805 std::ostringstream os;
806 os <<
"Invalid socket_id: " << socket_id;
807 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
811 tlm::tlm_generic_payload trans;
815 trans.set_data_ptr(
reinterpret_cast<unsigned char *
>(&value));
816 trans.set_data_length(4);
817 trans.set_streaming_width(4);
819 trans.set_command(tlm::TLM_READ_COMMAND);
820 trans.set_address(0x4);
822 auto ret = initiator_sockets_[socket_id]->transport_dbg(trans);
830 auto fd = function_data_.begin();
831 std::advance(fd, socket_id);
832 fd->second.command = value;
836 for (
const auto &bar : bar_info_) {
840 if (bar.function != fd->first) {
844 int expected_bar_id = bar.offset == 0x30 ? 6 : (bar.offset - 0x10) / 4;
846 if (bar_id != -1 && bar_id != expected_bar_id) {
850 trans.set_address(bar.offset);
851 initiator_sockets_[socket_id]->transport_dbg(trans);
852 fd->second.base_address[expected_bar_id] = value;
854 if (expected_bar_id == 6) {
856 PCIE_MAPPING_INTERCONNECT_TAG,
857 "Expansion ROM BAR can't support 64-bit address");
860 trans.set_address(bar.offset + 4);
861 initiator_sockets_[socket_id]->transport_dbg(trans);
862 fd->second.base_address[expected_bar_id + 1] = value;
868template <
unsigned int BUSWIDTH,
typename TYPES>
869void PcieMappingInterconnect<BUSWIDTH, TYPES>::
871 std::ostringstream os;
872 os <<
"Adding mapping of type: "
873 << pcieTypeName(type);
874 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
875 pcie_map_extension_.add_map(info, type);
876 if (sender_.failed_transaction_.payload()) {
877 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG,
"Failure to add map");
882template <
unsigned int BUSWIDTH,
typename TYPES>
883void PcieMappingInterconnect<BUSWIDTH, TYPES>::
887 auto it = std::find_if(
888 address_id_mem_map_.begin(),
889 address_id_mem_map_.end(),
891 const std::pair<std::pair<size_t, size_t>,
size_t> &entry) {
892 return entry.second == socket_id;
895 if (it != address_id_mem_map_.end()) {
896 base = it->first.first;
897 address_id_mem_map_.erase(it);
900 auto it = std::find_if(
901 address_id_io_map_.begin(),
902 address_id_io_map_.end(),
904 const std::pair<std::pair<size_t, size_t>,
size_t> &entry) {
905 return entry.second == socket_id;
908 if (it != address_id_io_map_.end()) {
909 base = it->first.first;
910 address_id_io_map_.erase(it);
914 if (base != 0xffffffffffffffff) {
915 std::ostringstream os;
916 os <<
"Deleting mapping of type: "
917 << pcieTypeName(type) <<
", base: 0x" << std::hex << base;
918 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
920 pcie_map_extension_.del_map(base, type);
921 if (sender_.failed_transaction_.payload()) {
922 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG,
"Failure to del map");
928template <
unsigned int BUSWIDTH,
typename TYPES>
929void PcieMappingInterconnect<BUSWIDTH, TYPES>::
930updateMappings(
int function_id,
int bar_id) {
931 for (
const auto &bi : bar_info_) {
932 if (function_id != -1 && bi.function != function_id) {
936 auto header = function_data_.at(bi.function);
938 int expected_bar_id = bi.offset == 0x30 ? 6 : (bi.offset - 0x10) / 4;
939 if (bar_id != -1 && bar_id != expected_bar_id) {
943 uint64_t base_address = header.base_address[expected_bar_id];
945 if (expected_bar_id == 6) {
947 PCIE_MAPPING_INTERCONNECT_TAG,
948 "Expansion ROM BAR can't support 64-bit address");
950 base_address |=
static_cast<uint64_t
>(
951 header.base_address[expected_bar_id + 1]) << 32;
955 bool enable = header.command & 1;
959 if (bi.offset == 0x30) {
960 enable = base_address & 1;
962 enable = (header.command >> 1) & 1;
965 base_address &= ~((1ULL << bi.size_bits) - 1);
966 size_t socket_id = fn_bar_id_map_.at(
967 std::make_pair(bi.function, bi.offset));
968 delMap(socket_id, type);
973 types::map_info_t info(base_address, base_address,
974 1ULL << bi.size_bits, function_id);
975 auto address_range = std::make_pair(info.base,
976 info.base + info.length);
979 address_id_mem_map_[address_range] = socket_id;
980 std::ostringstream os;
981 os <<
"Memory address for function " << bi.function
982 <<
" and bar ID " << expected_bar_id
983 <<
" in range of [0x" << std::hex << info.base
984 <<
"-0x" << info.base + info.length <<
"] maps to socket ID "
986 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
988 address_id_io_map_[address_range] = socket_id;
989 std::ostringstream os;
990 os <<
"IO address for function " << bi.function
991 <<
" and bar ID " << expected_bar_id
992 <<
" in range of [0x" << std::hex << info.base
993 <<
"-0x" << info.base + info.length <<
"] maps to socket ID "
995 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
1002template <
unsigned int BUSWIDTH,
typename TYPES>
1003void PcieMappingInterconnect<BUSWIDTH, TYPES>::
1004updateCommand(uint16_t function_id, uint16_t old_command) {
1005 if (function_data_[function_id].command != old_command) {
1006 updateMappings(function_id);
1010template <
unsigned int BUSWIDTH,
typename TYPES>
1011void PcieMappingInterconnect<BUSWIDTH, TYPES>::
1012interceptCfgHeaderAccess(
size_t socket_id,
1013 tlm::tlm_generic_payload &trans) {
1014 unsigned int size = trans.get_data_length();
1016 if (trans.get_byte_enable_ptr() || trans.get_streaming_width() != size) {
1021 if (!trans.is_write()) {
1026 uint64_t *data =
reinterpret_cast<uint64_t *
>(trans.get_data_ptr());
1028 auto it = function_data_.begin();
1029 std::advance(it, socket_id);
1030 uint16_t function_id = it->first;
1031 auto &header = it->second;
1032 sc_dt::uint64 offset = trans.get_address();
1035 uint16_t old_command = header.command;
1036 retrieveFunctionData(socket_id, -1);
1037 header.command = (*data) & 0xffff;
1038 updateCommand(function_id, old_command);
1047 int bar_id = (offset - 0x10) / 4;
1048 retrieveFunctionData(socket_id, bar_id);
1055 header.base_address[bar_id] = *data & 0xffffffff;
1056 if (size == 8 && !(offset % 8)) {
1057 header.base_address[bar_id + 1] = *data >> 32;
1059 updateMappings(function_id, bar_id);
1064 retrieveFunctionData(socket_id, bar_id);
1065 header.base_address[bar_id] = *data & 0xffffffff;
1066 updateMappings(function_id, bar_id);
1071 for (
auto &state : sriov_states_) {
1072 if (
static_cast<int>(function_id) != state.pf_function)
1074 const sc_dt::uint64 cap = state.cap_offset;
1075 const uint32_t written =
static_cast<uint32_t
>(*data);
1076 if (offset == cap + 0x08) {
1077 const uint16_t old_ctrl = state.control;
1078 state.control =
static_cast<uint16_t
>(written & 0xFFFFu);
1088 const bool vf_enable_was = old_ctrl & 0x1u;
1089 const bool vf_enable_now = state.control & 0x1u;
1090 const bool vf_mse_was = (old_ctrl >> 3) & 0x1u;
1091 const bool vf_mse_now = (state.control >> 3) & 0x1u;
1092 const bool bars_were_live = vf_enable_was && vf_mse_was;
1093 const bool bars_are_live = vf_enable_now && vf_mse_now;
1094 if (vf_enable_was != vf_enable_now) {
1095 updateVfCfgMappings(state, vf_enable_now);
1097 if (bars_were_live != bars_are_live) {
1098 updateVfBarMappings(state, bars_are_live);
1100 }
else if (offset == cap + 0x10) {
1101 state.num_vfs =
static_cast<uint16_t
>(written & 0xFFFFu);
1102 }
else if (offset >= cap + 0x24 && offset < cap + 0x24 + 6 * 4) {
1106 const int idx =
static_cast<int>((offset - (cap + 0x24)) / 4);
1107 state.vf_bar[idx] = written;
1112 const bool vf_en = (state.control & 0x1u) != 0;
1113 const bool vf_mse = ((state.control >> 3) & 0x1u) != 0;
1114 if (vf_en && vf_mse)
1115 updateVfBarMappings(state,
true);
1121template <
unsigned int BUSWIDTH,
typename TYPES>
1122size_t PcieMappingInterconnect<BUSWIDTH, TYPES>::
1124 tlm::tlm_generic_payload &trans)
const {
1126 auto found = function_data_.find(function_id);
1127 if (found == function_data_.end()) {
1128 std::ostringstream os;
1129 os <<
"Function id(" << function_id
1130 <<
") not found for this device";
1131 throw std::invalid_argument {
1135 return std::distance(function_data_.begin(), found);
1137 size_t address = trans.get_address();
1138 for (
const auto &entry : address_id_mem_map_) {
1139 auto startAddress = entry.first.first;
1140 auto endAddress = entry.first.second;
1141 auto id = entry.second;
1143 if (address >= startAddress && address < endAddress) {
1144 if (enable_base_address_subtraction) {
1145 trans.set_address(address - startAddress);
1150 throw std::invalid_argument {
1151 "Unable to find the initiator_socket to forward the MEM transaction"
1154 size_t address = trans.get_address();
1155 for (
const auto &entry : address_id_io_map_) {
1156 auto startAddress = entry.first.first;
1157 auto endAddress = entry.first.second;
1158 auto id = entry.second;
1160 if (address >= startAddress && address < endAddress) {
1161 if (enable_base_address_subtraction) {
1162 trans.set_address(address - startAddress);
1167 throw std::invalid_argument {
1168 "Unable to find the initiator_socket to forward the IO transaction"
1171 return function_data_.size() + bar_info_.size();
1173 throw std::invalid_argument {
1174 "Unsupported PCIe type"
1178template <
unsigned int BUSWIDTH,
typename TYPES>
1182 if (map_helper ==
nullptr) {
1185 "Simics class pcie_map_helper_cpp is required."
1186 "Try load the module pcie-map-helper-c++ first.");
1190 if (SIM_c_get_interface(simulation_obj_,
"pcie_device") ==
nullptr) {
1192 if (!SIM_object_is_configured(simulation_obj_)) {
1195 "Simulation object is not configured yet, cannot get"
1196 " its gasket_list attribute");
1203 int gasket_count = SIM_attr_list_size(gasket_list);
1204 for (
int i = 0; i < gasket_count; ++i) {
1205 auto obj = SIM_attr_object(SIM_attr_list_item(gasket_list, i));
1206 if (SIM_c_get_interface(obj,
"pcie_device")) {
1211 if (gasket_obj_.object() ==
nullptr) {
1214 "No gasket object implemented the required"
1215 " pcie_device interface");
1219 gasket_obj_ = simulation_obj_.object();
1222 for (
const auto &fd : function_data_) {
1223 auto pcie_type = std_to_attr<>(
1225 auto forward_target = std_to_attr<>(
1226 std::pair<std::string, ConfObjectRef>(
"forward_target",
1228 auto function_id = std_to_attr<>(
1229 std::pair<std::string, int>(
"function_id", fd.first));
1230 attr_value_t attr = SIM_make_attr_list(3, pcie_type, forward_target,
1233 auto obj_name = gasket_obj_.name() +
".port.cfg" + \
1234 std::to_string(fd.first);
1237 std::ignore = SIM_clear_exception();
1241 SIM_attr_free(&attr);
1245template <
unsigned int BUSWIDTH,
typename TYPES>
1248 std::string name =
"port.cfg";
1249 if (function_number_has_8bits_) {
1250 name += std::to_string(device_id & 0xff);
1252 name += std::to_string(device_id & 7);
1254 auto map_helper = SIM_object_descendant(gasket_obj_, name.c_str());
1257 "Could not find map helper object with name '%s.%s'",
1258 gasket_obj_.name().c_str(), name.c_str());
1263template <
unsigned int BUSWIDTH,
typename TYPES>
1264size_t PcieMappingInterconnect<BUSWIDTH, TYPES>::
1265validateTransaction(tlm::tlm_generic_payload &trans) {
1266 PcieTlmExtension *pcie_ext =
nullptr;
1267 trans.get_extension<PcieTlmExtension>(pcie_ext);
1269 if (pcie_ext ==
nullptr) {
1270 trans.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);
1271 SC_REPORT_ERROR(PCIE_MAPPING_INTERCONNECT_TAG,
1272 "PcieTlmExtension is required but not found");
1276 std::ostringstream os;
1277 os <<
"Received a PCIe transaction with type "
1278 << pcieTypeName(pcie_ext->type);
1279 if (pcie_ext->device_id_set) {
1280 os <<
", " << pcieDeviceIdStr(pcie_ext->device_id);
1282 os <<
", address 0x" << std::hex << trans.get_address() << std::endl;
1283 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
1287 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG,
1288 "Only support following PCIe types: MEM/IO/CFG/MSG");
1289 trans.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);
1294 && !pcie_ext->device_id_set) {
1295 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG,
1296 "PCIe device ID ATOM is required");
1297 trans.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);
1301 size_t socket_id = 0;
1305 const uint16_t fn = function_number_has_8bits_
1306 ? (pcie_ext->device_id & 0xFF)
1307 : (pcie_ext->device_id & 7);
1308 socket_id = findSocketId(pcie_ext->type, fn, trans);
1309 }
catch (
const std::exception &e) {
1310 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, e.what());
1311 trans.set_response_status(tlm::TLM_ADDRESS_ERROR_RESPONSE);
1315 if (socket_id >= initiator_sockets_.size()) {
1317 os <<
"Initiator socket ID " << socket_id <<
" not created yet";
1318 SC_REPORT_INFO(PCIE_MAPPING_INTERCONNECT_TAG, os.str().c_str());
1319 trans.set_response_status(tlm::TLM_GENERIC_ERROR_RESPONSE);
1324 interceptCfgHeaderAccess(socket_id, trans);
1330template <
unsigned int BUSWIDTH,
typename TYPES>
1331void PcieMappingInterconnect<BUSWIDTH, TYPES>::
1332transaction_b_transport(tlm::tlm_generic_payload &trans,
1333 sc_core::sc_time &t) {
1334 trans.set_response_status(tlm::TLM_OK_RESPONSE);
1335 size_t socket_id = validateTransaction(trans);
1336 if (trans.get_response_status() == tlm::TLM_OK_RESPONSE) {
1337 initiator_sockets_.at(socket_id)->b_transport(trans, t);
1341template <
unsigned int BUSWIDTH,
typename TYPES>
1342unsigned int PcieMappingInterconnect<BUSWIDTH, TYPES>::
1343transaction_transport_dbg(tlm::tlm_generic_payload &trans) {
1344 trans.set_response_status(tlm::TLM_OK_RESPONSE);
1345 size_t socket_id = validateTransaction(trans);
1346 if (trans.get_response_status() == tlm::TLM_OK_RESPONSE) {
1347 return initiator_sockets_.at(socket_id)->transport_dbg(trans);
1356template <
unsigned int BUSWIDTH,
typename TYPES>
1357void PcieMappingInterconnect<BUSWIDTH, TYPES>::
1358pcie_map_invalidate_direct_mem_ptr(sc_dt::uint64 start_range,
1359 sc_dt::uint64 end_range) {
1360 pcie_map_target_socket_->invalidate_direct_mem_ptr(start_range,
1367template <
unsigned int BUSWIDTH,
typename TYPES>
1368void PcieMappingInterconnect<BUSWIDTH, TYPES>::pcie_map_b_transport(
1369 tlm::tlm_generic_payload &trans,
1370 sc_core::sc_time &t) {
1371 pcie_map_initiator_socket->b_transport(trans, t);
1377template <
unsigned int BUSWIDTH,
typename TYPES>
1378unsigned int PcieMappingInterconnect<BUSWIDTH, TYPES>::pcie_map_transport_dbg(
1379 tlm::tlm_generic_payload &trans) {
1380 return pcie_map_initiator_socket->transport_dbg(trans);
1386template <
unsigned int BUSWIDTH,
typename TYPES>
1387bool PcieMappingInterconnect<BUSWIDTH, TYPES>::pcie_map_get_direct_mem_ptr(
1388 tlm::tlm_generic_payload &trans,
1389 tlm::tlm_dmi &dmi_data) {
1390 return pcie_map_initiator_socket->get_direct_mem_ptr(trans, dmi_data);
1393template <
unsigned int BUSWIDTH,
typename TYPES>
1394void PcieMappingInterconnect<BUSWIDTH, TYPES>::
1395castToTarget(sc_core::sc_object *
object, supported_target_socket_t *target) {
1396 if (
object ==
nullptr) {
1397 SC_REPORT_ERROR(PCIE_MAPPING_INTERCONNECT_TAG,
1398 "Unable to castToTarget from a nullptr");
1402 auto *tlm_target =
dynamic_cast<
1403 tlm::tlm_target_socket<BUSWIDTH, TYPES> *
>(object);
1405 target->tlm = tlm_target;
1409 auto *multi_target =
dynamic_cast<
1410 tlm_utils::multi_target_base<BUSWIDTH, TYPES> *
>(object);
1412 target->multi = multi_target;
1416 SC_REPORT_ERROR(PCIE_MAPPING_INTERCONNECT_TAG,
1417 "Unable to dynamic-cast PCIe target socket");
Definition: pcie_mapping_interconnect.h:83
void send_extension(iface::Transaction *transaction) override
Called by extension after the extension is set on the payload.
Definition: pcie_mapping_interconnect.h:88
virtual ~PcieMappingInterconnectExtensionSender()
Definition: pcie_mapping_interconnect.h:85
iface::Transaction failed_transaction_
Definition: pcie_mapping_interconnect.h:97
void send_failed(iface::Transaction *transaction) override
Called by extension if method_call invocation was missing.
Definition: pcie_mapping_interconnect.h:92
Definition: pcie_mapping_interconnect.h:107
PcieMappingInterconnect(sc_core::sc_module_name="PcieMappingInterconnect")
Definition: pcie_mapping_interconnect.h:122
void connected(uint16_t device_id)
Definition: pcie_mapping_interconnect.h:436
void before_end_of_elaboration() override
Definition: pcie_mapping_interconnect.h:393
bool enable_base_address_subtraction
Definition: pcie_mapping_interconnect.h:209
SC_HAS_PROCESS(PcieMappingInterconnect)
initiator_socket_t pcie_map_initiator_socket
IC -> Simics, forwards the upstream pcie-map transactions.
Definition: pcie_mapping_interconnect.h:204
void connect(iface::PcieDeviceQueryInterface *pci, iface::PcieBaseAddressRegisterQueryInterface *bar, iface::PcieResetInterface *reset, ConfObjectRef o, iface::PcieSriovQueryInterface *sriov=nullptr)
Called by (outer) composite class to retrieve the required information to connect the IC with the PCI...
Definition: pcie_mapping_interconnect.h:562
void hotReset()
Definition: pcie_mapping_interconnect.h:481
void createCfgMapHelper()
Definition: pcie_mapping_interconnect.h:1180
target_socket_t pcie_device_target_socket
Definition: pcie_mapping_interconnect.h:202
std::map< std::pair< size_t, size_t >, size_t > addressIdMemMap() const
Definition: pcie_mapping_interconnect.h:629
target_socket_t transaction_target_socket
Definition: pcie_mapping_interconnect.h:200
void disconnected(uint16_t device_id)
Definition: pcie_mapping_interconnect.h:471
sc_core::sc_in< bool > warm_reset_pin
Definition: pcie_mapping_interconnect.h:206
std::map< std::pair< size_t, size_t >, size_t > addressIdIoMap() const
Definition: pcie_mapping_interconnect.h:635
Generic extension sender initialized with a TLM2 initiator socket of TSocket type.
Definition: extension_sender.h:35
void send_extension(Transaction *transaction) override
Called by extension after the extension is set on the payload.
Definition: extension_sender.h:55
void init(TSocket *socket)
Definition: extension_sender.h:40
Transaction transaction() override
Called by extension to get a new Transaction.
Definition: extension_sender.h:49
void send_failed(Transaction *transaction) override
Called by extension if method_call invocation was missing.
Definition: extension_sender.h:58
void init(ExtensionSenderInterface *sender, tlm::tlm_generic_payload *payload)
Deprecated, use the init(ExtensionSenderInterface *sender) instead.
Definition: extension.h:45
Interface that allows the Simics glue to perform snooping and automatic connection of the device's ta...
Definition: pcie_device_query_interface.h:51
virtual std::vector< PCIeBar > getBarInfo()=0
BAR register information.
Interface required from a SystemC PCIe device in order to connect to Simics.
Definition: pcie_device_query_interface.h:30
virtual sc_core::sc_object * getMsgTargetSocket()=0
virtual sc_core::sc_object * getConfigTargetSocket()=0
virtual sc_core::sc_object * getPcieMapInitiatorSocket()=0
Extension for Simics pcie_map interface.
Definition: pcie_map_extension.h:28
Definition: pcie_device_query_interface.h:93
Interface providing static SR-IOV configuration to the PcieMappingInterconnect.
Definition: pcie_device_query_interface.h:124
Class that encapsulates a generic_payload and returns it to the TransactionPool when the Transaction ...
Definition: transaction.h:31
conf_object_t * SIM_create_object(conf_class_t *NOTNULL cls, const char *name, attr_value_t attrs)
conf_object_t * SIM_get_object(const char *NOTNULL name)
attr_value_t SIM_get_attribute(conf_object_t *NOTNULL obj, const char *name)
conf_class_t * SIM_get_class(const char *NOTNULL name)
@ Log_Configuration
Definition: adapter_log_groups.h:25
pcie_type_t
Definition: pcie_type.h:22
@ PCIE_Type_Cfg
Definition: pcie_type.h:26
@ PCIE_Type_Mem
Definition: pcie_type.h:24
@ PCIE_Type_Msg
Definition: pcie_type.h:27
@ PCIE_Type_Not_Set
Definition: pcie_type.h:23
@ PCIE_Type_Other
Definition: pcie_type.h:28
@ PCIE_Type_IO
Definition: pcie_type.h:25
Reduced, stand-alone, version of the Simics map_info_t struct.
Definition: map_info.h:25
uint64_t physical_address_t
Definition: map_info.h:26