gpu.cpp 4.43 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/** GPU unit tests.
 *
 * @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
 * @copyright 2017-2018, 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/>.
 *********************************************************************************/

23
24
25
26
27
28
29
30
31
32
#include <criterion/criterion.h>

#include <map>
#include <string>

#include <villas/log.hpp>
#include <villas/fpga/card.hpp>
#include <villas/fpga/ips/dma.hpp>
#include <villas/fpga/ips/bram.hpp>

33
#include <villas/utils.hpp>
34
35
36
37
38
39
40
41
42

#include "global.hpp"

#include <villas/memory.hpp>
#include <villas/gpu.hpp>


Test(fpga, gpu_dma, .description = "GPU DMA tests")
{
43
	auto logger = villas::logging.get("unittest:dma");
44
45
46

	auto& card = state.cards.front();

Steffen Vogel's avatar
Steffen Vogel committed
47
	auto gpuPlugin = villas::Plugin::Registry<GpuFactory>("cuda");
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
	cr_assert_not_null(gpuPlugin, "No GPU plugin found");

	auto gpus = gpuPlugin->make();
	cr_assert(gpus.size() > 0, "No GPUs found");

	// just get first cpu
	auto& gpu = gpus.front();

	size_t count = 0;
	for(auto& ip : card->ips) {
		// skip non-dma IPs
		if(*ip != villas::fpga::Vlnv("xilinx.com:ip:axi_bram_ctrl:"))
			continue;

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

64
		auto bram = dynamic_cast<villas::fpga::ip::Bram*>(ip.get());
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
		cr_assert_not_null(bram, "Couldn't find BRAM");

		count++;

		size_t len = 4 * (1 << 10);

		/* Allocate memory to use with DMA */

		auto bram0 = bram->getAllocator().allocate<char>(len);
		auto bram1 = bram->getAllocator().allocate<char>(len);

		gpu->makeAccessibleFromPCIeOrHostRam(bram0.getMemoryBlock());
		gpu->makeAccessibleFromPCIeOrHostRam(bram1.getMemoryBlock());

		auto hostRam0 = villas::HostRam::getAllocator().allocate<char>(len);
		auto hostRam1 = villas::HostRam::getAllocator().allocate<char>(len);

		gpu->makeAccessibleFromPCIeOrHostRam(hostRam0.getMemoryBlock());
		gpu->makeAccessibleFromPCIeOrHostRam(hostRam1.getMemoryBlock());

		auto dmaRam0 = villas::HostDmaRam::getAllocator().allocate<char>(len);
		auto dmaRam1 = villas::HostDmaRam::getAllocator().allocate<char>(len);

		gpu->makeAccessibleFromPCIeOrHostRam(dmaRam0.getMemoryBlock());
		gpu->makeAccessibleFromPCIeOrHostRam(dmaRam1.getMemoryBlock());

		auto gpuMem0 = gpu->getAllocator().allocate<char>(64 << 10);
		auto gpuMem1 = gpu->getAllocator().allocate<char>(64 << 10);

		gpu->makeAccessibleToPCIeAndVA(gpuMem0.getMemoryBlock());
		gpu->makeAccessibleToPCIeAndVA(gpuMem1.getMemoryBlock());


//		auto& src = bram0;
//		auto& dst = bram1;

//		auto& src = hostRam0;
//		auto& dst = hostRam1;

		auto& src = dmaRam0;
//		auto& dst = dmaRam1;

//		auto& src = gpuMem0;
		auto& dst = gpuMem1;


		std::list<std::pair<std::string, std::function<void()>>> memcpyFuncs = {
		    {"cudaMemcpy", [&]() {gpu->memcpySync(src.getMemoryBlock(), dst.getMemoryBlock(), len);}},
		    {"CUDA kernel", [&]() {gpu->memcpyKernel(src.getMemoryBlock(), dst.getMemoryBlock(), len);}},
	    };

		auto dmaIp = card->lookupIp(villas::fpga::Vlnv("xilinx.com:ip:axi_dma:"));
		auto dma = dynamic_cast<villas::fpga::ip::Dma*>(dmaIp);

		if(dma != nullptr and dma->connectLoopback()) {
			memcpyFuncs.push_back({
			    "DMA memcpy", [&]() {
			        if(not dma->makeAccesibleFromVA(src.getMemoryBlock()) or
			           not dma->makeAccesibleFromVA(dst.getMemoryBlock())) {
			            return;
			        }
			        dma->memcpy(src.getMemoryBlock(), dst.getMemoryBlock(), len);
			    }});
		}

		for(auto& [name, memcpyFunc] : memcpyFuncs) {
			logger->info("Testing {}", name);

			/* Get new random data */
134
			const size_t lenRandom = utils::read_random(&src, len);
135
136
137
138
139
140
			cr_assert(len == lenRandom, "Failed to get random data");

			memcpyFunc();
			const bool success = memcmp(&src, &dst, len) == 0;

			logger->info("  {}", success ?
141
142
			                 CLR_GRN("Passed") :
			                 CLR_RED("Failed"));
143
144
145
146
147
148
149
150
		}

		villas::MemoryManager::get().dump();
	}


	cr_assert(count > 0, "No BRAM found");
}