/* GPU2RTDS IP core * * Author: Daniel Krebs * SPDX-FileCopyrightText: 2017 Daniel Krebs * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include using namespace villas::fpga::ip; bool Rtds2Gpu::init() { Hls::init(); xInstance.IsReady = XIL_COMPONENT_IS_READY; xInstance.Ctrl_BaseAddress = getBaseAddr(registerMemory); status.value = 0; started = false; // maxFrameSize = getMaxFrameSize(); maxFrameSize = 16; logger->info("Max. frame size supported: {}", maxFrameSize); return true; } void Rtds2Gpu::dump(spdlog::level::level_enum logLevel) { const auto baseaddr = XRtds2gpu_Get_baseaddr(&xInstance); const auto data_offset = XRtds2gpu_Get_data_offset(&xInstance); const auto doorbell_offset = XRtds2gpu_Get_doorbell_offset(&xInstance); const auto frame_size = XRtds2gpu_Get_frame_size(&xInstance); logger->log(logLevel, "Rtds2Gpu registers (IP base {:#x}):", xInstance.Ctrl_BaseAddress); logger->log(logLevel, " Base address (bytes): {:#x}", baseaddr); logger->log(logLevel, " Doorbell offset (bytes): {:#x}", doorbell_offset); logger->log(logLevel, " Data offset (bytes): {:#x}", data_offset); logger->log(logLevel, " Frame size (words): {:#x}", frame_size); logger->log(logLevel, " Status: {:#x}", status.value); logger->log(logLevel, " Running: {}", (status.is_running ? "yes" : "no")); logger->log(logLevel, " Frame too short: {}", (status.frame_too_short ? "yes" : "no")); logger->log(logLevel, " Frame too long: {}", (status.frame_too_long ? "yes" : "no")); logger->log(logLevel, " Frame size invalid: {}", (status.invalid_frame_size ? "yes" : "no")); logger->log(logLevel, " Last count: {}", (int)status.last_count); logger->log(logLevel, " Last seq. number: {}", (int)status.last_seq_nr); logger->log(logLevel, " Max. frame size: {}", (int)status.max_frame_size); } bool Rtds2Gpu::startOnce(const MemoryBlock &mem, size_t frameSize, size_t dataOffset, size_t doorbellOffset) { auto &mm = MemoryManager::get(); if (frameSize > maxFrameSize) { logger->error("Requested frame size of {} exceeds max. frame size of {}", frameSize, maxFrameSize); return false; } auto translationFromIp = mm.getTranslation( getMasterAddrSpaceByInterface(axiInterface), mem.getAddrSpaceId()); // Set address of memory block in HLS IP XRtds2gpu_Set_baseaddr(&xInstance, translationFromIp.getLocalAddr(0)); XRtds2gpu_Set_doorbell_offset(&xInstance, doorbellOffset); XRtds2gpu_Set_data_offset(&xInstance, dataOffset); XRtds2gpu_Set_frame_size(&xInstance, frameSize); // Prepare memory with all zeroes auto translationFromProcess = mm.getTranslationFromProcess(mem.getAddrSpaceId()); auto memory = reinterpret_cast(translationFromProcess.getLocalAddr(0)); memset(memory, 0, mem.getSize()); // Start IP return start(); } bool Rtds2Gpu::updateStatus() { if (not XRtds2gpu_Get_status_vld(&xInstance)) return false; status.value = XRtds2gpu_Get_status(&xInstance); return true; } size_t Rtds2Gpu::getMaxFrameSize() { XRtds2gpu_Set_frame_size(&xInstance, 0); start(); while (not isFinished()) ; updateStatus(); return status.max_frame_size; } void Rtds2Gpu::dumpDoorbell(uint32_t doorbellRegister) const { auto &doorbell = reinterpret_cast(doorbellRegister); logger->info("Doorbell register: {:#08x}", doorbell.value); logger->info(" Valid: {}", doorbell.is_valid ? "yes" : "no"); logger->info(" Count: {}", (int)doorbell.count); logger->info(" Seq. number: {}", (int)doorbell.seq_nr); } static char n[] = "Rtds2Gpu"; static char d[] = "HLS RTDS2GPU IP"; static char v[] = "acs.eonerc.rwth-aachen.de:hls:rtds2gpu:"; static NodePlugin f;