diff --git a/src/nouveau/mme/meson.build b/src/nouveau/mme/meson.build index f0db4730c16..74f853b6104 100644 --- a/src/nouveau/mme/meson.build +++ b/src/nouveau/mme/meson.build @@ -109,6 +109,24 @@ idep_nouveau_mme = declare_dependency( ) if with_tests and not with_platform_android + test('mme_builder', + executable( + 'mme_builder_test', + files('tests/mme_runner.cpp', 'tests/mme_builder_test.cpp'), + gnu_symbol_visibility : 'hidden', + include_directories : [inc_include, inc_src], + dependencies : [ + dep_libdrm, + idep_gtest, + idep_mesautil, + idep_nvidia_headers, + idep_nouveau_mme, + idep_nouveau_ws + ], + ), + suite : ['nouveau'], + ) + executable( 'mme_fermi_sim_hw_test', files('tests/mme_runner.cpp', 'tests/mme_fermi_sim_hw_test.cpp'), diff --git a/src/nouveau/mme/tests/mme_builder_test.cpp b/src/nouveau/mme/tests/mme_builder_test.cpp new file mode 100644 index 00000000000..48d720ff963 --- /dev/null +++ b/src/nouveau/mme/tests/mme_builder_test.cpp @@ -0,0 +1,179 @@ +#include "mme_runner.h" +#include "mme_tu104_sim.h" + +#include + +#include "nvk_clc597.h" + +class mme_builder_test : public ::testing::Test { +public: + mme_builder_test(); + ~mme_builder_test(); + + std::vector sims; + uint32_t expected[DATA_DWORDS]; + +private: + mme_fermi_sim_runner fermi_sim; + mme_tu104_sim_runner tu104_sim; +}; + +#define DATA_ADDR 0xc0ffee00 + +mme_builder_test::mme_builder_test() : + fermi_sim(DATA_ADDR), + tu104_sim(DATA_ADDR) +{ + memset(expected, 0, sizeof(expected)); + sims.push_back(&fermi_sim); + sims.push_back(&tu104_sim); +} + +mme_builder_test::~mme_builder_test() +{ } + +#define ASSERT_SIM_DATA(sim) do { \ + for (uint32_t i = 0; i < DATA_DWORDS; i++) \ + ASSERT_EQ((sim)->data[i], expected[i]); \ +} while (0) + +TEST_F(mme_builder_test, sanity) +{ + const uint32_t canary = 0xc0ffee01; + + expected[0] = canary; + + for (auto sim : sims) { + mme_builder b; + mme_builder_init(&b, sim->devinfo); + + sim->mme_store_data(&b, 0, mme_imm(canary)); + + auto macro = mme_builder_finish_vec(&b); + + std::vector params; + sim->run_macro(macro, params); + ASSERT_SIM_DATA(sim); + } +} + +static uint32_t +merge(uint32_t x, uint32_t y, + uint16_t dst_pos, uint16_t bits, uint16_t src_pos) +{ + x &= ~(BITFIELD_MASK(bits) << dst_pos); + y &= (BITFIELD_MASK(bits) << src_pos); + return x | ((y >> src_pos) << dst_pos); +} + +static const uint32_t add_cases[] = { + 0x00000001, + 0xffffffff, + 0x0000ffff, + 0x00008000, + 0x0001ffff, + 0xffff8000, + 0x00010000, + 0x00020000, + 0xfffc0000, + 0xfffe0000, +}; + +TEST_F(mme_builder_test, add) +{ + for (auto sim : sims) { + mme_builder b; + mme_builder_init(&b, sim->devinfo); + + mme_value x = mme_load(&b); + mme_value y = mme_load(&b); + + sim->mme_store_data(&b, 0, mme_add(&b, x, y)); + + auto macro = mme_builder_finish_vec(&b); + + for (uint32_t i = 0; i < ARRAY_SIZE(add_cases); i++) { + for (uint32_t j = 0; j < ARRAY_SIZE(add_cases); j++) { + std::vector params; + params.push_back(add_cases[i]); + params.push_back(add_cases[j]); + + sim->run_macro(macro, params); + ASSERT_EQ(sim->data[0], add_cases[i] + add_cases[j]); + } + } + } +} + +TEST_F(mme_builder_test, add_imm) +{ + for (auto sim : sims) { + mme_builder b; + mme_builder_init(&b, sim->devinfo); + + mme_value x = mme_load(&b); + + for (uint32_t j = 0; j < ARRAY_SIZE(add_cases); j++) { + mme_value y = mme_imm(add_cases[j]); + sim->mme_store_data(&b, j, mme_add(&b, x, y), true); + } + + auto macro = mme_builder_finish_vec(&b); + + for (uint32_t i = 0; i < ARRAY_SIZE(add_cases); i++) { + std::vector params; + params.push_back(add_cases[i]); + + sim->run_macro(macro, params); + + for (uint32_t j = 0; j < ARRAY_SIZE(add_cases); j++) + ASSERT_EQ(sim->data[j], add_cases[i] + add_cases[j]); + } + } +} + +TEST_F(mme_builder_test, merge) +{ + static const struct { + uint16_t dst_pos; + uint16_t bits; + uint16_t src_pos; + } cases[] = { + { 12, 12, 20 }, + { 12, 8, 20 }, + { 8, 12, 20 }, + { 12, 16, 8 }, + { 24, 12, 8 }, + }; + + static const uint32_t x = 0x0c406fe0; + static const uint32_t y = 0x76543210; + + for (uint32_t i = 0; i < ARRAY_SIZE(cases); i++) { + expected[i] = merge(x, y, cases[i].dst_pos, + cases[i].bits, cases[i].src_pos); + } + + for (auto sim : sims) { + mme_builder b; + mme_builder_init(&b, sim->devinfo); + + mme_value xv = mme_load(&b); + mme_value yv = mme_load(&b); + + for (uint32_t i = 0; i < ARRAY_SIZE(cases); i++) { + mme_value mv = mme_merge(&b, xv, yv, cases[i].dst_pos, + cases[i].bits, cases[i].src_pos); + sim->mme_store_data(&b, i, mv, true); + } + + auto macro = mme_builder_finish_vec(&b); + + std::vector params; + params.push_back(x); + params.push_back(y); + + sim->run_macro(macro, params); + ASSERT_SIM_DATA(sim); + } +} diff --git a/src/nouveau/mme/tests/mme_runner.cpp b/src/nouveau/mme/tests/mme_runner.cpp index 542c769b323..440d8a1f6b1 100644 --- a/src/nouveau/mme/tests/mme_runner.cpp +++ b/src/nouveau/mme/tests/mme_runner.cpp @@ -7,6 +7,8 @@ #include "mme_fermi_sim.h" #include "mme_tu104_sim.h" +#include "nvk_clc597.h" + #include "nouveau_bo.h" #include "nouveau_context.h" @@ -29,6 +31,13 @@ mme_hw_runner::mme_hw_runner() : memset(&push, 0, sizeof(push)); } +void +mme_runner::mme_store_data(mme_builder *b, uint32_t dw_idx, + mme_value data, bool free_reg) +{ + mme_store_imm_addr(b, data_addr + dw_idx * 4, data, free_reg); +} + mme_hw_runner::~mme_hw_runner() { if (push_bo) { @@ -178,3 +187,69 @@ mme_hw_runner::run_macro(const std::vector& macro, submit_push(); } + +mme_fermi_sim_runner::mme_fermi_sim_runner(uint64_t data_addr) +{ + memset(&info, 0, sizeof(info)); + info.cls_eng3d = FERMI_A; + + memset(data_store, 0, sizeof(data_store)); + + this->devinfo = &info; + this->data_addr = data_addr, + this->data = data_store; +} + +mme_fermi_sim_runner::~mme_fermi_sim_runner() +{ } + +void +mme_fermi_sim_runner::run_macro(const std::vector& macro, + const std::vector& params) +{ + std::vector insts(macro.size()); + mme_fermi_decode(&insts[0], ¯o[0], macro.size()); + + /* First, make a copy of the data and simulate the macro */ + mme_fermi_sim_mem sim_mem = { + .addr = data_addr, + .data = data, + .size = DATA_BO_SIZE, + }; + mme_fermi_sim(insts.size(), &insts[0], + params.size(), ¶ms[0], + 1, &sim_mem); +} + +mme_tu104_sim_runner::mme_tu104_sim_runner(uint64_t data_addr) +{ + memset(&info, 0, sizeof(info)); + info.cls_eng3d = TURING_A; + + memset(data_store, 0, sizeof(data_store)); + + this->devinfo = &info; + this->data_addr = data_addr, + this->data = data_store; +} + +mme_tu104_sim_runner::~mme_tu104_sim_runner() +{ } + +void +mme_tu104_sim_runner::run_macro(const std::vector& macro, + const std::vector& params) +{ + std::vector insts(macro.size()); + mme_tu104_decode(&insts[0], ¯o[0], macro.size()); + + /* First, make a copy of the data and simulate the macro */ + mme_tu104_sim_mem sim_mem = { + .addr = data_addr, + .data = data, + .size = DATA_BO_SIZE, + }; + mme_tu104_sim(insts.size(), &insts[0], + params.size(), ¶ms[0], + 1, &sim_mem); +} diff --git a/src/nouveau/mme/tests/mme_runner.h b/src/nouveau/mme/tests/mme_runner.h index 8f3cbd5ceb8..d57dda60249 100644 --- a/src/nouveau/mme/tests/mme_runner.h +++ b/src/nouveau/mme/tests/mme_runner.h @@ -11,6 +11,7 @@ struct nouveau_ws_device; #include "nvk_cl9097.h" #define DATA_BO_SIZE 4096 +#define DATA_DWORDS 1024 class mme_runner { public: @@ -20,6 +21,9 @@ public: virtual void run_macro(const std::vector& macro, const std::vector& params) = 0; + void mme_store_data(mme_builder *b, uint32_t dw_idx, + mme_value data, bool free_reg = false); + const nv_device_info *devinfo; uint64_t data_addr; uint32_t *data; @@ -49,6 +53,32 @@ private: struct nv_push push; }; +class mme_fermi_sim_runner : public mme_runner { +public: + mme_fermi_sim_runner(uint64_t data_addr); + virtual ~mme_fermi_sim_runner(); + + virtual void run_macro(const std::vector& macro, + const std::vector& params); + +private: + struct nv_device_info info; + uint32_t data_store[DATA_DWORDS]; +}; + +class mme_tu104_sim_runner : public mme_runner { +public: + mme_tu104_sim_runner(uint64_t data_addr); + virtual ~mme_tu104_sim_runner(); + + virtual void run_macro(const std::vector& macro, + const std::vector& params); + +private: + struct nv_device_info info; + uint32_t data_store[DATA_DWORDS]; +}; + inline std::vector mme_builder_finish_vec(mme_builder *b) {