// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

<%!
import vec_test_helpers
%>\
<%def name="test_opivv(op_code)">
namespace ${op_code}_vv_test {
namespace {

using namespace test_v_helpers;

uint8_t src_vector_1[MAXVL_BYTES];
uint8_t src_vector_2[MAXVL_BYTES];
uint8_t dest_vector[MAXVL_BYTES];
uint8_t ref_dest_vector[MAXVL_BYTES];

<%
template_helper = vec_test_helpers.VecTemplateHelper(op_code)
sews = template_helper.get_sews()
lmuls = template_helper.get_lmuls()
%>\
class ${op_code.capitalize()}Test : public ::testing::Test {
 protected:
  void SetUp() override { zero_vector_registers(); }
  void TearDown() override { zero_vector_registers(); }
};
% for sew in sews:
% for lmul in lmuls:
<%
template_helper.sew = sew
%>\
${insert_vv_test(template_helper, lmul)}
%endfor
%endfor

}  // namespace
}  // namespace ${op_code}_vv_test
</%def>

<%def name="insert_vv_test(template_helper, lmul)">
<%
# Initialize the variables for a given test config
op_code = template_helper.op_code
sew = template_helper.sew
ref_opcode = template_helper.get_ref_opcode()
dest_sew, src2_sew, src1_sew, _ =  template_helper.get_sew_sizes()
datatypes = template_helper.get_softrvv_template_data_type()
var_types = template_helper.get_var_types()
mnemonic = template_helper.get_mnemonic(
  vec_test_helpers.VecTemplateHelper.OperandType.VECTOR)
%>\
TEST_F(${op_code.capitalize()}Test, ${mnemonic.lower().replace(".","_")}${sew}m${lmul}) {
  for (int i = 0; i < AVL_COUNT; i++) {
    int32_t avl = AVLS[i];
    int vlmax;
    int vl;
% if not template_helper.is_floating() and template_helper.is_narrowing():
    vector_test_setup<${var_types.src2_type}>(
        VLMUL::LMUL_M${lmul}, avl,
        {src_vector_2});
    vector_test_setup<${var_types.src1_type}>(
        VLMUL::LMUL_M${lmul}, avl,
        {src_vector_1});
    /* When a narrowing instruction is used sew matches dest size */
    std::tie(vlmax, vl) = vector_test_setup<${var_types.dest_type}>(
        VLMUL::LMUL_M${lmul}, avl,
        {dest_vector, ref_dest_vector});
% elif not template_helper.is_floating() and template_helper.is_widening():
    /* When a widening instruction is used sew matches src2 size */
    vector_test_setup<${var_types.dest_type}>(
        VLMUL::LMUL_M${lmul}, avl,
        {dest_vector, ref_dest_vector});
    vector_test_setup<${var_types.src1_type}>(
        VLMUL::LMUL_M${lmul}, avl,
        {src_vector_1});
    std::tie(vlmax, vl) = vector_test_setup<${var_types.src2_type}>(
        VLMUL::LMUL_M${lmul}, avl,
        {src_vector_2});
% else:
    /* For non narrowing instructions all vectors have same type*/
    std::tie(vlmax, vl) = vector_test_setup<${var_types.dest_type}>(
        VLMUL::LMUL_M${lmul}, avl,
        {dest_vector, ref_dest_vector, src_vector_1, src_vector_2});
% endif

    if (avl > vlmax) {
      continue;
    }
    ${var_types.src1_type} *ptr_vec_1 = reinterpret_cast<${var_types.src1_type} *>(src_vector_1);
    ${var_types.src2_type} *ptr_vec_2 = reinterpret_cast<${var_types.src2_type} *>(src_vector_2);
    ${var_types.dest_type} *ptr_dest_vec = reinterpret_cast<${var_types.dest_type} *>(dest_vector);
    ${var_types.dest_type} *ptr_ref_dest_vec = reinterpret_cast<${var_types.dest_type} *>(ref_dest_vector);

    // set up values to test up to index of the AVL
    fill_random_vector<${var_types.src1_type}>(ptr_vec_1, avl);
    fill_random_vector<${var_types.src2_type}>(ptr_vec_2, avl);
    memset(dest_vector, 0, MAXVL_BYTES);
    memset(ref_dest_vector, 0, MAXVL_BYTES);

    // Generate reference vector
    % if template_helper.is_floating():
      softrvv::${ref_opcode}_vv(ptr_ref_dest_vec, ptr_vec_2, ptr_vec_1, avl);
    % else:
      softrvv::${ref_opcode}_vv<${datatypes}>(ptr_ref_dest_vec, ptr_vec_2, ptr_vec_1, avl);
    % endif
    // Load vector registers
    __asm__ volatile("vle${src1_sew}.v v8, (%0)" : : "r"(ptr_vec_1));
    __asm__ volatile("vle${src2_sew}.v v16, (%0)" : : "r"(ptr_vec_2));

    // Run target instruction
    __asm__ volatile("${mnemonic} v24, v16, v8");

    // Store result vector register
    __asm__ volatile("vse${dest_sew}.v v24, (%0)" : : "r"(ptr_dest_vec));
    // Check vector elements
    assert_vec_elem_eq<${var_types.dest_type}>(vlmax, dest_vector, ref_dest_vector);
  }
}
</%def>
