nouveau/mme: Unify some of the test framework

Most of the actual nouveau device enumeration and test running framework
was copy+paste between the two.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
Faith Ekstrand
2023-01-30 20:12:06 -06:00
committed by Marge Bot
parent 94ea7cad3a
commit 15295e32ec
5 changed files with 353 additions and 480 deletions
+2 -2
View File
@@ -111,7 +111,7 @@ idep_nouveau_mme = declare_dependency(
if with_tests and not with_platform_android
executable(
'mme_fermi_sim_hw_test',
files('tests/mme_fermi_sim_hw_test.cpp'),
files('tests/mme_runner.cpp', 'tests/mme_fermi_sim_hw_test.cpp'),
gnu_symbol_visibility : 'hidden',
include_directories : [inc_include, inc_src],
dependencies : [
@@ -127,7 +127,7 @@ if with_tests and not with_platform_android
executable(
'mme_tu104_sim_hw_test',
files('tests/mme_tu104_sim_hw_test.cpp'),
files('tests/mme_runner.cpp', 'tests/mme_tu104_sim_hw_test.cpp'),
gnu_symbol_visibility : 'hidden',
include_directories : [inc_include, inc_src],
dependencies : [
+25 -238
View File
@@ -1,187 +1,32 @@
#include <fcntl.h>
#include <string.h>
#include <xf86drm.h>
#include <vector>
#include "mme_runner.h"
#include <gtest/gtest.h>
#include "mme_builder.h"
#include "mme_fermi_sim.h"
#include "nouveau_bo.h"
#include "nouveau_context.h"
#include "nouveau_device.h"
/* nouveau_drm.h isn't C++-friendly */
#define class cls
#include <nouveau_drm.h>
#undef class
#include <xf86drm.h>
#include "nv_push.h"
/* we use Fermi Compute and 2D as interface are identical between Fermi and Volta*/
#include "nvk_cl9097.h"
#include "nvk_cl902d.h"
/* for VOLTA_A */
#include "nvk_clc397.h"
class mme_fermi_sim_test : public ::testing::Test {
class mme_fermi_sim_test : public ::testing::Test, public mme_hw_runner {
public:
mme_fermi_sim_test();
~mme_fermi_sim_test();
void SetUp();
void push_macro(uint32_t id, const std::vector<uint32_t>& macro);
void reset_push();
void submit_push();
void test_macro(const mme_builder *b,
const std::vector<uint32_t>& macro,
const std::vector<uint32_t>& params);
struct nv_push *p;
uint64_t data_addr;
uint32_t *data;
struct nouveau_ws_device *dev;
private:
struct nouveau_ws_context *ctx;
struct nouveau_ws_bo *data_bo;
struct nouveau_ws_bo *push_bo;
void *push_map;
struct nv_push push;
};
mme_fermi_sim_test::mme_fermi_sim_test() :
data(NULL), dev(NULL), ctx(NULL), data_bo(NULL), push_bo(NULL)
{
memset(&push, 0, sizeof(push));
}
::testing::Test(),
mme_hw_runner()
{ }
mme_fermi_sim_test::~mme_fermi_sim_test()
{
if (push_bo) {
nouveau_ws_bo_unmap(push_bo, push_map);
nouveau_ws_bo_destroy(push_bo);
}
if (ctx)
nouveau_ws_context_destroy(ctx);
if (dev)
nouveau_ws_device_destroy(dev);
}
#define PUSH_SIZE 64 * 4096
#define DATA_BO_SIZE 4096
{ }
void
mme_fermi_sim_test::SetUp()
{
drmDevicePtr devices[8];
int max_devices = drmGetDevices2(0, devices, 8);
int i;
for (i = 0; i < max_devices; i++) {
if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER &&
devices[i]->bustype == DRM_BUS_PCI &&
devices[i]->deviceinfo.pci->vendor_id == 0x10de) {
dev = nouveau_ws_device_new(devices[i]);
if (dev == NULL)
continue;
if (dev->info.cls_eng3d < FERMI_A || dev->info.cls_eng3d > VOLTA_A) {
nouveau_ws_device_destroy(dev);
dev = NULL;
continue;
}
/* Found a Fermi+ device */
break;
}
}
/* We need a Fermi+ device */
ASSERT_TRUE(dev != NULL);
int ret = nouveau_ws_context_create(dev, &ctx);
ASSERT_EQ(ret, 0);
uint32_t data_bo_flags = NOUVEAU_WS_BO_GART | NOUVEAU_WS_BO_MAP;
data_bo = nouveau_ws_bo_new_mapped(dev, DATA_BO_SIZE, 0,
(nouveau_ws_bo_flags)data_bo_flags,
NOUVEAU_WS_BO_RDWR, (void **)&data);
ASSERT_TRUE(data_bo != NULL);
memset(data, 139, DATA_BO_SIZE);
data_addr = data_bo->offset;
uint32_t push_bo_flags = NOUVEAU_WS_BO_GART | NOUVEAU_WS_BO_MAP;
push_bo = nouveau_ws_bo_new_mapped(dev, PUSH_SIZE, 0,
(nouveau_ws_bo_flags)push_bo_flags,
NOUVEAU_WS_BO_WR, &push_map);
ASSERT_TRUE(push_bo != NULL);
reset_push();
}
void
mme_fermi_sim_test::reset_push()
{
nv_push_init(&push, (uint32_t *)push_map, PUSH_SIZE / 4);
p = &push;
P_MTHD(p, NV9097, SET_OBJECT);
P_NV9097_SET_OBJECT(p, {
.class_id = dev->info.cls_eng3d,
.engine_id = 0,
});
}
void
mme_fermi_sim_test::submit_push()
{
struct drm_nouveau_gem_pushbuf_bo bos[2];
memset(bos, 0, sizeof(bos));
bos[0].handle = push_bo->handle,
bos[0].valid_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[0].read_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[1].handle = data_bo->handle,
bos[1].valid_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[1].read_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[1].write_domains = NOUVEAU_GEM_DOMAIN_GART;
struct drm_nouveau_gem_pushbuf_push push;
memset(&push, 0, sizeof(push));
push.bo_index = 0;
push.offset = 0;
push.length = nv_push_dw_count(&this->push) * 4;
struct drm_nouveau_gem_pushbuf req;
memset(&req, 0, sizeof(req));
req.channel = ctx->channel;
req.nr_buffers = 2;
req.buffers = (uintptr_t)bos;
req.nr_push = 1;
req.push = (uintptr_t)&push;
int ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
&req, sizeof(req));
ASSERT_EQ(ret, 0);
bool ok = nouveau_ws_bo_wait(data_bo, NOUVEAU_WS_BO_RDWR);
ASSERT_TRUE(ok);
}
void
mme_fermi_sim_test::push_macro(uint32_t id, const std::vector<uint32_t> &macro)
{
P_MTHD(p, NV9097, LOAD_MME_START_ADDRESS_RAM_POINTER);
P_NV9097_LOAD_MME_START_ADDRESS_RAM_POINTER(p, id);
P_NV9097_LOAD_MME_START_ADDRESS_RAM(p, 0);
P_1INC(p, NV9097, LOAD_MME_INSTRUCTION_RAM_POINTER);
P_NV9097_LOAD_MME_INSTRUCTION_RAM_POINTER(p, 0);
P_INLINE_ARRAY(p, &macro[0], macro.size());
ASSERT_TRUE(set_up_hw(FERMI_A, VOLTA_A));
}
void
@@ -205,33 +50,13 @@ mme_fermi_sim_test::test_macro(const mme_builder *b,
params.size(), &params[0],
1, &sim_mem);
/* Now run the macro on the GPU */
push_macro(0, macro);
P_1INC(p, NV9097, CALL_MME_MACRO(0));
if (params.empty()) {
P_NV9097_CALL_MME_MACRO(p, 0, 0);
} else {
P_INLINE_ARRAY(p, &params[0], params.size());
}
submit_push();
run_macro(macro, params);
/* Check the results */
for (uint32_t i = 0; i < data_dwords; i++)
ASSERT_EQ(data[i], sim_data[i]);
}
static std::vector<uint32_t>
mme_builder_finish_vec(mme_builder *b)
{
size_t size = 0;
uint32_t *dw = mme_builder_finish(b, &size);
std::vector<uint32_t> vec(dw, dw + (size / 4));
free(dw);
return vec;
}
static mme_fermi_reg
mme_fermi_value_as_reg(mme_value val)
{
@@ -239,50 +64,12 @@ mme_fermi_value_as_reg(mme_value val)
return (mme_fermi_reg)(MME_FERMI_REG_ZERO + val.reg);
}
static inline uint32_t
high32(uint64_t x)
{
return (uint32_t)(x >> 32);
}
static inline uint32_t
low32(uint64_t x)
{
return (uint32_t)x;
}
static void
mme_store_imm_addr(mme_builder *b, uint64_t addr, mme_value v, bool free_reg)
{
mme_mthd(b, NV9097_SET_REPORT_SEMAPHORE_A);
mme_emit(b, mme_imm(high32(addr)));
mme_emit(b, mme_imm(low32(addr)));
mme_emit(b, v);
mme_emit(b, mme_imm(0x10000000));
if (free_reg && v.type == MME_VALUE_TYPE_REG)
mme_free_reg(b, v);
}
static void
mme_store(mme_builder *b, struct mme_value64 addr, mme_value v, bool free_reg)
{
mme_mthd(b, NV9097_SET_REPORT_SEMAPHORE_A);
mme_emit(b, addr.hi);
mme_emit(b, addr.lo);
mme_emit(b, v);
mme_emit(b, mme_imm(0x10000000));
if (free_reg && v.type == MME_VALUE_TYPE_REG)
mme_free_reg(b, v);
}
TEST_F(mme_fermi_sim_test, sanity)
{
const uint32_t canary = 0xc0ffee01;
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_store_imm_addr(&b, data_addr, mme_imm(canary), false);
@@ -295,7 +82,7 @@ TEST_F(mme_fermi_sim_test, sanity)
TEST_F(mme_fermi_sim_test, add)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -314,7 +101,7 @@ TEST_F(mme_fermi_sim_test, add)
TEST_F(mme_fermi_sim_test, add_imm)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
@@ -367,7 +154,7 @@ TEST_F(mme_fermi_sim_test, add_imm)
TEST_F(mme_fermi_sim_test, add_imm_no_carry)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x_lo = mme_load(&b);
mme_value x_hi = mme_load(&b);
@@ -479,7 +266,7 @@ TEST_F(mme_fermi_sim_test, add_imm_no_carry)
TEST_F(mme_fermi_sim_test, addc)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
struct mme_value64 x = { mme_load(&b), mme_load(&b) };
struct mme_value64 y = { mme_load(&b), mme_load(&b) };
@@ -503,7 +290,7 @@ TEST_F(mme_fermi_sim_test, addc)
TEST_F(mme_fermi_sim_test, sub)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -522,7 +309,7 @@ TEST_F(mme_fermi_sim_test, sub)
TEST_F(mme_fermi_sim_test, subb)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
struct mme_value64 x = { mme_load(&b), mme_load(&b) };
struct mme_value64 y = { mme_load(&b), mme_load(&b) };
@@ -547,7 +334,7 @@ TEST_F(mme_fermi_sim_test, subb)
TEST_F(mme_fermi_sim_test, op) \
{ \
mme_builder b; \
mme_builder_init(&b, &dev->info); \
mme_builder_init(&b, devinfo); \
\
mme_value val = mme_load(&b); \
mme_value shift1 = mme_load(&b); \
@@ -574,7 +361,7 @@ SHIFT_TEST(srl)
TEST_F(mme_fermi_sim_test, op) \
{ \
mme_builder b; \
mme_builder_init(&b, &dev->info); \
mme_builder_init(&b, devinfo); \
\
mme_value x = mme_load(&b); \
mme_value y = mme_load(&b); \
@@ -609,7 +396,7 @@ static bool c_ieq(int32_t x, int32_t y) { return x == y; };
TEST_F(mme_fermi_sim_test, if_##op) \
{ \
mme_builder b; \
mme_builder_init(&b, &dev->info); \
mme_builder_init(&b, devinfo); \
\
mme_value x = mme_load(&b); \
mme_value y = mme_load(&b); \
@@ -665,7 +452,7 @@ mme_fermi_inc_whole_inst(mme_builder *b, mme_value val)
TEST_F(mme_fermi_sim_test, while_##op) \
{ \
mme_builder b; \
mme_builder_init(&b, &dev->info); \
mme_builder_init(&b, devinfo); \
\
mme_value x = mme_mov(&b, mme_zero()); \
mme_value y = mme_mov(&b, mme_zero()); \
@@ -721,7 +508,7 @@ WHILE_TEST(ine, 0, 1, 7)
TEST_F(mme_fermi_sim_test, loop)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value count = mme_load(&b);
@@ -761,7 +548,7 @@ TEST_F(mme_fermi_sim_test, loop)
TEST_F(mme_fermi_sim_test, merge)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -793,7 +580,7 @@ TEST_F(mme_fermi_sim_test, merge)
TEST_F(mme_fermi_sim_test, branch_delay_slot)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -823,7 +610,7 @@ TEST_F(mme_fermi_sim_test, branch_delay_slot)
TEST_F(mme_fermi_sim_test, state)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -854,7 +641,7 @@ TEST_F(mme_fermi_sim_test, scratch_limit)
static const uint32_t chunk_size = 32;
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value start = mme_load(&b);
mme_value count = mme_load(&b);
@@ -901,7 +688,7 @@ TEST_F(mme_fermi_sim_test, scratch_limit)
TEST_F(mme_fermi_sim_test, load_imm_to_reg)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
uint32_t vals[] = {
0x0001ffff,
+180
View File
@@ -0,0 +1,180 @@
#include "mme_runner.h"
#include <fcntl.h>
#include <string.h>
#include <xf86drm.h>
#include "mme_fermi_sim.h"
#include "mme_tu104_sim.h"
#include "nouveau_bo.h"
#include "nouveau_context.h"
/* nouveau_drm.h isn't C++-friendly */
#define class cls
#include <nouveau_drm.h>
#undef class
mme_runner::mme_runner() :
devinfo(NULL), data_addr(0), data(NULL)
{ }
mme_runner::~mme_runner()
{ }
mme_hw_runner::mme_hw_runner() :
mme_runner(), p(NULL), dev(NULL), ctx(NULL),
data_bo(NULL), push_bo(NULL), push_map(NULL)
{
memset(&push, 0, sizeof(push));
}
mme_hw_runner::~mme_hw_runner()
{
if (push_bo) {
nouveau_ws_bo_unmap(push_bo, push_map);
nouveau_ws_bo_destroy(push_bo);
}
if (ctx)
nouveau_ws_context_destroy(ctx);
if (dev)
nouveau_ws_device_destroy(dev);
}
#define PUSH_SIZE 64 * 4096
bool
mme_hw_runner::set_up_hw(uint16_t min_cls, uint16_t max_cls)
{
drmDevicePtr devices[8];
int max_devices = drmGetDevices2(0, devices, 8);
int i;
for (i = 0; i < max_devices; i++) {
if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER &&
devices[i]->bustype == DRM_BUS_PCI &&
devices[i]->deviceinfo.pci->vendor_id == 0x10de) {
dev = nouveau_ws_device_new(devices[i]);
if (dev == NULL)
continue;
if (dev->info.cls_eng3d < min_cls || dev->info.cls_eng3d > max_cls) {
nouveau_ws_device_destroy(dev);
dev = NULL;
continue;
}
/* Found a Turning+ device */
break;
}
}
if (dev == NULL)
return false;
devinfo = &dev->info;
int ret = nouveau_ws_context_create(dev, &ctx);
if (ret)
return false;
uint32_t data_bo_flags = NOUVEAU_WS_BO_GART | NOUVEAU_WS_BO_MAP;
data_bo = nouveau_ws_bo_new_mapped(dev, DATA_BO_SIZE, 0,
(nouveau_ws_bo_flags)data_bo_flags,
NOUVEAU_WS_BO_RDWR, (void **)&data);
if (data_bo == NULL)
return false;
memset(data, 139, DATA_BO_SIZE);
data_addr = data_bo->offset;
uint32_t push_bo_flags = NOUVEAU_WS_BO_GART | NOUVEAU_WS_BO_MAP;
push_bo = nouveau_ws_bo_new_mapped(dev, PUSH_SIZE, 0,
(nouveau_ws_bo_flags)push_bo_flags,
NOUVEAU_WS_BO_WR, &push_map);
if (push_bo == NULL)
return false;
reset_push();
return true;
}
void
mme_hw_runner::reset_push()
{
nv_push_init(&push, (uint32_t *)push_map, PUSH_SIZE / 4);
p = &push;
P_MTHD(p, NV9097, SET_OBJECT);
P_NV9097_SET_OBJECT(p, {
.class_id = dev->info.cls_eng3d,
.engine_id = 0,
});
}
void
mme_hw_runner::submit_push()
{
struct drm_nouveau_gem_pushbuf_bo bos[2];
memset(bos, 0, sizeof(bos));
bos[0].handle = push_bo->handle,
bos[0].valid_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[0].read_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[1].handle = data_bo->handle,
bos[1].valid_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[1].read_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[1].write_domains = NOUVEAU_GEM_DOMAIN_GART;
struct drm_nouveau_gem_pushbuf_push push;
memset(&push, 0, sizeof(push));
push.bo_index = 0;
push.offset = 0;
push.length = nv_push_dw_count(&this->push) * 4;
struct drm_nouveau_gem_pushbuf req;
memset(&req, 0, sizeof(req));
req.channel = ctx->channel;
req.nr_buffers = 2;
req.buffers = (uintptr_t)bos;
req.nr_push = 1;
req.push = (uintptr_t)&push;
int ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
&req, sizeof(req));
ASSERT_EQ(ret, 0);
bool ok = nouveau_ws_bo_wait(data_bo, NOUVEAU_WS_BO_RDWR);
ASSERT_TRUE(ok);
}
void
mme_hw_runner::push_macro(uint32_t id, const std::vector<uint32_t> &macro)
{
P_MTHD(p, NV9097, LOAD_MME_START_ADDRESS_RAM_POINTER);
P_NV9097_LOAD_MME_START_ADDRESS_RAM_POINTER(p, id);
P_NV9097_LOAD_MME_START_ADDRESS_RAM(p, 0);
P_1INC(p, NV9097, LOAD_MME_INSTRUCTION_RAM_POINTER);
P_NV9097_LOAD_MME_INSTRUCTION_RAM_POINTER(p, 0);
P_INLINE_ARRAY(p, &macro[0], macro.size());
}
void
mme_hw_runner::run_macro(const std::vector<uint32_t>& macro,
const std::vector<uint32_t>& params)
{
push_macro(0, macro);
P_1INC(p, NV9097, CALL_MME_MACRO(0));
if (params.empty()) {
P_NV9097_CALL_MME_MACRO(p, 0, 0);
} else {
P_INLINE_ARRAY(p, &params[0], params.size());
}
submit_push();
}
+100
View File
@@ -0,0 +1,100 @@
#include <gtest/gtest.h>
#include <vector>
#include "mme_builder.h"
struct nouveau_bo;
struct nouveau_ws_contxt;
struct nouveau_ws_device;
#include "nv_push.h"
#include "nvk_cl9097.h"
#define DATA_BO_SIZE 4096
class mme_runner {
public:
mme_runner();
virtual ~mme_runner();
virtual void run_macro(const std::vector<uint32_t>& macro,
const std::vector<uint32_t>& params) = 0;
const nv_device_info *devinfo;
uint64_t data_addr;
uint32_t *data;
};
class mme_hw_runner : public mme_runner {
public:
mme_hw_runner();
virtual ~mme_hw_runner();
bool set_up_hw(uint16_t min_cls, uint16_t max_cls);
void push_macro(uint32_t id, const std::vector<uint32_t>& macro);
void reset_push();
void submit_push();
virtual void run_macro(const std::vector<uint32_t>& macro,
const std::vector<uint32_t>& params);
struct nv_push *p;
private:
struct nouveau_ws_device *dev;
struct nouveau_ws_context *ctx;
struct nouveau_ws_bo *data_bo;
struct nouveau_ws_bo *push_bo;
void *push_map;
struct nv_push push;
};
inline std::vector<uint32_t>
mme_builder_finish_vec(mme_builder *b)
{
size_t size = 0;
uint32_t *dw = mme_builder_finish(b, &size);
std::vector<uint32_t> vec(dw, dw + (size / 4));
free(dw);
return vec;
}
inline uint32_t
high32(uint64_t x)
{
return (uint32_t)(x >> 32);
}
inline uint32_t
low32(uint64_t x)
{
return (uint32_t)x;
}
inline void
mme_store_imm_addr(mme_builder *b, uint64_t addr, mme_value v,
bool free_reg = false)
{
mme_mthd(b, NV9097_SET_REPORT_SEMAPHORE_A);
mme_emit(b, mme_imm(high32(addr)));
mme_emit(b, mme_imm(low32(addr)));
mme_emit(b, v);
mme_emit(b, mme_imm(0x10000000));
if (free_reg && v.type == MME_VALUE_TYPE_REG)
mme_free_reg(b, v);
}
inline void
mme_store(mme_builder *b, struct mme_value64 addr, mme_value v,
bool free_reg = false)
{
mme_mthd(b, NV9097_SET_REPORT_SEMAPHORE_A);
mme_emit(b, addr.hi);
mme_emit(b, addr.lo);
mme_emit(b, v);
mme_emit(b, mme_imm(0x10000000));
if (free_reg && v.type == MME_VALUE_TYPE_REG)
mme_free_reg(b, v);
}
+46 -240
View File
@@ -1,183 +1,31 @@
#include <fcntl.h>
#include <string.h>
#include <xf86drm.h>
#include <vector>
#include <gtest/gtest.h>
#include "mme_builder.h"
#include "mme_runner.h"
#include "mme_tu104_sim.h"
#include "nouveau_bo.h"
#include "nouveau_context.h"
#include "nouveau_device.h"
/* nouveau_drm.h isn't C++-friendly */
#define class cls
#include <nouveau_drm.h>
#undef class
#include <xf86drm.h>
#include "nv_push.h"
#include "nvk_clc597.h"
class mme_tu104_sim_test : public ::testing::Test {
class mme_tu104_sim_test : public ::testing::Test, public mme_hw_runner {
public:
mme_tu104_sim_test();
~mme_tu104_sim_test();
void SetUp();
void push_macro(uint32_t id, const std::vector<uint32_t>& macro);
void reset_push();
void submit_push();
void test_macro(const mme_builder *b,
const std::vector<uint32_t>& macro,
const std::vector<uint32_t>& params);
struct nv_push *p;
uint64_t data_addr;
uint32_t *data;
struct nouveau_ws_device *dev;
private:
struct nouveau_ws_context *ctx;
struct nouveau_ws_bo *data_bo;
struct nouveau_ws_bo *push_bo;
void *push_map;
struct nv_push push;
};
mme_tu104_sim_test::mme_tu104_sim_test() :
data(NULL), dev(NULL), ctx(NULL), data_bo(NULL), push_bo(NULL)
{
memset(&push, 0, sizeof(push));
}
::testing::Test(),
mme_hw_runner()
{ }
mme_tu104_sim_test::~mme_tu104_sim_test()
{
if (push_bo) {
nouveau_ws_bo_unmap(push_bo, push_map);
nouveau_ws_bo_destroy(push_bo);
}
if (ctx)
nouveau_ws_context_destroy(ctx);
if (dev)
nouveau_ws_device_destroy(dev);
}
#define PUSH_SIZE 64 * 4096
#define DATA_BO_SIZE 4096
{ }
void
mme_tu104_sim_test::SetUp()
{
drmDevicePtr devices[8];
int max_devices = drmGetDevices2(0, devices, 8);
int i;
for (i = 0; i < max_devices; i++) {
if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER &&
devices[i]->bustype == DRM_BUS_PCI &&
devices[i]->deviceinfo.pci->vendor_id == 0x10de) {
dev = nouveau_ws_device_new(devices[i]);
if (dev == NULL)
continue;
if (dev->info.cls_eng3d < TURING_A) {
nouveau_ws_device_destroy(dev);
dev = NULL;
continue;
}
/* Found a Turning+ device */
break;
}
}
/* We need a Turing+ device */
ASSERT_TRUE(dev != NULL);
int ret = nouveau_ws_context_create(dev, &ctx);
ASSERT_EQ(ret, 0);
uint32_t data_bo_flags = NOUVEAU_WS_BO_GART | NOUVEAU_WS_BO_MAP;
data_bo = nouveau_ws_bo_new_mapped(dev, DATA_BO_SIZE, 0,
(nouveau_ws_bo_flags)data_bo_flags,
NOUVEAU_WS_BO_RDWR, (void **)&data);
ASSERT_TRUE(data_bo != NULL);
memset(data, 139, DATA_BO_SIZE);
data_addr = data_bo->offset;
uint32_t push_bo_flags = NOUVEAU_WS_BO_GART | NOUVEAU_WS_BO_MAP;
push_bo = nouveau_ws_bo_new_mapped(dev, PUSH_SIZE, 0,
(nouveau_ws_bo_flags)push_bo_flags,
NOUVEAU_WS_BO_WR, &push_map);
ASSERT_TRUE(push_bo != NULL);
reset_push();
}
void
mme_tu104_sim_test::reset_push()
{
nv_push_init(&push, (uint32_t *)push_map, PUSH_SIZE / 4);
p = &push;
P_MTHD(p, NVC597, SET_OBJECT);
P_NVC597_SET_OBJECT(p, {
.class_id = dev->info.cls_eng3d,
.engine_id = 0,
});
}
void
mme_tu104_sim_test::submit_push()
{
struct drm_nouveau_gem_pushbuf_bo bos[2];
memset(bos, 0, sizeof(bos));
bos[0].handle = push_bo->handle,
bos[0].valid_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[0].read_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[1].handle = data_bo->handle,
bos[1].valid_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[1].read_domains = NOUVEAU_GEM_DOMAIN_GART;
bos[1].write_domains = NOUVEAU_GEM_DOMAIN_GART;
struct drm_nouveau_gem_pushbuf_push push;
memset(&push, 0, sizeof(push));
push.bo_index = 0;
push.offset = 0;
push.length = nv_push_dw_count(&this->push) * 4;
struct drm_nouveau_gem_pushbuf req;
memset(&req, 0, sizeof(req));
req.channel = ctx->channel;
req.nr_buffers = 2;
req.buffers = (uintptr_t)bos;
req.nr_push = 1;
req.push = (uintptr_t)&push;
int ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
&req, sizeof(req));
ASSERT_EQ(ret, 0);
bool ok = nouveau_ws_bo_wait(data_bo, NOUVEAU_WS_BO_RDWR);
ASSERT_TRUE(ok);
}
void
mme_tu104_sim_test::push_macro(uint32_t id, const std::vector<uint32_t> &macro)
{
P_MTHD(p, NVC597, LOAD_MME_START_ADDRESS_RAM_POINTER);
P_NVC597_LOAD_MME_START_ADDRESS_RAM_POINTER(p, id);
P_NVC597_LOAD_MME_START_ADDRESS_RAM(p, 0);
P_1INC(p, NVC597, LOAD_MME_INSTRUCTION_RAM_POINTER);
P_NVC597_LOAD_MME_INSTRUCTION_RAM_POINTER(p, 0);
P_INLINE_ARRAY(p, &macro[0], macro.size());
ASSERT_TRUE(set_up_hw(TURING_A, UINT16_MAX));
}
void
@@ -218,16 +66,6 @@ mme_tu104_sim_test::test_macro(const mme_builder *b,
ASSERT_EQ(data[i], sim_data[i]);
}
static std::vector<uint32_t>
mme_builder_finish_vec(mme_builder *b)
{
size_t size = 0;
uint32_t *dw = mme_builder_finish(b, &size);
std::vector<uint32_t> vec(dw, dw + (size / 4));
free(dw);
return vec;
}
static mme_tu104_reg
mme_value_as_reg(mme_value val)
{
@@ -235,44 +73,12 @@ mme_value_as_reg(mme_value val)
return (mme_tu104_reg)(MME_TU104_REG_R0 + val.reg);
}
static inline uint32_t
high32(uint64_t x)
{
return (uint32_t)(x >> 32);
}
static inline uint32_t
low32(uint64_t x)
{
return (uint32_t)x;
}
static void
mme_store_imm_addr(mme_builder *b, uint64_t addr, mme_value v)
{
mme_mthd(b, NVC597_SET_REPORT_SEMAPHORE_A);
mme_emit(b, mme_imm(high32(addr)));
mme_emit(b, mme_imm(low32(addr)));
mme_emit(b, v);
mme_emit(b, mme_imm(0x10000000));
}
static void
mme_store(mme_builder *b, struct mme_value64 addr, mme_value v)
{
mme_mthd(b, NVC597_SET_REPORT_SEMAPHORE_A);
mme_emit(b, addr.hi);
mme_emit(b, addr.lo);
mme_emit(b, v);
mme_emit(b, mme_imm(0x10000000));
}
TEST_F(mme_tu104_sim_test, sanity)
{
const uint32_t canary = 0xc0ffee01;
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_store_imm_addr(&b, data_addr, mme_imm(canary));
@@ -285,7 +91,7 @@ TEST_F(mme_tu104_sim_test, sanity)
TEST_F(mme_tu104_sim_test, multi_param)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value v0 = mme_alloc_reg(&b);
mme_value v1 = mme_alloc_reg(&b);
@@ -323,7 +129,7 @@ TEST_F(mme_tu104_sim_test, multi_param)
TEST_F(mme_tu104_sim_test, pred_param)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value v0 = mme_load(&b);
mme_value v1 = mme_mov(&b, mme_imm(240));
@@ -358,7 +164,7 @@ TEST_F(mme_tu104_sim_test, pred_param)
TEST_F(mme_tu104_sim_test, out_imm0)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_mthd(&b, NVC597_SET_REPORT_SEMAPHORE_A);
mme_emit(&b, mme_imm(high32(data_addr + 0)));
@@ -387,7 +193,7 @@ TEST_F(mme_tu104_sim_test, out_imm0)
TEST_F(mme_tu104_sim_test, out_imm1)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_mthd(&b, NVC597_SET_REPORT_SEMAPHORE_A);
mme_emit(&b, mme_imm(high32(data_addr + 0)));
@@ -416,7 +222,7 @@ TEST_F(mme_tu104_sim_test, out_imm1)
TEST_F(mme_tu104_sim_test, out_immhigh0)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_mthd(&b, NVC597_SET_REPORT_SEMAPHORE_A);
mme_emit(&b, mme_imm(high32(data_addr + 0)));
@@ -445,7 +251,7 @@ TEST_F(mme_tu104_sim_test, out_immhigh0)
TEST_F(mme_tu104_sim_test, out_immhigh1)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_mthd(&b, NVC597_SET_REPORT_SEMAPHORE_A);
mme_emit(&b, mme_imm(high32(data_addr + 0)));
@@ -474,7 +280,7 @@ TEST_F(mme_tu104_sim_test, out_immhigh1)
TEST_F(mme_tu104_sim_test, out_imm32)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_mthd(&b, NVC597_SET_REPORT_SEMAPHORE_A);
mme_emit(&b, mme_imm(high32(data_addr + 0)));
@@ -507,7 +313,7 @@ TEST_F(mme_tu104_sim_test, reg_imm32)
const uint32_t canary = 0xc0ffee01;
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value v = mme_alloc_reg(&b);
@@ -550,7 +356,7 @@ TEST_F(mme_tu104_sim_test, pred_alu)
for (uint32_t i = 0; i < ARRAY_SIZE(preds); i++) {
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value pred = mme_load(&b);
mme_value v0 = mme_mov(&b, mme_imm(i * 100 + 13));
@@ -606,7 +412,7 @@ TEST_F(mme_tu104_sim_test, pred_out)
for (uint32_t i = 0; i < ARRAY_SIZE(preds); i++) {
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value pred = mme_load(&b);
@@ -657,7 +463,7 @@ TEST_F(mme_tu104_sim_test, pred_out)
TEST_F(mme_tu104_sim_test, add)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -676,7 +482,7 @@ TEST_F(mme_tu104_sim_test, add)
TEST_F(mme_tu104_sim_test, add_imm)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
@@ -722,7 +528,7 @@ TEST_F(mme_tu104_sim_test, add_imm)
TEST_F(mme_tu104_sim_test, addc)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
struct mme_value64 x = { mme_load(&b), mme_load(&b) };
struct mme_value64 y = { mme_load(&b), mme_load(&b) };
@@ -746,7 +552,7 @@ TEST_F(mme_tu104_sim_test, addc)
TEST_F(mme_tu104_sim_test, addc_imm)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x_lo = mme_load(&b);
mme_value x_hi = mme_load(&b);
@@ -847,7 +653,7 @@ TEST_F(mme_tu104_sim_test, addc_imm)
TEST_F(mme_tu104_sim_test, sub)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -866,7 +672,7 @@ TEST_F(mme_tu104_sim_test, sub)
TEST_F(mme_tu104_sim_test, subb)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
struct mme_value64 x = { mme_load(&b), mme_load(&b) };
struct mme_value64 y = { mme_load(&b), mme_load(&b) };
@@ -890,7 +696,7 @@ TEST_F(mme_tu104_sim_test, subb)
TEST_F(mme_tu104_sim_test, mul)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -909,7 +715,7 @@ TEST_F(mme_tu104_sim_test, mul)
TEST_F(mme_tu104_sim_test, mul_imm)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
@@ -944,7 +750,7 @@ TEST_F(mme_tu104_sim_test, mul_imm)
TEST_F(mme_tu104_sim_test, mul_mulh)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -972,7 +778,7 @@ mme_mulu(struct mme_builder *b, struct mme_value x, struct mme_value y)
TEST_F(mme_tu104_sim_test, mulu_imm)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
@@ -1007,7 +813,7 @@ TEST_F(mme_tu104_sim_test, mulu_imm)
TEST_F(mme_tu104_sim_test, mulu_mulh)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -1029,7 +835,7 @@ TEST_F(mme_tu104_sim_test, mulu_mulh)
TEST_F(mme_tu104_sim_test, clz)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value bits = mme_clz(&b, mme_load(&b));
mme_store_imm_addr(&b, data_addr, bits);
@@ -1046,7 +852,7 @@ TEST_F(mme_tu104_sim_test, clz)
TEST_F(mme_tu104_sim_test, op) \
{ \
mme_builder b; \
mme_builder_init(&b, &dev->info); \
mme_builder_init(&b, devinfo); \
\
mme_value val = mme_load(&b); \
mme_value shift1 = mme_load(&b); \
@@ -1074,7 +880,7 @@ SHIFT_TEST(sra)
TEST_F(mme_tu104_sim_test, op) \
{ \
mme_builder b; \
mme_builder_init(&b, &dev->info); \
mme_builder_init(&b, devinfo); \
\
mme_value x = mme_load(&b); \
mme_value y = mme_load(&b); \
@@ -1104,7 +910,7 @@ BITOP_TEST(xor)
TEST_F(mme_tu104_sim_test, merge)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -1134,7 +940,7 @@ TEST_F(mme_tu104_sim_test, merge)
TEST_F(mme_tu104_sim_test, op) \
{ \
mme_builder b; \
mme_builder_init(&b, &dev->info); \
mme_builder_init(&b, devinfo); \
\
mme_value x = mme_load(&b); \
mme_value y = mme_load(&b); \
@@ -1191,7 +997,7 @@ mme_inc_whole_inst(mme_builder *b, mme_value val)
TEST_F(mme_tu104_sim_test, loop)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value count = mme_load(&b);
@@ -1231,7 +1037,7 @@ TEST_F(mme_tu104_sim_test, loop)
TEST_F(mme_tu104_sim_test, jal)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_mov(&b, mme_zero());
mme_value y = mme_mov(&b, mme_zero());
@@ -1265,7 +1071,7 @@ TEST_F(mme_tu104_sim_test, jal)
TEST_F(mme_tu104_sim_test, bxx_fwd)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value vals[10];
for (uint32_t i = 0; i < 10; i++)
@@ -1291,7 +1097,7 @@ TEST_F(mme_tu104_sim_test, bxx_fwd)
TEST_F(mme_tu104_sim_test, bxx_bwd)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value vals[15];
for (uint32_t i = 0; i < 15; i++)
@@ -1346,7 +1152,7 @@ static bool c_ine(int32_t x, int32_t y) { return x != y; };
TEST_F(mme_tu104_sim_test, if_##op) \
{ \
mme_builder b; \
mme_builder_init(&b, &dev->info); \
mme_builder_init(&b, devinfo); \
\
mme_value x = mme_load(&b); \
mme_value y = mme_load(&b); \
@@ -1398,7 +1204,7 @@ IF_TEST(ine)
TEST_F(mme_tu104_sim_test, while_##op) \
{ \
mme_builder b; \
mme_builder_init(&b, &dev->info); \
mme_builder_init(&b, devinfo); \
\
mme_value x = mme_mov(&b, mme_zero()); \
mme_value y = mme_mov(&b, mme_zero()); \
@@ -1462,7 +1268,7 @@ WHILE_TEST(ine, 0, 1, 7)
TEST_F(mme_tu104_sim_test, do_ble)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_alu(&b, R5, ADD, LOAD0, ZERO);
mme_alu(&b, R6, ADD, ZERO, ZERO);
@@ -1497,7 +1303,7 @@ TEST_F(mme_tu104_sim_test, do_ble)
TEST_F(mme_tu104_sim_test, dread_dwrite)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -1526,7 +1332,7 @@ TEST_F(mme_tu104_sim_test, dwrite_dma)
const uint32_t canary8 = canary5 & 0x00ffff00;
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value x = mme_load(&b);
mme_value y = mme_load(&b);
@@ -1567,7 +1373,7 @@ TEST_F(mme_tu104_sim_test, dram_limit)
static const uint32_t chunk_size = 32;
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value start = mme_load(&b);
mme_value count = mme_load(&b);
@@ -1609,7 +1415,7 @@ TEST_F(mme_tu104_sim_test, dram_limit)
TEST_F(mme_tu104_sim_test, dma_read_fifoed)
{
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_mthd(&b, NVC597_SET_MME_DATA_RAM_ADDRESS);
mme_emit(&b, mme_zero());
@@ -1647,7 +1453,7 @@ TEST_F(mme_tu104_sim_test, scratch_limit)
static const uint32_t chunk_size = 32;
mme_builder b;
mme_builder_init(&b, &dev->info);
mme_builder_init(&b, devinfo);
mme_value start = mme_load(&b);
mme_value count = mme_load(&b);