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