From 02e093d407bce5107644a9a8cc171af49c9b4ebf Mon Sep 17 00:00:00 2001 From: Krishna Yalamarthy Date: Fri, 26 Mar 2021 11:26:20 -0400 Subject: [PATCH 1/2] partial update sampler unit test --- hw/unit_tests/tex_unit/tex_sampler/Makefile | 30 +++ hw/unit_tests/tex_unit/tex_sampler/main.cpp | 215 ++++++++++++++++++ .../tex_unit/tex_sampler/vl_simulator.h | 81 +++++++ 3 files changed, 326 insertions(+) create mode 100644 hw/unit_tests/tex_unit/tex_sampler/Makefile create mode 100644 hw/unit_tests/tex_unit/tex_sampler/main.cpp create mode 100644 hw/unit_tests/tex_unit/tex_sampler/vl_simulator.h diff --git a/hw/unit_tests/tex_unit/tex_sampler/Makefile b/hw/unit_tests/tex_unit/tex_sampler/Makefile new file mode 100644 index 00000000..c6de8aa1 --- /dev/null +++ b/hw/unit_tests/tex_unit/tex_sampler/Makefile @@ -0,0 +1,30 @@ +TOP = VX_tex_sampler + +PARAMS ?= + +INCLUDE = -I../../../rtl/ -I../../../rtl/libs -I../../../rtl/tex_unit + +SRCS = main.cpp + +all: build + +CF += -std=c++11 -fms-extensions -I../.. +VF += $(PARAMS) + +VF += --language 1800-2009 --assert -Wall --trace +VF += -Wno-DECLFILENAME +VF += --x-initial unique +VF += -exe $(SRCS) $(INCLUDE) +VF += $(PARAMS) + +gen: + verilator $(VF) -cc $(TOP).v -CFLAGS '$(CF)' --exe $(SRCS) + +build: gen + (cd obj_dir && make -j -f V$(TOP).mk) + +run: build + (cd obj_dir && ./V$(TOP)) + +clean: + rm -rf obj_dir diff --git a/hw/unit_tests/tex_unit/tex_sampler/main.cpp b/hw/unit_tests/tex_unit/tex_sampler/main.cpp new file mode 100644 index 00000000..a67b38cb --- /dev/null +++ b/hw/unit_tests/tex_unit/tex_sampler/main.cpp @@ -0,0 +1,215 @@ +#include "vl_simulator.h" +#include "VVX_tex_sampler.h" +#include +#include + +#define MAX_TICKS 20 +#define MAX_UNIT_CYCLES 5 +#define NUM_THREADS + +#define CHECK(x) \ + do { \ + if (x) \ + break; \ + std::cout << "FAILED: " << #x << std::endl; \ + std::abort(); \ + } while (false) + +uint64_t ticks = 0; + +// using Device = VVX_tex_sampler; + +template +class testbench +{ +private: + vl_simulator sim; + std::map input_map; + std::map output_map; + +public: + + struct UnitTest { + bool use_reset; + unsigned int num_cycles; + bool use_cmodel; + struct Output outputs[MAX_UNIT_CYCLES]; + struct Input inputs[MAX_UNIT_CYCLES]; + unsigned int num_output_check; + unsigned int check_output_cycle[MAX_UNIT_CYCLES]; + } + + struct Input { + bool req_valid; + unsigned int req_wid; + unsigned int req_tmask; + unsigned int req_PC; + unsigned int req_rd; + unsigned int req_wb; + unsigned int req_filter; + unsigned int req_format; + unsigned int req_u[NUM_THREADS]; + unsigned int req_v[NUM_THREADS]; + unsigned int req_texels[NUM_THREADS][4]; + bool rsp_ready; + } + + struct Output { + int output_cycle; + // outputs + bool req_ready; + bool rsp_valid; + unsigned int rsp_wid; + unsigned int rsp_tmask; + unsigned int rsp_PC; + unsigned int rsp_rd; + bool rsp_wb; + unsigned int rsp_data[NUM_THREADS]; + } + + testbench(/* args */){ + + } + + ~testbench(){ + } + + void unittest_Cmodel(struct UnitTest * test){ + int cycles = test->num_cycles; + int num_outputs = test->num_output_check; + + // struct Input* inputs = new (struct Input)[cycles]; + struct Output* outputs = new (struct Output)[num_outputs]; + + // implement c model and assign outputs to struct + + if (test->inputs[0]->req_filter == 0){ + for (int i = 0; i < NUM_THREADS; i++) + outputs[0]->rsp_data[0] = test->inputs->req_texels[i][0]; + } else { + // for (int i = 0; i < NUM_THREADS; i++){ + // uint32_t low[4], high[4]; + // for (int j = 0; j < 4; j++){ + // low[j] = test->inputs->req_texels[i][j] & 0x00ff00ff; + // high[j] = (test->inputs->req_texels[i][j] >> 8) & 0x00ff00ff; + // } + + // } + } + outputs[0]->output_cycle = 1; + test->num_cycles = 1; + test->outputs = &outputs; + + } + + void generate_test_vectors(struct UnitTest * tests, int num_tests, bool is_pipe){ + // for all unit tests create output test vectors (w w/o c-model) + int prev_test_cycle = 0; + + for (int i = 0; i < num_tests; i++) + { + int op_counter = 0; + int ip_counter = 0; + + int test_cycle = 0; + int last_ip_cycle = 0; + + struct UnitTest curr_test = tests[i]; + + if (curr_test->use_cmodel){ + unittest_Cmodel(&curr_test); + } + + for (int j = 0; j < curr_test->num_cycles; j++) + { + if (curr_test->inputs[ip_counter]->input_cycle == test_cycle){ + input_map.insert(std::make_pair(prev_test_cycle + test_cycle, curr_test->inputs[j])); + last_ip_cycle = prev_test_cycle + test_cycle; + ip_counter++; + } + + if (curr_test->outputs[op_counter]->output_cycle == test_cycle){ + output_map.insert(std::make_pair(prev_test_cycle + test_cycle, curr_test->outputs[op_counter])); + op_counter++; + } + + test_cycle++; + } + + if(!is_pipe){ + prev_test_cycle += (test_cycle - 1); + } + else{ + prev_test_cycle = last_ip_cycle + 1; + } + + } + + } + + void run(){ + + ticks = sim.reset(0); + int cycle = 0; + + while (ticks < MAX_TICKS) { + + auto input = input_map.find(cycle); + auto output = output_map.find(cycle); + + if (input != input_map.end()){ + sim->req_valid = input->req_valid; + sim->req_wid = input->req_wid; + sim->req_tmask = input->req_tmask; + sim->req_PC = input->req_PC; + sim->req_rd = input->req_rd; + sim->req_wb = input->req_wb; + sim->req_filter = input->req_filter; + sim->req_format = input->req_format; + // sim->req_u = input->req_u[NUM_THREADS]; + // sim->req_v = input->req_v[NUM_THREADS]; + vl_setw(sim->req_texels, input->req_texels) + // sim->req_texels = input->req_texels[NUM_THREADS][4]; + sim->rsp_ready = input->rsp_ready; + } else{ + std::cout << "Warning! No Input on Cycle " << cycle << std::endl; + } + + if(output != output_map.end()){ + CHECK(sim->req_ready == output->req_ready); + CHECK(sim->rsp_valid == output->rsp_valid); + CHECK(sim->rsp_wid == output->rsp_wid); + CHECK(sim->rsp_tmask == output->rsp_tmask); + CHECK(sim->rsp_PC == output->rsp_PC); + CHECK(sim->rsp_rd == output->rsp_rd); + CHECK(sim->rsp_wb == output->rsp_wb); + CHECK(vl_cmpw(sim->rsp_data, output->rsp_data)); + } + + cycle++; + ticks = sim.step(ticks,2); + } + } + + std::cout << "PASSED!" << std::endl; + std::cout << "Simulation time: " << std::dec << ticks/2 << " cycles" << std::endl; + +}; + + +double sc_time_stamp() { + return ticks; +} + +int main(int argc, char **argv) { + // Initialize Verilators variables + Verilated::commandArgs(argc, argv); + + testbench sampler_testbench; + + sampler_testbench.generate_test_vectors(tests, 1, 0); + sampler_test_bench.run(); + + + return 0; +} \ No newline at end of file diff --git a/hw/unit_tests/tex_unit/tex_sampler/vl_simulator.h b/hw/unit_tests/tex_unit/tex_sampler/vl_simulator.h new file mode 100644 index 00000000..16486adf --- /dev/null +++ b/hw/unit_tests/tex_unit/tex_sampler/vl_simulator.h @@ -0,0 +1,81 @@ +#pragma once + +#include +#include +#include "verilated.h" + +#ifdef VM_TRACE +#include // Trace file format header +#endif + +template +class vl_simulator { +private: + + T top_; +#ifdef VM_TRACE + VerilatedVcdC tfp_; +#endif + +public: + + vl_simulator() { + top_.clk = 0; + top_.reset = 0; + #ifdef VM_TRACE + Verilated::traceEverOn(true); + top_.trace(&tfp_, 99); + tfp_.open("trace.vcd"); + #endif + } + + ~vl_simulator() { + #ifdef VM_TRACE + tfp_.close(); + #endif + top_.final(); + } + + uint64_t reset(uint64_t ticks) { + top_.reset = 1; + ticks = this->step(ticks, 2); + top_.reset = 0; + return ticks; + } + + uint64_t step(uint64_t ticks, uint32_t count = 1) { + while (count--) { + top_.eval(); + #ifdef VM_TRACE + tfp_.dump(ticks); + #endif + top_.clk = !top_.clk; + ++ticks; + } + return ticks; + } + + T* operator->() { + return &top_; + } +}; + +template +void vl_setw(uint32_t* sig, Args&&... args) { + std::array arr{static_cast(std::forward(args))...}; + for (size_t i = 0; i < sizeof... (Args); ++i) { + sig[i] = arr[i]; + } +} + +template +int vl_cmpw(const uint32_t* sig, Args&&... args) { + std::array arr{static_cast(std::forward(args))...}; + for (size_t i = 0; i < sizeof... (Args); ++i) { + if (sig[i] < arr[i]) + return -1; + if (sig[i] > arr[i]) + return 1; + } + return 0; +} \ No newline at end of file From c1e25135fd7c52ad342eaf3d7c5ba8db7387ef3e Mon Sep 17 00:00:00 2001 From: Krishna Yalamarthy Date: Sat, 27 Mar 2021 19:35:14 -0400 Subject: [PATCH 2/2] tex sampler unit test pass - pt sampling, rgba8 --- hw/rtl/tex_unit/VX_tex_sampler.v | 13 +- hw/unit_tests/tex_unit/tex_sampler/main.cpp | 314 +++++++----------- .../tex_unit/tex_sampler/main.cpp.copy | 215 ++++++++++++ .../tex_unit/tex_sampler/vl_simulator.h | 35 ++ 4 files changed, 382 insertions(+), 195 deletions(-) create mode 100644 hw/unit_tests/tex_unit/tex_sampler/main.cpp.copy diff --git a/hw/rtl/tex_unit/VX_tex_sampler.v b/hw/rtl/tex_unit/VX_tex_sampler.v index 7b623d6b..3db8e09d 100644 --- a/hw/rtl/tex_unit/VX_tex_sampler.v +++ b/hw/rtl/tex_unit/VX_tex_sampler.v @@ -54,18 +54,11 @@ module VX_tex_sampler #( .formatted_texel(formatted_data) ); - //blendU/blendV calculation - wire [`BLEND_FRAC_64-1:0] blendU; - wire [`BLEND_FRAC_64-1:0] blendV; - - assign blendU = req_u[i][`BLEND_FRAC_64-1:0]; - assign blendV = req_v[i][`BLEND_FRAC_64-1:0]; - VX_tex_bilerp #( .CORE_ID (CORE_ID) ) tex_bilerp ( - .blendU(blendU), //blendU - .blendV(blendV), //blendV + .blendU(req_u[i][`BLEND_FRAC_64-1:0]), //blendU + .blendV(req_v[i][`BLEND_FRAC_64-1:0]), //blendV .color_enable(color_enable), .texels(formatted_data), @@ -76,7 +69,7 @@ module VX_tex_sampler #( end for (genvar i = 0;i<`NUM_THREADS ;i++ ) begin - assign req_data[i] = (req_filter == `TEX_FILTER_BITS'h0) ? req_texels[i][0] : req_data_bilerp[i]; + assign req_data[i] = (req_filter == `TEX_FILTER_BITS'(0)) ? req_texels[i][0] : req_data_bilerp[i]; end assign stall_out = ~rsp_ready; diff --git a/hw/unit_tests/tex_unit/tex_sampler/main.cpp b/hw/unit_tests/tex_unit/tex_sampler/main.cpp index a67b38cb..aac3bc22 100644 --- a/hw/unit_tests/tex_unit/tex_sampler/main.cpp +++ b/hw/unit_tests/tex_unit/tex_sampler/main.cpp @@ -1,12 +1,52 @@ #include "vl_simulator.h" #include "VVX_tex_sampler.h" #include -#include #define MAX_TICKS 20 -#define MAX_UNIT_CYCLES 5 #define NUM_THREADS + + + // // outputs + // bool req_ready; + // bool rsp_valid; + // unsigned int rsp_wid; + // unsigned int rsp_tmask; + // unsigned int rsp_PC; + // unsigned int rsp_rd; + // bool rsp_wb; + // unsigned int rsp_data[NUM_THREADS]; + + + // if (input != input_map.end()){ + // sim->req_valid = input->req_valid; + // sim->req_wid = input->req_wid; + // sim->req_tmask = input->req_tmask; + // sim->req_PC = input->req_PC; + // sim->req_rd = input->req_rd; + // sim->req_wb = input->req_wb; + // sim->req_filter = input->req_filter; + // sim->req_format = input->req_format; + // // sim->req_u = input->req_u[NUM_THREADS]; + // // sim->req_v = input->req_v[NUM_THREADS]; + // vl_setw(sim->req_texels, input->req_texels) + // // sim->req_texels = input->req_texels[NUM_THREADS][4]; + // sim->rsp_ready = input->rsp_ready; + // } else{ + // std::cout << "Warning! No Input on Cycle " << cycle << std::endl; + // } + + // if(output != output_map.end()){ + // CHECK(sim->req_ready == output->req_ready); + // CHECK(sim->rsp_valid == output->rsp_valid); + // CHECK(sim->rsp_wid == output->rsp_wid); + // CHECK(sim->rsp_tmask == output->rsp_tmask); + // CHECK(sim->rsp_PC == output->rsp_PC); + // CHECK(sim->rsp_rd == output->rsp_rd); + // CHECK(sim->rsp_wb == output->rsp_wb); + // CHECK(vl_cmpw(sim->rsp_data, output->rsp_data)); + // } + #define CHECK(x) \ do { \ if (x) \ @@ -17,199 +57,103 @@ uint64_t ticks = 0; -// using Device = VVX_tex_sampler; - -template -class testbench -{ -private: - vl_simulator sim; - std::map input_map; - std::map output_map; - -public: - - struct UnitTest { - bool use_reset; - unsigned int num_cycles; - bool use_cmodel; - struct Output outputs[MAX_UNIT_CYCLES]; - struct Input inputs[MAX_UNIT_CYCLES]; - unsigned int num_output_check; - unsigned int check_output_cycle[MAX_UNIT_CYCLES]; - } - - struct Input { - bool req_valid; - unsigned int req_wid; - unsigned int req_tmask; - unsigned int req_PC; - unsigned int req_rd; - unsigned int req_wb; - unsigned int req_filter; - unsigned int req_format; - unsigned int req_u[NUM_THREADS]; - unsigned int req_v[NUM_THREADS]; - unsigned int req_texels[NUM_THREADS][4]; - bool rsp_ready; - } - - struct Output { - int output_cycle; - // outputs - bool req_ready; - bool rsp_valid; - unsigned int rsp_wid; - unsigned int rsp_tmask; - unsigned int rsp_PC; - unsigned int rsp_rd; - bool rsp_wb; - unsigned int rsp_data[NUM_THREADS]; - } - - testbench(/* args */){ - - } - - ~testbench(){ - } - - void unittest_Cmodel(struct UnitTest * test){ - int cycles = test->num_cycles; - int num_outputs = test->num_output_check; - - // struct Input* inputs = new (struct Input)[cycles]; - struct Output* outputs = new (struct Output)[num_outputs]; - - // implement c model and assign outputs to struct - - if (test->inputs[0]->req_filter == 0){ - for (int i = 0; i < NUM_THREADS; i++) - outputs[0]->rsp_data[0] = test->inputs->req_texels[i][0]; - } else { - // for (int i = 0; i < NUM_THREADS; i++){ - // uint32_t low[4], high[4]; - // for (int j = 0; j < 4; j++){ - // low[j] = test->inputs->req_texels[i][j] & 0x00ff00ff; - // high[j] = (test->inputs->req_texels[i][j] >> 8) & 0x00ff00ff; - // } - - // } - } - outputs[0]->output_cycle = 1; - test->num_cycles = 1; - test->outputs = &outputs; - - } - - void generate_test_vectors(struct UnitTest * tests, int num_tests, bool is_pipe){ - // for all unit tests create output test vectors (w w/o c-model) - int prev_test_cycle = 0; - - for (int i = 0; i < num_tests; i++) - { - int op_counter = 0; - int ip_counter = 0; - - int test_cycle = 0; - int last_ip_cycle = 0; - - struct UnitTest curr_test = tests[i]; - - if (curr_test->use_cmodel){ - unittest_Cmodel(&curr_test); - } - - for (int j = 0; j < curr_test->num_cycles; j++) - { - if (curr_test->inputs[ip_counter]->input_cycle == test_cycle){ - input_map.insert(std::make_pair(prev_test_cycle + test_cycle, curr_test->inputs[j])); - last_ip_cycle = prev_test_cycle + test_cycle; - ip_counter++; - } - - if (curr_test->outputs[op_counter]->output_cycle == test_cycle){ - output_map.insert(std::make_pair(prev_test_cycle + test_cycle, curr_test->outputs[op_counter])); - op_counter++; - } - - test_cycle++; - } - - if(!is_pipe){ - prev_test_cycle += (test_cycle - 1); - } - else{ - prev_test_cycle = last_ip_cycle + 1; - } - - } - - } - - void run(){ - - ticks = sim.reset(0); - int cycle = 0; - - while (ticks < MAX_TICKS) { - - auto input = input_map.find(cycle); - auto output = output_map.find(cycle); - - if (input != input_map.end()){ - sim->req_valid = input->req_valid; - sim->req_wid = input->req_wid; - sim->req_tmask = input->req_tmask; - sim->req_PC = input->req_PC; - sim->req_rd = input->req_rd; - sim->req_wb = input->req_wb; - sim->req_filter = input->req_filter; - sim->req_format = input->req_format; - // sim->req_u = input->req_u[NUM_THREADS]; - // sim->req_v = input->req_v[NUM_THREADS]; - vl_setw(sim->req_texels, input->req_texels) - // sim->req_texels = input->req_texels[NUM_THREADS][4]; - sim->rsp_ready = input->rsp_ready; - } else{ - std::cout << "Warning! No Input on Cycle " << cycle << std::endl; - } - - if(output != output_map.end()){ - CHECK(sim->req_ready == output->req_ready); - CHECK(sim->rsp_valid == output->rsp_valid); - CHECK(sim->rsp_wid == output->rsp_wid); - CHECK(sim->rsp_tmask == output->rsp_tmask); - CHECK(sim->rsp_PC == output->rsp_PC); - CHECK(sim->rsp_rd == output->rsp_rd); - CHECK(sim->rsp_wb == output->rsp_wb); - CHECK(vl_cmpw(sim->rsp_data, output->rsp_data)); - } - - cycle++; - ticks = sim.step(ticks,2); - } - } - - std::cout << "PASSED!" << std::endl; - std::cout << "Simulation time: " << std::dec << ticks/2 << " cycles" << std::endl; - -}; - - double sc_time_stamp() { return ticks; } +using Device = VVX_tex_sampler; + int main(int argc, char **argv) { // Initialize Verilators variables Verilated::commandArgs(argc, argv); - testbench sampler_testbench; + vl_simulator sim; - sampler_testbench.generate_test_vectors(tests, 1, 0); - sampler_test_bench.run(); + // run test + ticks = sim.reset(0); + while (ticks < MAX_TICKS) { + switch (ticks) { + case 0: + std::cout << "cycle 1" << std::endl; + // input values + sim->req_valid = 1; + sim->req_wid = 3; + sim->req_tmask = 11; + sim->req_PC = 0x0505; + sim->req_wb = 1; + sim->req_filter = 0; + sim->req_format = 3; + sim->rsp_ready = 1; + break; + + case 2: + std::cout << "cycle 2" << std::endl; + sim->req_valid = 1; + sim->req_wid = 0; + sim->req_tmask = 15; + sim->req_PC = 0x0515; + sim->req_wb = 1; + sim->req_filter = 0; + sim->req_format = 3; + vl_setw(sim->req_texels, 0xffff, 0xfffa, 0xfffb, 0xfffc, + 0xfffd, 0xafff, 0xbfff, 0xcfff, + 0xdfff, 0xabcd, 0xdfdd, 0xeabf, + 0xaaaa, 0xbbbb, 0xcccc, 0xdddd); + sim->rsp_ready = 1; + + break; + case 4: + //bilerp input r8b8g8a8 + std::cout << "cycle 3: point sampling check" << std::endl; + + sim->req_valid = 1; + sim->rsp_ready = 1; + sim->req_wid = 0; + sim->req_tmask = 15; + sim->req_PC = 0x0519; + // sim->req_rd = req_rd; + sim->req_wb = 1; + sim->req_filter = 1; + sim->req_format = 3; + /* + 1u ------- 0u 1v ------- 1v tex0 ------- tex1 + | | | | | | + | | | | | | + | | | | | | + 1u ------- 0u 0v ------- 0v tex2 ------- tex3 + */ + vl_packsetw(sim->req_u, 20, 0x0080, 0x0000, 0x0080, 0x0040); // 1/2, 0, 1/2, 1/4 + vl_packsetw(sim->req_v, 20, 0x0000, 0x0080, 0x0080, 0x0040); // 0, 1/2, 1/2, 1/4 + // vl_setw(sim->req_texels, 0xffff, 0xfffa, 0xfffb, 0xfffc, 0xfffd, 0xafff, 0xbfff, 0xcfff, 0xdfff, 0xabcd, 0xdfdd, 0xeabf, 0xaaaa, 0xbbbb, 0xcccc, 0xdddd); + // vl_setw(sim->req_texels, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000); + vl_setw(sim->req_texels, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, + 0x00000000, 0xffffffff, 0x00000000, 0x00000000, + 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, + 0xffffffff, 0x00000000, 0xffffffff, 0x00000000); + + // point sampling output check + CHECK(!vl_cmpw(sim->rsp_data, 0xffff, 0xfffd, 0xdfff, 0xaaaa)); + + break; + + case 6: + + sim->req_valid = 1; + sim->rsp_ready = 1; + // bilerp sampling output check + + std::cout << "cycle 4: bilerp r8g8b8a8 check" << std::endl; + CHECK(!vl_cmpw(sim->rsp_data, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x3f3f3f3f)); + + } + + // advance clock + ticks = sim.step(ticks, 2); + } + + std::cout << "PASSED!" << std::endl; + std::cout << "Simulation time: " << std::dec << ticks/2 << " cycles" << std::endl; return 0; } \ No newline at end of file diff --git a/hw/unit_tests/tex_unit/tex_sampler/main.cpp.copy b/hw/unit_tests/tex_unit/tex_sampler/main.cpp.copy new file mode 100644 index 00000000..d60be3f6 --- /dev/null +++ b/hw/unit_tests/tex_unit/tex_sampler/main.cpp.copy @@ -0,0 +1,215 @@ +#include "vl_simulator.h" +#include "VVX_tex_sampler.h" +#include +#include + +#define MAX_TICKS 20 +#define MAX_UNIT_CYCLES 5 +#define NUM_THREADS + +#define CHECK(x) \ + do { \ + if (x) \ + break; \ + std::cout << "FAILED: " << #x << std::endl; \ + std::abort(); \ + } while (false) + +uint64_t ticks = 0; + +// using Device = VVX_tex_sampler; + +template +class testbench +{ +private: + vl_simulator sim; + std::map input_map; + std::map output_map; + +public: + + struct UnitTest { + bool use_reset; + unsigned int num_cycles; + bool use_cmodel; + struct Output outputs[MAX_UNIT_CYCLES]; + struct Input inputs[MAX_UNIT_CYCLES]; + unsigned int num_output_check; + unsigned int check_output_cycle[MAX_UNIT_CYCLES]; + } + + struct Input { + bool req_valid; + unsigned int req_wid; + unsigned int req_tmask; + unsigned int req_PC; + unsigned int req_rd; + unsigned int req_wb; + unsigned int req_filter; + unsigned int req_format; + unsigned int req_u[NUM_THREADS]; + unsigned int req_v[NUM_THREADS]; + unsigned int req_texels[NUM_THREADS][4]; + bool rsp_ready; + } + + struct Output { + int output_cycle; + // outputs + bool req_ready; + bool rsp_valid; + unsigned int rsp_wid; + unsigned int rsp_tmask; + unsigned int rsp_PC; + unsigned int rsp_rd; + bool rsp_wb; + unsigned int rsp_data[NUM_THREADS]; + } + + testbench(/* args */){ + + } + + ~testbench(){ + } + + void unittest_Cmodel(struct UnitTest * test){ + int cycles = test->num_cycles; + int num_outputs = test->num_output_check; + + // struct Input* inputs = new (struct Input)[cycles]; + struct Output* outputs = new (struct Output)[num_outputs]; + + // implement c model and assign outputs to struct + + if (test->inputs[0]->req_filter == 0){ + for (int i = 0; i < NUM_THREADS; i++) + outputs[0]->rsp_data[0] = test->inputs->req_texels[i][0]; + } else { + // for (int i = 0; i < NUM_THREADS; i++){ + // uint32_t low[4], high[4]; + // for (int j = 0; j < 4; j++){ + // low[j] = test->inputs->req_texels[i][j] & 0x00ff00ff; + // high[j] = (test->inputs->req_texels[i][j] >> 8) & 0x00ff00ff; + // } + + // } + } + outputs[0]->output_cycle = 1; + test->num_cycles = 1; + test->outputs = &outputs; + + } + + void generate_test_vectors(struct UnitTest * tests, int num_tests, bool is_pipe){ + // for all unit tests create output test vectors (w w/o c-model) + int prev_test_cycle = 0; + + for (int i = 0; i < num_tests; i++) + { + int op_counter = 0; + int ip_counter = 0; + + int test_cycle = 0; + int last_ip_cycle = 0; + + struct UnitTest curr_test = tests[i]; + + if (curr_test->use_cmodel){ + unittest_Cmodel(&curr_test); + } + + for (int j = 0; j < curr_test->num_cycles; j++) + { + if (curr_test->inputs[ip_counter]->input_cycle == test_cycle){ + input_map.insert(std::make_pair(prev_test_cycle + test_cycle, curr_test->inputs[j])); + last_ip_cycle = prev_test_cycle + test_cycle; + ip_counter++; + } + + if (curr_test->outputs[op_counter]->output_cycle == test_cycle){ + output_map.insert(std::make_pair(prev_test_cycle + test_cycle, curr_test->outputs[op_counter])); + op_counter++; + } + + test_cycle++; + } + + if(!is_pipe){ + prev_test_cycle += (test_cycle - 1); + } + else{ + prev_test_cycle = last_ip_cycle + 1; + } + + } + + } + + void run(){ + + ticks = sim.reset(0); + int cycle = 0; + + while (ticks < MAX_TICKS) { + + auto input = input_map.find(cycle); + auto output = output_map.find(cycle); + + if (input != input_map.end()){ + sim->req_valid = input->req_valid; + sim->req_wid = input->req_wid; + sim->req_tmask = input->req_tmask; + sim->req_PC = input->req_PC; + sim->req_rd = input->req_rd; + sim->req_wb = input->req_wb; + sim->req_filter = input->req_filter; + sim->req_format = input->req_format; + // sim->req_u = input->req_u[NUM_THREADS]; + // sim->req_v = input->req_v[NUM_THREADS]; + vl_setw(sim->req_texels, input->req_texels) + // sim->req_texels = input->req_texels[NUM_THREADS][4]; + sim->rsp_ready = input->rsp_ready; + } else{ + std::cout << "Warning! No Input on Cycle " << cycle << std::endl; + } + + if(output != output_map.end()){ + CHECK(sim->req_ready == output->req_ready); + CHECK(sim->rsp_valid == output->rsp_valid); + CHECK(sim->rsp_wid == output->rsp_wid); + CHECK(sim->rsp_tmask == output->rsp_tmask); + CHECK(sim->rsp_PC == output->rsp_PC); + CHECK(sim->rsp_rd == output->rsp_rd); + CHECK(sim->rsp_wb == output->rsp_wb); + CHECK(vl_cmpw(sim->rsp_data, output->rsp_data)); + } + + cycle++; + ticks = sim.step(ticks,2); + } + } + + std::cout << "PASSED!" << std::endl; + std::cout << "Simulation time: " << std::dec << ticks/2 << " cycles" << std::endl; + +}; + + +double sc_time_stamp() { + return ticks; +} + +int main(int argc, char **argv) { + // Initialize Verilators variables + Verilated::commandArgs(argc, argv); + + testbench sampler_testbench; + + sampler_testbench.generate_test_vectors(tests, 1, 0); + sampler_testbench.run(); + + + return 0; +} \ No newline at end of file diff --git a/hw/unit_tests/tex_unit/tex_sampler/vl_simulator.h b/hw/unit_tests/tex_unit/tex_sampler/vl_simulator.h index 16486adf..a868979b 100644 --- a/hw/unit_tests/tex_unit/tex_sampler/vl_simulator.h +++ b/hw/unit_tests/tex_unit/tex_sampler/vl_simulator.h @@ -3,6 +3,7 @@ #include #include #include "verilated.h" +#include #ifdef VM_TRACE #include // Trace file format header @@ -68,6 +69,40 @@ void vl_setw(uint32_t* sig, Args&&... args) { } } +template +void vl_packsetw(uint32_t* sig, int in_width, Args&&... args) { + std::array arr{static_cast(std::forward(args))...}; + std::array packed_arr; + + int rem = in_width; + size_t j = 0; + + for (size_t i = 0; i < (sizeof... (Args)*in_width)/32 + 1; ++i) { + packed_arr[i] = 0; + int bits = 0; + while (bits<32) + { + if (32-bits>rem) + { + packed_arr[i] = ( ( (arr[j] & ( ((1<> in_width-rem) << bits ) | packed_arr[i]; + bits += rem; + rem = in_width; + j++; + } + else + { + packed_arr[i] = (arr[j] & ((1< int vl_cmpw(const uint32_t* sig, Args&&... args) { std::array arr{static_cast(std::forward(args))...};