--- /dev/null
+#include "mme_runner.h"
+#include "mme_tu104_sim.h"
+
+#include <vector>
+
+#include "nvk_clc597.h"
+
+class mme_builder_test : public ::testing::Test {
+public:
+ mme_builder_test();
+ ~mme_builder_test();
+
+ std::vector<mme_runner *> 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<uint32_t> 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<uint32_t> 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<uint32_t> 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<uint32_t> params;
+ params.push_back(x);
+ params.push_back(y);
+
+ sim->run_macro(macro, params);
+ ASSERT_SIM_DATA(sim);
+ }
+}
#include "mme_fermi_sim.h"
#include "mme_tu104_sim.h"
+#include "nvk_clc597.h"
+
#include "nouveau_bo.h"
#include "nouveau_context.h"
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) {
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<uint32_t>& macro,
+ const std::vector<uint32_t>& params)
+{
+ std::vector<mme_fermi_inst> 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<uint32_t>& macro,
+ const std::vector<uint32_t>& params)
+{
+ std::vector<mme_tu104_inst> 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);
+}
#include "nvk_cl9097.h"
#define DATA_BO_SIZE 4096
+#define DATA_DWORDS 1024
class mme_runner {
public:
virtual void run_macro(const std::vector<uint32_t>& macro,
const std::vector<uint32_t>& 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;
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<uint32_t>& macro,
+ const std::vector<uint32_t>& 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<uint32_t>& macro,
+ const std::vector<uint32_t>& params);
+
+private:
+ struct nv_device_info info;
+ uint32_t data_store[DATA_DWORDS];
+};
+
inline std::vector<uint32_t>
mme_builder_finish_vec(mme_builder *b)
{