1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-30 00:00:11 +01:00
VILLASnode/fpga/include/villas/fpga/node.hpp
Steffen Vogel 3d73c759ea Reformat all code with clang-format
Signed-off-by: Steffen Vogel <post@steffenvogel.de>
2024-02-29 19:34:27 +01:00

168 lines
4.7 KiB
C++

/* Interlectual Property component.
*
* This class represents a module within the FPGA.
*
* Author: Steffen Vogel <post@steffenvogel.de>
* Author: Daniel Krebs <github@daniel-krebs.net>
* SPDX-FileCopyrightText: 2017 Institute for Automation of Complex Power Systems, RWTH Aachen University
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <fmt/ostream.h>
#include <jansson.h>
#include <map>
#include <string>
#include <villas/config.hpp>
#include <villas/fpga/core.hpp>
#include <villas/graph/directed.hpp>
namespace villas {
namespace fpga {
namespace ip {
class StreamVertex : public graph::Vertex {
public:
StreamVertex(const std::string &node, const std::string &port, bool isMaster)
: graph::Vertex(), nodeName(node), portName(port), isMaster(isMaster) {}
std::string getName() const {
return nodeName + "/" + portName + "(" + (isMaster ? "M" : "S") + ")";
}
friend std::ostream &operator<<(std::ostream &stream,
const StreamVertex &vertex) {
return stream << vertex.getIdentifier() << ": " << vertex.getName();
}
public:
std::string nodeName;
std::string portName;
bool isMaster;
};
class StreamGraph : public graph::DirectedGraph<StreamVertex> {
public:
StreamGraph() : graph::DirectedGraph<StreamVertex>("stream:graph") {}
std::shared_ptr<StreamVertex> getOrCreateStreamVertex(const std::string &node,
const std::string &port,
bool isMaster) {
for (auto &vertexEntry : vertices) {
auto &vertex = vertexEntry.second;
if (vertex->nodeName == node and vertex->portName == port and
vertex->isMaster == isMaster)
return vertex;
}
// Vertex not found, create new one
auto vertex = std::make_shared<StreamVertex>(node, port, isMaster);
addVertex(vertex);
return vertex;
}
};
class Node : public virtual Core {
public:
using Ptr = std::shared_ptr<Node>;
friend class NodeFactory;
const StreamVertex &getMasterPort(const std::string &name) const {
return *portsMaster.at(name);
}
const std::map<std::string, std::shared_ptr<StreamVertex>> &
getMasterPorts() const {
return portsMaster;
}
const StreamVertex &getSlavePort(const std::string &name) const {
return *portsSlave.at(name);
}
const std::map<std::string, std::shared_ptr<StreamVertex>> &
getSlavePorts() const {
return portsSlave;
}
bool connect(const StreamVertex &from, const StreamVertex &to);
bool connect(const StreamVertex &from, const StreamVertex &to, bool reverse) {
bool ret;
ret = connect(from, to);
if (reverse)
ret &= connect(to, from);
return ret;
}
// Easy-usage assuming that the slave IP to connect to only has one slave
// port and implements the getDefaultSlavePort() function
bool connect(const Node &slaveNode, bool reverse = false) {
return this->connect(this->getDefaultMasterPort(),
slaveNode.getDefaultSlavePort(), reverse);
}
// Used by easy-usage connect, will throw if not implemented by derived node
virtual const StreamVertex &getDefaultSlavePort() const;
// Used by easy-usage connect, will throw if not implemented by derived node
virtual const StreamVertex &getDefaultMasterPort() const;
static const StreamGraph &getGraph() { return streamGraph; }
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;
protected:
std::map<std::string, std::shared_ptr<StreamVertex>> portsMaster;
std::map<std::string, std::shared_ptr<StreamVertex>> portsSlave;
static StreamGraph streamGraph;
};
class NodeFactory : public CoreFactory {
public:
using CoreFactory::CoreFactory;
virtual void parse(Core &, json_t *);
};
template <typename T, const char *name, const char *desc, const char *vlnv>
class NodePlugin : public NodeFactory {
public:
virtual std::string getName() const { return name; }
virtual std::string getDescription() const { return desc; }
private:
// Get a VLNV identifier for which this IP / Node type can be used.
virtual Vlnv getCompatibleVlnv() const { return Vlnv(vlnv); }
// Create a concrete IP instance
Core *make() const { return new T; }
};
} // namespace ip
} // namespace fpga
} // namespace villas
#ifndef FMT_LEGACY_OSTREAM_FORMATTER
template <>
class fmt::formatter<villas::fpga::ip::StreamVertex>
: public fmt::ostream_formatter {};
template <>
class fmt::formatter<villas::fpga::ip::Node> : public fmt::ostream_formatter {};
#endif