diff --git a/fpga/include/villas/fpga/ip_node.hpp b/fpga/include/villas/fpga/ip_node.hpp index 3a319a27d..6f7f92486 100644 --- a/fpga/include/villas/fpga/ip_node.hpp +++ b/fpga/include/villas/fpga/ip_node.hpp @@ -57,6 +57,12 @@ public: bool connect(int port, const StreamPort& to); bool disconnect(int port); + bool loopbackPossible() const; + bool connectLoopback(); + +private: + std::pair getLoopbackPorts() const; + protected: std::map portsMaster; std::map portsSlave; diff --git a/fpga/lib/ip_node.cpp b/fpga/lib/ip_node.cpp index 31503e31a..e456949a5 100644 --- a/fpga/lib/ip_node.cpp +++ b/fpga/lib/ip_node.cpp @@ -4,15 +4,18 @@ #include "utils.hpp" #include "fpga/ip_node.hpp" +#include "fpga/ips/switch.hpp" +#include "fpga/card.hpp" namespace villas { namespace fpga { namespace ip { + bool IpNodeFactory::configureJson(IpCore& ip, json_t* json_ip) { - auto ipNode = reinterpret_cast(ip); + auto& ipNode = reinterpret_cast(ip); json_t* json_ports = json_object_get(json_ip, "ports"); if(json_ports == nullptr) { @@ -88,6 +91,48 @@ IpNodeFactory::populatePorts(std::map& portMap, json_t* return true; } +std::pair +IpNode::getLoopbackPorts() const +{ + for(auto& [masterNum, masterTo] : portsMaster) { + for(auto& [slaveNum, slaveTo] : portsSlave) { + // TODO: should we also check which IP both ports are connected to? + if(masterTo.nodeName == slaveTo.nodeName) { + return { masterNum, slaveNum }; + } + } + } + + return { -1, -1 }; +} + +bool +IpNode::loopbackPossible() const +{ + auto ports = getLoopbackPorts(); + return (ports.first != -1) and (ports.second != -1); +} + +bool +IpNode::connectLoopback() +{ + auto ports = getLoopbackPorts(); + const auto& portMaster = portsMaster[ports.first]; + const auto& portSlave = portsSlave[ports.second]; + + // TODO: verify this is really a switch! + auto axiStreamSwitch = reinterpret_cast( + card->lookupIp(portMaster.nodeName)); + + if(axiStreamSwitch == nullptr) { + cpp_error << "Cannot find IP " << *axiStreamSwitch; + return false; + } + + // switch's slave port is our master port and vice versa + return axiStreamSwitch->connect(portMaster.portNumber, portSlave.portNumber); +} + } // namespace ip } // namespace fpga } // namespace villas