// 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_opivf(op_code)">
namespace ${op_code}_vf_test {
namespace {

using namespace test_v_helpers;

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_vf_test(template_helper, lmul)}
%endfor
%endfor

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

<%def name="insert_vf_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, _, __ = 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.SCALAR)
%>\
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;

    std::tie(vlmax, vl) = vector_test_setup<${var_types.dest_type}>(
        VLMUL::LMUL_M${lmul}, avl,
        {dest_vector, ref_dest_vector, src_vector_2});

    if (avl > vlmax) {
      continue;
    }
    ${var_types.src2_type} *ptr_vec_2 = reinterpret_cast<${var_types.src2_type} *>(src_vector_2);
    ${var_types.imm_type} test_val = static_cast<${var_types.imm_type}>(rand());
    ${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.src2_type}>(ptr_vec_2, avl);

    // Generate reference vector
    softrvv::${ref_opcode}_vf(ptr_ref_dest_vec, ptr_vec_2, &test_val, avl);
    // Load vector registers
    __asm__ volatile("vle${src2_sew}.v v8, (%0)" : : "r"(ptr_vec_2));

    // Run target instruction
    __asm__ volatile("${mnemonic} v24, v8, %[RS1]" ::[RS1] "f"(test_val));

    // 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>
