diff --git a/backends/uio/include/UioAccess.h b/backends/uio/include/UioAccess.h index 0e3596aac..6e2df1c15 100644 --- a/backends/uio/include/UioAccess.h +++ b/backends/uio/include/UioAccess.h @@ -2,29 +2,67 @@ // SPDX-License-Identifier: LGPL-3.0-or-later #pragma once +// The mainline kernel linux define the maximum number of UIO maps as 5 +#ifndef MAX_UIO_MAPS +# define MAX_UIO_MAPS 5 +#endif + #include +#include #include #include #include +#include namespace ChimeraTK { /// @brief Implements a generic userspace interface for UIO devices. class UioAccess { private: - boost::filesystem::path _deviceFilePath; + /// @brief Implements map interface for UIO devices . + class UioMap { + public: + UioMap(); + UioMap(int deviceFileDescriptor, size_t uioMapIdx, const std::string& uioMapPath); + ~UioMap(); + UioMap(const UioMap&) = delete; + UioMap& operator=(const UioMap&) = delete; + UioMap(UioMap&& other) noexcept; + UioMap& operator=(UioMap&&) noexcept; + + explicit operator bool() const noexcept; + + /// @brief Read data from the specified memory offset address. The address range starts at '0'. + /// @param address Start address of memory to read from + /// @param data Address pointer to which data is to be copied + /// @param sizeInBytes Number of bytes to copy + void read(uint64_t address, int32_t* data, size_t sizeInBytes); + + /// @brief Write data to the specified memory offset address. The address range starts at '0'. + /// @param address Start address of memory to write to + /// @param data Address pointer from which data is to be copied + /// @param sizeInBytes Number of bytes to copy + void write(uint64_t address, int32_t const* data, size_t sizeInBytes); + + private: + /// @brief Calculate the address from the perspective of the UIO map + /// @param address Start address of memory of the request + /// @param sizeInBytes Number of bytes to copy + /// @param isWrite Determines if it is a read or a write request + /// @return Unsigned value + size_t validateAndGetMapOffset(uint64_t address, size_t sizeInBytes, bool isWrite); + size_t _deviceLowerBound = 0; + size_t _deviceHigherBound = 0; + void* _deviceUserBase = nullptr; + }; + int _deviceFileDescriptor = 0; - void* _deviceUserBase = nullptr; - void* _deviceKernelBase = nullptr; - size_t _deviceMemSize = 0; + boost::filesystem::path _deviceFilePath; + std::string _filename; + std::array _maps; uint32_t _lastInterruptCount = 0; std::atomic _opened{false}; - - /// @brief Maps user space memory range to address range of UIO device. - void UioMMap(); - - /// @brief Unmaps user space memory range for address range of UIO device. - void UioUnmap(); + uint8_t _maps_number = 0; /// @brief Subtracts uint32_t values taking overflow into account. /// @param minuend Minuend of subtraction @@ -35,12 +73,17 @@ namespace ChimeraTK { /// @brief Reads a decimal formatted value from a file as unsigned 32-bit integer. /// @param fileName File path to read from /// @return Unsigned value - uint32_t readUint32FromFile(std::string fileName); + static uint32_t readUint32FromFile(std::string fileName); /// @brief Reads a hexadecimal formatted value from a file as unsigned 64-bit integer. /// @param fileName File path to read from /// @return Unsigned value - uint64_t readUint64HexFromFile(std::string fileName); + static uint64_t readUint64HexFromFile(std::string fileName); + + /// @brief Get an UIO map handle + /// @param map The map to open + /// @return Reference to the opened map + UioAccess::UioMap& getMap(size_t map); public: explicit UioAccess(const std::string& deviceFilePath); @@ -52,8 +95,11 @@ namespace ChimeraTK { /// @brief Closes UIO device. void close(); + /// @brief Check whether the passed map index is valid. + bool mapIndexValid(uint64_t map); + /// @brief Read data from the specified memory offset address. The address range starts at '0'. - /// @param map Selected UIO memory region. Only region '0' is currently supported. + /// @param map Selected UIO memory region. /// @param address Start address of memory to read from /// @param data Address pointer to which data is to be copied /// @param sizeInBytes Number of bytes to copy diff --git a/backends/uio/src/UioAccess.cc b/backends/uio/src/UioAccess.cc index dbc9fcc9d..4a9b8b503 100644 --- a/backends/uio/src/UioAccess.cc +++ b/backends/uio/src/UioAccess.cc @@ -7,85 +7,209 @@ #include +#include + #include #include +#include #include +#include #include #include +#include namespace ChimeraTK { - UioAccess::UioAccess(const std::string& deviceFilePath) : _deviceFilePath(deviceFilePath.c_str()) {} + UioAccess::UioMap::UioMap() = default; - UioAccess::~UioAccess() { - close(); + /********************************************************************************************************************/ + + UioAccess::UioMap::UioMap(int deviceFileDescriptor, size_t uioMapIdx, const std::string& uioMapPath) + : _deviceLowerBound(readUint64HexFromFile(uioMapPath + "/addr")), + _deviceHigherBound(_deviceLowerBound + readUint64HexFromFile(uioMapPath + "/size")) { + size_t mapSize = _deviceHigherBound - _deviceLowerBound; + + void* mapped = mmap(nullptr, mapSize, PROT_READ | PROT_WRITE, MAP_SHARED, deviceFileDescriptor, + static_cast(uioMapIdx * getpagesize())); + + if(mapped == MAP_FAILED) { + _deviceLowerBound = 0; + _deviceHigherBound = 0; + throw ChimeraTK::runtime_error(std::format("UIO: Cannot allocate memory for UIO map '{}'", uioMapPath)); + } + + _deviceUserBase = mapped; } - void UioAccess::open() { + /********************************************************************************************************************/ + + UioAccess::UioMap::~UioMap() { + if(*this) { + auto mapSize = _deviceHigherBound - _deviceLowerBound; + munmap(_deviceUserBase, mapSize); + } + } + + /********************************************************************************************************************/ + + UioAccess::UioMap::UioMap(UioMap&& other) noexcept + : _deviceLowerBound(std::exchange(other._deviceLowerBound, 0)), + _deviceHigherBound(std::exchange(other._deviceHigherBound, 0)), + _deviceUserBase(std::exchange(other._deviceUserBase, nullptr)) {} + + /********************************************************************************************************************/ + + UioAccess::UioMap& UioAccess::UioMap::operator=(UioMap&& other) noexcept { + if(this != &other) { + if(*this) { + auto mapSize = _deviceHigherBound - _deviceLowerBound; + munmap(_deviceUserBase, mapSize); + } + + this->_deviceLowerBound = std::exchange(other._deviceLowerBound, 0); + this->_deviceHigherBound = std::exchange(other._deviceHigherBound, 0); + this->_deviceUserBase = std::exchange(other._deviceUserBase, nullptr); + } + return *this; + } + + /********************************************************************************************************************/ + + UioAccess::UioMap::operator bool() const noexcept { + return _deviceUserBase != nullptr; + } + + /********************************************************************************************************************/ + + void UioAccess::UioMap::read(uint64_t address, int32_t* data, size_t sizeInBytes) { + volatile int32_t* rptr = static_cast(_deviceUserBase) + + validateAndGetMapOffset(address, sizeInBytes, false) / sizeof(int32_t); + + while(sizeInBytes >= sizeof(int32_t)) { + *(data++) = *(rptr++); + sizeInBytes -= sizeof(int32_t); + } + } + + /********************************************************************************************************************/ + + void UioAccess::UioMap::write(uint64_t address, int32_t const* data, size_t sizeInBytes) { + volatile int32_t* __restrict__ wptr = static_cast(_deviceUserBase) + + validateAndGetMapOffset(address, sizeInBytes, true) / sizeof(int32_t); + + while(sizeInBytes >= sizeof(int32_t)) { + *(wptr++) = *(data++); + sizeInBytes -= sizeof(int32_t); + } + } + + /********************************************************************************************************************/ + + size_t UioAccess::UioMap::validateAndGetMapOffset(uint64_t address, size_t sizeInBytes, bool isWrite) { + if(!*this) [[unlikely]] { + std::string requestType = isWrite ? "Write" : "Read"; + throw ChimeraTK::logic_error(std::format("UIO: {} request on unmapped memory region", requestType)); + } + + // Register addresses are absolute bus addresses; convert to map offset the same way as the single-map backend. + size_t offset = address % _deviceLowerBound; + + if(offset + sizeInBytes > _deviceHigherBound - _deviceLowerBound) [[unlikely]] { + std::string requestType = isWrite ? "Write" : "Read"; + throw ChimeraTK::logic_error( + std::format("UIO: {} request exceeds device memory region of map (offset = {}, size = {})", requestType, + offset, _deviceHigherBound - _deviceLowerBound)); + } + + return offset; + } + + /********************************************************************************************************************/ + + UioAccess::UioAccess(const std::string& deviceFilePath) : _deviceFilePath(deviceFilePath.c_str()) { if(boost::filesystem::is_symlink(_deviceFilePath)) { _deviceFilePath = boost::filesystem::canonical(_deviceFilePath); } - std::string fileName = _deviceFilePath.filename().string(); - _deviceKernelBase = (void*)readUint64HexFromFile("/sys/class/uio/" + fileName + "/maps/map0/addr"); - _deviceMemSize = readUint64HexFromFile("/sys/class/uio/" + fileName + "/maps/map0/size"); - _lastInterruptCount = readUint32FromFile("/sys/class/uio/" + fileName + "/event"); + _filename = _deviceFilePath.filename().string(); + + for(_maps_number = 0; _maps_number < MAX_UIO_MAPS; _maps_number++) { + std::string uioMapPath = std::format("/sys/class/uio/{}/maps/map{}", _filename, _maps_number); + if(!boost::filesystem::is_directory(uioMapPath)) break; + } + } + + /********************************************************************************************************************/ + + UioAccess::~UioAccess() { + close(); + } + + /********************************************************************************************************************/ + + void UioAccess::open() { + _lastInterruptCount = readUint32FromFile(std::format("/sys/class/uio/{}/event", _filename)); // Open UIO device file here, so that interrupt thread can run before calling open() _deviceFileDescriptor = ::open(_deviceFilePath.c_str(), O_RDWR); if(_deviceFileDescriptor < 0) { - throw ChimeraTK::runtime_error("UIO: Failed to open device file '" + getDeviceFilePath() + "'"); + throw ChimeraTK::runtime_error(std::format("UIO: Failed to open device file '{}'", getDeviceFilePath())); } - UioMMap(); + _opened = true; } + /********************************************************************************************************************/ + void UioAccess::close() { if(_opened) { - UioUnmap(); + for(auto& map : _maps) map = UioMap{}; ::close(_deviceFileDescriptor); _opened = false; } } - void UioAccess::read(uint64_t map, uint64_t address, int32_t* __restrict__ data, size_t sizeInBytes) { - if(map > 0) { - throw ChimeraTK::logic_error("UIO: Multiple memory regions are not supported"); - } + /********************************************************************************************************************/ - // This is a temporary work around, because register nodes of current map use absolute bus addresses. - address = address % reinterpret_cast(_deviceKernelBase); + bool UioAccess::mapIndexValid(uint64_t map) { + return map < _maps_number; + } - if(address + sizeInBytes > _deviceMemSize) { - throw ChimeraTK::logic_error("UIO: Read request exceeds device memory region"); - } + /********************************************************************************************************************/ - volatile int32_t* rptr = static_cast(_deviceUserBase) + address / sizeof(int32_t); - while(sizeInBytes >= sizeof(int32_t)) { - *(data++) = *(rptr++); - sizeInBytes -= sizeof(int32_t); + void UioAccess::read(uint64_t map, uint64_t address, int32_t* __restrict__ data, size_t sizeInBytes) { + if(!mapIndexValid(map)) [[unlikely]] { + throw ChimeraTK::logic_error( + std::format("UIO: Attempt to access map{} outside the range (registered maps = {})", map, _maps_number)); } + + getMap(map).read(address, data, sizeInBytes); } + /********************************************************************************************************************/ + void UioAccess::write(uint64_t map, uint64_t address, int32_t const* data, size_t sizeInBytes) { - if(map > 0) { - throw ChimeraTK::logic_error("UIO: Multiple memory regions are not supported"); + if(!mapIndexValid(map)) [[unlikely]] { + throw ChimeraTK::logic_error( + std::format("UIO: Attempt to access map{} outside the range (registered maps = {})", map, _maps_number)); } - // This is a temporary work around, because register nodes of current map use absolute bus addresses. - address = address % reinterpret_cast(_deviceKernelBase); + getMap(map).write(address, data, sizeInBytes); + } - if(address + sizeInBytes > _deviceMemSize) { - throw ChimeraTK::logic_error("UIO: Write request exceeds device memory region"); - } + /********************************************************************************************************************/ - volatile int32_t* __restrict__ wptr = static_cast(_deviceUserBase) + address / sizeof(int32_t); - while(sizeInBytes >= sizeof(int32_t)) { - *(wptr++) = *(data++); - sizeInBytes -= sizeof(int32_t); + UioAccess::UioMap& UioAccess::getMap(size_t map) { + if(!_maps[map]) [[unlikely]] { + std::string uioMapPath = std::format("/sys/class/uio/{}/maps/map{}", _filename, map); + _maps[map] = UioAccess::UioMap(_deviceFileDescriptor, map, uioMapPath); } + + return _maps[map]; } + /********************************************************************************************************************/ + uint32_t UioAccess::waitForInterrupt(int timeoutMs) { // Represents the total interrupt count since system uptime. uint32_t totalInterruptCount = 0; @@ -120,6 +244,8 @@ namespace ChimeraTK { return occurredInterruptCount; } + /********************************************************************************************************************/ + void UioAccess::clearInterrupts() { uint32_t unmask = 1; ssize_t ret = ::write(_deviceFileDescriptor, &unmask, sizeof(unmask)); @@ -129,22 +255,13 @@ namespace ChimeraTK { } } + /********************************************************************************************************************/ + std::string UioAccess::getDeviceFilePath() { return _deviceFilePath.string(); } - void UioAccess::UioMMap() { - _deviceUserBase = mmap(NULL, _deviceMemSize, PROT_READ | PROT_WRITE, MAP_SHARED, _deviceFileDescriptor, 0); - if(_deviceUserBase == MAP_FAILED) { - ::close(_deviceFileDescriptor); - throw ChimeraTK::runtime_error("UIO: Cannot allocate memory for UIO device '" + getDeviceFilePath() + "'"); - } - return; - } - - void UioAccess::UioUnmap() { - munmap(_deviceUserBase, _deviceMemSize); - } + /********************************************************************************************************************/ uint32_t UioAccess::subtractUint32OverflowSafe(uint32_t minuend, uint32_t subtrahend) { if(subtrahend > minuend) { @@ -156,6 +273,8 @@ namespace ChimeraTK { } } + /********************************************************************************************************************/ + uint32_t UioAccess::readUint32FromFile(std::string fileName) { uint64_t value = 0; std::ifstream inputFile(fileName); @@ -167,6 +286,8 @@ namespace ChimeraTK { return (uint32_t)value; } + /********************************************************************************************************************/ + uint64_t UioAccess::readUint64HexFromFile(std::string fileName) { uint64_t value = 0; std::ifstream inputFile(fileName); @@ -177,4 +298,5 @@ namespace ChimeraTK { } return value; } + } // namespace ChimeraTK diff --git a/backends/uio/src/UioBackend.cc b/backends/uio/src/UioBackend.cc index b6ad83032..842a02bc3 100644 --- a/backends/uio/src/UioBackend.cc +++ b/backends/uio/src/UioBackend.cc @@ -12,10 +12,14 @@ namespace ChimeraTK { _uioAccess = std::make_shared("/dev/" + deviceName); } + /********************************************************************************************************************/ + UioBackend::~UioBackend() { UioBackend::closeImpl(); } + /********************************************************************************************************************/ + boost::shared_ptr UioBackend::createInstance( // FIXME #11279 Implement API breaking changes from linter warnings // NOLINTNEXTLINE(performance-unnecessary-value-param) @@ -31,6 +35,8 @@ namespace ChimeraTK { return boost::make_shared(address, parameters["map"], parameters["DataConsistencyKeys"]); } + /********************************************************************************************************************/ + void UioBackend::open() { if(_opened) { if(isFunctional()) { @@ -43,6 +49,8 @@ namespace ChimeraTK { setOpenedAndClearException(); } + /********************************************************************************************************************/ + void UioBackend::closeImpl() { if(_opened) { if(_interruptWaitingThread.joinable()) { @@ -56,10 +64,14 @@ namespace ChimeraTK { _opened = false; } + /********************************************************************************************************************/ + bool UioBackend::barIndexValid(uint64_t bar) { - return (bar == 0); + return _uioAccess->mapIndexValid(bar); } + /********************************************************************************************************************/ + void UioBackend::read(uint64_t bar, uint64_t address, int32_t* data, size_t sizeInBytes) { assert(_opened); checkActiveException(); @@ -67,6 +79,8 @@ namespace ChimeraTK { _uioAccess->read(bar, address, data, sizeInBytes); } + /********************************************************************************************************************/ + void UioBackend::write(uint64_t bar, uint64_t address, int32_t const* data, size_t sizeInBytes) { assert(_opened); checkActiveException(); @@ -74,6 +88,8 @@ namespace ChimeraTK { _uioAccess->write(bar, address, data, sizeInBytes); } + /********************************************************************************************************************/ + std::future UioBackend::activateSubscription( uint32_t interruptNumber, boost::shared_ptr> asyncDomain) { std::promise subscriptionDonePromise; @@ -95,6 +111,8 @@ namespace ChimeraTK { return subscriptionDoneFuture; } + /********************************************************************************************************************/ + std::string UioBackend::readDeviceInfo() { std::string result = std::string("UIO backend: Device path = " + _uioAccess->getDeviceFilePath()); if(!isOpen()) { @@ -104,6 +122,8 @@ namespace ChimeraTK { return result; } + /********************************************************************************************************************/ + void UioBackend::waitForInterruptLoop(std::promise subscriptionDonePromise) { try { // also the scope for the promiseFulfiller diff --git a/tests/executables_src/testUioBackendUnified.cpp b/tests/executables_src/testUioBackendUnified.cpp index a4b3c34f6..2bf76ee0c 100644 --- a/tests/executables_src/testUioBackendUnified.cpp +++ b/tests/executables_src/testUioBackendUnified.cpp @@ -7,6 +7,7 @@ #include using namespace boost::unit_test_framework; +#include "Device.h" #include "MapFileParser.h" #include "UnifiedBackendTest.h" @@ -19,6 +20,7 @@ using namespace boost::unit_test_framework; #include #include +#include using namespace ChimeraTK; @@ -43,12 +45,10 @@ struct TestLocker { } } - ~TestLocker() { - // FIXME: It would be nice to unlink the file here, so it does not unnecessarily remain in the file system. - // Unfortunately, this somehow spoils the locking. Completely unclear why. - - // unlink(lockfile.c_str()); - } + // FIXME: It would be nice to unlink the file here, so it does not unnecessarily remain in the file system. + // Unfortunately, this somehow spoils the locking. Completely unclear why. + // unlink(lockfile.c_str()); + ~TestLocker() = default; }; static TestLocker testLocker; @@ -67,8 +67,6 @@ class RawUioAccess { explicit RawUioAccess(const std::string& filePath, const std::string& mapFile); ~RawUioAccess(); void sendInterrupt() const; - [[nodiscard]] size_t getMemorySize() const; - void* data(); template T read(const std::string& name); template @@ -78,8 +76,8 @@ class RawUioAccess { int _uioFileDescriptor; int _uioProcFd; std::filesystem::path _deviceFilePath; - size_t _deviceMemSize = 0; - void* _memoryPointer{nullptr}; + std::vector _mapSizes; + std::vector _mapPointers; NumericAddressedRegisterCatalogue _catalogue; static uint64_t readUint64HexFromFile(const std::string& filePath); @@ -103,17 +101,23 @@ RawUioAccess::RawUioAccess(const std::string& filePath, const std::string& mapFi throw std::runtime_error("failed to open UIO device '" + filePath + "'"); } - // Determine size of UIO memory region std::string fileName = _deviceFilePath.filename().string(); - _deviceMemSize = readUint64HexFromFile("/sys/class/uio/" + fileName + "/maps/map0/size"); - - _memoryPointer = mmap(nullptr, _deviceMemSize, PROT_READ | PROT_WRITE, MAP_SHARED, _uioFileDescriptor, 0); - - if(_memoryPointer == MAP_FAILED) { - throw std::runtime_error("UioMmap construction failed"); + for(size_t mapIdx = 0;; ++mapIdx) { + std::string mapPath = "/sys/class/uio/" + fileName + "/maps/map" + std::to_string(mapIdx); + if(!std::filesystem::is_directory(mapPath)) { + break; + } + size_t mapSize = readUint64HexFromFile(mapPath + "/size"); + void* ptr = mmap(nullptr, mapSize, PROT_READ | PROT_WRITE, MAP_SHARED, _uioFileDescriptor, + static_cast(mapIdx * getpagesize())); + if(ptr == MAP_FAILED) { + throw std::runtime_error("UioMmap construction failed for map" + std::to_string(mapIdx)); + } + _mapSizes.push_back(mapSize); + _mapPointers.push_back(ptr); } - MapFileParser p; - auto [cat, metaCat] = p.parse(mapFile); + + auto [cat, metaCat] = MapFileParser::parse(mapFile); _catalogue = std::move(cat); } @@ -122,7 +126,9 @@ RawUioAccess::RawUioAccess(const std::string& filePath, const std::string& mapFi /**********************************************************************************************************************/ RawUioAccess::~RawUioAccess() { - munmap(_memoryPointer, _deviceMemSize); + for(size_t i = 0; i < _mapPointers.size(); ++i) { + munmap(_mapPointers[i], _mapSizes[i]); + } close(_uioFileDescriptor); close(_uioProcFd); } @@ -136,22 +142,11 @@ void RawUioAccess::sendInterrupt() const { /**********************************************************************************************************************/ -size_t RawUioAccess::getMemorySize() const { - return _deviceMemSize; -} - -/**********************************************************************************************************************/ - -void* RawUioAccess::data() { - return _memoryPointer; -} - -/**********************************************************************************************************************/ - template T RawUioAccess::read(const std::string& name) { auto r = _catalogue.getBackendRegister(name); - return *reinterpret_cast(reinterpret_cast(data()) + r.address); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + return *reinterpret_cast(reinterpret_cast(_mapPointers[r.bar]) + r.address); } /**********************************************************************************************************************/ @@ -159,7 +154,8 @@ T RawUioAccess::read(const std::string& name) { template void RawUioAccess::write(const std::string& name, T value) { auto r = _catalogue.getBackendRegister(name); - *reinterpret_cast(reinterpret_cast(data()) + r.address) = value; + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + *reinterpret_cast(reinterpret_cast(_mapPointers[r.bar]) + r.address) = value; sendInterrupt(); } @@ -243,7 +239,15 @@ struct ScalarDescriptor { /**********************************************************************************************************************/ -struct Scalar32 : ScalarDescriptor { +struct Scalar32Map0 : ScalarDescriptor { + static std::string path() { return "BSP.SCRATCH"; } + static bool isReadable() { return true; } + static bool isWriteable() { return true; } +}; + +/**********************************************************************************************************************/ + +struct Scalar32Map1 : ScalarDescriptor { static std::string path() { return "TIMING.WORD_ID"; } static bool isReadable() { return true; } static bool isWriteable() { return false; } @@ -251,7 +255,7 @@ struct Scalar32 : ScalarDescriptor { /**********************************************************************************************************************/ -struct Scalar32Async : ScalarDescriptor { +struct Scalar32Map1Async : ScalarDescriptor { static std::string path() { return "MOTOR_CONTROL.MOTOR_POSITION"; } static bool isReadable() { return true; } static bool isWriteable() { return false; } @@ -262,8 +266,31 @@ struct Scalar32Async : ScalarDescriptor { /**********************************************************************************************************************/ +struct Scalar32Map2 : ScalarDescriptor { + static std::string path() { return "FCM.WORD_REV_SWITCH"; } + static bool isReadable() { return true; } + static bool isWriteable() { return true; } +}; + +/**********************************************************************************************************************/ + +BOOST_AUTO_TEST_CASE(testBrokenMap) { + Device dev; + dev.open(cdd); + BOOST_CHECK_THROW(dev.getScalarRegisterAccessor("/BROKEN/REG"), + ChimeraTK::logic_error); // NOLINT(clang-diagnostic-unused-result) + dev.close(); +} + +/**********************************************************************************************************************/ + BOOST_AUTO_TEST_CASE(testUnified) { - UnifiedBackendTest<>().addRegister().addRegister().runTests(cdd); + UnifiedBackendTest<>() + .addRegister() + .addRegister() + .addRegister() + .addRegister() + .runTests(cdd); } /**********************************************************************************************************************/ diff --git a/tests/uioBackendTest.mapp b/tests/uioBackendTest.mapp index fa109a583..e553ee0f2 100644 --- a/tests/uioBackendTest.mapp +++ b/tests/uioBackendTest.mapp @@ -1,102 +1,103 @@ -FCM.WORD_SPI_DIVIDER 1 73728 4 0 16 0 0 RW -FCM.WORD_BYTES_TO_WRITE 1 73740 4 0 16 0 0 RW -FCM.WORD_BYTES_TO_READ 1 73744 4 0 16 0 0 RW -FCM.WORD_CONTROL 1 73748 4 0 8 0 0 RW -FCM.WORD_TCK 1 73752 4 0 1 0 0 RW -FCM.WORD_TMS 1 73756 4 0 1 0 0 RW -FCM.WORD_TDI 1 73760 4 0 1 0 0 RW -FCM.WORD_TDO 1 73764 4 0 1 0 0 RO -FCM.WORD_MAGIC 1 73784 4 0 32 0 0 RO -FCM.WORD_REV_SWITCH 1 73788 4 0 32 0 0 RW -FCM.WORD_REV_SEL 1 73792 4 0 2 0 0 RW -FCM.WORD_CRC_ERROR 1 73796 4 0 1 0 0 RO -FCM.WORD_CRC_ERROR_CNT 1 73800 4 0 32 0 0 RO -FCM.WORD_ECC_ERROR_CNT 1 73804 4 0 32 0 0 RO -FCM.WORD_ECC_SYNDROME 1 73824 4 0 13 0 0 RO -BSP.PRJ_ID 1 0 4 0 32 0 0 RO -BSP.PRJ_VERSION 1 4 4 0 32 0 0 RO -BSP.PRJ_SHASUM 1 8 4 0 32 0 0 RO -BSP.PRJ_TIMESTAMP 1 12 4 0 32 0 0 RO -BSP.ID 1 16 4 0 32 0 0 RO -BSP.VERSION 1 20 4 0 32 0 0 RO -BSP.SCRATCH 1 24 4 0 32 0 0 RW -BSP.MIG_INIT_DONE 1 28 4 0 1 0 0 RO -TIMING.WORD_ID 1 2684420608 4 0 32 0 0 RO -TIMING.WORD_VERSION 1 2684420612 4 0 32 0 0 RO -TIMING.WORD_ENABLE 1 2684420616 4 0 8 0 0 RW -TIMING.WORD_SOURCE_SEL 8 2684420640 32 0 8 0 0 RW -TIMING.WORD_SYNC_SEL 8 2684420672 32 0 8 0 0 RW -TIMING.WORD_DIVIDER_VALUE 8 2684420704 32 0 32 0 0 RW -TIMING.WORD_TRIGGER_CNT 8 2684420736 32 0 32 0 0 RO -TIMING.WORD_EXT_TRIGGER_CNT 8 2684420768 32 0 32 0 0 RO -TIMING.WORD_DELAY_ENABLE 8 2684420800 32 0 1 0 0 RW -TIMING.WORD_DELAY_VALUE 8 2684420832 32 0 32 0 0 RW -TIMING.WORD_MANUAL_TRG 8 2684420864 32 0 1 0 0 RW -DAQ.WORD_ID 1 2684452864 4 0 32 0 0 RO -DAQ.WORD_VERSION 1 2684452868 4 0 32 0 0 RO -DAQ.WORD_ENABLE 1 2684452872 4 0 3 0 0 RW -DAQ.WORD_MUX_SEL 3 2684452880 12 0 8 0 0 RW -DAQ.WORD_STROBE_DIV 3 2684452892 12 0 32 0 0 RW -DAQ.WORD_STROBE_COUNT 3 2684452904 12 0 32 0 0 RO -DAQ.WORD_SAMPLES 3 2684452916 12 0 32 0 0 RW -DAQ.WORD_DUB_BUF_ENA 3 2684452928 12 0 1 0 0 RW -DAQ.WORD_DUB_BUF_CURR 3 2684452940 12 0 1 0 0 RO -DAQ.WORD_DUB_BUF_PNUM 3 2684452952 12 0 32 0 0 RO -DAQ.WORD_FIFO_STATUS 3 2684452964 12 0 32 0 0 RO -DAQ.WORD_SENT_BURST_CNT 3 2684452976 12 0 32 0 0 RO -DAQ.WORD_TRG_DELAY_VAL 3 2684452988 12 0 32 0 0 RW -DAQ.WORD_TRG_DELAY_ENA 3 2684453000 12 0 1 0 0 RW -DAQ.WORD_TRG_CNT_BUF0 3 2684453012 12 0 16 0 0 RO -DAQ.WORD_TRG_CNT_BUF1 3 2684453024 12 0 16 0 0 RO -DAQ.WORD_TIMESTAMP_RST 3 2684453036 12 0 1 0 0 RW -MOTOR_CONTROL.IRQ 0 0 0 0 0 0 0 INTERRUPT0 -MOTOR_CONTROL.ID 1 2684473344 4 0 32 0 0 RO -MOTOR_CONTROL.VERSION 1 2684473348 4 0 32 0 0 RO -MOTOR_CONTROL.MOTOR_START 1 2684473352 4 0 1 0 0 RW -MOTOR_CONTROL.MOTOR_DESTINATION 1 2684473356 4 0 32 0 0 RW -MOTOR_CONTROL.MOTOR_MAX_ACC 1 2684473360 4 0 32 0 0 RW -MOTOR_CONTROL.MOTOR_MAX_VEL 1 2684473364 4 0 32 0 0 RW -MOTOR_CONTROL.MOTOR_BASE_VEL 1 2684473368 4 0 32 0 0 RW -MOTOR_CONTROL.MOTOR_PULSE_WIDTH 1 2684473372 4 0 32 0 0 RW -MOTOR_CONTROL.MOTOR_POSITION 1 2684473376 4 0 32 0 0 INTERRUPT0 -MOTOR_CONTROL.MOTOR_POSITION_RESET 1 2684473380 4 0 1 0 0 RW -UNIO.WORD_ID 1 2684473472 4 0 32 0 0 RO -UNIO.WORD_VERSION 1 2684473476 4 0 32 0 0 RO -UNIO.WORD_USER 1 2684473480 4 0 32 0 0 RW -UNIO.WORD_LED 1 2684473492 4 0 1 0 0 RW -UNIO.WORD_DAC0_DATA 1 2684473496 4 0 12 0 0 RW -UNIO.WORD_DAC1_DATA 1 2684473500 4 0 12 0 0 RW -UNIO.WORD_ADC0_DATA 1 2684473504 4 0 12 0 0 RO -UNIO.WORD_ADC1_DATA 1 2684473508 4 0 12 0 0 RO -UNIO.WORD_CPLD_RESET 1 2684473512 4 0 1 0 0 RW -UNIO.WORD_IO_INPUT 6 2684473516 24 0 8 0 0 RO -UNIO.WORD_IO_OUTPUT 6 2684473540 24 0 8 0 0 RW -UNIO.WORD_IO_DIR 1 2684473564 4 0 6 0 0 RW -UNIO.WORD_IO_VOL 1 2684473568 4 0 6 0 0 RW -UNIO.WORD_IO_ENABLE 1 2684473572 4 0 1 0 0 RW -APP.ID 1 2684420096 4 0 32 0 0 RO -APP.VERSION 1 2684420100 4 0 32 0 0 RO -APP.STATUS 1 2684420104 4 0 32 0 0 RO -APP.MLVDS_I 1 2684420108 4 0 8 0 0 RO -APP.MLVDS_O 1 2684420112 4 0 8 0 0 RW -APP.MLVDS_OE 1 2684420116 4 0 8 0 0 RW -FCM.AREA_WRITE 1024 65536 4096 0 8 0 0 RW +FCM.WORD_SPI_DIVIDER 1 73728 4 2 16 0 0 RW +FCM.WORD_BYTES_TO_WRITE 1 73740 4 2 16 0 0 RW +FCM.WORD_BYTES_TO_READ 1 73744 4 2 16 0 0 RW +FCM.WORD_CONTROL 1 73748 4 2 8 0 0 RW +FCM.WORD_TCK 1 73752 4 2 1 0 0 RW +FCM.WORD_TMS 1 73756 4 2 1 0 0 RW +FCM.WORD_TDI 1 73760 4 2 1 0 0 RW +FCM.WORD_TDO 1 73764 4 2 1 0 0 RO +FCM.WORD_MAGIC 1 73784 4 2 32 0 0 RO +FCM.WORD_REV_SWITCH 1 73788 4 2 32 0 0 RW +FCM.WORD_REV_SEL 1 73792 4 2 2 0 0 RW +FCM.WORD_CRC_ERROR 1 73796 4 2 1 0 0 RO +FCM.WORD_CRC_ERROR_CNT 1 73800 4 2 32 0 0 RO +FCM.WORD_ECC_ERROR_CNT 1 73804 4 2 32 0 0 RO +FCM.WORD_ECC_SYNDROME 1 73824 4 2 13 0 0 RO +BSP.PRJ_ID 1 0 4 0 32 0 0 RO +BSP.PRJ_VERSION 1 4 4 0 32 0 0 RO +BSP.PRJ_SHASUM 1 8 4 0 32 0 0 RO +BSP.PRJ_TIMESTAMP 1 12 4 0 32 0 0 RO +BSP.ID 1 16 4 0 32 0 0 RO +BSP.VERSION 1 20 4 0 32 0 0 RO +BSP.SCRATCH 1 24 4 0 32 0 0 RW +BSP.MIG_INIT_DONE 1 28 4 0 1 0 0 RO +TIMING.WORD_ID 1 2684420608 4 1 32 0 0 RO +TIMING.WORD_VERSION 1 2684420612 4 1 32 0 0 RO +TIMING.WORD_ENABLE 1 2684420616 4 1 8 0 0 RW +TIMING.WORD_SOURCE_SEL 8 2684420640 32 1 8 0 0 RW +TIMING.WORD_SYNC_SEL 8 2684420672 32 1 8 0 0 RW +TIMING.WORD_DIVIDER_VALUE 8 2684420704 32 1 32 0 0 RW +TIMING.WORD_TRIGGER_CNT 8 2684420736 32 1 32 0 0 RO +TIMING.WORD_EXT_TRIGGER_CNT 8 2684420768 32 1 32 0 0 RO +TIMING.WORD_DELAY_ENABLE 8 2684420800 32 1 1 0 0 RW +TIMING.WORD_DELAY_VALUE 8 2684420832 32 1 32 0 0 RW +TIMING.WORD_MANUAL_TRG 8 2684420864 32 1 1 0 0 RW +DAQ.WORD_ID 1 2684452864 4 1 32 0 0 RO +DAQ.WORD_VERSION 1 2684452868 4 1 32 0 0 RO +DAQ.WORD_ENABLE 1 2684452872 4 1 3 0 0 RW +DAQ.WORD_MUX_SEL 3 2684452880 12 1 8 0 0 RW +DAQ.WORD_STROBE_DIV 3 2684452892 12 1 32 0 0 RW +DAQ.WORD_STROBE_COUNT 3 2684452904 12 1 32 0 0 RO +DAQ.WORD_SAMPLES 3 2684452916 12 1 32 0 0 RW +DAQ.WORD_DUB_BUF_ENA 3 2684452928 12 1 1 0 0 RW +DAQ.WORD_DUB_BUF_CURR 3 2684452940 12 1 1 0 0 RO +DAQ.WORD_DUB_BUF_PNUM 3 2684452952 12 1 32 0 0 RO +DAQ.WORD_FIFO_STATUS 3 2684452964 12 1 32 0 0 RO +DAQ.WORD_SENT_BURST_CNT 3 2684452976 12 1 32 0 0 RO +DAQ.WORD_TRG_DELAY_VAL 3 2684452988 12 1 32 0 0 RW +DAQ.WORD_TRG_DELAY_ENA 3 2684453000 12 1 1 0 0 RW +DAQ.WORD_TRG_CNT_BUF0 3 2684453012 12 1 16 0 0 RO +DAQ.WORD_TRG_CNT_BUF1 3 2684453024 12 1 16 0 0 RO +DAQ.WORD_TIMESTAMP_RST 3 2684453036 12 1 1 0 0 RW +MOTOR_CONTROL.IRQ 0 0 0 0 0 0 0 INTERRUPT0 +MOTOR_CONTROL.ID 1 2684473344 4 1 32 0 0 RO +MOTOR_CONTROL.VERSION 1 2684473348 4 1 32 0 0 RO +MOTOR_CONTROL.MOTOR_START 1 2684473352 4 1 1 0 0 RW +MOTOR_CONTROL.MOTOR_DESTINATION 1 2684473356 4 1 32 0 0 RW +MOTOR_CONTROL.MOTOR_MAX_ACC 1 2684473360 4 1 32 0 0 RW +MOTOR_CONTROL.MOTOR_MAX_VEL 1 2684473364 4 1 32 0 0 RW +MOTOR_CONTROL.MOTOR_BASE_VEL 1 2684473368 4 1 32 0 0 RW +MOTOR_CONTROL.MOTOR_PULSE_WIDTH 1 2684473372 4 1 32 0 0 RW +MOTOR_CONTROL.MOTOR_POSITION 1 2684473376 4 1 32 0 1 INTERRUPT0 +MOTOR_CONTROL.MOTOR_POSITION_RESET 1 2684473380 4 1 1 0 0 RW +UNIO.WORD_ID 1 2684473472 4 1 32 0 0 RO +UNIO.WORD_VERSION 1 2684473476 4 1 32 0 0 RO +UNIO.WORD_USER 1 2684473480 4 1 32 0 0 RW +UNIO.WORD_LED 1 2684473492 4 1 1 0 0 RW +UNIO.WORD_DAC0_DATA 1 2684473496 4 1 12 0 0 RW +UNIO.WORD_DAC1_DATA 1 2684473500 4 1 12 0 0 RW +UNIO.WORD_ADC0_DATA 1 2684473504 4 1 12 0 0 RO +UNIO.WORD_ADC1_DATA 1 2684473508 4 1 12 0 0 RO +UNIO.WORD_CPLD_RESET 1 2684473512 4 1 1 0 0 RW +UNIO.WORD_IO_INPUT 6 2684473516 24 1 8 0 0 RO +UNIO.WORD_IO_OUTPUT 6 2684473540 24 1 8 0 0 RW +UNIO.WORD_IO_DIR 1 2684473564 4 1 6 0 0 RW +UNIO.WORD_IO_VOL 1 2684473568 4 1 6 0 0 RW +UNIO.WORD_IO_ENABLE 1 2684473572 4 1 1 0 0 RW +APP.ID 1 2684420096 4 1 32 0 0 RO +APP.VERSION 1 2684420100 4 1 32 0 0 RO +APP.STATUS 1 2684420104 4 1 32 0 0 RO +APP.MLVDS_I 1 2684420108 4 1 8 0 0 RO +APP.MLVDS_O 1 2684420112 4 1 8 0 0 RW +APP.MLVDS_OE 1 2684420116 4 1 8 0 0 RW +FCM.AREA_WRITE 1024 65536 4096 2 8 0 0 RW -FCM.AREA_READ 1024 69632 4096 0 8 0 0 RW +FCM.AREA_READ 1024 69632 4096 2 8 0 0 RW -DAQ.AREA_DAQ_TIMES_0 1024 2684456960 4096 0 32 0 0 RO +DAQ.AREA_DAQ_TIMES_0 1024 2684456960 4096 1 32 0 0 RO -DAQ.AREA_DAQ_TIMES_1 1024 2684461056 4096 0 32 0 0 RO +DAQ.AREA_DAQ_TIMES_1 1024 2684461056 4096 1 32 0 0 RO -DAQ.AREA_DAQ_TIMES_2 1024 2684469248 4096 0 32 0 0 RO +DAQ.AREA_DAQ_TIMES_2 1024 2684469248 4096 1 32 0 0 RO -BSP.FCM 2073 65536 8292 0 32 0 0 RW -ch0_BSP.BSP 18457 0 73828 0 32 0 0 RW -APP.TIMING 72 2684420608 288 0 32 0 0 RW -APP.DAQ 5120 2684452864 20480 0 32 0 0 RW -APP.MOTOR_CONTROL 10 2684473344 40 0 32 0 0 RW -APP.UNIO 26 2684473472 104 0 32 0 0 RW -ch0_APP.APP 13370 2684420096 53480 0 32 0 0 RW -ch0_top.ch0_BSP 18457 0 73828 0 32 0 0 RW -ch0_top.ch0_APP 13370 2684420096 53480 0 32 0 0 RW +BSP.FCM 2073 65536 8292 0 32 0 0 RW +ch0_BSP.BSP 18457 0 73828 0 32 0 0 RW +APP.TIMING 72 2684420608 288 1 32 0 0 RW +APP.DAQ 5120 2684452864 20480 1 32 0 0 RW +APP.MOTOR_CONTROL 10 2684473344 40 1 32 0 0 RW +APP.UNIO 26 2684473472 104 1 32 0 0 RW +ch0_APP.APP 13370 2684420096 53480 1 32 0 0 RW +ch0_top.ch0_BSP 18457 0 73828 0 32 0 0 RW +ch0_top.ch0_APP 13370 2684420096 53480 1 32 0 0 RW +BROKEN.REG 1 0 4 3 32 0 0 RW