From a0c5acce4cbb8a5ee3734fe849433cb64760eded Mon Sep 17 00:00:00 2001 From: Daniel Krebs Date: Mon, 4 Jun 2018 14:00:15 +0200 Subject: [PATCH] ip-node: implement connect interface and update AxiStreamSwitch implementation --- fpga/include/villas/fpga/ip_node.hpp | 7 ++- fpga/include/villas/fpga/ips/switch.hpp | 11 +++-- fpga/lib/ip_node.cpp | 61 ++++++++++++++++++++++++ fpga/lib/ips/switch.cpp | 62 +++++++++++++------------ 4 files changed, 105 insertions(+), 36 deletions(-) diff --git a/fpga/include/villas/fpga/ip_node.hpp b/fpga/include/villas/fpga/ip_node.hpp index f305d60f1..00ce93a56 100644 --- a/fpga/include/villas/fpga/ip_node.hpp +++ b/fpga/include/villas/fpga/ip_node.hpp @@ -101,7 +101,7 @@ public: std::string nodeName; }; - bool connect(std::string portName, const StreamPort& to); + bool connect(const StreamVertex& from, const StreamVertex& to); bool disconnect(std::string portName); const StreamVertex& @@ -115,6 +115,11 @@ public: bool loopbackPossible() const; bool connectLoopback(); +protected: + virtual bool + connectInternal(const std::string& slavePort, + const std::string& masterPort); + private: std::pair getLoopbackPorts() const; diff --git a/fpga/include/villas/fpga/ips/switch.hpp b/fpga/include/villas/fpga/ips/switch.hpp index 280b73785..99cdfa788 100644 --- a/fpga/include/villas/fpga/ips/switch.hpp +++ b/fpga/include/villas/fpga/ips/switch.hpp @@ -46,13 +46,14 @@ public: bool init(); - bool connect(int portSlave, int portMaster); - bool disconnectMaster(int port); - bool disconnectSlave(int port); + bool connectInternal(const std::string& slavePort, + const std::string& masterPort); private: - static constexpr int PORT_DISABLED = -1; + int portNameToNum(const std::string& portName); +private: + static constexpr const char* PORT_DISABLED = "DISABLED"; static constexpr char registerMemory[] = "Reg"; std::list getMemoryBlocks() const @@ -65,7 +66,7 @@ private: int num_ports; XAxis_Switch xSwitch; - std::map portMapping; + std::map portMapping; }; diff --git a/fpga/lib/ip_node.cpp b/fpga/lib/ip_node.cpp index 589d10034..d1d8b49a2 100644 --- a/fpga/lib/ip_node.cpp +++ b/fpga/lib/ip_node.cpp @@ -93,6 +93,56 @@ IpNode::getLoopbackPorts() const return { "", "" }; } +bool IpNode::connect(const StreamVertex& from, const StreamVertex& to) +{ + StreamGraph::Path path; + if(not streamGraph.getPath(from.getIdentifier(), to.getIdentifier(), path)) { + logger->error("No path from {} to {}", from, to); + return false; + } + + if(path.size() == 0) { + return true; + } + + auto currentEdge = path.begin(); + auto firstEdge = streamGraph.getEdge(*currentEdge); + auto firstHopNode = streamGraph.getVertex(firstEdge->getVertexTo()); + + auto nextHopNode = firstHopNode; + + // check if next hop is an internal connection + if(firstHopNode->nodeName == getInstanceName()) { + + if(not connectInternal(from.portName, firstHopNode->portName)) { + logger->error("Making internal connection from {} to {} failed", + from, *firstHopNode); + return false; + } + + // we have to advance to next hop + if(++currentEdge == path.end()) { + // arrived at the end of path + return true; + } + + auto secondEdge = streamGraph.getEdge(*currentEdge); + auto secondHopNode = streamGraph.getVertex(secondEdge->getVertexTo()); + nextHopNode = secondHopNode; + } + + auto nextHopNodeIp = reinterpret_cast + (card->lookupIp(nextHopNode->nodeName)); + + if(nextHopNodeIp == nullptr) { + logger->error("Cannot find IP {}, this shouldn't happen!", + nextHopNode->nodeName); + return false; + } + + return nextHopNodeIp->connect(*nextHopNode, to); +} + bool IpNode::loopbackPossible() const { @@ -100,6 +150,17 @@ IpNode::loopbackPossible() const return (not ports.first.empty()) and (not ports.second.empty()); } +bool +IpNode::connectInternal(const std::string& slavePort, + const std::string& masterPort) +{ + (void) slavePort; + (void) masterPort; + + logger->warn("This IP doesn't implement an internal connection"); + return false; +} + bool IpNode::connectLoopback() { diff --git a/fpga/lib/ips/switch.cpp b/fpga/lib/ips/switch.cpp index 4ac1be06f..bc30e27b4 100644 --- a/fpga/lib/ips/switch.cpp +++ b/fpga/lib/ips/switch.cpp @@ -52,19 +52,36 @@ AxiStreamSwitch::init() XAxisScr_MiPortDisableAll(&xSwitch); XAxisScr_RegUpdateEnable(&xSwitch); - // initialize internal mapping - for(size_t portMaster = 0; portMaster < portsMaster.size(); portMaster++) { - portMapping[portMaster] = PORT_DISABLED; + for(auto& [masterName, masterPort] : portsMaster) { + + // initialize internal mapping + portMapping[masterName] = PORT_DISABLED; + + // each slave port may be internally routed to a master port + for(auto& [slaveName, slavePort] : portsSlave) { + (void) slaveName; + + streamGraph.addDefaultEdge(slavePort->getIdentifier(), + masterPort->getIdentifier()); + } } return true; } bool -AxiStreamSwitch::connect(int portSlave, int portMaster) +AxiStreamSwitch::connectInternal(const std::string& portSlave, + const std::string& portMaster) { + if(portSlave.substr(0, 1) != "S" or + portMaster.substr(0, 1) != "M") { + logger->error("sanity check failed"); + return false; + } + if(portMapping[portMaster] == portSlave) { - logger->debug("Ports already connected"); + logger->debug("Ports already connected (slave {} to master {}", + portSlave, portMaster); return true; } @@ -75,45 +92,30 @@ AxiStreamSwitch::connect(int portSlave, int portMaster) slave, master, master); XAxisScr_RegUpdateDisable(&xSwitch); - XAxisScr_MiPortDisable(&xSwitch, master); + XAxisScr_MiPortDisable(&xSwitch, portNameToNum(master)); XAxisScr_RegUpdateEnable(&xSwitch); + + portMapping[master] = PORT_DISABLED; } } /* Reconfigure switch */ XAxisScr_RegUpdateDisable(&xSwitch); - XAxisScr_MiPortEnable(&xSwitch, portMaster, portSlave); + XAxisScr_MiPortEnable(&xSwitch, portNameToNum(portMaster), portNameToNum(portSlave)); XAxisScr_RegUpdateEnable(&xSwitch); + portMapping[portMaster] = portSlave; + logger->debug("Connect slave {} to master {}", portSlave, portMaster); return true; } -bool -AxiStreamSwitch::disconnectMaster(int port) +int +AxiStreamSwitch::portNameToNum(const std::string& portName) { - logger->debug("Disconnect slave {} from master {}", - portMapping[port], port); - - XAxisScr_MiPortDisable(&xSwitch, port); - portMapping[port] = PORT_DISABLED; - return true; -} - -bool -AxiStreamSwitch::disconnectSlave(int port) -{ - for(auto [master, slave] : portMapping) { - if(slave == port) { - logger->debug("Disconnect slave {} from master {}", slave, master); - XAxisScr_MiPortDisable(&xSwitch, master); - return true; - } - } - - logger->debug("Slave {} hasn't been connected to any master", port); - return true; + const std::string number = portName.substr(1, 2); + return std::stoi(number); } bool