Add support for mako templated tests to softrvv. Change-Id: Ic2a7fbae0af62882dbc611114fcf921fe2334342
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f2c4bb..5ba1680 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -30,6 +30,8 @@ include(vec_cc_binary) include(vec_cc_test) include(vec_cc_generated_test) +include(softrvv_vec_cc_generated_test) + add_subdirectory(springbok) add_subdirectory(hello_vec)
diff --git a/cmake/softrvv_vec_cc_generated_test.cmake b/cmake/softrvv_vec_cc_generated_test.cmake new file mode 100644 index 0000000..38893b7 --- /dev/null +++ b/cmake/softrvv_vec_cc_generated_test.cmake
@@ -0,0 +1,42 @@ +function(softrvv_vec_cc_generated_test) + cmake_parse_arguments( + _RULE + "" + "NAME" + "TEMPLATE;LINKOPTS;TIMEOUT" + ${ARGN} + ) + +set(_TEST_NAME "softrvv_${_RULE_NAME}_test") +set(_OP_CODE ${_RULE_NAME}) +string(REPLACE ".tpl" "" _TEST_SRC_FILENAME ${_RULE_TEMPLATE}) + +set(_TEST_SRC ${CMAKE_CURRENT_BINARY_DIR}/generated/${_TEST_SRC_FILENAME}) +find_file(_SOFTRVV_GEN_VEC_SCRIPT generate_softrvv_vector_tests.py ${CMAKE_SOURCE_DIR}/scripts) +add_custom_command( + OUTPUT + ${_TEST_SRC} + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/templates/${_RULE_TEMPLATE} + ${CMAKE_CURRENT_SOURCE_DIR}/templates/base.tpl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/templates/opivv_opivx_test.tpl.cpp + COMMAND python3 ${_SOFTRVV_GEN_VEC_SCRIPT} + --template-path=${CMAKE_CURRENT_SOURCE_DIR}/templates/ + --template=${_RULE_TEMPLATE} + --out-path=${CMAKE_CURRENT_BINARY_DIR}/generated/ + --op=${_OP_CODE} +) + +vec_cc_test( + NAME + ${_TEST_NAME} + SRCS + ${_TEST_SRC} + DEPS + softrvv + LINKOPTS + ${_RULE_LINKOPTS} + TIMEOUT + ${_RULE_TIMEOUT} +) +endfunction()
diff --git a/scripts/generate_softrvv_vector_tests.py b/scripts/generate_softrvv_vector_tests.py new file mode 100644 index 0000000..9e337bd --- /dev/null +++ b/scripts/generate_softrvv_vector_tests.py
@@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +""" +Generate tests for softrvv +TODO(henryherman) Look into combining the different template workflows +""" +import os +import logging +import argparse +from collections import namedtuple +from pathlib import Path + +from mako.lookup import TemplateLookup +import mako.exceptions + +parser = argparse.ArgumentParser( + description='Generate tests for vector instructions.') + +parser.add_argument('--template-path', dest='template_path', + help='path to templates', required=True) +parser.add_argument('--template', dest='template_name', + help='template name', required=True) +parser.add_argument('-v', '--verbose', help='increase output verbosity', + action='store_true') +parser.add_argument('--out-path', dest='out_path', + help='Path to output files', default='.') +parser.add_argument('--op', dest='op', + help='op instruction', default='') + +args = parser.parse_args() + +if args.verbose: + logging.basicConfig(level=logging.DEBUG) + +def main(): + """ Main routine for generating softrvv tests from templates.""" + mylookup = TemplateLookup(directories=[args.template_path, "."]) + try: + template = mylookup.get_template(args.template_name) + except mako.exceptions.TopLevelLookupException: + parser.error("Template does not exist %s" % args.template_name) + logging.debug("Template %s found", args.template_name) + Path(args.out_path).mkdir(parents=True, exist_ok=True) + outfile_name = args.template_name.replace(".tpl", "") + full_outfile_path = os.path.join(args.out_path, outfile_name) + logging.debug("Generating file %s", full_outfile_path) + with open(full_outfile_path, "w+") as outfile: + outfile.write(template.render(op=args.op)) + +if __name__ == "__main__": + main()
diff --git a/softrvv/tests/templates/base.tpl.cpp b/softrvv/tests/templates/base.tpl.cpp new file mode 100644 index 0000000..a9887cb --- /dev/null +++ b/softrvv/tests/templates/base.tpl.cpp
@@ -0,0 +1,16 @@ +<%! +import numpy as np + +def to_carr_str(arr): + return ", ".join(("%s" % x for x in arr)) + +%> +/* File is auto-generated. */ +#include <riscv_vector.h> +#include <springbok.h> +#include <stdio.h> +#include <stdlib.h> + +#include "pw_unit_test/framework.h" +#include "softrvv.h" +${self.body()}
diff --git a/softrvv/tests/templates/opivv_opivx_test.tpl.cpp b/softrvv/tests/templates/opivv_opivx_test.tpl.cpp new file mode 100644 index 0000000..7134d91 --- /dev/null +++ b/softrvv/tests/templates/opivv_opivx_test.tpl.cpp
@@ -0,0 +1,40 @@ +<%def name="test_opivv_opivx(dtype, op, src1, src2, rs1, ref_vv, ref_vx)"> +namespace softrvv_${op}_test { +namespace { + +${dtype} src1[] = {${src1}}; +${dtype} src2[] = {${src2}}; +${dtype} rs1 = ${rs1}; +const ${dtype} kAVL = sizeof(src1)/sizeof(src1[0]); +${dtype} dest[kAVL]; + +${dtype} ref_vv[] = {${ref_vv}}; +${dtype} ref_vx[] = {${ref_vx}}; + +template <typename T> +void assert_vec_elem_eq(int avl, void *test_vector_1, void *test_vector_2) { + T *ptr_vec_1 = reinterpret_cast<T *>(test_vector_1); + T *ptr_vec_2 = reinterpret_cast<T *>(test_vector_2); + for (int idx = 0; idx < avl; idx++) { + ASSERT_EQ(ptr_vec_1[idx], ptr_vec_2[idx]); + } +} + +class SoftRvv${op.capitalize()}Test : public ::testing::Test { + protected: + void SetUp() override { memset(dest, 0, sizeof(dest)); } +}; + +TEST_F(SoftRvv${op.capitalize()}Test, VV) { + softrvv::${op}_vv<${dtype}>(dest, src1, src2, kAVL); + assert_vec_elem_eq<${dtype}>(kAVL, dest, ref_vv); +} + +TEST_F(SoftRvv${op.capitalize()}Test, VX) { + softrvv::${op}_vx<${dtype}>(dest, src1, &rs1, kAVL); + assert_vec_elem_eq<${dtype}>(kAVL, dest, ref_vx); +} + +} // namespace +} // namespace softrvv_${op}_test +</%def>