From 3e505c74bf5fe80fe0464c8a365ece2898160c97 Mon Sep 17 00:00:00 2001 From: Daniel Krebs Date: Fri, 13 Apr 2018 15:30:12 +0200 Subject: [PATCH] ips/bram: add block RAM IP and use it with DMA test --- fpga/include/villas/fpga/ips/bram.hpp | 87 +++++++++++++++++++++++++++ fpga/lib/CMakeLists.txt | 1 + fpga/lib/ips/bram.cpp | 32 ++++++++++ fpga/tests/dma.cpp | 8 ++- 4 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 fpga/include/villas/fpga/ips/bram.hpp create mode 100644 fpga/lib/ips/bram.cpp diff --git a/fpga/include/villas/fpga/ips/bram.hpp b/fpga/include/villas/fpga/ips/bram.hpp new file mode 100644 index 000000000..01a46256f --- /dev/null +++ b/fpga/include/villas/fpga/ips/bram.hpp @@ -0,0 +1,87 @@ +/** Block-Raam related helper functions + * * + * @author Daniel Krebs + * @copyright 2018, Daniel Krebs + * @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 "memory.hpp" +#include "fpga/ip.hpp" + +namespace villas { +namespace fpga { +namespace ip { + + +class Bram : public IpCore +{ + friend class BramFactory; +public: + + bool init(); + + LinearAllocator& + getAllocator() + { return *allocator; } + +private: + static constexpr const char* memoryBlock = "Mem0"; + std::list getMemoryBlocks() const + { return { memoryBlock }; } + + size_t size; + std::unique_ptr allocator; +}; + + + +class BramFactory : public IpCoreFactory { +public: + + BramFactory() : + IpCoreFactory(getName()) + {} + + bool configureJson(IpCore& ip, json_t *json_ip); + + IpCore* create() + { return new Bram; } + + std::string + getName() const + { return "Bram"; } + + std::string + getDescription() const + { return "Block RAM"; } + + Vlnv getCompatibleVlnv() const + { return {"xilinx.com:ip:axi_bram_ctrl:"}; } +}; + +} // namespace ip +} // namespace fpga +} // namespace villas + +/** @} */ diff --git a/fpga/lib/CMakeLists.txt b/fpga/lib/CMakeLists.txt index d30414b8e..84733d3f8 100644 --- a/fpga/lib/CMakeLists.txt +++ b/fpga/lib/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCES ips/intc.cpp ips/pcie.cpp ips/dma.cpp + ips/bram.cpp kernel/kernel.c kernel/pci.c diff --git a/fpga/lib/ips/bram.cpp b/fpga/lib/ips/bram.cpp new file mode 100644 index 000000000..11dda7f67 --- /dev/null +++ b/fpga/lib/ips/bram.cpp @@ -0,0 +1,32 @@ +#include "fpga/ips/bram.hpp" + +namespace villas { +namespace fpga { +namespace ip { + +static BramFactory factory; + +bool +BramFactory::configureJson(IpCore& ip, json_t* json_ip) +{ + auto& bram = reinterpret_cast(ip); + + if(json_unpack(json_ip, "{ s: i }", "size", &bram.size) != 0) { + getLogger()->error("Cannot parse 'size'"); + return false; + } + + return true; +} + +bool Bram::init() +{ + allocator = std::make_unique + (getAddressSpaceId(memoryBlock), this->size, 0); + + return true; +} + +} // namespace ip +} // namespace fpga +} // namespace villas diff --git a/fpga/tests/dma.cpp b/fpga/tests/dma.cpp index e8bb4c08d..63c1c0470 100644 --- a/fpga/tests/dma.cpp +++ b/fpga/tests/dma.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -36,13 +37,18 @@ Test(fpga, dma, .description = "DMA") continue; } + // find a block RAM IP to write to + auto bramIp = state.cards.front()->lookupIp(villas::fpga::Vlnv("xilinx.com:ip:axi_bram_ctrl:")); + auto bram = reinterpret_cast(bramIp); + cr_assert_not_null(bram, "Couldn't find BRAM"); + // Simple DMA can only transfer up to 4 kb due to PCIe page size burst // limitation size_t len = 4 * (1 << 10); /* Allocate memory to use with DMA */ auto src = villas::HostRam::getAllocator().allocate(len); - auto dst = villas::HostRam::getAllocator().allocate(len); + auto dst = bram->getAllocator().allocate(len); /* Get new random data */ const size_t lenRandom = read_random(&src, len);