text: # This Source Code Form is subject to the terms of the Mozilla Public
  # License, v. 2.0. If a copy of the MPL was not distributed with this file,
  # You can obtain one at http://mozilla.org/MPL/2.0/.
  #
  # Copyright (c) 2014-2022, Lars Asplund lars.anders.asplund@gmail.com
  
  from pathlib import Path
  from itertools import product
  from vunit import VUnit
  
  ROOT = Path(__file__).parent
  
  UI = VUnit.from_argv()
  UI.add_random()
  UI.add_verification_components()
  LIB = UI.library("vunit_lib")
  LIB.add_source_files(ROOT / "test" / "*.vhd")
  
  
  def encode(tb_cfg):
      return ",".join(["%s:%s" % (key, str(tb_cfg[key])) for key in tb_cfg])
  
  
  def gen_wb_tests(obj, *args):
      for dat_width, num_cycles, strobe_prob, ack_prob, stall_prob, slave_inst in product(*args):
          tb_cfg = dict(
              dat_width=dat_width,
              #  TODO remove fixed addr
              adr_width=32,
              strobe_prob=strobe_prob,
              ack_prob=ack_prob,
              stall_prob=stall_prob,
              num_cycles=num_cycles,
              slave_inst=slave_inst,
          )
          config_name = encode(tb_cfg)
          obj.add_config(name=config_name, generics=dict(encoded_tb_cfg=encode(tb_cfg)))
  
  
  def gen_avalon_tests(obj, *args):
      for data_width, num_cycles, readdatavalid_prob, waitrequest_prob in product(*args):
          tb_cfg = dict(
              data_width=data_width,
              readdatavalid_prob=readdatavalid_prob,
              waitrequest_prob=waitrequest_prob,
              num_cycles=num_cycles,
          )
          config_name = encode(tb_cfg)
          obj.add_config(name=config_name, generics=dict(encoded_tb_cfg=encode(tb_cfg)))
  
  
  def gen_avalon_master_tests(obj, *args):
      for (
          transfers,
          readdatavalid_prob,
          waitrequest_prob,
          write_prob,
          read_prob,
      ) in product(*args):
          tb_cfg = dict(
              readdatavalid_prob=readdatavalid_prob,
              waitrequest_prob=waitrequest_prob,
              write_prob=write_prob,
              read_prob=read_prob,
              transfers=transfers,
          )
          config_name = encode(tb_cfg)
          obj.add_config(name=config_name, generics=dict(encoded_tb_cfg=encode(tb_cfg)))
  
  
  tb_avalon_slave = LIB.test_bench("tb_avalon_slave")
  
  for test in tb_avalon_slave.get_tests():
      gen_avalon_tests(test, [32], [1, 2, 64], [1.0, 0.3], [0.0, 0.4])
  
  tb_avalon_master = LIB.test_bench("tb_avalon_master")
  
  for test in tb_avalon_master.get_tests():
      if test.name == "wr single rd single":
          gen_avalon_master_tests(test, [1], [1.0], [0.0], [1.0], [1.0])
      else:
          gen_avalon_master_tests(test, [64], [1.0, 0.3], [0.0, 0.7], [1.0, 0.3], [1.0, 0.3])
  
  TB_WISHBONE_SLAVE = LIB.test_bench("tb_wishbone_slave")
  
  for test in TB_WISHBONE_SLAVE.get_tests():
      #  TODO strobe_prob not implemented in slave tb
      gen_wb_tests(
          test,
          [8, 32],
          [1, 64],
          [1.0],
          [0.3, 1.0],
          [0.4, 0.0],
          [
              True,
          ],
      )
  
  
  TB_WISHBONE_MASTER = LIB.test_bench("tb_wishbone_master")
  
  for test in TB_WISHBONE_MASTER.get_tests():
      if test.name == "slave comb ack":
          gen_wb_tests(
              test,
              [32],
              [64],
              [1.0],
              [1.0],
              [0.0],
              [
                  False,
              ],
          )
      else:
          gen_wb_tests(
              test,
              [8, 32],
              [1, 64],
              [0.3, 1.0],
              [0.3, 1.0],
              [0.4, 0.0],
              [
                  True,
              ],
          )
  
  
  TB_AXI_STREAM = LIB.test_bench("tb_axi_stream")
  
  for id_length in [0, 8]:
      for dest_length in [0, 8]:
          for user_length in [0, 8]:
              for test in TB_AXI_STREAM.get_tests("*check"):
                  test.add_config(
                      name="id_l=%d dest_l=%d user_l=%d" % (id_length, dest_length, user_length),
                      generics=dict(
                          g_id_length=id_length,
                          g_dest_length=dest_length,
                          g_user_length=user_length,
                      ),
                  )
  
  TB_AXI_STREAM_PROTOCOL_CHECKER = LIB.test_bench("tb_axi_stream_protocol_checker")
  
  for data_length in [0, 8]:
      for test in TB_AXI_STREAM_PROTOCOL_CHECKER.get_tests("*passing*tdata*"):
          test.add_config(name="data_length=%d" % data_length, generics=dict(data_length=data_length))
  
  for test in TB_AXI_STREAM_PROTOCOL_CHECKER.get_tests("*failing*tid width*"):
      test.add_config(name="dest_length=25", generics=dict(dest_length=25))
      test.add_config(name="id_length=8 dest_length=17", generics=dict(id_length=8, dest_length=17))
  
  TEST_FAILING_MAX_WAITS = TB_AXI_STREAM_PROTOCOL_CHECKER.test(
      "Test failing check of that tready comes within max_waits after valid"
  )
  for max_waits in [0, 8]:
      TEST_FAILING_MAX_WAITS.add_config(name="max_waits=%d" % max_waits, generics=dict(max_waits=max_waits))
  
  TB_AXI_STREAM.test("test random stall on master").add_config(
      name="stall_master", generics=dict(g_stall_percentage_master=30)
  )
  
  TB_AXI_STREAM.test("test random pop stall on slave").add_config(
      name="stall_slave", generics=dict(g_stall_percentage_slave=30)
  )
  
  TB_AXI_STREAM.test("test random check stall on slave").add_config(
      name="stall_slave", generics=dict(g_stall_percentage_slave=40)
  )
  
  UI.main()
  