Skip to content

Commit c841e7a

Browse files
committed
testing script
1 parent e9bf0af commit c841e7a

File tree

2 files changed

+185
-35
lines changed

2 files changed

+185
-35
lines changed

pass/extractor/tests/create_yaml_for_hagent.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def block_scalar_representer(dumper, value):
99
return dumper.represent_scalar('tag:yaml.org,2002:str', value, style='|')
1010

1111

12-
def generate_yaml(input_file, model_name_version, output_file):
12+
def generate_yaml(input_file, top_name, model_name_version, output_file):
1313
try:
1414

1515
with open(input_file, "r") as f:
@@ -19,36 +19,41 @@ def generate_yaml(input_file, model_name_version, output_file):
1919

2020

2121
yaml_content = {
22-
"replicate_code": {
23-
"llm": {"model": model_name_version},
22+
#"replicate_code": {
23+
"llm": {"model": model_name_version},
24+
"top_name": top_name,
2425
"replicate_code_prompt1": [
2526
{
2627
"role": "system",
2728
"content": "You are a super smart Verilog and timing expert."
2829
"You have been tasked with improving the frequency of a verilog code."
2930
"You provide a higher frequency code which passes LEC."
30-
"If you cannot improve frequency any further, return the text \"no change possible\"."
31-
"However, make sure that you only return the code that passes LEC."
31+
"Make sure that you only return the code that passes LEC."
3232
"Take care that:"
3333
"The semantics are preserved exactly as in the original netlist (including word instantiation and sign‐extension)"
3434
"while breaking a long combinational critical path."
3535
"The resultant code is functionally equivalent to the original and passes LEC."
3636
},
3737
{
3838
"role": "user",
39-
"content": f"This is the current Verilog:\n```\n{code_content}\n```\n"
39+
"content": "This is the current Verilog:\n```\n{code_content}\n```\n"
4040
"The above code has comments with the word CRITICAL providing hints on the where the critical path resides. These are likely statements or related statements that need to be optimized."
4141
"Please do not change semantics, just split the always blocks in separate always blocks "
4242
"and try to improve the performance when possible."
4343
}
4444
]
45-
}
45+
#}
4646
}
4747

4848
if "o3" in model_name_version:
49-
yaml_content["replicate_code"]["threshold"] = 40
49+
#yaml_content["replicate_code"]["threshold"] = 40
50+
yaml_content["threshold"] = 40
5051
elif "o4" in model_name_version:
51-
yaml_content["replicate_code"]["temperature"] = 40
52+
yaml_content["temperature"] = 40
53+
#yaml_content["replicate_code"]["temperature"] = 40
54+
55+
yaml_content["code_content"]=code_content
56+
#yaml_content["replicate_code"]["code_content"]=code_content
5257

5358
with open(output_file, "w") as f:
5459
yaml.dump(yaml_content, f, default_flow_style=False, sort_keys=False, allow_unicode=True, default_style=None, indent=2)
@@ -72,11 +77,14 @@ def generate_yaml(input_file, model_name_version, output_file):
7277
try:
7378
parser = argparse.ArgumentParser(description="Generate a YAML file from an input file and model name version.")
7479
parser.add_argument("input_file", help="Path to the input file containing code.")
80+
parser.add_argument("top_name", help="top_name.")
7581
parser.add_argument("-m", "--model_name_version", required=True, help="Model name as string.")
7682
parser.add_argument("-o", "--output_file", required=True, help="Name of the output YAML file (as module name preferred).")
7783

7884
args = parser.parse_args()
79-
generate_yaml(args.input_file, args.model_name_version, args.output_file)
85+
print("I GOT:")
86+
print(f"{args.input_file}, {args.top_name}, {args.model_name_version}, {args.output_file}\n")
87+
generate_yaml(args.input_file, args.top_name, args.model_name_version, args.output_file)
8088
except TypeError as e:
8189
print(f"Error: Invalid argument type passed to argparse: {e}")
8290
sys.exit(1)

pass/extractor/tests/splitRTLandSynthesize.sh

Lines changed: 167 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ test_dir=$(pwd)
1818
rtl_real_src_dir="${test_dir}/rtl_real_source"
1919
synth_dir="${test_dir}/nl_single"
2020
synalign_log_file="${test_dir}/extractor_alignment_tests/${top_name}_Synalign.log"
21-
21+
original_arrival_time=0.00
2222
# which is the top module?
2323
if [[ "$PWD" == *"PipelineDino"* ]]; then
2424
top_name="PipelinedCPU"
@@ -32,6 +32,9 @@ fi
3232
rtl_path="${test_dir}/rtl_modules"
3333
rtl_selected_top_path="${test_dir}/rtl_single"
3434
rtl_selected_top_file="${rtl_selected_top_path}/${top_name}.v"
35+
rtl_opt_dir="${test_dir}/rtl_optimized"
36+
INPUT_YAMLS="/home/sgarg3/hagent/hagent/step/replicate_code/tests/input_yamls"
37+
GEN_YAMLS="/home/sgarg3/hagent/generated_yamls"
3538

3639
#example of what this function does: top.v(rtl)--{yosys}-->rtl_single/pipelinedCPU.v(rtl)
3740
create_selected_top_file () {
@@ -186,7 +189,7 @@ fi
186189
# Extract the line with "slack" and get the corresponding value
187190
# -m 1 --> will select only the 1st occurence. otherwise all the slack values will be printed.
188191
arrival_time=$(grep -m 1 -oP '\s*-?\d+\.\d+\s+data arrival time' "$latest_report" | awk '{print $1}')
189-
192+
original_arrival_time=arrival_time
190193
# Output the slack value
191194
echo "arrival_time: $arrival_time"
192195

@@ -293,7 +296,16 @@ inou/yosys/lgcheck --top
293296

294297
}
295298

296-
create_yaml_for_hagent() {
299+
create_yaml_and_call_hagent() {
300+
301+
# Use sed to replace "module <top_name>_original" with "module <top_name>" in place
302+
sed -i "s/module[[:space:]]\+${top_name}_original\>/module ${top_name}/" "$rtl_path/liveparse/${top_name}.v"
303+
if [ -f "$rtl_path/liveparse/${top_name}_commented.v" ]; then
304+
sed -i "s/module[[:space:]]\+${top_name}_original\>/module ${top_name}/" "$rtl_path/liveparse/${top_name}_commented.v"
305+
fi
306+
echo "NOTE: Reverted SynAlign renaming in $rtl_path/liveparse/${top_name}.v"
307+
308+
297309
# Find all files ending with "_commented.v" and store in an array
298310
files=($(find "${rtl_path}/liveparse/" -type f -name "*_commented.v"))
299311

@@ -316,38 +328,168 @@ create_yaml_for_hagent() {
316328
base_name=$(basename "$file" "_commented.v") # Extract module name
317329
output_file="${base_name}.yaml" # Construct output file name
318330
echo "Creating yaml for $file -> $output_file"
319-
python3 ../create_yaml_for_hagent.py $file -m "openai/o3-mini-2025-01-31" -o ${rtl_path}/liveparse/$output_file
320-
done
331+
python3 ../create_yaml_for_hagent.py $file $base_name -m "openai/o3-mini-2025-01-31" -o ${rtl_path}/liveparse/$output_file
332+
333+
#now call hagent for each of these files.
334+
335+
# Check and create input_yamls if it doesn't exist
336+
if [ ! -d "$INPUT_YAMLS" ]; then
337+
echo "Creating directory: $INPUT_YAMLS"
338+
mkdir -p "$INPUT_YAMLS"
339+
else
340+
echo "Directory already exists: $INPUT_YAMLS"
341+
fi
342+
343+
# Check and create generated_yamls if it doesn't exist
344+
if [ ! -d "$GEN_YAMLS" ]; then
345+
echo "Creating directory: $GEN_YAMLS"
346+
mkdir -p "$GEN_YAMLS"
347+
else
348+
echo "Directory already exists: $GEN_YAMLS"
349+
fi
350+
351+
#run hagent:
352+
cp ${rtl_path}/liveparse/$output_file ${INPUT_YAMLS}/$output_file
353+
echo "Copying ${rtl_path}/liveparse/$output_file to ${INPUT_YAMLS}/$output_file"
354+
355+
356+
#go to hagent replicate_code directory
357+
cd ~/hagent/
358+
ret_val=$?
359+
if [ $ret_val -ne 0 ]; then
360+
echo "\n--------hagent folder not found. check the directory structure and make necessary changes.--------\n\n"
361+
exit $ret_val
362+
fi
363+
#rm res.log ; #rm replicate_code.log ; #poetry run python3 ./hagent/step/replicate_code/replicate_code.py -ogenerated_yamls/ALU.yaml ./hagent/step/replicate_code/tests/input_yamls/ALU.yaml |& tee res.log
364+
poetry run python3 ./hagent/step/replicate_code/replicate_code.py -o${GEN_YAMLS}/${base_name}.yaml ${INPUT_YAMLS}/${base_name}.yaml 2>&1 | tee ${GEN_YAMLS}/${base_name}.log
365+
echo "writing to ${GEN_YAMLS}/${base_name}.log...."
366+
cd $test_dir
321367

368+
done
322369

323370

324371
}
325372

373+
synth_yosys_and_calc_new_freq() {
326374

327-
##call_hagent() {
328-
##}
375+
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
376+
echo " Synthesize optimized design: $top_name ... "
377+
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
378+
## #Check if any file ending with "_optimized.v" is created using hagent:
379+
## #if they are created then bring them (without _optimized.v) to rtl_optimized directory in the test dir
380+
if [ ! -d "$rtl_opt_dir" ]; then
381+
mkdir -p "$rtl_opt_dir"
382+
else
383+
rm -r $rtl_opt_dir/*
384+
fi
385+
#get all orig files for synth:
386+
#files=$(find "${rtl_path}/liveparse" -type f -name "*.v" ! -name "*_optimized.v" ! -name "*_commented.v") # Find all .v files but exclude _optimized.v and _commented.v
387+
find "$rtl_path/liveparse" -type f -name "*.v" ! -name "*_optimized.v" ! -name "*_commented.v" -exec cp {} "$rtl_opt_dir" \;
388+
#get optimized file from GEN_YAMLS and use these optimized modules instead of original modules:
389+
files=$(find "$GEN_YAMLS" -type f -name "*_optimized.v")
390+
if [ -z "$files" ]; then
391+
echo "No *_optimized.v files found in $GEN_YAMLS."
392+
else
393+
echo "$files" | while read -r file; do
394+
new_name=$(basename "$file" | sed 's/_optimized//')
395+
cp "$file" "$rtl_opt_dir/$new_name"
396+
echo "Copied and renamed: $file -> $rtl_opt_dir/$new_name"
397+
done
398+
fi
329399

330-
##./clean_tests.sh
331-
##create_selected_top_file
332-
##split_into_modules
333-
##synth_yosys
334-
##calc_frequency_and_create_color_dot_json
335-
###now we need to lower the arrival time to improve frequency.
336-
###Which part of rtl does the nodes in above reported timing path belong to?
337-
##run_synalign
338-
###orig files are from liveparse/
339-
##cd $test_dir
340-
##comment_rtl
341-
##
342-
##echo `pwd`
400+
#now we have all files to be synthesized in rtl_opt_dir
401+
mkdir $rtl_opt_dir/synth_file
402+
optimized_netlist="$rtl_opt_dir/synth_file/${top_name}_synth.v"
403+
yosys -p "
404+
read_verilog -sv -defer $rtl_opt_dir/*.v
405+
hierarchy -top $top_name;
406+
flatten $top_name;
407+
opt;
408+
synth -top $top_name;
409+
dfflibmap -liberty $LIBERTY_FILE;
410+
printattrs;
411+
stat;
412+
abc -liberty $LIBERTY_FILE -dff -keepff -g aig;
413+
stat;
414+
write_verilog $optimized_netlist;
415+
" > synth_top.log
416+
if [ $? -eq 0 ]; then
417+
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
418+
echo " Synthesis using Yosys completed. "
419+
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
420+
else
421+
echo "~~~~~~~~~~~~~ ERROR: YOSYS synthesis failed! ~~~~~~~~~~~"
422+
exit 1
423+
fi
343424

344-
#now use AI to generate optimized versions of _commented.v files(modules)
345-
create_yaml_for_hagent
346-
##call_hagent to create _optimized.v as well as run lec check on _optimized and _commented versions
347425

426+
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
427+
echo " Find frequency using openSTA for $top_name ... "
428+
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
429+
cd $test_dir
430+
mkdir $rtl_opt_dir/timing
431+
# Define variables
432+
new_sta_tcl="$rtl_opt_dir/timing/run_sta.tcl" # Replace with the actual SDC filename
433+
434+
# Create the SDC file and write the required content
435+
cat > "$new_sta_tcl" <<EOF
436+
read_liberty $LIBERTY_FILE
437+
set_units -time ns -capacitance pF -voltage V -current mA -resistance kOhm -distance um
438+
set_operating_conditions ff_100C_1v95
439+
read_verilog $optimized_netlist
440+
link_design $top_name
441+
read_sdc ${top_name}.sdc
442+
report_checks -path_delay max > ${rtl_opt_dir}/timing/timing_report.rpt
443+
EOF
444+
445+
echo "SDC file created: $new_sta_tcl"
446+
447+
# Run OpenSTA
448+
echo "source $new_sta_tcl" | ~/opensta/OpenSTA/app/sta
449+
450+
# Find the latest timing report file
451+
latest_report=$(ls ${rtl_opt_dir}/timing/timing_report.rpt 2>/dev/null | tail -n 1)
452+
# Check if a file was found
453+
if [ ! -n "$latest_report" ]; then
454+
echo "No timing report found."
455+
exit 1
456+
fi
457+
458+
# Extract the line with "slack" and get the corresponding value
459+
arrival_time=$(grep -m 1 -oP '\s*-?\d+\.\d+\s+data arrival time' "$latest_report" | awk '{print $1}')
460+
original_arrival_time=arrival_time
461+
# Output the slack value
462+
echo "new arrival_time: $arrival_time"
463+
464+
improved_arrival_time_diff=$(echo "$original_arrival_time - $arrival_time" | bc)
465+
echo "####################################################################"
466+
echo "NOTE: improvement in arrival time: $improved_arrival_time_diff ns"
467+
echo "####################################################################"
348468

349-
#if lec fails, get another version from LLM and retry LEC until it passes.
350-
##write the chat command: "your solution fails LEC. try again."
351469

470+
}
471+
472+
473+
./clean_tests.sh
474+
create_selected_top_file
475+
split_into_modules
476+
synth_yosys
477+
calc_frequency_and_create_color_dot_json
478+
#now we need to lower the arrival time to improve frequency.
479+
#Which part of rtl does the nodes in above reported timing path belong to?
480+
run_synalign
481+
#orig files are from liveparse/
482+
cd $test_dir
483+
comment_rtl
484+
485+
echo `pwd`
486+
487+
#now use AI to generate optimized versions of _commented.v files(modules)
488+
create_yaml_and_call_hagent
489+
#call_hagent to create _optimized.v as well as run lec check on _optimized and _commented versions
490+
#if lec fails, get another version from LLM and retry LEC until it passes.
491+
#write the chat command: "your solution fails LEC. try again."
352492
#if lec passes, stitch optimized version with all other modules and create a neww top and re run synth+timing to check if freq. improved!
353493

494+
synth_yosys_and_calc_new_freq
495+

0 commit comments

Comments
 (0)