Files
TBgen_App/prompt_scripts/utils.py

803 lines
31 KiB
Python
Raw Normal View History

2026-03-30 16:46:48 +08:00
"""
Description : some tool functions for prompt scripts and their stages
Author : Ruidi Qiu (r.qiu@tum.de)
Time : 2024/4/25 13:26:06
LastEdited : 2024/9/3 20:55:11
"""
import math
from utils.utils import run_with_timeout
####################################
# used by pychecker_SEQ
def extract_signals(header):
"""
- given the header of a module, extract the signals
- output format: [{"name": "signal_name", "width": "[x:x]", "type": "input/output"}, ...]
"""
def get_width_ifhave(signal):
if len(signal) > 2 and "[" in signal[-2] and "]" in signal[-2]:
# remove other parts except the [x:x]
width = signal[-2]
width = width.split("[")[1].split("]")[0]
width = "[" + width + "]"
return width
else:
return ""
signals = header.split("(")[1].split(")")[0].split(",")
signals = [signal.strip().split(" ") for signal in signals]
signals = [{"name": signal[-1], "width": get_width_ifhave(signal), "type": signal[0]} for signal in signals]
return signals
def fdisplay_code_gen(header, ckeck_en=True):
"""
- input: head, like:
module top_module(
input clk,
input reset,
output reg [3:0] q);
- return:
- no check: $fdisplay(file, "scenario: %d, clk = %d, reset = %d, q = %d", scenario, clk, reset, q);
- check: $fdisplay(file, "[check]scenario: %d, clk = %d, reset = %d, q = %d", scenario, clk, reset, q);
"""
signals = extract_signals(header)
begining = '$fdisplay(file, "'
ending = ");"
check = "[check]" if ckeck_en else ""
middle1 = check + "scenario: %d"
middle2 = ", scenario"
middle1_signals = ""
middle2_signals = ""
for signal in signals:
middle1_signals += ", %s = %%d" % signal["name"]
middle2_signals += ", %s" % signal["name"]
middle1 += middle1_signals + '"'
middle2 += middle2_signals
return begining + middle1 + middle2 + ending
@run_with_timeout(timeout=30)
def pychecker_SEQ_TB_standardization(code, header):
"""
- refine the TB code
- 1. patch the weird bug of gpt generated verilog code
- 2. add $fdisplay in the repeat block if not exist
- 3. split the delay to multiple #10
- 4. add #10 in front of the second $display if there are two $display and no delay between them
- 5. add $fdisplay in front of the second #10 if there are two #10 and no $display between them
- 6. find the repeat block and change from repeat-#10-$fdisplay-#10 to #10-repeat-$fdisplay-#10
- 7. find all the $fdisplay sentence and rewrite them in a standard format
"""
code = verilog_patch(code)
code = add_fdisplay_to_repeat(code, header)
code = split_delay_to_delays(code)
code = find_and_rewrite_fdisplay(code, header)
code = add_delay_into_2displays_or_scenarios(code)
code = refine_repeat_fdisplay(code)
code = add_display_into_2delays(code, header)
return code
@run_with_timeout(timeout=30)
def pychecker_CMB_TB_standardization(code, header):
"""
different from pychecker_SEQ_TB_standardization, there is no timing issues in CMB
"""
code = verilog_patch(code)
code = find_and_rewrite_fdisplay(code, header)
return code
def find_and_rewrite_fdisplay(code:str, header:str):
"""
This function is used to find all the $fdisplay sentence and rewrite them in a standard format
"""
fdisplay_check = fdisplay_code_gen(header, ckeck_en=True)
fdisplay_nocheck = fdisplay_code_gen(header, ckeck_en=False)
current_location = 0
code_processed = ""
code_todo = code
start = 0
end = 0
while True:
start = code_todo[current_location:].find("$fdisplay")
if start == -1:
break
end = code_todo[start:].find(");") + start +1
display_sentence = code_todo[start:end+1]
code_processed += code_todo[:start]
code_todo = code_todo[end+1:]
check_en = True if "[check]" in display_sentence else False
if check_en:
code_processed += fdisplay_check
else:
code_processed += fdisplay_nocheck
code = code_processed + code_todo
return code
def add_fdisplay_to_repeat(code:str, header:str):
code_done = ""
code_todo = code
while True:
repeat_start = code_todo.find("repeat")
if repeat_start == -1:
break
# check if no display until the next scenario
next_scenario = code_todo[repeat_start:].find("$fdisplay") # it is ok even if it is -1
if "[check]" not in code_todo[repeat_start:repeat_start+next_scenario]:
fdisplay_code = fdisplay_code_gen(header, ckeck_en=True) + " "
else:
fdisplay_code = fdisplay_code_gen(header, ckeck_en=False) + " "
# check if this repeat is single-line or multi-line
new_line = min_no_minusone(code_todo[repeat_start:].find("\n"), code_todo[repeat_start:].find("//"))
if "begin" not in code_todo[repeat_start:repeat_start+new_line]:
# single-line repeat, add begin end
repeat_end = new_line + repeat_start
after_repeat = code_todo[repeat_start:repeat_start+new_line].find(")") + 2 + repeat_start
repeat_block = code_todo[repeat_start:after_repeat] + "begin " + code_todo[after_repeat:repeat_end] + " end"
else:
repeat_end = code_todo[repeat_start:].find("end") + repeat_start
repeat_block = code_todo[repeat_start:repeat_end]
# check if there is a $fdisplay in the repeat block
if "$fdisplay" not in repeat_block:
# no fdisplay, add one in front of the first delay
delay_start = repeat_block.find("#")
# add the fdisplay before the first delay
code_done += code_todo[:repeat_start] + repeat_block[:delay_start] + fdisplay_code + repeat_block[delay_start:]
else:
code_done += code_todo[:repeat_start] + repeat_block
code_todo = code_todo[repeat_end:]
code_done += code_todo
return code_done
# def add_delay_into_2displays(code):
# """
# - is there are two $display and there is no delay between them, add #10 at the front of the second $display
# - two kinds of action: insert #10 into two displays; insert #10 into one display and
# """
# code_todo = code
# code_done = ""
# while True:
# if "$fdisplay" in code_todo:
# # find the next $fdisplay
# start_first = code_todo.find("$fdisplay")
# end_first = code_todo[start_first:].find(");") + start_first + 2
# start_second = code_todo[end_first:].find("$fdisplay") + end_first
# if start_second == -1:
# break
# # check if there is a delay between them
# subcode = code_todo[end_first:start_second]
# delay_exist = ("#" in subcode)
# if (not delay_exist):
# code_done += code_todo[:end_first] + " #10; "
# else:
# code_done += code_todo[:end_first]
# code_todo = code_todo[end_first:]
# else:
# code_done += code_todo
# break
# return code_done
def add_delay_into_2displays_or_scenarios(code):
"""
- is there are two $display and there is no delay between them, add #10 at the front of the second $display
- three cases:
- two displays: if no delay, insert
- display and scenario: if no delay, insert
- scenario and display: delete the delay (not sure if we should do, to be continue)
"""
code_todo = code
code_done = ""
new_scenario_next = True
while True:
if "$fdisplay" in code_todo:
# find the next $fdisplay or scenario
if new_scenario_next:
start_first = code_todo.find("scenario =")
end_first = code_todo[start_first:].find(";") + start_first + 1
new_scenario_next = False
new_scenario_now = True
else:
start_first = code_todo.find("$fdisplay")
end_first = code_todo[start_first:].find(");") + start_first + 2
new_scenario_now = False
# check scenario
start_scenario = code_todo[end_first:].find("scenario =" )
start_second = code_todo[end_first:].find("$fdisplay")
if start_second == -1:
code_done += code_todo
break
if not (start_scenario == -1) and (start_scenario < start_second):
# next is a new scenario
start_second = start_scenario
new_scenario_next = True
start_second += end_first
# check and insert delay
subcode = code_todo[end_first:start_second]
if new_scenario_now:
# it is ok if there is no delay between scenario and display because delay already exists behind the last scenario
code_done += code_todo[:end_first]
else:
if (not ("#" in subcode)):
code_done += code_todo[:end_first] + " #10; "
else:
code_done += code_todo[:end_first]
code_todo = code_todo[end_first:]
else:
code_done += code_todo
break
return code_done
def refine_repeat_fdisplay(code:str):
"""
- good repeat block: $display->#10->repeat{$display->#10}n->$display->#10
- bad repeat block: $display->repeat{#10->$display->#10}n->$display->#10
- this code standardization is newly added in AutoBench2
"""
# capture the repeat block
code_todo = code
code_done = ""
while "repeat" in code_todo:
repeat_start = code_todo.find("repeat")
repeat_end = code_todo[repeat_start:].find("end") + repeat_start
repeat_block = code_todo[repeat_start:repeat_end]
# check if the repeat block satisfies the condition
delay_amount_in_repeat = repeat_block.count("#10")
display_amount_in_repeat = repeat_block.count("$fdisplay")
if delay_amount_in_repeat == display_amount_in_repeat + 1:
# then we need to move one delay out
first_delay_pos = repeat_block.find("#10")
first_display_pos = repeat_block[first_delay_pos:].find("$fdisplay") + first_delay_pos
repeat_block = repeat_block[:first_delay_pos] + repeat_block[first_display_pos:]
before_repeat = code_todo[:repeat_start]
before_repeat_last_newline = before_repeat.rfind("\n")
# replace the last "\n" with " #10;\n"
before_repeat = before_repeat[:before_repeat_last_newline] + " #10;\n" + before_repeat[before_repeat_last_newline+1:]
code_done += before_repeat + repeat_block
# code_done += code_todo[:repeat_start] + repeat_block
code_todo = code_todo[repeat_end:]
elif delay_amount_in_repeat + 1 == display_amount_in_repeat:
# then we need to move one #10 in
# we add a #10 before the first $fdisplay
first_display_pos = repeat_block.find("$fdisplay")
repeat_block = repeat_block[:first_display_pos] + "#10; " + repeat_block[first_display_pos:]
# then we delete the last #10 before the repeat block
before_repeat = code_todo[:repeat_start]
before_repeat_last_delay = before_repeat.rfind("#10")
before_repeat = before_repeat[:before_repeat_last_delay] + before_repeat[before_repeat_last_delay+4:]
code_done += before_repeat + repeat_block
code_todo = code_todo[repeat_end:]
else:
code_done += code_todo[:repeat_start] + repeat_block
code_todo = code_todo[repeat_end:]
code_done += code_todo
return code_done
def add_display_into_2delays(code:str, header:str=None):
"""if there are two #10 and there is no $fdisplay between them, add $fdisplay at the front of the second #10"""
def find_display(code:str):
load = ""
check = ""
start = code.find("$fdisplay")
end = code[start:].find(")") + start
first_display = code[start:end+1] + ";"
if "[check]" in first_display:
check = first_display
load = check.replace("[check]", "")
else:
load = first_display
check = load.replace('"scenario: ', '"[check]scenario: ')
return load, check
if header is None:
load, check = find_display(code)
else:
load = fdisplay_code_gen(header, ckeck_en=False)
check = fdisplay_code_gen(header, ckeck_en=True)
code_parts = code.split("#10")
if len(code_parts) >= 2:
# make sure there are at least two #10
for idx, subcode in enumerate(code_parts[:-2]):
real_idx = idx
if "$fdisplay" not in subcode:
code_parts[real_idx] += load + " "
return "#10".join(code_parts)
def split_delay_to_delays(code:str):
# start from the first Scenario/scenario
start = max(code.find("scenario"), code.find("Scenario"))
code_before = code[:start]
code = code[start:]
code = code.split("#")
for idx, subcode in enumerate(code):
if idx != 0:
# find the delay number; i.e., "20 asdbuaw" return "20"
digit = ""
for char in subcode:
if char.isdigit():
digit += char
else:
break
if digit and (digit != "10"):
delay_time = int(digit)
delay10_num = math.ceil(delay_time / 10.0)
# replace the original delay with multiple #10
new_delay = "#10; " * delay10_num
new_delay = new_delay[1:-2]
code[idx] = new_delay + subcode[len(digit):]
return code_before + "#".join(code)
def verilog_patch(vcode:str):
"""
here is a patch for a weird bug of gpt generated verilog code
the bug is "initial begin ... }" or "initial { ... }"
"""
if r"{\n" in vcode:
vcode = vcode.replace(r"{\n", r"begin\n")
# scan the code line by line
vcode_lines = vcode.split("\n")
endmodule = False
for i, line in enumerate(vcode_lines):
line_temp = line.replace(" ", "")
if line_temp == "}":
vcode_lines[i] = line.replace("}", "end")
if "endmodule" in line_temp:
if endmodule:
vcode_lines[i] = line.replace("endmodule", "")
else:
endmodule = True
return "\n".join(vcode_lines)
@run_with_timeout(timeout=30)
def circuit_type_by_code(code:str):
"""
- input: code
- output: "CMB" or "SEQ"
"""
def string_to_words(string:str):
words = string.split(" ")
words = [word for word in words if word != ""]
return words
# _SEQ_exit_pos = 0 # for debug
circuit_type = "CMB" # will be changed to "SEQ" if sequential
if "always" in code:
while True:
always_start = code.find("always")
if always_start == -1:
break
if code[always_start-1] not in [" ", "\n", "\t", ";"]:
code = code[always_start+6:]
continue
elif code[always_start+6] not in [" ", "@"]:
# check always_ff, _comb and _latch
if code[always_start+6] == "_":
always_word = code[always_start:code[always_start:].find(" ")+always_start]
if always_word == "always_ff" or always_word == "always_latch":
circuit_type = "SEQ"
break
code = code[always_start+6:]
continue
# check if there is a begin till next ";"
next_semicolon = code[always_start:].find(";")
if "begin" in code[always_start:always_start+next_semicolon]:
has_begin = True
always_end = code[always_start:].find("end") + always_start
else:
has_begin = False
always_end = next_semicolon + always_start
always_block = code[always_start:always_end]
# currently we use a naive way to check if the always block is sequential or not; will be improved in the future
# check if () exist for the sensitivity list
at_pos = always_block.find("@")
# check the first not-" " character after "@"
char_pos = at_pos
for char in always_block[at_pos+1:]:
char_pos += 1
if char != " ":
break
has_bracket = True if char == "(" else False
signal_list = []
if has_bracket:
sensitivity_list = always_block[always_block.find("(")+1:always_block.find(")")]
sensitivity_list = sensitivity_list.split(",")
for signal in sensitivity_list:
# get none-space words:
signal_seg = string_to_words(signal)
if len(signal_seg) > 1 and ("posedge" in signal_seg or "negedge" in signal_seg):
circuit_type = "SEQ"
# _SEQ_exit_pos = 1
break
signal_list.append(signal_seg[-1])
else: # no bracket, always @ a begin xxx = xxx end;
sensitivity_list_end = always_block[char_pos:].find(" ")
sensitivity_signal = always_block[char_pos:char_pos+sensitivity_list_end]
signal_list.append(sensitivity_signal)
if "*" in signal_list:
code = code[always_end:]
continue
if circuit_type == "SEQ":
# _SEQ_exit_pos = 2
break
else:
break_always_block = string_to_words(always_block)
if "<=" in break_always_block:
circuit_type = "SEQ"
# currently we use a naive way. Following codes are skipped
# check_next_signal = False
# for seg in break_always_block:
# if check_next_signal:
# if seg not in signal_list:
# circuit_type = "SEQ"
# break
# if "=" in seg:
# check_next_signal = True
# else:
# check_next_signal = False
if circuit_type == "SEQ":
# _SEQ_exit_pos = 3
break
code = code[always_end:]
return circuit_type
class given_TB:
def __init__(self, header) -> None:
"""
1. initialize sim time, module testbench and signals
2. initialize "integer file, scenario;"
3. instantiate the DUT
4. clock generation (if have)
5. scenario based test
6. endmodule
"""
self.header = header
self.signals = extract_signals(self.header)
self.TB_code_head = ""
self.TB_code_head += "`timescale 1ns / 1ps\nmodule testbench;\n"
self.TB_code_head += self.initial_signals(self.signals) + "\n"
self.TB_code_head += "integer file, scenario;\n"
self.TB_code_head += "// DUT instantiation\n"
self.TB_code_head += self.instantiate_module_by_signals("top_module", "DUT", self.signals) + "\n"
self.TB_code_head += self.clock_generation()
self.TB_code_head += '\ninitial begin\n file = $fopen("TBout.txt", "w");\nend\n'
# self.TB_code_test = '// Test scenarios\ninitial begin\n file = $fopen("TBout.txt", "w");\n\n // write your codes here\n\n $fclose(file);\n $finish;\nend\n'
self.TB_code_test = '// Scenario Based Test\ninitial begin\n\n // write your scenario checking codes here, according to scenario information\n\n $fclose(file);\n $finish;\nend\n'
self.TB_code_tail = "\nendmodule\n"
def gen_template(self):
return self.TB_code_head + self.TB_code_test + self.TB_code_tail
def clock_generation(self):
clk_en = False
for signal in self.signals:
if signal["name"] in ["clk", "clock"]:
clk_en = True
clk = signal["name"]
break
if not clk_en:
return ""
else:
return "// Clock generation\ninitial begin\n [clk] = 0;\n forever #5 [clk] = ~[clk];\nend\n".replace("[clk]", clk)
@staticmethod
def initial_signals(signals):
"""
- this function is used to initialize signals
"""
initial_str = ""
for signal in signals:
if signal["type"] == "input":
initial_str += f"reg {signal['width']} {signal['name']};\n"
else:
initial_str += f"wire {signal['width']} {signal['name']};\n"
return initial_str
@staticmethod
def instantiate_module_by_signals(module_name, instantiate_name, signals):
"""
- this function is used to instantiate a module by signals
- the signals should be like [{"name": "a", "width": "[3:0]", "type": "input"}, ...]
"""
instantiate_str = f"{module_name} {instantiate_name} (\n"
for signal in signals:
if signal["width"]:
instantiate_str += f"\t.{signal['name']}({signal['name']}),\n"
else:
instantiate_str += f"\t.{signal['name']}({signal['name']}),\n"
instantiate_str = instantiate_str[:-2] + "\n);"
return instantiate_str
# used by stage 5
def signal_dictlist_template(header:str, exclude_clk:bool=False, use_check_en:bool = True) -> str:
"""
for the automatic generation of signals in testbench
target: given the DUT header, generate the signal output template
eg: if we have a DUT header like "module DUT(input a, b, c, output d, e);", the signal output template should be like "[{"check_en": 0, "scenario": 1, "a": 1, "b": 0, "c":1, "d": 0, "e": 0}, {"check_en": 1, "scenario": 1, "a": 0, "b": 0, "c":1, "d": 0, "e": 0}]"
"""
signals_dictlist1 = header_to_dictlist(header, exclude_clk=exclude_clk, use_check_en=use_check_en)
signals_dictlist2 = header_to_dictlist(header, exclude_clk=exclude_clk, use_check_en=use_check_en)
signals_dictlist3 = header_to_dictlist(header, check_en=True, exclude_clk=exclude_clk, use_check_en=use_check_en)
signals_dictlist = signals_dictlist1 + signals_dictlist2 + signals_dictlist3
return str(signals_dictlist)
def header_to_dictlist(header:str, value=1, scenario_idx=1, check_en = False, exclude_clk:bool=False, use_check_en:bool = True) -> str:
"""
- header: the header of DUT
- template_scenario_idx: the scenario index in the template
- signal_value: the value of the signal in the template
- only: None: both input signal and output signal; "input": only input signal; "output": only output signal
- from header to signals in txt
- for the automatic generation of signals in testbench
- target: given the DUT header, generate the signal output template
- eg: if we have a DUT header like "module DUT(input clk, load, data, output q);", the signal output template should be like "$fdisplay(file, "scenario: %d, clk = %d, load = %d, data = %d, q = %d", scenario, clk, load, data, q);"
"""
signals = extract_signals(header)
if exclude_clk:
signals = [signal for signal in signals if signal["name"] not in ["clk", "clock"]]
dict_out = {}
dict_list_out = [dict_out]
if use_check_en:
dict_out["check_en"] = check_en
dict_out["scenario"] = scenario_idx
for signal in signals:
dict_out[signal["name"]] = value
return dict_list_out
def signal_dictlist_template_CMB(header:str, exclude_clk:bool=False) -> str:
"""
for the automatic generation of signals in testbench
target: given the DUT header, generate the signal output template
eg: if we have a DUT header like "module DUT(input a, b, c, output d, e);", the signal output template should be like "[{"check_en": 0, "scenario": 1, "a": 1, "b": 0, "c":1, "d": 0, "e": 0}, {"check_en": 1, "scenario": 1, "a": 0, "b": 0, "c":1, "d": 0, "e": 0}]"
"""
signals_dictlist1 = header_to_dictlist(header, exclude_clk=exclude_clk)
return str(signals_dictlist1)
def header_to_dictlist_CMB(header:str, value=1, scenario_idx=1, exclude_clk:bool=False) -> str:
"""
- header: the header of DUT
- template_scenario_idx: the scenario index in the template
- signal_value: the value of the signal in the template
- only: None: both input signal and output signal; "input": only input signal; "output": only output signal
- from header to signals in txt
- for the automatic generation of signals in testbench
- target: given the DUT header, generate the signal output template
- eg: if we have a DUT header like "module DUT(input clk, load, data, output q);", the signal output template should be like "$fdisplay(file, "scenario: %d, clk = %d, load = %d, data = %d, q = %d", scenario, clk, load, data, q);"
"""
signals = extract_signals(header)
if exclude_clk:
signals = [signal for signal in signals if signal["name"] not in ["clk", "clock"]]
dict_out = {}
dict_list_out = [dict_out]
# dict_out["scenario"] = scenario_idx
for signal in signals:
dict_out[signal["name"]] = value
return dict_list_out
def min_no_minusone(a, b):
if a == -1:
return b
if b == -1:
return a
return min(a, b)
if __name__ == "__main__":
code = """
`timescale 1ns / 1ps
module testbench;
reg clk;
reg areset;
reg x;
wire z;
integer file, scenario;
// DUT instantiation
top_module DUT (
.clk(clk),
.areset(areset),
.x(x),
.z(z)
);
// Clock generation
initial begin
clk = 0;
forever #5 clk = ~clk;
end
initial begin
file = $fopen("TBout.txt", "w");
end
// Scenario Based Test
initial begin
// Scenario 1
scenario = 1;
areset = 1;
x = 0;
repeat(2) begin
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", scenario, clk, areset, x, z);
#10;
end
areset = 0;
repeat(4) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 1, clk, areset, x, z);
#10;
end
// Scenario 2
scenario = 2;
areset = 1;
x = 0;
repeat(3) begin
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", scenario, clk, areset, x, z);
#10;
end
areset = 0;
repeat(8) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 2, clk, areset, x, z);
#10;
end
areset = 1;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 2, clk, areset, x, z);
#10;
areset = 0;
repeat(4) begin
x = 1;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 2, clk, areset, x, z);
#10;
end
// Scenario 3
scenario = 3;
areset = 0;
repeat(3) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 3, clk, areset, x, z);
#10;
end
areset = 1;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 3, clk, areset, x, z);
#10;
areset = 0;
repeat(3) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 3, clk, areset, x, z);
#10;
end
// Scenario 4
scenario = 4;
areset = 1;
x = 0;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", scenario, clk, areset, x, z);
#10;
areset = 0;
repeat(3) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 4, clk, areset, x, z);
#10;
end
x = 0;
repeat(2) begin
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 4, clk, areset, x, z);
#10;
end
scenario = 25; // 11001 in binary
repeat(5) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 4, clk, areset, x, z);
#10;
end
// Scenario 5
scenario = 5;
areset = 0;
repeat(8) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 5, clk, areset, x, z);
#10;
end
areset = 1;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 5, clk, areset, x, z);
#10;
areset = 0;
scenario = 170; // 10101010 in binary
repeat(8) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 5, clk, areset, x, z);
#10;
end
// Scenario 6
scenario = 6;
areset = 1;
x = 0;
repeat(4) begin
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", scenario, clk, areset, x, z);
#10;
end
areset = 0;
repeat(8) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 6, clk, areset, x, z);
#10;
end
x = 1;
repeat(5) begin
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 6, clk, areset, x, z);
#10;
end
// Scenario 7
scenario = 7;
areset = 0;
x = 0;
repeat(5) begin
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", scenario, clk, areset, x, z);
#10;
end
x = 1;
repeat(5) begin
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", scenario, clk, areset, x, z);
#10;
end
areset = 1;
repeat(2) begin
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", scenario, clk, areset, x, z);
#10;
end
areset = 0;
scenario = 10; // 01010 in binary
repeat(5) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 7, clk, areset, x, z);
#10;
end
// Scenario 8
scenario = 8;
areset = 1;
x = 0;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", scenario, clk, areset, x, z);
#10;
areset = 0;
scenario = 455; // 111000111 in binary
repeat(9) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 8, clk, areset, x, z);
#10;
end
areset = 1;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 8, clk, areset, x, z);
#10;
areset = 0;
scenario = 56; // 000111000 in binary
repeat(9) begin
x = scenario % 2;
scenario = scenario / 2;
$fdisplay(file, "[check]scenario: %d, clk = %d, areset = %d, x = %d, z = %d", 8, clk, areset, x, z);
#10;
end
$fclose(file);
$finish;
end
endmodule"""
header = """module top_module (
input clk,
input areset,
input x,
output z
);"""
code = pychecker_SEQ_TB_standardization(code, header)
print(code)