Ejemplo n.º 1
0
def declare_signals(testbench_config, testbench):
    """
    Declare all signals used to connect to the DUT

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated

    Returns:
        str: Updated testbench
    """
    dut = testbench_config.modules["DUT"]
    clocks_in = dut.ports.get_clocks("input")
    signals = dut.ports.get_signals()
    resets = dut.ports.get_resets()
    interfaces = testbench_config.get_from_dut("interfaces")

    tb_signal_list = ""
    max_signal_size = 0
    leading_spaces = include.get_indentation("SONAR_TB_SIGNAL_LIST", testbench)
    for clock in clocks_in:
        if tb_signal_list != "":
            tb_signal_list += leading_spaces
        tb_signal_list += "logic " + clock.name + ";\n"
    for signal in itertools.chain(signals, resets):
        if int(signal.size) == 1:
            tb_signal_list += leading_spaces + "logic " + signal.name + ";\n"
        else:
            tb_signal_list += (leading_spaces + "logic [" +
                               str(int(signal.size) - 1) + ":0] " +
                               signal.name + ";\n")
        if int(signal.size) > max_signal_size:
            max_signal_size = int(signal.size)
    for interface in interfaces:
        for signal_type, signal in interface.signals.items():
            if int(signal.size) == 1:
                tb_signal_list += (leading_spaces + "logic " + interface.name +
                                   "_" + signal_type + ";\n")
            else:
                tb_signal_list += (leading_spaces + "logic [" +
                                   str(int(signal.size) - 1) + ":0] " +
                                   interface.name + "_" + signal_type + ";\n")
            if int(signal.size) > max_signal_size:
                max_signal_size = int(signal.size)
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_TB_SIGNAL_LIST",
                                               tb_signal_list[:-1])
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_MAX_DATA_SIZE",
                                               max_signal_size)
    return testbench
Ejemplo n.º 2
0
def set_waits(testbench_config, testbench):
    """
    Add the logic to handle wait conditions

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated

    Returns:
        str: Updated testbench
    """
    # TODO need to handle this if wait_conditions is empty (sv will error out)
    wait_conditions = testbench_config.get_from_dut("wait_conditions")

    replace_str = ""
    leading_spaces = include.get_indentation("SONAR_IF_ELSE_WAIT", testbench)
    for condition in wait_conditions:
        if replace_str != "":
            replace_str += leading_spaces + "else "
        replace_str += ('if(interfaceType_par == "' + condition["key"] +
                        '") begin\n')
        regex_variable = re.compile(r"\$\d+")
        condition_str = condition["condition"]
        variables = re.findall(regex_variable, condition["condition"])
        for variable in variables:
            condition_str = condition_str.replace(variable,
                                                  f"args[{variable[1:]}]")
        if not condition_str.endswith(";"):
            condition_str += ";"
        replace_str += leading_spaces + include.TAB_SIZE + condition_str + "\n"
        replace_str += leading_spaces + "end\n"
    testbench = include.replace_in_testbenches(testbench, "SONAR_IF_ELSE_WAIT",
                                               replace_str[:-1])

    return testbench
Ejemplo n.º 3
0
def add_headers(testbench_config, testbench, lang):
    """
    Add any header files to the testbench

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated
        lang (str): Language of the testbench

    Returns:
        str: Updated testbench
    """
    headers = ""
    if "Headers" in testbench_config.metadata:
        for header_tuple in testbench_config.metadata["Headers"]:
            if isinstance(header_tuple, (list, tuple)):
                header_file = header_tuple[0]
                header_mode = header_tuple[1]
            else:
                header_file = header_tuple
                header_mode = "auto"

            if header_mode == "cpp":
                headers += f'#include "{header_file}"\n'
            elif header_mode == "sv":
                headers += f'`include "{header_file}"\n'
            elif header_mode == "auto":
                if header_file.endswith((".h", ".hpp")) and lang == "cpp":
                    headers += f'#include "{header_file}"\n'
                elif header_file.endswith((".v", ".sv")) and lang == "sv":
                    headers += f'`include "{header_file}"\n'
    testbench = include.replace_in_testbenches(testbench, "SONAR_HEADER_FILE",
                                               headers)
    return testbench
Ejemplo n.º 4
0
def set_signals(testbench_config, testbench):
    """
    Add commands to interact with signals when reading the data file

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated

    Returns:
        str: Updated testbench
    """
    dut = testbench_config.modules["DUT"]
    signals_in = dut.ports.get_signals("input")

    ifelse_signal = ""
    leading_spaces = include.get_indentation("SONAR_IF_ELSE_SIGNAL", testbench)

    for signal in signals_in:
        if "type" not in signal:
            if ifelse_signal != "":
                ifelse_signal += leading_spaces + "else "
            ifelse_signal += ('if(!strcmp(interfaceType, "' + signal.name +
                              '")){\n')
            ifelse_signal += (leading_spaces + TAB_SIZE + signal.name +
                              " = args[0];\n")
            ifelse_signal += leading_spaces + "}\n"

    # TODO fix this
    # ifelse_signal = ""  # clear this since it's not being used right now

    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_IF_ELSE_SIGNAL",
                                               ifelse_signal[:-1])
    return testbench
Ejemplo n.º 5
0
def create_testbench(testbench_config, testbench, directory):
    """
    Create the testbench for this language backend

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated
        directory (str): Path to the directory to place generated files

    Returns:
        Tuple(str, str): The testbench and the data file
    """
    testbench = include.set_metadata(testbench_config, testbench)
    testbench = include.replace_in_testbenches(
        testbench,
        "SONAR_DATA_FILE",
        '"' + os.path.join(
            directory, f'{testbench_config.metadata["Module_Name"]}_cpp.dat"'),
    )

    # this is currently not used: no signals can be set in cpp
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_IF_ELSE_SIGNAL", "")

    # testbench = instantiate_dut(testbench_config, testbench)
    testbench = declare_signals(testbench_config, testbench)
    testbench = set_signals(testbench_config, testbench)
    testbench = set_interfaces(testbench_config, testbench)

    data_file = write_data_file(testbench_config)

    max_args = 0
    for line in data_file:
        first_word = line.split(" ")[0]
        if first_word not in ["TestVector", "ParallelSection", "Packet"]:
            arg_count = int(quoteSplit(line)[3])
            if arg_count > max_args:
                max_args = arg_count

    testbench = include.replace_in_testbenches(testbench, "SONAR_MAX_ARG_NUM",
                                               max_args)

    return testbench, "\n".join(data_file)
Ejemplo n.º 6
0
def declare_signals(testbench_config, testbench):
    """
    Declare and instantiate the variables used for the signals in the testbench

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated

    Returns:
        str: Updated testbench
    """
    dut = testbench_config.modules["DUT"]
    signals = dut.ports.get_signals()
    interfaces = testbench_config.get_from_dut("interfaces")

    tb_signal_list = ""
    max_signal_size = 0
    leading_spaces = include.get_indentation("SONAR_TB_SIGNAL_LIST", testbench)
    for signal in signals:
        # TODO fix leading spaces on first entry
        tb_signal_list += (leading_spaces + "ap_uint<" + str(signal.size) +
                           "> " + signal.name + ";\n")
        if int(signal.size) > max_signal_size:
            max_signal_size = int(signal.size)
    for interface in interfaces:
        if isinstance(interface, AXI4LiteSlave):
            data_width_c = interface.get_signal("wdata").size
            for regs in interface.registers:
                tb_signal_list += (leading_spaces +
                                   f"ap_uint<{data_width_c}> {regs};\n")
        elif isinstance(interface, AXI4Stream):
            tb_signal_list += (leading_spaces + interface.iClass + " " +
                               interface.name + ";\n")
            tb_signal_list += (leading_spaces + interface.flit + " " +
                               interface.name + "_flit;\n")
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_TB_SIGNAL_LIST",
                                               tb_signal_list[:-1])
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_MAX_DATA_SIZE",
                                               max_signal_size)
    return testbench
Ejemplo n.º 7
0
def instantiate_dut(testbench_config, testbench):
    """
    Instantiate the device-under-test

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated

    Returns:
        str: Updated testbench
    """
    # pylint: disable=too-many-locals
    dut = testbench_config.modules["DUT"]
    clocks_in = dut.ports.get_clocks("input")
    signals_in = dut.ports.get_signals("input")
    resets_in = dut.ports.get_resets("input")
    signals_out = dut.ports.get_signals("output")
    parameters = testbench_config.get_from_dut("parameters")
    interfaces = testbench_config.get_from_dut("interfaces")

    dut_inst = ""
    leading_spaces = include.get_indentation("SONAR_DUT_INST", testbench)
    module_name = testbench_config.metadata["Module_Name"]
    if parameters:
        dut_inst += testbench_config.metadata["Module_Name"] + " #(\n"
        for parameter in parameters[:-1]:
            dut_inst += f"{leading_spaces}{include.TAB_SIZE}.{parameter[0]}({str(parameter[1])}),\n"
        dut_inst += f"{leading_spaces}{include.TAB_SIZE}.{parameters[-1][0]}({str(parameters[-1][1])})\n"
        dut_inst += f"{leading_spaces}) {module_name}_i (\n"
    else:
        dut_inst += f"{module_name} {module_name}_i (\n"
    for signal in itertools.chain(clocks_in, resets_in):
        dut_inst += f"{leading_spaces}{include.TAB_SIZE}.{signal.name}({signal.name}),\n"
    dut_type = testbench_config.modules["DUT"].type
    for signal in itertools.chain(signals_in, signals_out):
        port_name = modify_signal_name(signal.name, dut_type)
        dut_inst += (
            f"{leading_spaces}{include.TAB_SIZE}.{port_name}({signal.name}),\n"
        )
    for interface in interfaces:
        for signal_type, signal in interface.signals.items():
            dut_inst += (leading_spaces + include.TAB_SIZE + "." +
                         interface.name + "_" + signal.name + "(" +
                         interface.name + "_" + signal_type + "),\n")
    dut_inst = dut_inst[:-2] + "\n"
    dut_inst += leading_spaces + ");"
    testbench = include.replace_in_testbenches(testbench, "SONAR_DUT_INST",
                                               dut_inst)

    return testbench
Ejemplo n.º 8
0
def set_interfaces(testbench_config, testbench):
    """
    When reading commands, add the logic to assign interact with interfaces

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated

    Returns:
        str: Updated testbench
    """
    interfaces = testbench_config.get_from_dut("interfaces")

    replace_str = ""
    leading_spaces = include.get_indentation("SONAR_ELSE_IF_INTERFACE_IN",
                                             testbench)
    for index, interface in enumerate(interfaces):
        if replace_str != "":
            replace_str += leading_spaces
        replace_str += 'else if(interfaceType_par == "$$name") begin\n'
        replace_str += (leading_spaces + include.TAB_SIZE +
                        f"$$interfaceType_$$index(args, retval[{index}]);\n")
        replace_str += (leading_spaces + include.TAB_SIZE +
                        f"if(retval[{index}] != 0) begin\n")
        replace_str += (leading_spaces + include.TAB_SIZE * 2 +
                        "error = 1'b1;\n")
        replace_str += leading_spaces + include.TAB_SIZE * 2 + "$stop;\n"
        replace_str += leading_spaces + include.TAB_SIZE + "end\n"
        replace_str += leading_spaces + "end\n"
        replace_str = include.replace_variables(replace_str, interface)
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_ELSE_IF_INTERFACE_IN",
                                               replace_str[:-1])
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_INTERFACES_COUNT",
                                               len(interfaces))
    return testbench
Ejemplo n.º 9
0
def set_signals(testbench_config, testbench, used_interfaces):
    """
    When reading commands, add the logic to assign values to individual signals

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated
        used_interfaces (dict): Each used interface appears once

    Returns:
        str: Updated testbench
    """
    dut = testbench_config.modules["DUT"]
    signals_in = dut.ports.get_signals("input")
    resets_in = dut.ports.get_resets("input")
    interfaces = testbench_config.get_from_dut("interfaces")

    ifelse_signal = ""
    leading_spaces = include.get_indentation("SONAR_IF_ELSE_SIGNAL", testbench)
    for signal in itertools.chain(signals_in, resets_in):
        if ifelse_signal != "":
            ifelse_signal += leading_spaces + "else "
        ifelse_signal += ('if(interfaceType_par == "' + signal.name +
                          '") begin\n' + leading_spaces + include.TAB_SIZE +
                          signal.name + " = args[0];\n" + leading_spaces +
                          "end\n")
    for interface in interfaces:
        curr_interface = used_interfaces[interface.interface_type]
        for signal_type, signal in interface.signals.items():
            if (interface.direction in ("slave", "mixed")
                    and signal_type in curr_interface.signals["output"]) or (
                        interface.direction in ("master")
                        and signal_type in curr_interface.signals["input"]):
                if ifelse_signal != "":
                    ifelse_signal += leading_spaces + "else "
                ifelse_signal += ('if(interfaceType_par == "' +
                                  interface.name + "_" + signal_type +
                                  '") begin\n' + leading_spaces +
                                  include.TAB_SIZE + interface.name + "_" +
                                  signal_type + " = args[0];\n" +
                                  leading_spaces + "end\n")
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_IF_ELSE_SIGNAL",
                                               ifelse_signal[:-1])
    return testbench
Ejemplo n.º 10
0
def create_clocks(testbench_config, testbench):
    """
    Create clocks used in the testbench

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated

    Returns:
        str: Updated testbench
    """
    # TODO make the initial state of the clock configurable (i.e. for diff. clocks)
    dut = testbench_config.modules["DUT"]
    clocks_in = dut.ports.get_clocks("input")

    largest_clock = ""
    largest_period = 0
    regex_int_str = re.compile(r"([0-9]+([\.][0-9]+)*)([a-z]+)")
    for clock in clocks_in:
        regex_match = regex_int_str.match(clock.period)
        if regex_match.group(3) == "s":
            period = float(regex_match.group(1)) * 10**15
        elif regex_match.group(3) == "ms":
            period = float(regex_match.group(1)) * 10**12
        elif regex_match.group(3) == "us":
            period = float(regex_match.group(1)) * 10**9
        elif regex_match.group(3) == "ns":
            period = float(regex_match.group(1)) * 10**6
        elif regex_match.group(3) == "ps":
            period = float(regex_match.group(1)) * 10**3
        else:
            period = float(regex_match.group(1))
        if period > largest_period:
            largest_period = period
            largest_clock = clock.name
    testbench = include.replace_in_testbenches(testbench, "SONAR_VECTOR_CLOCK",
                                               largest_clock)

    return testbench
Ejemplo n.º 11
0
def add_signal_endpoints(testbench_config, testbench):
    """
    Add signals' sources/sinks

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated

    Returns:
        str: The testbench
    """
    endpoints_str = ""
    leading_spaces = include.get_indentation("SONAR_INCLUDE_ENDPOINTS",
                                             testbench)
    all_endpoints = testbench_config.get_from_dut("endpoints")
    for signal_index, endpoint_dict in enumerate(all_endpoints.items()):
        signal, endpoints = endpoint_dict
        if endpoints_str != "":
            endpoints_str += leading_spaces
        endpoints_str = (
            f"logic [$$size-1:0] $$name_endpoint[{len(endpoints)}];\n")
        endpoints_str += (
            leading_spaces +
            f"assign $$name = $$name_endpoint[{signal_index}];\n")

        for endpoint in endpoints:
            endpoints_str += endpoint.instantiate(leading_spaces)
            endpoints_str = endpoints_str.replace(
                "$$size", str(endpoint.arguments["size"]))
        endpoints_str = endpoints_str.replace("$$name", signal)
        endpoints_str = endpoints_str.replace("$$endpointIndex",
                                              str(signal_index))

    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_INCLUDE_ENDPOINTS",
                                               endpoints_str[:-1])
    return testbench
Ejemplo n.º 12
0
def instantiate_exerciser(testbench_config, testbench):
    """
    Instantiate the Exerciser module

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated

    Returns:
        str: Updated testbench
    """
    dut = testbench_config.modules["DUT"]
    clocks_in = dut.ports.get_clocks("input")
    signals = dut.ports.get_signals()
    resets = dut.ports.get_resets()
    interfaces = testbench_config.get_from_dut("interfaces")

    exerciser_int = ""
    leading_spaces = include.get_indentation("SONAR_EXERCISER_INT", testbench)
    exerciser_int += "exerciser exerciser_i(\n"
    for clock in clocks_in:
        exerciser_int += (leading_spaces + include.TAB_SIZE + "." +
                          clock.name + "(" + clock.name + "),\n")
    for interface in interfaces:
        for signal_type, signal in interface.signals.items():
            exerciser_int += (leading_spaces + include.TAB_SIZE + "." +
                              interface.name + "_" + signal_type + "(" +
                              interface.name + "_" + signal_type + "),\n")
    for signal in itertools.chain(signals, resets):
        exerciser_int += (leading_spaces + include.TAB_SIZE + "." +
                          signal.name + "(" + signal.name + "),\n")
    exerciser_int = exerciser_int[:-2] + "\n"
    exerciser_int += leading_spaces + ");\n"
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_EXERCISER_INT",
                                               exerciser_int[:-1])
    return testbench
Ejemplo n.º 13
0
def add_timeformat(testbench_config, testbench):
    """
    Configure the time format for the testbench

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated

    Raises:
        SonarInvalidArgError: Invalid time format

    Returns:
        str: Updated testbench
    """
    time_format_str = "$timeformat("
    precision = str(testbench_config.metadata["Time_Format"]["precision"])
    time_format = testbench_config.metadata["Time_Format"]["unit"]
    if time_format.endswith("fs"):
        time_format_str += "-15, " + precision + ', " fs", 0);'
    elif time_format.endswith("ps"):
        time_format_str += "-12, " + precision + ', " ps", 0);'
    elif time_format.endswith("ns"):
        time_format_str += "-9, " + precision + ', " ns", 0);'
    elif time_format.endswith("us"):
        time_format_str += "-6, " + precision + ', " us", 0);'
    elif time_format.endswith("ms"):
        time_format_str += "-3, " + precision + ', " ms", 0);'
    elif time_format.endswith("s"):
        time_format_str += "0, " + precision + ', " s", 0);'
    else:
        logger.error("Unknown time format: %s",
                     testbench_config.metadata["Time_Format"])
        raise SonarInvalidArgError
    testbench = include.replace_in_testbenches(testbench, "SONAR_TIMEFORMAT",
                                               time_format_str)
    return testbench
Ejemplo n.º 14
0
def set_interfaces(testbench_config, testbench):
    """
    Add commands to interact with interfaces when reading the data file

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated

    Returns:
        str: Updated testbench
    """
    dut = testbench_config.modules["DUT"]
    interfaces_slave = dut.ports.get_interfaces("slave")
    interfaces_master = dut.ports.get_interfaces("master")
    interfaces_mixed = dut.ports.get_interfaces("mixed")

    replace_str = ""
    leading_spaces = include.get_indentation("SONAR_ELSE_IF_INTERFACE_IN",
                                             testbench)
    for interface in itertools.chain(interfaces_slave, interfaces_mixed):
        if replace_str != "":
            replace_str += leading_spaces + "else "
        replace_str += ('if(!strcmp(interfaceType, "' + interface.name +
                        '")){\n')
        # in cpp, only consider first endpoint
        endpoint = interface.endpoints[0]
        replace_str = include.command_var_replace(
            replace_str,
            interface,
            leading_spaces + TAB_SIZE,
            "cpp",
            "master",
            endpoint,
        )
        replace_str += leading_spaces + "}\n"
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_ELSE_IF_INTERFACE_IN",
                                               replace_str[:-1])

    replace_str_2 = ""
    leading_spaces = include.get_indentation("SONAR_ELSE_IF_INTERFACE_OUT",
                                             testbench)
    for interface in interfaces_master:
        if replace_str != "" or replace_str_2 != "":
            replace_str_2 += (leading_spaces + "else "
                              )  # TODO fix this on first one. too many spaces
        replace_str_2 += ('if(!strcmp(interfaceType, "' + interface.name +
                          '")){\n')
        # in cpp, only consider first endpoint
        endpoint = interface.endpoints[0]
        replace_str_2 = include.command_var_replace(
            replace_str_2,
            interface,
            leading_spaces + TAB_SIZE,
            "cpp",
            "slave",
            endpoint,
        )
        replace_str_2 += leading_spaces + "}\n"
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_ELSE_IF_INTERFACE_OUT",
                                               replace_str_2[:-1])
    return testbench
Ejemplo n.º 15
0
def add_interfaces(testbench_config, testbench, directory):
    """
    Add interfaces and their sources/sinks

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated
        directory (str): Path to the directory to place generated files

    Returns:
        str: The testbench
    """
    # pylint: disable=too-many-locals, too-many-statements
    endpoints_str = ""
    imports_str = ""
    used_interfaces = {}
    leading_spaces = include.get_indentation(
        "SONAR_INCLUDE_INTERFACE_ENDPOINTS", testbench)
    interfaces = testbench_config.get_from_dut("interfaces")
    # endpoints = testbench_config.get_from_dut("endpoints_flat")
    for interface_index, interface in enumerate(interfaces):
        if interface.interface_type not in used_interfaces:
            used_interfaces[interface.interface_type] = True
            imports_str += interface.core.import_packages_global()

        endpoint_str = ""
        if interface.direction == "master":
            signals = interface.core.signals["input"]
        else:
            signals = interface.core.signals["output"]
        action = {
            "signals":
            signals,
            "commands": [
                f"logic [$$size-1:0] $$name_$$signal_endpoint[{len(interface.endpoints)}];\n"
                f"assign $$name_$$signal = $$name_$$signal_endpoint[endpoint_select[{interface_index}]];\n"
            ],
        }
        for command in action["commands"]:
            endpoint_str = include.replace_signals(
                interface,
                action,
                command,
                endpoint_str,
                "",
                interface.core.args["sv"],
            )
        for endpoint_index, endpoint in enumerate(interface.endpoints):
            endpoint_str = add_prologue(endpoint_str, endpoint, interface)
            endpoint_str = add_initial_blocks(endpoint_str, endpoint,
                                              interface)
            endpoint_str = instantiate_endpoint_ips(endpoint_str, endpoint)

            for key in endpoint.actions["sv"].keys():
                # for key, _commands in endpoint.core.actions["sv"].items():
                endpoint_str += f"task $$interfaceType_$$index_{key}_$$endpointIndex(input logic [MAX_DATA_SIZE-1:0] args [MAX_ARG_NUM], output int retval);\n"
                endpoint_str += include.TAB_SIZE + "retval = 0;\n"
                endpoint_str = include.command_var_replace(
                    endpoint_str,
                    interface,
                    include.TAB_SIZE,
                    "sv",
                    key,
                    endpoint,
                )
                endpoint_str += "endtask\n"

            endpoint_str = endpoint_str.replace("$$endpointIndex",
                                                str(endpoint_index))
            endpoint.source_tcl(interface, directory)
            for key, value in endpoint.arguments.items():
                endpoint_str = endpoint_str.replace(f"$${key}", str(value))

        endpoint_str += "task $$interfaceType_$$index(input logic [MAX_DATA_SIZE-1:0] args [MAX_ARG_NUM], output int retval);\n"
        endpoint_str += include.TAB_SIZE + "retval = 0;\n"
        # for key, _commands in endpoint.core.actions["sv"].items():
        for endpoint_index, endpoint in enumerate(interface.endpoints):
            imports_str += endpoint.import_packages_local(interface)
            for key in endpoint.actions["sv"].keys():
                endpoint_str += include.TAB_SIZE
                if endpoint_index != 0:
                    endpoint_str += "else "
                arg_index = get_nth_index(endpoint.actions["sv"], key)
                endpoint_str += f"if (endpoint_select[{interface_index}] == {endpoint_index} && args[0] == {arg_index}) begin\n"
                endpoint_str += (
                    include.TAB_SIZE * 2 +
                    f"$$interfaceType_$$index_{key}_$$endpointIndex(args, retval);\n"
                )
                endpoint_str += include.TAB_SIZE + "end\n"
            endpoint_str = endpoint_str.replace("$$endpointIndex",
                                                str(endpoint_index))
        endpoint_str += f"{include.TAB_SIZE}else begin\n"
        endpoint_str += include.TAB_SIZE * 2 + '$error("Unknown command!");\n'
        endpoint_str += f"{include.TAB_SIZE}end\n"

        endpoint_str += "endtask\n"
        endpoint_str = include.replace_variables(endpoint_str, interface)

        filename = interface.interface_type + f"_{interface.index}.sv"
        filepath = os.path.join(directory, filename)
        with open(filepath, "w+") as f:
            f.write(endpoint_str)
        if endpoints_str != "":
            endpoints_str += leading_spaces
        endpoints_str += f'`include "{filename}"\n'

    testbench = include.replace_in_testbenches(
        testbench, "SONAR_INCLUDE_INTERFACE_ENDPOINTS", endpoints_str)
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_IMPORT_PACKAGES",
                                               imports_str[:-1])
    return testbench
Ejemplo n.º 16
0
def create_testbench(testbench_config, testbench, directory):
    """
    Create the testbench for this language backend

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated
        directory (str): Path to the directory to place generated files

    Returns:
        Tuple(str, str): The testbench and the data file
    """
    testbench = include.set_metadata(testbench_config, testbench)
    testbench = add_timeformat(testbench_config, testbench)

    testbench = include.replace_in_testbenches(testbench, "SONAR_CURR_DATE",
                                               datetime.datetime.now())
    testbench = include.replace_in_testbenches(
        testbench,
        "SONAR_DATA_FILE",
        '"' + os.path.join(
            directory, f'{testbench_config.metadata["Module_Name"]}_sv.dat"'),
    )
    testbench = include.replace_in_testbenches(testbench, "SONAR_MAX_VECTORS",
                                               len(testbench_config.vectors))

    used_interfaces = {}
    interfaces = testbench_config.get_from_dut("interfaces")
    for interface in interfaces:
        used_interfaces[interface.interface_type] = include.get_interface(
            interface.interface_type)

    testbench, testbench_config = add_exerciser_ports(testbench_config,
                                                      testbench,
                                                      used_interfaces)
    testbench = instantiate_dut(testbench_config, testbench)
    testbench = instantiate_exerciser(testbench_config, testbench)

    testbench = declare_signals(testbench_config, testbench)
    testbench = set_signals(testbench_config, testbench, used_interfaces)
    testbench = set_interfaces(testbench_config, testbench)
    testbench = create_clocks(testbench_config, testbench)

    testbench = set_waits(testbench_config, testbench)

    testbench = sv_interfaces.add_signal_endpoints(testbench_config, testbench)
    testbench = sv_interfaces.add_interfaces(testbench_config, testbench,
                                             directory)

    data_file, max_threads = write_data_file(testbench_config)

    max_args = 0
    for line in data_file:
        first_word = line.split(" ")[0]
        if first_word not in ["TestVector", "ParallelSection", "Packet"]:
            arg_count = int(quoteSplit(line)[2])
            if arg_count > max_args:
                max_args = arg_count

    testbench = include.replace_in_testbenches(testbench, "SONAR_MAX_ARG_NUM",
                                               max_args)
    testbench = include.replace_in_testbenches(testbench, "SONAR_MAX_PARALLEL",
                                               max_threads)

    return testbench, "\n".join(data_file)
Ejemplo n.º 17
0
def add_exerciser_ports(testbench_config, testbench, used_interfaces):
    """
    Add the ports of the Exerciser

    Args:
        testbench_config (Testbench): The testbench configuration
        testbench (str): The testbench being generated
        used_interfaces (dict): Each used interface appears once

    Returns:
        str: Updated testbench
    """
    def add_interfaces(exerciser_ports):
        interfaces = testbench_config.get_from_dut("interfaces_dict")
        for direction in ["slave", "master", "mixed"]:
            for interface in interfaces[direction]:
                curr_interface = used_interfaces[interface.interface_type]
                for signal_type, signal in interface.signals.items():
                    exerciser_ports += leading_spaces
                    if direction in ["slave", "mixed"]:
                        if signal_type in curr_interface.signals["input"]:
                            exerciser_ports += "input "
                        else:
                            exerciser_ports += "output "
                            init_signals.append(interface.name + "_" +
                                                signal_type)
                    else:
                        if signal_type in curr_interface.signals["output"]:
                            exerciser_ports += "input "
                        else:
                            exerciser_ports += "output "
                            init_signals.append(interface.name + "_" +
                                                signal_type)
                    exerciser_ports += "logic "
                    if int(signal.size) != 1:
                        exerciser_ports += ("[" + str(int(signal.size) - 1) +
                                            ":0] ")
                    exerciser_ports += (interface.name + "_" + signal_type +
                                        ",\n")
        return exerciser_ports

    def resolve_init_signals():
        init_commands = []
        for init_signal in init_signals:
            init_commands.append({"signal": {"name": init_signal, "value": 0}})

        for i, vector in enumerate(testbench_config.vectors):
            for j, thread in enumerate(vector.threads):
                for k, command in enumerate(thread.commands):
                    if ("macro" in command
                            and command["macro"] == "INIT_SIGNALS"):
                        testbench_config.vectors[i].threads[j].commands[k][
                            "commands"] = init_commands

    dut = testbench_config.modules["DUT"]
    clocks_in = dut.ports.get_clocks("input")
    signals_in = dut.ports.get_signals("input")
    resets_in = dut.ports.get_resets("input")
    signals_out = dut.ports.get_signals("output")

    init_signals = []

    exerciser_ports = ""
    leading_spaces = include.get_indentation("SONAR_EXERCISER_PORTS",
                                             testbench)
    for clock in clocks_in:
        if exerciser_ports != "":
            exerciser_ports += leading_spaces
        exerciser_ports += "output logic " + clock.name + ",\n"

    exerciser_ports = add_interfaces(exerciser_ports)

    for signal in itertools.chain(signals_in, resets_in):
        exerciser_ports += leading_spaces + "output logic "
        if int(signal.size) != 1:
            exerciser_ports += "[" + str(int(signal.size) - 1) + ":0] "
        exerciser_ports += signal.name + ",\n"
        init_signals.append(signal.name)
    for signal in signals_out:
        exerciser_ports += leading_spaces + "input logic "
        if int(signal.size) != 1:
            exerciser_ports += "[" + str(int(signal.size) - 1) + ":0] "
        exerciser_ports += signal.name + ",\n"
    testbench = include.replace_in_testbenches(testbench,
                                               "SONAR_EXERCISER_PORTS",
                                               exerciser_ports[:-2])

    resolve_init_signals()

    return testbench, testbench_config