rtds2gpu.cpp 7.44 KB
Newer Older
Daniel Krebs's avatar
Daniel Krebs committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/** FIFO unit test.
 *
 * @file
 * @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
 * @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 <http://www.gnu.org/licenses/>.
 *********************************************************************************/

#include <criterion/criterion.h>

#include <villas/log.hpp>
#include <villas/memory.hpp>
#include <villas/fpga/card.hpp>

#include <villas/fpga/ips/rtds2gpu.hpp>
Daniel Krebs's avatar
Daniel Krebs committed
31
#include <villas/fpga/ips/gpu2rtds.hpp>
Daniel Krebs's avatar
Daniel Krebs committed
32
33
#include <villas/fpga/ips/switch.hpp>
#include <villas/fpga/ips/dma.hpp>
34
#include <villas/fpga/ips/rtds.hpp>
Daniel Krebs's avatar
Daniel Krebs committed
35
36
37
38
39

#include "global.hpp"


static constexpr size_t SAMPLE_SIZE		= 4;
40
static constexpr size_t SAMPLE_COUNT	= 1;
Daniel Krebs's avatar
Daniel Krebs committed
41
42
static constexpr size_t FRAME_SIZE		= SAMPLE_COUNT * SAMPLE_SIZE;

43
static constexpr size_t DOORBELL_OFFSET = SAMPLE_COUNT;
Daniel Krebs's avatar
Daniel Krebs committed
44
45
static constexpr size_t DATA_OFFSET = 0;

Daniel Krebs's avatar
Daniel Krebs committed
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
static void dumpMem(const uint32_t* addr, size_t len)
{
	const size_t bytesPerLine = 16;
	const size_t lines = (len) / bytesPerLine + 1;
	const uint8_t* buf = reinterpret_cast<const uint8_t*>(addr);

	size_t bytesRead = 0;

	for(size_t line = 0; line < lines; line++) {
		const unsigned base = line * bytesPerLine;
		printf("0x%04x: ", base);

		for(size_t i = 0; i < bytesPerLine && bytesRead < len; i++) {
			printf("0x%02x ", buf[base + i]);
			bytesRead++;
		}
		puts("");
	}
}
Daniel Krebs's avatar
Daniel Krebs committed
65
66
67
68
69
70

Test(fpga, rtds2gpu, .description = "Rtds2Gpu")
{
	auto logger = loggerGetOrCreate("unittest:rtds2gpu");

	for(auto& ip : state.cards.front()->ips) {
71
		if(*ip != villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:"))
Daniel Krebs's avatar
Daniel Krebs committed
72
73
74
75
76
			continue;

		logger->info("Testing {}", *ip);


Daniel Krebs's avatar
Daniel Krebs committed
77
		/* Collect neccessary IPs */
Daniel Krebs's avatar
Daniel Krebs committed
78

79
		auto rtds2gpu = dynamic_cast<villas::fpga::ip::Rtds2Gpu&>(*ip);
Daniel Krebs's avatar
Daniel Krebs committed
80

Daniel Krebs's avatar
Daniel Krebs committed
81
82
		auto axiSwitch = dynamic_cast<villas::fpga::ip::AxiStreamSwitch*>(
		                     state.cards.front()->lookupIp(villas::fpga::Vlnv("xilinx.com:ip:axis_switch:")));
83
84

		auto dma = dynamic_cast<villas::fpga::ip::Dma*>(
Daniel Krebs's avatar
Daniel Krebs committed
85
86
		                     state.cards.front()->lookupIp(villas::fpga::Vlnv("xilinx.com:ip:axi_dma:")));

Daniel Krebs's avatar
Daniel Krebs committed
87
88
89
		auto gpu2rtds = dynamic_cast<villas::fpga::ip::Gpu2Rtds*>(
		                     state.cards.front()->lookupIp(villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:")));

90
91
		auto rtds = dynamic_cast<villas::fpga::ip::Rtds*>(
		                     state.cards.front()->lookupIp(villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:")));
Daniel Krebs's avatar
Daniel Krebs committed
92

Daniel Krebs's avatar
Daniel Krebs committed
93

Daniel Krebs's avatar
Daniel Krebs committed
94
95
		cr_assert_not_null(axiSwitch, "No AXI switch IP found");
		cr_assert_not_null(dma, "No DMA IP found");
Daniel Krebs's avatar
Daniel Krebs committed
96
		cr_assert_not_null(gpu2rtds, "No Gpu2Rtds IP found");
97
		cr_assert_not_null(rtds, "RTDS IP not found");
Daniel Krebs's avatar
Daniel Krebs committed
98
99
100

		rtds2gpu.dump(spdlog::level::debug);
		gpu2rtds->dump(spdlog::level::debug);
Daniel Krebs's avatar
Daniel Krebs committed
101
102


Daniel Krebs's avatar
Daniel Krebs committed
103
		/* Allocate and prepare memory */
Daniel Krebs's avatar
Daniel Krebs committed
104

Daniel Krebs's avatar
Daniel Krebs committed
105
106
107
		// allocate space for all samples and doorbell register
		auto dmaMemSrc = villas::HostDmaRam::getAllocator(0).allocate<uint32_t>(SAMPLE_COUNT + 1);
		auto dmaMemDst = villas::HostDmaRam::getAllocator(0).allocate<uint32_t>(SAMPLE_COUNT + 1);
Daniel Krebs's avatar
Daniel Krebs committed
108
109
		auto dmaMemDst2 = villas::HostDmaRam::getAllocator(0).allocate<uint32_t>(SAMPLE_COUNT + 1);

Daniel Krebs's avatar
Daniel Krebs committed
110

Daniel Krebs's avatar
Daniel Krebs committed
111
112
		memset(&dmaMemSrc, 0x11, dmaMemSrc.getMemoryBlock().getSize());
		memset(&dmaMemDst, 0x55, dmaMemDst.getMemoryBlock().getSize());
Daniel Krebs's avatar
Daniel Krebs committed
113
		memset(&dmaMemDst2, 0x77, dmaMemDst2.getMemoryBlock().getSize());
Daniel Krebs's avatar
Daniel Krebs committed
114

Daniel Krebs's avatar
Daniel Krebs committed
115
116
		const uint32_t* dataSrc = &dmaMemSrc[DATA_OFFSET];
		const uint32_t* dataDst = &dmaMemDst[DATA_OFFSET];
Daniel Krebs's avatar
Daniel Krebs committed
117
118
119
120
121
122
		const uint32_t* dataDst2 = &dmaMemDst2[0];

		dumpMem(dataSrc, dmaMemSrc.getMemoryBlock().getSize());
		dumpMem(dataDst, dmaMemDst.getMemoryBlock().getSize());
		dumpMem(dataDst2, dmaMemDst2.getMemoryBlock().getSize());

Daniel Krebs's avatar
Daniel Krebs committed
123

124
125
		// connect AXI Stream from DMA to Rtds2Gpu IP
		cr_assert(dma->connect(rtds2gpu));
Daniel Krebs's avatar
Daniel Krebs committed
126

127
		cr_assert(rtds2gpu.startOnce(dmaMemDst.getMemoryBlock(), SAMPLE_COUNT, DATA_OFFSET * 4, DOORBELL_OFFSET * 4),
Daniel Krebs's avatar
Daniel Krebs committed
128
		          "Preparing Rtds2Gpu IP failed");
Daniel Krebs's avatar
Daniel Krebs committed
129

Daniel Krebs's avatar
Daniel Krebs committed
130
131
		cr_assert(dma->write(dmaMemSrc.getMemoryBlock(), FRAME_SIZE),
		          "Starting DMA MM2S transfer failed");
Daniel Krebs's avatar
Daniel Krebs committed
132

Daniel Krebs's avatar
Daniel Krebs committed
133
134
		cr_assert(dma->writeComplete(),
		          "DMA failed");
Daniel Krebs's avatar
Daniel Krebs committed
135

Daniel Krebs's avatar
Daniel Krebs committed
136
		while(not rtds2gpu.isFinished());
Daniel Krebs's avatar
Daniel Krebs committed
137

Daniel Krebs's avatar
Daniel Krebs committed
138
139
140
		const uint32_t* doorbellDst = &dmaMemDst[DOORBELL_OFFSET];
		rtds2gpu.dump(spdlog::level::info);
		rtds2gpu.dumpDoorbell(*doorbellDst);
Daniel Krebs's avatar
Daniel Krebs committed
141

Daniel Krebs's avatar
Daniel Krebs committed
142
		cr_assert(memcmp(dataSrc, dataDst, FRAME_SIZE) == 0, "Memory not equal");
Daniel Krebs's avatar
Daniel Krebs committed
143

Daniel Krebs's avatar
Daniel Krebs committed
144
145
146
147

		for(size_t i = 0; i < SAMPLE_COUNT; i++) {
			gpu2rtds->registerFrames[i] = dmaMemDst[i];
		}
148
149
150
151


		// connect AXI Stream from Gpu2Rtds IP to DMA
		cr_assert(gpu2rtds->connect(*dma));
Daniel Krebs's avatar
Daniel Krebs committed
152
153
154
155
156
157
158
159
160
161

		cr_assert(dma->read(dmaMemDst2.getMemoryBlock(), FRAME_SIZE),
		          "Starting DMA S2MM transfer failed");

		cr_assert(gpu2rtds->startOnce(SAMPLE_COUNT),
		          "Preparing Gpu2Rtds IP failed");

		cr_assert(dma->readComplete(),
		          "DMA failed");

162
		while(not gpu2rtds->isFinished());
Daniel Krebs's avatar
Daniel Krebs committed
163
164
165
166
167
168
169

		cr_assert(memcmp(dataSrc, dataDst2, FRAME_SIZE) == 0, "Memory not equal");

		dumpMem(dataSrc, dmaMemSrc.getMemoryBlock().getSize());
		dumpMem(dataDst, dmaMemDst.getMemoryBlock().getSize());
		dumpMem(dataDst2, dmaMemDst2.getMemoryBlock().getSize());

Daniel Krebs's avatar
Daniel Krebs committed
170
171
172
		logger->info(TXT_GREEN("Passed"));
	}
}
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

Test(fpga, rtds2gpu_rtt_cpu, .description = "Rtds2Gpu RTT via CPU")
{
	auto logger = loggerGetOrCreate("unittest:rtds2gpu");

	/* Collect neccessary IPs */

	auto gpu2rtds = dynamic_cast<villas::fpga::ip::Gpu2Rtds*>(
	                     state.cards.front()->lookupIp(villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:gpu2rtds:")));

	auto rtds2gpu = dynamic_cast<villas::fpga::ip::Rtds2Gpu*>(
	                     state.cards.front()->lookupIp(villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:hls:rtds2gpu:")));

	cr_assert_not_null(gpu2rtds, "No Gpu2Rtds IP found");
	cr_assert_not_null(rtds2gpu, "No Rtds2Gpu IP not found");

	for(auto& ip : state.cards.front()->ips) {
		if(*ip != villas::fpga::Vlnv("acs.eonerc.rwth-aachen.de:user:rtds_axis:"))
			continue;

		auto& rtds = dynamic_cast<villas::fpga::ip::Rtds&>(*ip);
		logger->info("Testing {}", rtds);

		auto dmaRam = villas::HostDmaRam::getAllocator().allocate<uint32_t>(SAMPLE_COUNT + 1);
		uint32_t* data = &dmaRam[DATA_OFFSET];
198
		uint32_t* doorbell = &dmaRam[DOORBELL_OFFSET];
199
200
201
202
203
204
205
206
207
208
209
210
211

		// TEST: rtds loopback via switch
//		cr_assert(rtds.connect(rtds));
//		logger->info("loopback");
//		while(1);

		cr_assert(rtds.connect(*rtds2gpu));
		cr_assert(gpu2rtds->connect(rtds));


		size_t count = 0;
		while(true) {
			rtds2gpu->doorbellReset(*doorbell);
212
			rtds2gpu->startOnce(dmaRam.getMemoryBlock(), SAMPLE_COUNT, DATA_OFFSET * 4, DOORBELL_OFFSET * 4);
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234

			//			while(not rtds2gpu->isFinished());
			while(not rtds2gpu->doorbellIsValid(*doorbell));

//			rtds2gpu->dump();
//			rtds2gpu->dumpDoorbell(data[1]);
//			dumpMem(data, FRAME_SIZE + SAMPLE_SIZE);

			// copy samples to gpu2rtds IP
			for(size_t i = 0; i < SAMPLE_COUNT; i++) {
				gpu2rtds->registerFrames[i] = data[i];
			}

			gpu2rtds->startOnce(SAMPLE_COUNT);
//			while(not gpu2rtds->isFinished());


			count++;
//			logger->debug("Successful iterations {}, data {}", count, data[0]);
		}
	}
}