From 79f37ce35215f7358bdef6b16bbaeb4ea24fad74 Mon Sep 17 00:00:00 2001 From: daniel-k Date: Thu, 21 Dec 2017 21:23:54 +0100 Subject: [PATCH] ips/switch: add C++ implementation of switch --- fpga/include/villas/fpga/ips/switch.hpp | 94 ++++++++++++++++++ fpga/lib/CMakeLists.txt | 1 + fpga/lib/ips/switch.cpp | 121 ++++++++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 fpga/include/villas/fpga/ips/switch.hpp create mode 100644 fpga/lib/ips/switch.cpp diff --git a/fpga/include/villas/fpga/ips/switch.hpp b/fpga/include/villas/fpga/ips/switch.hpp new file mode 100644 index 000000000..bc1fbd7c8 --- /dev/null +++ b/fpga/include/villas/fpga/ips/switch.hpp @@ -0,0 +1,94 @@ +/** AXI Stream interconnect related helper functions + * + * These functions present a simpler interface to Xilinx' AXI Stream switch driver (XAxis_Switch_*) + * + * @file + * @author Steffen Vogel + * @author Daniel Krebs + * @copyright 2017, Steffen Vogel + * @license GNU General Public License (version 3) + * + * VILLASfpga + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +/** @addtogroup fpga VILLASfpga + * @{ + */ + +#pragma once + +#include +#include + +#include +#include + +#include "fpga/ip_node.hpp" +#include "fpga/vlnv.hpp" + +namespace villas { +namespace fpga { +namespace ip { + +class AxiStreamSwitch : public IpNode { +public: + friend class AxiStreamSwitchFactory; + + bool start(); + + bool connect(int portSlave, int portMaster); + bool disconnectMaster(int port); + bool disconnectSlave(int port); + +private: + static constexpr int PORT_DISABLED = -1; + + struct Path { + IpCore* masterOut; + IpCore* slaveIn; + }; + + XAxis_Switch xilinxDriver; + std::map portMapping; +}; + + +class AxiStreamSwitchFactory : public IpNodeFactory { +public: + AxiStreamSwitchFactory() : + IpNodeFactory(getName()) {} + + IpCore* create() + { return new AxiStreamSwitch; } + + std::string getName() const + { return "AxiStreamSwitch"; } + + std::string getDescription() const + { return "Xilinx's AXI4-Stream switch"; } + + Vlnv getCompatibleVlnv() const + { return Vlnv("xilinx.com:ip:axis_interconnect:"); } + + std::list getDependencies() const + { return {}; } +}; + +} // namespace ip +} // namespace fpga +} // namespace villas + +/** @} */ diff --git a/fpga/lib/CMakeLists.txt b/fpga/lib/CMakeLists.txt index e4bb46b76..f249174c0 100644 --- a/fpga/lib/CMakeLists.txt +++ b/fpga/lib/CMakeLists.txt @@ -11,6 +11,7 @@ set(SOURCES ips/timer.cpp ips/model.c ips/switch.c + ips/switch.cpp ips/dft.c ips/fifo.c ips/dma.c diff --git a/fpga/lib/ips/switch.cpp b/fpga/lib/ips/switch.cpp new file mode 100644 index 000000000..d01e4791e --- /dev/null +++ b/fpga/lib/ips/switch.cpp @@ -0,0 +1,121 @@ +/** AXI Stream interconnect related helper functions + * + * These functions present a simpler interface to Xilinx' AXI Stream switch driver (XAxis_Switch_*) + * + * @author Steffen Vogel + * @author Daniel Krebs + * @copyright 2017, Steffen Vogel + * @license GNU General Public License (version 3) + * + * VILLASfpga + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include + +#include "log.hpp" +#include "fpga/ips/switch.hpp" + +namespace villas { +namespace fpga { +namespace ip { + +static AxiStreamSwitchFactory factory; + +bool +AxiStreamSwitch::start() +{ + /* Setup AXI-stream switch */ + XAxis_Switch_Config sw_cfg; + sw_cfg.MaxNumMI = portsMaster.size(); + sw_cfg.MaxNumSI = portsSlave.size(); + + if(XAxisScr_CfgInitialize(&xilinxDriver, &sw_cfg, getBaseaddr()) != XST_SUCCESS) { + cpp_error << "Cannot start " << *this; + return false; + } + + /* Disable all masters */ + XAxisScr_RegUpdateDisable(&xilinxDriver); + XAxisScr_MiPortDisableAll(&xilinxDriver); + XAxisScr_RegUpdateEnable(&xilinxDriver); + + // initialize internal mapping + for(int portMaster = 0; portMaster < portsMaster.size(); portMaster++) { + portMapping[portMaster] = PORT_DISABLED; + } + + + return true; +} + +bool +AxiStreamSwitch::connect(int portSlave, int portMaster) +{ + if(portMapping[portMaster] == portSlave) { + cpp_debug << "Ports already connected"; + return true; + } + + for(auto [master, slave] : portMapping) { + if(slave == portSlave) { + cpp_warn << "Slave " << slave << " has already been connected to " + << "master " << master << ". Disabling master " << master; + + XAxisScr_RegUpdateDisable(&xilinxDriver); + XAxisScr_MiPortDisable(&xilinxDriver, master); + XAxisScr_RegUpdateEnable(&xilinxDriver); + } + } + + /* Reconfigure switch */ + XAxisScr_RegUpdateDisable(&xilinxDriver); + XAxisScr_MiPortEnable(&xilinxDriver, portMaster, portSlave); + XAxisScr_RegUpdateEnable(&xilinxDriver); + + cpp_debug << "Connect slave " << portSlave << " to master " << portMaster; + + return true; +} + +bool +AxiStreamSwitch::disconnectMaster(int port) +{ + cpp_debug << "Disconnect slave " << portMapping[port] + << " from master " << port; + + XAxisScr_MiPortDisable(&xilinxDriver, port); + portMapping[port] = PORT_DISABLED; + return true; +} + +bool +AxiStreamSwitch::disconnectSlave(int port) +{ + for(auto [master, slave] : portMapping) { + if(slave == port) { + cpp_debug << "Disconnect slave " << slave << " from master " << master; + XAxisScr_MiPortDisable(&xilinxDriver, master); + return true; + } + } + + cpp_debug << "Slave " << port << " hasn't been connected to any master"; + return true; +} + +} // namespace ip +} // namespace fpga +} // namespace villas