Commit 6f20555b authored by Daniel Krebs's avatar Daniel Krebs

ip-node: implement connect interface and update AxiStreamSwitch implementation

parent a8ca4dc2
......@@ -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<std::string, std::string> getLoopbackPorts() const;
......
......@@ -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<MemoryBlockName> getMemoryBlocks() const
......@@ -65,7 +66,7 @@ private:
int num_ports;
XAxis_Switch xSwitch;
std::map<int, int> portMapping;
std::map<std::string, std::string> portMapping;
};
......
......@@ -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<IpNode*>
(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()
{
......
......@@ -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);
logger->debug("Connect slave {} to master {}", portSlave, portMaster);
portMapping[portMaster] = portSlave;
return true;
}
bool
AxiStreamSwitch::disconnectMaster(int port)
{
logger->debug("Disconnect slave {} from master {}",
portMapping[port], port);
logger->debug("Connect slave {} to master {}", portSlave, portMaster);
XAxisScr_MiPortDisable(&xSwitch, port);
portMapping[port] = PORT_DISABLED;
return true;
}
bool
AxiStreamSwitch::disconnectSlave(int port)
int
AxiStreamSwitch::portNameToNum(const std::string& portName)
{
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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment