From 832f8309a4fc30d6f5dff8d3c0938d77bb36f02f Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Sat, 27 May 2023 23:49:58 +0530 Subject: [PATCH 01/32] feat: added mako to Python requirements.txt --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index cadf3b47a..87d50d37e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,4 @@ nbsphinx cairosvg scipy ltspice +mako \ No newline at end of file From 45d2c600a615613c7407fa9746263e5421ee5b04 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Sun, 28 May 2023 23:03:53 +0530 Subject: [PATCH 02/32] feat: exported a verilog generation function --- openfasoc/generators/common/__init__.py | 0 .../generators/common/verilog_generation.py | 37 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 openfasoc/generators/common/__init__.py create mode 100644 openfasoc/generators/common/verilog_generation.py diff --git a/openfasoc/generators/common/__init__.py b/openfasoc/generators/common/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/openfasoc/generators/common/verilog_generation.py b/openfasoc/generators/common/verilog_generation.py new file mode 100644 index 000000000..d334b8959 --- /dev/null +++ b/openfasoc/generators/common/verilog_generation.py @@ -0,0 +1,37 @@ +from mako.template import Template +from os import path, makedirs, listdir + +def __get_output_filepath(filename, out_dir): + return path.join(out_dir, filename.replace(".template", "")) + +def __generate_file(input_path, output_path, parameters): + template = Template(filename=input_path) + + out_file = open(output_path, "w") + out_file.write(template.render(**parameters)) + +def __generate_subdirectory(src_dir, out_dir, parameters): + # generate the output directory if it doesn't exist + if not path.exists(out_dir): + makedirs(out_dir) + + for filename in listdir(src_dir): + file_path = path.join(src_dir, filename) + + if path.isdir(file_path): + # if the path is a subdirectory, recursively call the function + __generate_subdirectory(file_path, path.join(out_dir, filename), parameters) + else: + # if the path is a fine, generate the output + __generate_file( + file_path, + __get_output_filepath(filename, out_dir), + parameters + ) + +def generate_verilog( + parameters, + src_dir = "src", + out_dir = path.join("flow", "design", "src") +): + __generate_subdirectory(src_dir, out_dir, parameters) \ No newline at end of file From 7c58dbd5791e3add18dd9a6eec4c217c4e79fe6e Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 00:51:21 +0530 Subject: [PATCH 03/32] doc: added code hints to verilog generation functions --- openfasoc/generators/common/verilog_generation.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openfasoc/generators/common/verilog_generation.py b/openfasoc/generators/common/verilog_generation.py index d334b8959..a948f546e 100644 --- a/openfasoc/generators/common/verilog_generation.py +++ b/openfasoc/generators/common/verilog_generation.py @@ -1,16 +1,16 @@ from mako.template import Template from os import path, makedirs, listdir -def __get_output_filepath(filename, out_dir): +def __get_output_filepath(filename: str, out_dir: str) -> str: return path.join(out_dir, filename.replace(".template", "")) -def __generate_file(input_path, output_path, parameters): +def __generate_file(input_path: str, output_path: str, parameters: dict) -> None: template = Template(filename=input_path) out_file = open(output_path, "w") out_file.write(template.render(**parameters)) -def __generate_subdirectory(src_dir, out_dir, parameters): +def __generate_subdirectory(src_dir: str, out_dir: str, parameters: dict) -> None: # generate the output directory if it doesn't exist if not path.exists(out_dir): makedirs(out_dir) @@ -30,8 +30,8 @@ def __generate_subdirectory(src_dir, out_dir, parameters): ) def generate_verilog( - parameters, - src_dir = "src", - out_dir = path.join("flow", "design", "src") -): + parameters: dict, + src_dir: str = "src", + out_dir: str = path.join("flow", "design", "src") +) -> None: __generate_subdirectory(src_dir, out_dir, parameters) \ No newline at end of file From 60d11e902e0de3a3f23b65eefdd59e24e80c8276 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 16:00:46 +0530 Subject: [PATCH 04/32] feat: use the new verilog generation function in temp-sense-gen. --- .../temp-sense-gen/tools/temp-sense-gen.py | 103 +++++++++++------- 1 file changed, 61 insertions(+), 42 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py index 357fba902..3f9272b10 100755 --- a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py +++ b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py @@ -12,6 +12,10 @@ from readparamgen import args, check_search_done, designName from simulation import generate_runs +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) + +from common.verilog_generation import generate_verilog + genDir = os.path.join(os.path.dirname(os.path.relpath(__file__)), "../") srcDir = genDir + "src/" flowDir = genDir + "flow/" @@ -115,50 +119,65 @@ aux6 = "SLC_hs" ninv = ninv + 1 -TEMP_netlist.gen_temp_netlist(ninv, nhead, aux1, aux2, aux3, aux4, aux5, srcDir) - -with open(srcDir + "TEMP_ANALOG_hv.nl.v", "r") as rf: - filedata = rf.read() -header_list = re.findall("HEADER\s+(\w+)\(", filedata) -with open(genDir + "blocks/sky130hd/tempsenseInst_custom_net.txt", "w") as wf: - wf.write("r_VIN\n") - for header_cell in header_list: - wf.write("temp_analog_1." + header_cell + " VIN\n") - -with open(srcDir + "TEMP_ANALOG_lv.nl.v", "r") as rf: - filedata = rf.read() -lv_list = re.findall("\nsky130_fd_sc\w*\s+(\w+)\s+\(", filedata) -with open(genDir + "blocks/sky130hd/tempsenseInst_domain_insts.txt", "w") as wf: - for lv_cell in lv_list: - wf.write("temp_analog_0." + lv_cell + "\n") - -with open(srcDir + "tempsenseInst.v", "r") as rf: - filedata = rf.read() - filedata = re.sub("module\s*(\w+)\s*\n", "module " + designName + "\n", filedata) -with open(srcDir + "tempsenseInst.v", "w") as wf: - wf.write(filedata) - -with open(flowDir + "design/sky130hd/tempsense/config.mk", "r") as rf: - filedata = rf.read() - filedata = re.sub( - "export DESIGN_NAME\s*=\s*(\w+)", "export DESIGN_NAME = " + designName, filedata - ) -with open(flowDir + "design/sky130hd/tempsense/config.mk", "w") as wf: - wf.write(filedata) -shutil.copyfile( - srcDir + "TEMP_ANALOG_lv.nl.v", flowDir + "design/src/tempsense/TEMP_ANALOG_lv.nl.v" -) -shutil.copyfile( - srcDir + "TEMP_ANALOG_hv.nl.v", flowDir + "design/src/tempsense/TEMP_ANALOG_hv.nl.v" +# TODO: Previous code. Remove later. +# TEMP_netlist.gen_temp_netlist(ninv, nhead, aux1, aux2, aux3, aux4, aux5, srcDir) + +generate_verilog( + parameters={ + "cell_prefix": "sky130_fd_sc_hd__" if args.platform == "sky130hd" else "sky130_fd_sc_hs__", + "cell_suffix": "_1", + "header_cell": "HEADER" if args.platform == "sky130hd" else "HEADER_hs", + "slc_cell": "SLC" if args.platform == "sky130hd" else "SLC_hs", + "ninv": ninv, + "nhead": nhead + }, + out_dir=os.path.join('flow', 'design', 'src', 'tempsense') ) -shutil.copyfile( - srcDir + "TEMP_AUTO_def.v", flowDir + "design/src/tempsense/TEMP_AUTO_def.v" -) -shutil.copyfile( - srcDir + "tempsenseInst.v", flowDir + "design/src/tempsense/" + designName + ".v" -) -shutil.copyfile(srcDir + "counter.v", flowDir + "design/src/tempsense/counter" + ".v") + +# TODO: Previous code. Remove later. +# with open(srcDir + "TEMP_ANALOG_hv.nl.v", "r") as rf: +# filedata = rf.read() +# header_list = re.findall("HEADER\s+(\w+)\(", filedata) +# with open(genDir + "blocks/sky130hd/tempsenseInst_custom_net.txt", "w") as wf: +# wf.write("r_VIN\n") +# for header_cell in header_list: +# wf.write("temp_analog_1." + header_cell + " VIN\n") + +# with open(srcDir + "TEMP_ANALOG_lv.nl.v", "r") as rf: +# filedata = rf.read() +# lv_list = re.findall("\nsky130_fd_sc\w*\s+(\w+)\s+\(", filedata) +# with open(genDir + "blocks/sky130hd/tempsenseInst_domain_insts.txt", "w") as wf: +# for lv_cell in lv_list: +# wf.write("temp_analog_0." + lv_cell + "\n") + +# with open(srcDir + "tempsenseInst.v", "r") as rf: +# filedata = rf.read() +# filedata = re.sub("module\s*(\w+)\s*\n", "module " + designName + "\n", filedata) +# with open(srcDir + "tempsenseInst.v", "w") as wf: +# wf.write(filedata) + +# with open(flowDir + "design/sky130hd/tempsense/config.mk", "r") as rf: +# filedata = rf.read() +# filedata = re.sub( +# "export DESIGN_NAME\s*=\s*(\w+)", "export DESIGN_NAME = " + designName, filedata +# ) +# with open(flowDir + "design/sky130hd/tempsense/config.mk", "w") as wf: +# wf.write(filedata) + +# shutil.copyfile( +# srcDir + "TEMP_ANALOG_lv.nl.v", flowDir + "design/src/tempsense/TEMP_ANALOG_lv.nl.v" +# ) +# shutil.copyfile( +# srcDir + "TEMP_ANALOG_hv.nl.v", flowDir + "design/src/tempsense/TEMP_ANALOG_hv.nl.v" +# ) +# shutil.copyfile( +# srcDir + "TEMP_AUTO_def.v", flowDir + "design/src/tempsense/TEMP_AUTO_def.v" +# ) +# shutil.copyfile( +# srcDir + "tempsenseInst.v", flowDir + "design/src/tempsense/" + designName + ".v" +# ) +# shutil.copyfile(srcDir + "counter.v", flowDir + "design/src/tempsense/counter" + ".v") print("#----------------------------------------------------------------------") print("# Verilog Generated") From 5b4363e4b0dbc1348ed9f9de6725ea3e2c5f0d40 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 16:01:53 +0530 Subject: [PATCH 05/32] feat: converted temp-sense-gen Verilog to Mako templates --- .../temp-sense-gen/src/TEMP_ANALOG_hv.v | 13 ++++-- .../temp-sense-gen/src/TEMP_ANALOG_lv.v | 46 +++++++++++++++---- .../temp-sense-gen/src/counter_generic.v | 9 +++- 3 files changed, 54 insertions(+), 14 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v index a5875db55..edc959faa 100644 --- a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v +++ b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v @@ -1,3 +1,5 @@ +<%def name="cell(name)">${cell_prefix}${name}${cell_suffix} + module TEMP_ANALOG_hv ( input CLK_REF, @@ -26,8 +28,13 @@ counter async_counter_0( ); (* keep *) -@@ @nf a_header_@nh(.VIN(VIN)); -SLC -@@ @no a_buffer_0 (.A(lc_0), .nbout(lc_out)); +// @@ @nf a_header_@nh(.VIN(VIN)); +% for i in range(nhead): + ${header_cell} a_header_${i}(.VIN(VIN)); +% endfor +// SLC +${slc_cell} a_lc_0(.IN(out), .INB(outb), .VOUT(lc_0)); +// @@ @no a_buffer_0 (.A(lc_0), .nbout(lc_out)); +${cell('buf')} a_buffer_0 (.A(lc_0), .nbout(lc_out)); endmodule diff --git a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v index 5948b250a..dbc00f896 100644 --- a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v +++ b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v @@ -1,18 +1,44 @@ +<%def name="cell(name)">${cell_prefix}${name}${cell_suffix} + module TEMP_ANALOG_lv (EN, OUT, OUTB); input EN; // inout in_vin; output OUT, OUTB; wire n; -@@ wire n@nn; + +// @@ wire n@nn; +% for i in range(ninv + 1): + wire n${i + 1}; +% endfor wire nx1, nx2, nx3, nb1, nb2; -@@ @na a_nand_0 ( .A(EN), .B(n@n0), .Y(n1)); -@@ @nb a_inv_@ni ( .A(n@n1), .Y(n@n2)); -@@ @ng a_inv_m1 ( .A(n@n3), .Y(nx1)); -@@ @nk a_inv_m2 ( .A(n@n4), .Y(nx2)); -@@ @nm a_inv_m3 ( .A(nx2), .Y(nx3)); -@@ @np a_buf_3 ( .A(nx3), .nbout(nb2)); -@@ @nc a_buf_0 ( .A(nx1), .nbout(nb1)); -@@ @nd a_buf_1 ( .A(nb1), .nbout(OUT)); -@@ @ne a_buf_2 ( .A(nb2), .nbout(OUTB)); + +// @@ @na a_nand_0 ( .A(EN), .B(n@n0), .Y(n1)); +${cell('nand2')} a_nand_0 ( .A(EN), .B(${ninv + 1}, .Y(n1))); + +// @@ @nb a_inv_@ni ( .A(n@n1), .Y(n@n2)); +% for i in range(ninv): + ${cell('inv')} a_inv_${i} ( .A(n${i + 1}), .Y(n${i + 2})); +% endfor + +// @@ @ng a_inv_m1 ( .A(n@n3), .Y(nx1)); +${cell('inv')} a_inv_m1 ( .A(n${ninv + 1}), .Y(nx1)); + +// @@ @nk a_inv_m2 ( .A(n@n4), .Y(nx2)); +${cell('inv')} a_inv_m1 ( .A(n${ninv + 1}), .Y(nx2)); + +// @@ @nm a_inv_m3 ( .A(nx2), .Y(nx3)); +${cell('inv')} a_inv_m3 ( .A(nx2), .Y(nx3)); + +// @@ @np a_buf_3 ( .A(nx3), .nbout(nb2)); +${cell('buf')} a_buf_3 ( .A(nx3), .X(nb2)); + +// @@ @nc a_buf_0 ( .A(nx1), .nbout(nb1)); +${cell('buf')} a_buf_0 ( .A(nx1), .X(nb1)); + +// @@ @nd a_buf_1 ( .A(nb1), .nbout(OUT)); +${cell('buf')} a_buf_1 ( .A(nb1), .X(OUT)); + +// @@ @ne a_buf_2 ( .A(nb2), .nbout(OUTB)); +${cell('buf')} a_buf_2 ( .A(nb2), .X(OUTB)); endmodule diff --git a/openfasoc/generators/temp-sense-gen/src/counter_generic.v b/openfasoc/generators/temp-sense-gen/src/counter_generic.v index 2c0eef3e3..9d5edc4d0 100644 --- a/openfasoc/generators/temp-sense-gen/src/counter_generic.v +++ b/openfasoc/generators/temp-sense-gen/src/counter_generic.v @@ -1,3 +1,5 @@ +<%def name="cell(name)">${cell_prefix}${name}${cell_suffix} + module counter# ( parameter NBIT = 24 @@ -28,7 +30,12 @@ module counter# assign done_ref = WAKE && doneb; // BUFH_X4M_A9TR Buf_DONE(.A(done_pre), .Y(DONE)); // BUF_X0P4N_A10P5PP84TR_C14 Buf_DONE(.A(done_pre), .Y(DONE)); -@@ @np Buf_DONE(.A(done_pre), .nbout(DONE)); + +// TODO: Previous code. Remove later. +// @@ @np Buf_DONE(.A(done_pre), .nbout(DONE)); + +// .nbout replaced by X because X is hardcoded in TEMP_netlist.py +${cell('buf')} Buf_DONE(.A(done_pre), .X(DONE)); //assign RESET_CLK_REF = ~q1; always @ (*) begin From d3054997daf4133d3d3e7cd18df7770fdc54ce53 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 16:08:51 +0530 Subject: [PATCH 06/32] fix: fixed typos in TEMP_ANALOG_lv.v --- openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v index dbc00f896..55aa1e36b 100644 --- a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v +++ b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v @@ -13,7 +13,7 @@ module TEMP_ANALOG_lv (EN, OUT, OUTB); wire nx1, nx2, nx3, nb1, nb2; // @@ @na a_nand_0 ( .A(EN), .B(n@n0), .Y(n1)); -${cell('nand2')} a_nand_0 ( .A(EN), .B(${ninv + 1}, .Y(n1))); +${cell('nand2')} a_nand_0 ( .A(EN), .B(n${ninv + 1}), .Y(n1)); // @@ @nb a_inv_@ni ( .A(n@n1), .Y(n@n2)); % for i in range(ninv): @@ -24,7 +24,7 @@ ${cell('nand2')} a_nand_0 ( .A(EN), .B(${ninv + 1}, .Y(n1))); ${cell('inv')} a_inv_m1 ( .A(n${ninv + 1}), .Y(nx1)); // @@ @nk a_inv_m2 ( .A(n@n4), .Y(nx2)); -${cell('inv')} a_inv_m1 ( .A(n${ninv + 1}), .Y(nx2)); +${cell('inv')} a_inv_m2 ( .A(n${ninv + 1}), .Y(nx2)); // @@ @nm a_inv_m3 ( .A(nx2), .Y(nx3)); ${cell('inv')} a_inv_m3 ( .A(nx2), .Y(nx3)); From 98fb956d55a2da24d62a2f9eb3230bc2f3c189c6 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 16:09:39 +0530 Subject: [PATCH 07/32] fix: changed placeholder port nbout to X --- openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v index edc959faa..0aced3174 100644 --- a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v +++ b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v @@ -35,6 +35,6 @@ counter async_counter_0( // SLC ${slc_cell} a_lc_0(.IN(out), .INB(outb), .VOUT(lc_0)); // @@ @no a_buffer_0 (.A(lc_0), .nbout(lc_out)); -${cell('buf')} a_buffer_0 (.A(lc_0), .nbout(lc_out)); +${cell('buf')} a_buffer_0 (.A(lc_0), .X(lc_out)); endmodule From 688859b611d213f208cd5180123da7aff9da595b Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 16:11:58 +0530 Subject: [PATCH 08/32] feat: updated gitignore files --- .../generators/temp-sense-gen/flow/design/src/.gitignore | 1 + .../temp-sense-gen/flow/design/src/tempsense/.gitignore | 6 ------ openfasoc/generators/temp-sense-gen/src/.gitignore | 4 ---- 3 files changed, 1 insertion(+), 10 deletions(-) create mode 100644 openfasoc/generators/temp-sense-gen/flow/design/src/.gitignore delete mode 100644 openfasoc/generators/temp-sense-gen/flow/design/src/tempsense/.gitignore delete mode 100644 openfasoc/generators/temp-sense-gen/src/.gitignore diff --git a/openfasoc/generators/temp-sense-gen/flow/design/src/.gitignore b/openfasoc/generators/temp-sense-gen/flow/design/src/.gitignore new file mode 100644 index 000000000..6be86d734 --- /dev/null +++ b/openfasoc/generators/temp-sense-gen/flow/design/src/.gitignore @@ -0,0 +1 @@ +tempsense/ \ No newline at end of file diff --git a/openfasoc/generators/temp-sense-gen/flow/design/src/tempsense/.gitignore b/openfasoc/generators/temp-sense-gen/flow/design/src/tempsense/.gitignore deleted file mode 100644 index ca45c5c8d..000000000 --- a/openfasoc/generators/temp-sense-gen/flow/design/src/tempsense/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# These files are copied to flow/design/src/ by the temp-sense-gen.py tool: -counter.v -TEMP_ANALOG_hv.nl.v -TEMP_ANALOG_lv.nl.v -TEMP_AUTO_def.v -tempsenseInst_error.v diff --git a/openfasoc/generators/temp-sense-gen/src/.gitignore b/openfasoc/generators/temp-sense-gen/src/.gitignore deleted file mode 100644 index 61d41dcc3..000000000 --- a/openfasoc/generators/temp-sense-gen/src/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# These files are generated by the temp-sense-gen.py tool: -counter.v -TEMP_ANALOG_hv.nl.v -TEMP_ANALOG_lv.nl.v From 5e18789e3f948adbb4d5d1ad6ad234c7458c7e31 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 16:13:46 +0530 Subject: [PATCH 09/32] fix: removed unused imports in temp-sense-gen.py --- openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py index 3f9272b10..b65062253 100755 --- a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py +++ b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py @@ -2,13 +2,10 @@ import json import os -import re import shutil import subprocess as sp import sys -import time -import TEMP_netlist from readparamgen import args, check_search_done, designName from simulation import generate_runs From ac85fb9a5be0ec3787e731cc12af48e7825069aa Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 16:28:55 +0530 Subject: [PATCH 10/32] fix: removed extra tabs in Verilog source --- openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v | 2 +- openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v index 0aced3174..70b26ce64 100644 --- a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v +++ b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v @@ -30,7 +30,7 @@ counter async_counter_0( (* keep *) // @@ @nf a_header_@nh(.VIN(VIN)); % for i in range(nhead): - ${header_cell} a_header_${i}(.VIN(VIN)); +${header_cell} a_header_${i}(.VIN(VIN)); % endfor // SLC ${slc_cell} a_lc_0(.IN(out), .INB(outb), .VOUT(lc_0)); diff --git a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v index 55aa1e36b..a478b6836 100644 --- a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v +++ b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v @@ -8,7 +8,7 @@ module TEMP_ANALOG_lv (EN, OUT, OUTB); // @@ wire n@nn; % for i in range(ninv + 1): - wire n${i + 1}; +wire n${i + 1}; % endfor wire nx1, nx2, nx3, nb1, nb2; @@ -17,7 +17,7 @@ ${cell('nand2')} a_nand_0 ( .A(EN), .B(n${ninv + 1}), .Y(n1)); // @@ @nb a_inv_@ni ( .A(n@n1), .Y(n@n2)); % for i in range(ninv): - ${cell('inv')} a_inv_${i} ( .A(n${i + 1}), .Y(n${i + 2})); +${cell('inv')} a_inv_${i} ( .A(n${i + 1}), .Y(n${i + 2})); % endfor // @@ @ng a_inv_m1 ( .A(n@n3), .Y(nx1)); From 1a3bbd6c78b65b0743915f6f5d71b082b9adb94a Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 16:33:42 +0530 Subject: [PATCH 11/32] fix: removed a statement which incremented ninv --- openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py index b65062253..d519bb8e0 100755 --- a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py +++ b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py @@ -115,8 +115,6 @@ aux5 = "HEADER_hs" aux6 = "SLC_hs" -ninv = ninv + 1 - # TODO: Previous code. Remove later. # TEMP_netlist.gen_temp_netlist(ninv, nhead, aux1, aux2, aux3, aux4, aux5, srcDir) @@ -278,7 +276,7 @@ print("# Generating spice netlists for the macro") print("#----------------------------------------------------------------------") -stage_var = [int(ninv) - 1] +stage_var = [int(ninv)] header_var = [int(nhead)] # make a temp list, TODO: get from JSON config From ef5a28f8638a92508af9994f11c8d11d04267477 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 19:42:04 +0530 Subject: [PATCH 12/32] feat: commented unused code --- .../temp-sense-gen/tools/temp-sense-gen.py | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py index d519bb8e0..6409e1e07 100755 --- a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py +++ b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py @@ -100,22 +100,21 @@ print("#----------------------------------------------------------------------") -if args.platform == "sky130hd": - aux1 = "sky130_fd_sc_hd__nand2_1" - aux2 = "sky130_fd_sc_hd__inv_1" - aux3 = "sky130_fd_sc_hd__buf_1" - aux4 = "sky130_fd_sc_hd__buf_1" - aux5 = "HEADER" - aux6 = "SLC" -elif args.platform == "sky130hs": - aux1 = "sky130_fd_sc_hs__nand2_1" - aux2 = "sky130_fd_sc_hs__inv_1" - aux3 = "sky130_fd_sc_hs__buf_1" - aux4 = "sky130_fd_sc_hs__buf_1" - aux5 = "HEADER_hs" - aux6 = "SLC_hs" - # TODO: Previous code. Remove later. +# if args.platform == "sky130hd": +# aux1 = "sky130_fd_sc_hd__nand2_1" +# aux2 = "sky130_fd_sc_hd__inv_1" +# aux3 = "sky130_fd_sc_hd__buf_1" +# aux4 = "sky130_fd_sc_hd__buf_1" +# aux5 = "HEADER" +# aux6 = "SLC" +# elif args.platform == "sky130hs": +# aux1 = "sky130_fd_sc_hs__nand2_1" +# aux2 = "sky130_fd_sc_hs__inv_1" +# aux3 = "sky130_fd_sc_hs__buf_1" +# aux4 = "sky130_fd_sc_hs__buf_1" +# aux5 = "HEADER_hs" +# aux6 = "SLC_hs" # TEMP_netlist.gen_temp_netlist(ninv, nhead, aux1, aux2, aux3, aux4, aux5, srcDir) generate_verilog( From 9524faf5790c87153068a927678834eafdf42f13 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 19:56:38 +0530 Subject: [PATCH 13/32] feat: added designName as a parameter in the Verilog source --- openfasoc/generators/temp-sense-gen/src/tempsenseInst.v | 2 +- openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/openfasoc/generators/temp-sense-gen/src/tempsenseInst.v b/openfasoc/generators/temp-sense-gen/src/tempsenseInst.v index d17e54ed5..0ae66e307 100644 --- a/openfasoc/generators/temp-sense-gen/src/tempsenseInst.v +++ b/openfasoc/generators/temp-sense-gen/src/tempsenseInst.v @@ -1,4 +1,4 @@ -module tempsenseInst_error +module ${design_name} ( input CLK_REF, input RESET_COUNTERn, diff --git a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py index 6409e1e07..232ea7e89 100755 --- a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py +++ b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py @@ -119,6 +119,7 @@ generate_verilog( parameters={ + "design_name": designName, "cell_prefix": "sky130_fd_sc_hd__" if args.platform == "sky130hd" else "sky130_fd_sc_hs__", "cell_suffix": "_1", "header_cell": "HEADER" if args.platform == "sky130hd" else "HEADER_hs", From 3d74ba42b243b0604a7908847bd420a1baba40b7 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 20:09:43 +0530 Subject: [PATCH 14/32] feat: designName parameter code * uncommented code which inserts the designName in config.mk * removed code which inserts the designName parameter in Verilog --- .../temp-sense-gen/tools/temp-sense-gen.py | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py index 232ea7e89..eef013c88 100755 --- a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py +++ b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py @@ -5,6 +5,7 @@ import shutil import subprocess as sp import sys +import re from readparamgen import args, check_search_done, designName from simulation import generate_runs @@ -146,19 +147,13 @@ # for lv_cell in lv_list: # wf.write("temp_analog_0." + lv_cell + "\n") -# with open(srcDir + "tempsenseInst.v", "r") as rf: -# filedata = rf.read() -# filedata = re.sub("module\s*(\w+)\s*\n", "module " + designName + "\n", filedata) -# with open(srcDir + "tempsenseInst.v", "w") as wf: -# wf.write(filedata) - -# with open(flowDir + "design/sky130hd/tempsense/config.mk", "r") as rf: -# filedata = rf.read() -# filedata = re.sub( -# "export DESIGN_NAME\s*=\s*(\w+)", "export DESIGN_NAME = " + designName, filedata -# ) -# with open(flowDir + "design/sky130hd/tempsense/config.mk", "w") as wf: -# wf.write(filedata) +with open(flowDir + "design/sky130hd/tempsense/config.mk", "r") as rf: + filedata = rf.read() + filedata = re.sub( + "export DESIGN_NAME\s*=\s*(\w+)", "export DESIGN_NAME = " + designName, filedata + ) +with open(flowDir + "design/sky130hd/tempsense/config.mk", "w") as wf: + wf.write(filedata) # shutil.copyfile( # srcDir + "TEMP_ANALOG_lv.nl.v", flowDir + "design/src/tempsense/TEMP_ANALOG_lv.nl.v" From 835b9b63eb7022b20ca652d07659915f08a85a1c Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 20:25:14 +0530 Subject: [PATCH 15/32] feat: removed previous code * removed previous code used to generate output Verilog * removed previous code used to copy generated Verilog --- .../temp-sense-gen/tools/temp-sense-gen.py | 34 +------------------ 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py index eef013c88..0ee83f1e1 100755 --- a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py +++ b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py @@ -10,8 +10,8 @@ from readparamgen import args, check_search_done, designName from simulation import generate_runs +# TODO: Find a better way to import modules from parent directory sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) - from common.verilog_generation import generate_verilog genDir = os.path.join(os.path.dirname(os.path.relpath(__file__)), "../") @@ -100,24 +100,6 @@ print("# Verilog Generation") print("#----------------------------------------------------------------------") - -# TODO: Previous code. Remove later. -# if args.platform == "sky130hd": -# aux1 = "sky130_fd_sc_hd__nand2_1" -# aux2 = "sky130_fd_sc_hd__inv_1" -# aux3 = "sky130_fd_sc_hd__buf_1" -# aux4 = "sky130_fd_sc_hd__buf_1" -# aux5 = "HEADER" -# aux6 = "SLC" -# elif args.platform == "sky130hs": -# aux1 = "sky130_fd_sc_hs__nand2_1" -# aux2 = "sky130_fd_sc_hs__inv_1" -# aux3 = "sky130_fd_sc_hs__buf_1" -# aux4 = "sky130_fd_sc_hs__buf_1" -# aux5 = "HEADER_hs" -# aux6 = "SLC_hs" -# TEMP_netlist.gen_temp_netlist(ninv, nhead, aux1, aux2, aux3, aux4, aux5, srcDir) - generate_verilog( parameters={ "design_name": designName, @@ -155,20 +137,6 @@ with open(flowDir + "design/sky130hd/tempsense/config.mk", "w") as wf: wf.write(filedata) -# shutil.copyfile( -# srcDir + "TEMP_ANALOG_lv.nl.v", flowDir + "design/src/tempsense/TEMP_ANALOG_lv.nl.v" -# ) -# shutil.copyfile( -# srcDir + "TEMP_ANALOG_hv.nl.v", flowDir + "design/src/tempsense/TEMP_ANALOG_hv.nl.v" -# ) -# shutil.copyfile( -# srcDir + "TEMP_AUTO_def.v", flowDir + "design/src/tempsense/TEMP_AUTO_def.v" -# ) -# shutil.copyfile( -# srcDir + "tempsenseInst.v", flowDir + "design/src/tempsense/" + designName + ".v" -# ) -# shutil.copyfile(srcDir + "counter.v", flowDir + "design/src/tempsense/counter" + ".v") - print("#----------------------------------------------------------------------") print("# Verilog Generated") print("#----------------------------------------------------------------------") From 441f0048749273f1a5c41dae33b21a7b69b427a4 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 23:06:00 +0530 Subject: [PATCH 16/32] feat: removed `.template` replacement * removed code which replaces `.template` in source Verilog filenames because it seemed unncessary --- openfasoc/generators/common/verilog_generation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfasoc/generators/common/verilog_generation.py b/openfasoc/generators/common/verilog_generation.py index a948f546e..d7e7dbfb9 100644 --- a/openfasoc/generators/common/verilog_generation.py +++ b/openfasoc/generators/common/verilog_generation.py @@ -2,7 +2,7 @@ from os import path, makedirs, listdir def __get_output_filepath(filename: str, out_dir: str) -> str: - return path.join(out_dir, filename.replace(".template", "")) + return path.join(out_dir, filename) def __generate_file(input_path: str, output_path: str, parameters: dict) -> None: template = Template(filename=input_path) From a55f30f92e7f19fe8469fb6b83a352cb04aeef1b Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 23:17:23 +0530 Subject: [PATCH 17/32] refactor: rename counter_generic.v to counter.v because it's output filename is the same as the input filename --- .../temp-sense-gen/src/{counter_generic.v => counter.v} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename openfasoc/generators/temp-sense-gen/src/{counter_generic.v => counter.v} (100%) diff --git a/openfasoc/generators/temp-sense-gen/src/counter_generic.v b/openfasoc/generators/temp-sense-gen/src/counter.v similarity index 100% rename from openfasoc/generators/temp-sense-gen/src/counter_generic.v rename to openfasoc/generators/temp-sense-gen/src/counter.v From eef004fa13fbb9418568cfcbb500f68b3517a8fa Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 29 May 2023 23:19:01 +0530 Subject: [PATCH 18/32] feat: clean the generated verilog files in make clean --- openfasoc/generators/temp-sense-gen/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/openfasoc/generators/temp-sense-gen/Makefile b/openfasoc/generators/temp-sense-gen/Makefile index 4b220b542..1c2cf3806 100644 --- a/openfasoc/generators/temp-sense-gen/Makefile +++ b/openfasoc/generators/temp-sense-gen/Makefile @@ -69,6 +69,7 @@ clean: rm -f error_within_x.csv golden_error_opt.csv search_result.csv rm -rf work rm -rf tools/*.pyc tools/__pycache__/ + rm -rf flow/design/src/tempsense cd flow && make clean_all cd simulations && rm -rf run From 70c120ef24b5efcef72505223a707364cc47d46e Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Tue, 30 May 2023 18:28:52 +0530 Subject: [PATCH 19/32] docs: added docstrings to common API * added docstring to the __init__.py file * added docstrings to the functions defined in verilog_generation module --- openfasoc/generators/common/__init__.py | 9 ++++ .../generators/common/verilog_generation.py | 48 +++++++++++++++---- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/openfasoc/generators/common/__init__.py b/openfasoc/generators/common/__init__.py index e69de29bb..145fdcdbc 100644 --- a/openfasoc/generators/common/__init__.py +++ b/openfasoc/generators/common/__init__.py @@ -0,0 +1,9 @@ +"""A common module used in OpenFASOC generators. + +This module exports functions used in OpenFASOC generators. The following submodules and functions are exported. + +- `common.verilog_generation` + 1. `generate_verilog(parameters: dict, src_dir: str, out_dir: str) -> None`: Used to generate synthesizable Verilog files (for OpenROAD flow) from source Mako-based Verilog templates. + +See individual function documentation for more information on a particular function. +""" \ No newline at end of file diff --git a/openfasoc/generators/common/verilog_generation.py b/openfasoc/generators/common/verilog_generation.py index d7e7dbfb9..22ea609da 100644 --- a/openfasoc/generators/common/verilog_generation.py +++ b/openfasoc/generators/common/verilog_generation.py @@ -1,31 +1,51 @@ from mako.template import Template from os import path, makedirs, listdir -def __get_output_filepath(filename: str, out_dir: str) -> str: - return path.join(out_dir, filename) - def __generate_file(input_path: str, output_path: str, parameters: dict) -> None: + """Generates a single output Verilog file from its Mako template. + + Arguments: + - `input_path` (str): Path to the input file (Mako template) with the extension. + - `output_path` (str): Path to the output file location with the extension. + - `parameters` (dict): Dictionary of all the parameters used in the Mako template. + """ template = Template(filename=input_path) out_file = open(output_path, "w") out_file.write(template.render(**parameters)) def __generate_subdirectory(src_dir: str, out_dir: str, parameters: dict) -> None: + """Generates the output Verilog files of a single subdirectory of Mako templates. + + Reads Mako templates from a subdirectory (`src_dir`), generates the output files in the output directory (`out_dir`), and maintains the directory structure. i.e., templates from a subdirectory of the `src_dir` will be generated in a subdirectory in `out_dir` with the same name. + + This function recursively calls itself for subdirectories. + + Arguments: + - `src_dir` (str): Path to the source directory with Mako templates. + - `out_dir` (str): Path to the output directory. + - `parameters` (dict): Dictionary of all the parameters used in the Mako template. + """ # generate the output directory if it doesn't exist if not path.exists(out_dir): makedirs(out_dir) for filename in listdir(src_dir): - file_path = path.join(src_dir, filename) + input_filepath = path.join(src_dir, filename) + output_filepath = path.join(out_dir, filename) - if path.isdir(file_path): + if path.isdir(input_filepath): # if the path is a subdirectory, recursively call the function - __generate_subdirectory(file_path, path.join(out_dir, filename), parameters) + __generate_subdirectory( + input_filepath, + output_filepath, + parameters + ) else: # if the path is a fine, generate the output __generate_file( - file_path, - __get_output_filepath(filename, out_dir), + input_filepath, + output_filepath, parameters ) @@ -34,4 +54,16 @@ def generate_verilog( src_dir: str = "src", out_dir: str = path.join("flow", "design", "src") ) -> None: + """Generates output Verilog files from source Mako templates. + + Reads source Verilog files from `src_dir` and generates output Verilog files for synthesis in the OpenROAD flow. + The source files are Mako templates. See https://makotemplates.org for syntax and documentation. + + This function maintains the source directory (`src_dir`) structure in the output directory (`out_dir`). i.e., source files from a subdirectory of the `src_dir` will be generated in a subdirectory in `out_dir` with the same name. + + Arguments: + - `parameters` (dict): Dictionary of all the parameters used in the Mako templates. See https://makotemplates.org for documentation. + - `src_dir` (str): Path to the directory with the source Verilog templates. + - `out_dir` (str): Path to the directory in which the output will be generated. + """ __generate_subdirectory(src_dir, out_dir, parameters) \ No newline at end of file From 115747f3f4f943c52082da81c708885b0142bb6c Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Tue, 30 May 2023 23:46:11 +0530 Subject: [PATCH 20/32] feat: pre-imported common defs * added commonly used Verilog functions as defs in the Mako template * updated the source verilog code to use the new defs * added a TODO: comment to improve this way of importing defs in the future --- .../generators/common/verilog_generation.py | 18 +++++++++++++++++- .../temp-sense-gen/src/TEMP_ANALOG_hv.v | 2 -- .../temp-sense-gen/src/TEMP_ANALOG_lv.v | 2 -- .../generators/temp-sense-gen/src/counter.v | 2 -- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/openfasoc/generators/common/verilog_generation.py b/openfasoc/generators/common/verilog_generation.py index 22ea609da..2e0cfd250 100644 --- a/openfasoc/generators/common/verilog_generation.py +++ b/openfasoc/generators/common/verilog_generation.py @@ -1,6 +1,20 @@ from mako.template import Template from os import path, makedirs, listdir +# TODO: Find a better way to import common used defs in the future. +__COMMON_MAKO_DEFS = ''' +<%def name="cell(name)">${cell_prefix}${name}${cell_suffix} +''' + +def __mako_defs_preprocessor(input: str) -> str: + """A Mako preprocessor that appens commonly used defs to the template. + + Mako templates have a preprocessor argument. See https://docs.makotemplates.org/en/latest/usage.html#mako.template.Template.params.preprocessor. + This preprocessor adds defs commonly used in Verilog files to the template. + TODO: Find a better way to import common used defs in the future. + """ + return __COMMON_MAKO_DEFS + input + def __generate_file(input_path: str, output_path: str, parameters: dict) -> None: """Generates a single output Verilog file from its Mako template. @@ -9,7 +23,9 @@ def __generate_file(input_path: str, output_path: str, parameters: dict) -> None - `output_path` (str): Path to the output file location with the extension. - `parameters` (dict): Dictionary of all the parameters used in the Mako template. """ - template = Template(filename=input_path) + + # TODO: Find a better way to import common used defs in the future. + template = Template(filename=input_path, preprocessor=__mako_defs_preprocessor) out_file = open(output_path, "w") out_file.write(template.render(**parameters)) diff --git a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v index 70b26ce64..1bbe22cda 100644 --- a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v +++ b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v @@ -1,5 +1,3 @@ -<%def name="cell(name)">${cell_prefix}${name}${cell_suffix} - module TEMP_ANALOG_hv ( input CLK_REF, diff --git a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v index a478b6836..df89a9dc9 100644 --- a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v +++ b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v @@ -1,5 +1,3 @@ -<%def name="cell(name)">${cell_prefix}${name}${cell_suffix} - module TEMP_ANALOG_lv (EN, OUT, OUTB); input EN; // inout in_vin; diff --git a/openfasoc/generators/temp-sense-gen/src/counter.v b/openfasoc/generators/temp-sense-gen/src/counter.v index 9d5edc4d0..3a42d5bca 100644 --- a/openfasoc/generators/temp-sense-gen/src/counter.v +++ b/openfasoc/generators/temp-sense-gen/src/counter.v @@ -1,5 +1,3 @@ -<%def name="cell(name)">${cell_prefix}${name}${cell_suffix} - module counter# ( parameter NBIT = 24 From 67660e9e5798736f68dada90dd85e4353dabe37a Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Wed, 31 May 2023 15:49:23 +0530 Subject: [PATCH 21/32] feat: removed old commented Verilog code --- .../temp-sense-gen/src/TEMP_ANALOG_hv.v | 2 -- .../temp-sense-gen/src/TEMP_ANALOG_lv.v | 17 +---------------- .../generators/temp-sense-gen/src/counter.v | 6 +----- 3 files changed, 2 insertions(+), 23 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v index 1bbe22cda..7275003ba 100644 --- a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v +++ b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v @@ -26,13 +26,11 @@ counter async_counter_0( ); (* keep *) -// @@ @nf a_header_@nh(.VIN(VIN)); % for i in range(nhead): ${header_cell} a_header_${i}(.VIN(VIN)); % endfor // SLC ${slc_cell} a_lc_0(.IN(out), .INB(outb), .VOUT(lc_0)); -// @@ @no a_buffer_0 (.A(lc_0), .nbout(lc_out)); ${cell('buf')} a_buffer_0 (.A(lc_0), .X(lc_out)); endmodule diff --git a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v index df89a9dc9..1a3d55def 100644 --- a/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v +++ b/openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v @@ -4,39 +4,24 @@ module TEMP_ANALOG_lv (EN, OUT, OUTB); output OUT, OUTB; wire n; -// @@ wire n@nn; % for i in range(ninv + 1): wire n${i + 1}; % endfor + wire nx1, nx2, nx3, nb1, nb2; -// @@ @na a_nand_0 ( .A(EN), .B(n@n0), .Y(n1)); ${cell('nand2')} a_nand_0 ( .A(EN), .B(n${ninv + 1}), .Y(n1)); -// @@ @nb a_inv_@ni ( .A(n@n1), .Y(n@n2)); % for i in range(ninv): ${cell('inv')} a_inv_${i} ( .A(n${i + 1}), .Y(n${i + 2})); % endfor -// @@ @ng a_inv_m1 ( .A(n@n3), .Y(nx1)); ${cell('inv')} a_inv_m1 ( .A(n${ninv + 1}), .Y(nx1)); - -// @@ @nk a_inv_m2 ( .A(n@n4), .Y(nx2)); ${cell('inv')} a_inv_m2 ( .A(n${ninv + 1}), .Y(nx2)); - -// @@ @nm a_inv_m3 ( .A(nx2), .Y(nx3)); ${cell('inv')} a_inv_m3 ( .A(nx2), .Y(nx3)); - -// @@ @np a_buf_3 ( .A(nx3), .nbout(nb2)); ${cell('buf')} a_buf_3 ( .A(nx3), .X(nb2)); - -// @@ @nc a_buf_0 ( .A(nx1), .nbout(nb1)); ${cell('buf')} a_buf_0 ( .A(nx1), .X(nb1)); - -// @@ @nd a_buf_1 ( .A(nb1), .nbout(OUT)); ${cell('buf')} a_buf_1 ( .A(nb1), .X(OUT)); - -// @@ @ne a_buf_2 ( .A(nb2), .nbout(OUTB)); ${cell('buf')} a_buf_2 ( .A(nb2), .X(OUTB)); endmodule diff --git a/openfasoc/generators/temp-sense-gen/src/counter.v b/openfasoc/generators/temp-sense-gen/src/counter.v index 3a42d5bca..e119f06c9 100644 --- a/openfasoc/generators/temp-sense-gen/src/counter.v +++ b/openfasoc/generators/temp-sense-gen/src/counter.v @@ -29,11 +29,7 @@ module counter# // BUFH_X4M_A9TR Buf_DONE(.A(done_pre), .Y(DONE)); // BUF_X0P4N_A10P5PP84TR_C14 Buf_DONE(.A(done_pre), .Y(DONE)); -// TODO: Previous code. Remove later. -// @@ @np Buf_DONE(.A(done_pre), .nbout(DONE)); - -// .nbout replaced by X because X is hardcoded in TEMP_netlist.py -${cell('buf')} Buf_DONE(.A(done_pre), .X(DONE)); + ${cell('buf')} Buf_DONE(.A(done_pre), .X(DONE)); //assign RESET_CLK_REF = ~q1; always @ (*) begin From c8e85188eacfc4808b3a08dac83ef21748f44734 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Sat, 3 Jun 2023 15:38:38 +0530 Subject: [PATCH 22/32] fix: fixed generation of `blocks/sky130hd/*.txt` * uncommented code for generating `blocks/sky130hd/tempsenseInst_custom_net.txt` and `blocks/sky130hd/tempsenseInst_domain_insts.txt` files * updated the source file path to reflect the changes in Verilog generation --- .../temp-sense-gen/tools/temp-sense-gen.py | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py index 0ee83f1e1..fed2a3e9e 100755 --- a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py +++ b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py @@ -100,6 +100,8 @@ print("# Verilog Generation") print("#----------------------------------------------------------------------") +# The directory in which the output Verilog is generated +verilog_gen_dir=os.path.join('flow', 'design', 'src', 'tempsense') generate_verilog( parameters={ "design_name": designName, @@ -110,24 +112,25 @@ "ninv": ninv, "nhead": nhead }, - out_dir=os.path.join('flow', 'design', 'src', 'tempsense') + out_dir=verilog_gen_dir ) -# TODO: Previous code. Remove later. -# with open(srcDir + "TEMP_ANALOG_hv.nl.v", "r") as rf: -# filedata = rf.read() -# header_list = re.findall("HEADER\s+(\w+)\(", filedata) -# with open(genDir + "blocks/sky130hd/tempsenseInst_custom_net.txt", "w") as wf: -# wf.write("r_VIN\n") -# for header_cell in header_list: -# wf.write("temp_analog_1." + header_cell + " VIN\n") - -# with open(srcDir + "TEMP_ANALOG_lv.nl.v", "r") as rf: -# filedata = rf.read() -# lv_list = re.findall("\nsky130_fd_sc\w*\s+(\w+)\s+\(", filedata) -# with open(genDir + "blocks/sky130hd/tempsenseInst_domain_insts.txt", "w") as wf: -# for lv_cell in lv_list: -# wf.write("temp_analog_0." + lv_cell + "\n") +with open(os.path.join(verilog_gen_dir, "TEMP_ANALOG_hv.v"), "r") as rf: + filedata = rf.read() +header_list = re.findall("HEADER\s+(\w+)\(", filedata) + +with open(genDir + "blocks/sky130hd/tempsenseInst_custom_net.txt", "w") as wf: + wf.write("r_VIN\n") + for header_cell in header_list: + wf.write("temp_analog_1." + header_cell + " VIN\n") + +with open(os.path.join(verilog_gen_dir, "TEMP_ANALOG_lv.v"), "r") as rf: + filedata = rf.read() +lv_list = re.findall("\nsky130_fd_sc\w*\s+(\w+)\s+\(", filedata) + +with open(genDir + "blocks/sky130hd/tempsenseInst_domain_insts.txt", "w") as wf: + for lv_cell in lv_list: + wf.write("temp_analog_0." + lv_cell + "\n") with open(flowDir + "design/sky130hd/tempsense/config.mk", "r") as rf: filedata = rf.read() From 6d38d1065d85c01c451954bc9bbf310eb4a191d2 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 5 Jun 2023 16:46:04 +0530 Subject: [PATCH 23/32] refactor: convert all class privates to module privates * renamed all functions beginning with double _ to single _ to make them accessible using import --- openfasoc/generators/common/verilog_generation.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/openfasoc/generators/common/verilog_generation.py b/openfasoc/generators/common/verilog_generation.py index 2e0cfd250..bf5f9e676 100644 --- a/openfasoc/generators/common/verilog_generation.py +++ b/openfasoc/generators/common/verilog_generation.py @@ -6,7 +6,7 @@ <%def name="cell(name)">${cell_prefix}${name}${cell_suffix} ''' -def __mako_defs_preprocessor(input: str) -> str: +def _mako_defs_preprocessor(input: str) -> str: """A Mako preprocessor that appens commonly used defs to the template. Mako templates have a preprocessor argument. See https://docs.makotemplates.org/en/latest/usage.html#mako.template.Template.params.preprocessor. @@ -15,7 +15,7 @@ def __mako_defs_preprocessor(input: str) -> str: """ return __COMMON_MAKO_DEFS + input -def __generate_file(input_path: str, output_path: str, parameters: dict) -> None: +def _generate_file(input_path: str, output_path: str, parameters: dict) -> None: """Generates a single output Verilog file from its Mako template. Arguments: @@ -25,12 +25,12 @@ def __generate_file(input_path: str, output_path: str, parameters: dict) -> None """ # TODO: Find a better way to import common used defs in the future. - template = Template(filename=input_path, preprocessor=__mako_defs_preprocessor) + template = Template(filename=input_path, preprocessor=_mako_defs_preprocessor) out_file = open(output_path, "w") out_file.write(template.render(**parameters)) -def __generate_subdirectory(src_dir: str, out_dir: str, parameters: dict) -> None: +def _generate_subdirectory(src_dir: str, out_dir: str, parameters: dict) -> None: """Generates the output Verilog files of a single subdirectory of Mako templates. Reads Mako templates from a subdirectory (`src_dir`), generates the output files in the output directory (`out_dir`), and maintains the directory structure. i.e., templates from a subdirectory of the `src_dir` will be generated in a subdirectory in `out_dir` with the same name. @@ -52,14 +52,14 @@ def __generate_subdirectory(src_dir: str, out_dir: str, parameters: dict) -> Non if path.isdir(input_filepath): # if the path is a subdirectory, recursively call the function - __generate_subdirectory( + _generate_subdirectory( input_filepath, output_filepath, parameters ) else: # if the path is a fine, generate the output - __generate_file( + _generate_file( input_filepath, output_filepath, parameters @@ -82,4 +82,4 @@ def generate_verilog( - `src_dir` (str): Path to the directory with the source Verilog templates. - `out_dir` (str): Path to the directory in which the output will be generated. """ - __generate_subdirectory(src_dir, out_dir, parameters) \ No newline at end of file + _generate_subdirectory(src_dir, out_dir, parameters) \ No newline at end of file From 677bf9ffafd0ced897e21a1e46156a3a310c0a06 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 5 Jun 2023 21:30:53 +0530 Subject: [PATCH 24/32] test: added unit tests for the _generate_file function * Added unit tests using pytest in test/ directory * Used part of temp-sense-gen Verilog for unit tests * Added tests with 6 and 8 inverters --- .../expected-sky130hd-6inv/TEMP_ANALOG_lv.v | 36 ++++++++++++++ .../expected-sky130hd-8inv/TEMP_ANALOG_lv.v | 40 ++++++++++++++++ .../test-verilog/src/TEMP_ANALOG_lv.v | 27 +++++++++++ tests/common_api/test_verilog_generation.py | 47 +++++++++++++++++++ 4 files changed, 150 insertions(+) create mode 100644 tests/common_api/test-verilog/expected-sky130hd-6inv/TEMP_ANALOG_lv.v create mode 100644 tests/common_api/test-verilog/expected-sky130hd-8inv/TEMP_ANALOG_lv.v create mode 100644 tests/common_api/test-verilog/src/TEMP_ANALOG_lv.v create mode 100644 tests/common_api/test_verilog_generation.py diff --git a/tests/common_api/test-verilog/expected-sky130hd-6inv/TEMP_ANALOG_lv.v b/tests/common_api/test-verilog/expected-sky130hd-6inv/TEMP_ANALOG_lv.v new file mode 100644 index 000000000..e3f8ce9b7 --- /dev/null +++ b/tests/common_api/test-verilog/expected-sky130hd-6inv/TEMP_ANALOG_lv.v @@ -0,0 +1,36 @@ + + +module TEMP_ANALOG_lv (EN, OUT, OUTB); + input EN; +// inout in_vin; + output OUT, OUTB; + wire n; + +wire n1; +wire n2; +wire n3; +wire n4; +wire n5; +wire n6; +wire n7; + +wire nx1, nx2, nx3, nb1, nb2; + +sky130_fd_sc_hd__nand2_1 a_nand_0 ( .A(EN), .B(n7), .Y(n1)); + +sky130_fd_sc_hd__inv_1 a_inv_0 ( .A(n1), .Y(n2)); +sky130_fd_sc_hd__inv_1 a_inv_1 ( .A(n2), .Y(n3)); +sky130_fd_sc_hd__inv_1 a_inv_2 ( .A(n3), .Y(n4)); +sky130_fd_sc_hd__inv_1 a_inv_3 ( .A(n4), .Y(n5)); +sky130_fd_sc_hd__inv_1 a_inv_4 ( .A(n5), .Y(n6)); +sky130_fd_sc_hd__inv_1 a_inv_5 ( .A(n6), .Y(n7)); + +sky130_fd_sc_hd__inv_1 a_inv_m1 ( .A(n7), .Y(nx1)); +sky130_fd_sc_hd__inv_1 a_inv_m2 ( .A(n7), .Y(nx2)); +sky130_fd_sc_hd__inv_1 a_inv_m3 ( .A(nx2), .Y(nx3)); +sky130_fd_sc_hd__buf_1 a_buf_3 ( .A(nx3), .X(nb2)); +sky130_fd_sc_hd__buf_1 a_buf_0 ( .A(nx1), .X(nb1)); +sky130_fd_sc_hd__buf_1 a_buf_1 ( .A(nb1), .X(OUT)); +sky130_fd_sc_hd__buf_1 a_buf_2 ( .A(nb2), .X(OUTB)); + +endmodule diff --git a/tests/common_api/test-verilog/expected-sky130hd-8inv/TEMP_ANALOG_lv.v b/tests/common_api/test-verilog/expected-sky130hd-8inv/TEMP_ANALOG_lv.v new file mode 100644 index 000000000..6290932e3 --- /dev/null +++ b/tests/common_api/test-verilog/expected-sky130hd-8inv/TEMP_ANALOG_lv.v @@ -0,0 +1,40 @@ + + +module TEMP_ANALOG_lv (EN, OUT, OUTB); + input EN; +// inout in_vin; + output OUT, OUTB; + wire n; + +wire n1; +wire n2; +wire n3; +wire n4; +wire n5; +wire n6; +wire n7; +wire n8; +wire n9; + +wire nx1, nx2, nx3, nb1, nb2; + +sky130_fd_sc_hd__nand2_1 a_nand_0 ( .A(EN), .B(n9), .Y(n1)); + +sky130_fd_sc_hd__inv_1 a_inv_0 ( .A(n1), .Y(n2)); +sky130_fd_sc_hd__inv_1 a_inv_1 ( .A(n2), .Y(n3)); +sky130_fd_sc_hd__inv_1 a_inv_2 ( .A(n3), .Y(n4)); +sky130_fd_sc_hd__inv_1 a_inv_3 ( .A(n4), .Y(n5)); +sky130_fd_sc_hd__inv_1 a_inv_4 ( .A(n5), .Y(n6)); +sky130_fd_sc_hd__inv_1 a_inv_5 ( .A(n6), .Y(n7)); +sky130_fd_sc_hd__inv_1 a_inv_6 ( .A(n7), .Y(n8)); +sky130_fd_sc_hd__inv_1 a_inv_7 ( .A(n8), .Y(n9)); + +sky130_fd_sc_hd__inv_1 a_inv_m1 ( .A(n9), .Y(nx1)); +sky130_fd_sc_hd__inv_1 a_inv_m2 ( .A(n9), .Y(nx2)); +sky130_fd_sc_hd__inv_1 a_inv_m3 ( .A(nx2), .Y(nx3)); +sky130_fd_sc_hd__buf_1 a_buf_3 ( .A(nx3), .X(nb2)); +sky130_fd_sc_hd__buf_1 a_buf_0 ( .A(nx1), .X(nb1)); +sky130_fd_sc_hd__buf_1 a_buf_1 ( .A(nb1), .X(OUT)); +sky130_fd_sc_hd__buf_1 a_buf_2 ( .A(nb2), .X(OUTB)); + +endmodule diff --git a/tests/common_api/test-verilog/src/TEMP_ANALOG_lv.v b/tests/common_api/test-verilog/src/TEMP_ANALOG_lv.v new file mode 100644 index 000000000..1a3d55def --- /dev/null +++ b/tests/common_api/test-verilog/src/TEMP_ANALOG_lv.v @@ -0,0 +1,27 @@ +module TEMP_ANALOG_lv (EN, OUT, OUTB); + input EN; +// inout in_vin; + output OUT, OUTB; + wire n; + +% for i in range(ninv + 1): +wire n${i + 1}; +% endfor + +wire nx1, nx2, nx3, nb1, nb2; + +${cell('nand2')} a_nand_0 ( .A(EN), .B(n${ninv + 1}), .Y(n1)); + +% for i in range(ninv): +${cell('inv')} a_inv_${i} ( .A(n${i + 1}), .Y(n${i + 2})); +% endfor + +${cell('inv')} a_inv_m1 ( .A(n${ninv + 1}), .Y(nx1)); +${cell('inv')} a_inv_m2 ( .A(n${ninv + 1}), .Y(nx2)); +${cell('inv')} a_inv_m3 ( .A(nx2), .Y(nx3)); +${cell('buf')} a_buf_3 ( .A(nx3), .X(nb2)); +${cell('buf')} a_buf_0 ( .A(nx1), .X(nb1)); +${cell('buf')} a_buf_1 ( .A(nb1), .X(OUT)); +${cell('buf')} a_buf_2 ( .A(nb2), .X(OUTB)); + +endmodule diff --git a/tests/common_api/test_verilog_generation.py b/tests/common_api/test_verilog_generation.py new file mode 100644 index 000000000..48f051f16 --- /dev/null +++ b/tests/common_api/test_verilog_generation.py @@ -0,0 +1,47 @@ +import os +import sys +from shutil import rmtree + +# Add the common API to the path +# TODO: Find a better way to import the modules +sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'openfasoc', 'generators', 'common')) + +import verilog_generation + +TEST_VERILOG_DIR = os.path.join(os.path.dirname(__file__), 'test-verilog') +SRC_VERILOG_DIR = os.path.join(TEST_VERILOG_DIR, 'src') +TEST_FILENAME = 'TEMP_ANALOG_lv.v' + +def test_different_params(tmp_path): + PARAMETERS_1={ + "cell_prefix": "sky130_fd_sc_hd__", + "cell_suffix": "_1", + "ninv": 6 + } + + PARAMETERS_2={ + "cell_prefix": "sky130_fd_sc_hd__", + "cell_suffix": "_1", + "ninv": 8 + } + + input_path = os.path.join(SRC_VERILOG_DIR, TEST_FILENAME) + + output_path_1 = os.path.join(tmp_path, TEST_FILENAME + '.1') + output_path_2 = os.path.join(tmp_path, TEST_FILENAME + '.2') + + expected_file_1 = os.path.join(TEST_VERILOG_DIR, 'expected-sky130hd-6inv', TEST_FILENAME) + expected_file_2 = os.path.join(TEST_VERILOG_DIR, 'expected-sky130hd-8inv', TEST_FILENAME) + + verilog_generation._generate_file(input_path, output_path_1, PARAMETERS_1) + verilog_generation._generate_file(input_path, output_path_2, PARAMETERS_2) + + generated_verilog_1 = open(output_path_1).read() + generated_verilog_2 = open(output_path_2).read() + + + expected_verilog_1 = open(expected_file_1).read() + expected_verilog_2 = open(expected_file_2).read() + + assert generated_verilog_1 == expected_verilog_1, "Generated Verilog should be equal to the expected Verilog (6 inverters)." + assert generated_verilog_2 == expected_verilog_2, "Generated Verilog should be equal to the expected Verilog (8 inverters)." \ No newline at end of file From d97616b5a9989e087c7871b8f499b405ca538094 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Mon, 5 Jun 2023 21:38:00 +0530 Subject: [PATCH 25/32] test: added better error message in asserts --- tests/common_api/test_verilog_generation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/common_api/test_verilog_generation.py b/tests/common_api/test_verilog_generation.py index 48f051f16..3113e44ef 100644 --- a/tests/common_api/test_verilog_generation.py +++ b/tests/common_api/test_verilog_generation.py @@ -43,5 +43,5 @@ def test_different_params(tmp_path): expected_verilog_1 = open(expected_file_1).read() expected_verilog_2 = open(expected_file_2).read() - assert generated_verilog_1 == expected_verilog_1, "Generated Verilog should be equal to the expected Verilog (6 inverters)." - assert generated_verilog_2 == expected_verilog_2, "Generated Verilog should be equal to the expected Verilog (8 inverters)." \ No newline at end of file + assert generated_verilog_1 == expected_verilog_1, "Generated Verilog does not match the expected Verilog (6 inverters)." + assert generated_verilog_2 == expected_verilog_2, "Generated Verilog does not match the expected Verilog (8 inverters)." \ No newline at end of file From 2e5dda33e61790c633bc1ecc97fcbf6736910290 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Wed, 7 Jun 2023 23:24:34 +0530 Subject: [PATCH 26/32] test: added tests for files in subdirectory * tests if the directory structure of the source is maintained in the output * tests if output for files in subdirectories are generated as expected --- .../subdirectory/TEMP_ANALOG_hv.v | 38 +++++++++++++++++++ .../subdirectory/TEMP_ANALOG_hv.v | 38 +++++++++++++++++++ .../src/subdirectory/TEMP_ANALOG_hv.v | 36 ++++++++++++++++++ tests/common_api/test_verilog_generation.py | 38 ++++++++++++++++++- 4 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 tests/common_api/test-verilog/expected-sky130hd-6inv/subdirectory/TEMP_ANALOG_hv.v create mode 100644 tests/common_api/test-verilog/expected-sky130hd-8inv/subdirectory/TEMP_ANALOG_hv.v create mode 100644 tests/common_api/test-verilog/src/subdirectory/TEMP_ANALOG_hv.v diff --git a/tests/common_api/test-verilog/expected-sky130hd-6inv/subdirectory/TEMP_ANALOG_hv.v b/tests/common_api/test-verilog/expected-sky130hd-6inv/subdirectory/TEMP_ANALOG_hv.v new file mode 100644 index 000000000..a2eaf5c55 --- /dev/null +++ b/tests/common_api/test-verilog/expected-sky130hd-6inv/subdirectory/TEMP_ANALOG_hv.v @@ -0,0 +1,38 @@ + + +module TEMP_ANALOG_hv +( +input CLK_REF, +input RESET_COUNTERn, +input [3:0] SEL_CONV_TIME, +input out, outb, + +output [23:0] DOUT, +output DONE, +output lc_out, +inout VIN +); + +wire lc_0; +// reg iso; +// assign iso = 0 ; +counter async_counter_0( + // Input + .CLK_SENS (lc_out), + .CLK_REF (CLK_REF), + .RESET_COUNTERn (RESET_COUNTERn), + .SEL_CONV_TIME (SEL_CONV_TIME), + // Output + .DOUT (DOUT), + .DONE (DONE) +); + +(* keep *) +HEADER a_header_0(.VIN(VIN)); +HEADER a_header_1(.VIN(VIN)); +HEADER a_header_2(.VIN(VIN)); +// SLC +SLC a_lc_0(.IN(out), .INB(outb), .VOUT(lc_0)); +sky130_fd_sc_hd__buf_1 a_buffer_0 (.A(lc_0), .X(lc_out)); + +endmodule diff --git a/tests/common_api/test-verilog/expected-sky130hd-8inv/subdirectory/TEMP_ANALOG_hv.v b/tests/common_api/test-verilog/expected-sky130hd-8inv/subdirectory/TEMP_ANALOG_hv.v new file mode 100644 index 000000000..a2eaf5c55 --- /dev/null +++ b/tests/common_api/test-verilog/expected-sky130hd-8inv/subdirectory/TEMP_ANALOG_hv.v @@ -0,0 +1,38 @@ + + +module TEMP_ANALOG_hv +( +input CLK_REF, +input RESET_COUNTERn, +input [3:0] SEL_CONV_TIME, +input out, outb, + +output [23:0] DOUT, +output DONE, +output lc_out, +inout VIN +); + +wire lc_0; +// reg iso; +// assign iso = 0 ; +counter async_counter_0( + // Input + .CLK_SENS (lc_out), + .CLK_REF (CLK_REF), + .RESET_COUNTERn (RESET_COUNTERn), + .SEL_CONV_TIME (SEL_CONV_TIME), + // Output + .DOUT (DOUT), + .DONE (DONE) +); + +(* keep *) +HEADER a_header_0(.VIN(VIN)); +HEADER a_header_1(.VIN(VIN)); +HEADER a_header_2(.VIN(VIN)); +// SLC +SLC a_lc_0(.IN(out), .INB(outb), .VOUT(lc_0)); +sky130_fd_sc_hd__buf_1 a_buffer_0 (.A(lc_0), .X(lc_out)); + +endmodule diff --git a/tests/common_api/test-verilog/src/subdirectory/TEMP_ANALOG_hv.v b/tests/common_api/test-verilog/src/subdirectory/TEMP_ANALOG_hv.v new file mode 100644 index 000000000..7275003ba --- /dev/null +++ b/tests/common_api/test-verilog/src/subdirectory/TEMP_ANALOG_hv.v @@ -0,0 +1,36 @@ +module TEMP_ANALOG_hv +( +input CLK_REF, +input RESET_COUNTERn, +input [3:0] SEL_CONV_TIME, +input out, outb, + +output [23:0] DOUT, +output DONE, +output lc_out, +inout VIN +); + +wire lc_0; +// reg iso; +// assign iso = 0 ; +counter async_counter_0( + // Input + .CLK_SENS (lc_out), + .CLK_REF (CLK_REF), + .RESET_COUNTERn (RESET_COUNTERn), + .SEL_CONV_TIME (SEL_CONV_TIME), + // Output + .DOUT (DOUT), + .DONE (DONE) +); + +(* keep *) +% for i in range(nhead): +${header_cell} a_header_${i}(.VIN(VIN)); +% endfor +// SLC +${slc_cell} a_lc_0(.IN(out), .INB(outb), .VOUT(lc_0)); +${cell('buf')} a_buffer_0 (.A(lc_0), .X(lc_out)); + +endmodule diff --git a/tests/common_api/test_verilog_generation.py b/tests/common_api/test_verilog_generation.py index 3113e44ef..efcf29777 100644 --- a/tests/common_api/test_verilog_generation.py +++ b/tests/common_api/test_verilog_generation.py @@ -11,6 +11,7 @@ TEST_VERILOG_DIR = os.path.join(os.path.dirname(__file__), 'test-verilog') SRC_VERILOG_DIR = os.path.join(TEST_VERILOG_DIR, 'src') TEST_FILENAME = 'TEMP_ANALOG_lv.v' +TEST_SUBDIR_FILENAME = 'TEMP_ANALOG_hv.v' def test_different_params(tmp_path): PARAMETERS_1={ @@ -39,9 +40,42 @@ def test_different_params(tmp_path): generated_verilog_1 = open(output_path_1).read() generated_verilog_2 = open(output_path_2).read() - expected_verilog_1 = open(expected_file_1).read() expected_verilog_2 = open(expected_file_2).read() assert generated_verilog_1 == expected_verilog_1, "Generated Verilog does not match the expected Verilog (6 inverters)." - assert generated_verilog_2 == expected_verilog_2, "Generated Verilog does not match the expected Verilog (8 inverters)." \ No newline at end of file + assert generated_verilog_2 == expected_verilog_2, "Generated Verilog does not match the expected Verilog (8 inverters)." + +def test_directory_structure(tmp_path): + PARAMETERS={ + "cell_prefix": "sky130_fd_sc_hd__", + "cell_suffix": "_1", + "header_cell": "HEADER", + "slc_cell": "SLC", + "ninv": 6, + "nhead": 3 + } + + expected_file_1 = os.path.join(TEST_VERILOG_DIR, 'expected-sky130hd-6inv', TEST_FILENAME) + expected_file_2 = os.path.join(TEST_VERILOG_DIR, 'expected-sky130hd-6inv', 'subdirectory', TEST_SUBDIR_FILENAME) + + output_path_1 = os.path.join(tmp_path, TEST_FILENAME) + output_subdir = os.path.join(tmp_path, 'subdirectory') + output_path_2 = os.path.join(output_subdir, TEST_SUBDIR_FILENAME) + + verilog_generation.generate_verilog(PARAMETERS, SRC_VERILOG_DIR, tmp_path) + + # Check if all the expected files and directories exist + assert os.path.exists(output_path_1), "Generated Verilog file does not exist." + assert os.path.exists(output_subdir), "Subdirectory does not exist in generated Verilog." + assert os.path.exists(output_path_2), "Files from subdirectory do not exist in generated Verilog." + + # Check if all the expected files are correctly generated + generated_verilog_1 = open(output_path_1).read() + generated_verilog_2 = open(output_path_2).read() + + expected_verilog_1 = open(expected_file_1).read() + expected_verilog_2 = open(expected_file_2).read() + + assert generated_verilog_1 == expected_verilog_1, "Generated Verilog does not match the expected Verilog for first file." + assert generated_verilog_2 == expected_verilog_2, "Generated Verilog does not match the expected Verilog for the subdirectory file." From cc0f3b571d2083eeb7316e3d15fa25767d60cd77 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Wed, 7 Jun 2023 23:42:14 +0530 Subject: [PATCH 27/32] docs: update flow-tempsense.rst to reflect the changes * updated any filenames and links that have changed * mentioned the use of Mako syntax --- docs/source/flow-tempsense.rst | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/source/flow-tempsense.rst b/docs/source/flow-tempsense.rst index a493ca2ee..08f2448f3 100644 --- a/docs/source/flow-tempsense.rst +++ b/docs/source/flow-tempsense.rst @@ -45,20 +45,21 @@ Verilog generation Running ``make sky130hd_temp`` (temp for "temperature sensor") executes the `temp-sense-gen.py `_ script from temp-sense-gen/tools/. This file takes the input specifications from `test.json `_ and outputs Verilog files containing the description of the circuit. .. note:: - temp-sense-gen.py calls other modules from temp-sense-gen/tools/ during execution. For example, `readparamgen.py `_ is in charge of reading test.json, checking for correct user input and choosing the correct circuit elements. + temp-sense-gen.py calls other modules from temp-sense-gen/tools/ and generators/common/ during execution. For example, `readparamgen.py `_ is in charge of reading test.json, checking for correct user input and choosing the correct circuit elements. -The generator starts from a Verilog template of the temperature sensor circuit, located in `temp-sense-gen/src/ `_. The ``.v`` template files have lines marked with ``@@``, which are replaced according to the specifications. +The generator starts from a Verilog template of the temperature sensor circuit, located in `temp-sense-gen/src/ `_. The ``.v`` templates follow `Mako `_ syntax. For example, ``${param}`` is replaced with the value of the parameter ``param``. -Example: `counter_generic.v line 31 `_ is replaced during Verilog generation. +Example: In `counter.v line 31 `_, ``${cell('buf')}`` with the buffer cell which is ``sky130_fd_sc_hd__buf_1`` for sky130hd. .. code-block:: verilog - :emphasize-lines: 3 + :emphasize-lines: 4 :linenos: :lineno-start: 29 assign done_sens = WAKE_pre && doneb; - assign done_ref = WAKE && doneb; - @@ @np Buf_DONE(.A(done_pre), .nbout(DONE)); + assign done_ref = WAKE && doneb; + + ${cell('buf')} Buf_DONE(.A(done_pre), .X(DONE)); always @ (*) begin case (done_pre) @@ -87,15 +88,15 @@ OpenROAD Flow takes a design from the temp-sense-gen/flow/design/ directory and └── design ├── sky130hd │ └── tempsense - │ ├── config.mk <-- + │ ├── config.mk <-- │ └── constraint.sdc └── src └── tempsense - ├── counter.v <-- - ├── TEMP_ANALOG_hv.nl.v <-- - ├── TEMP_ANALOG_lv.nl.v <-- - ├── TEMP_AUTO_def.v <-- - └── tempsenseInst_error.v <-- + ├── counter.v <-- + ├── TEMP_ANALOG_hv.v <-- + ├── TEMP_ANALOG_lv.v <-- + ├── TEMP_AUTO_def.v <-- + └── tempsenseInst.v <-- For more information on OpenROAD Flow, check their `docs `_. From a0e4ee4f3f35c696ee16cb7411c02bfa36b773dc Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Fri, 9 Jun 2023 15:09:10 +0530 Subject: [PATCH 28/32] feat: export a map of common platform prefixes in verilog_generation module --- .../generators/common/verilog_generation.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/openfasoc/generators/common/verilog_generation.py b/openfasoc/generators/common/verilog_generation.py index bf5f9e676..ce5fdc3f7 100644 --- a/openfasoc/generators/common/verilog_generation.py +++ b/openfasoc/generators/common/verilog_generation.py @@ -82,4 +82,20 @@ def generate_verilog( - `src_dir` (str): Path to the directory with the source Verilog templates. - `out_dir` (str): Path to the directory in which the output will be generated. """ - _generate_subdirectory(src_dir, out_dir, parameters) \ No newline at end of file + _generate_subdirectory(src_dir, out_dir, parameters) + +# A dictionary of commonly used platforms and the prefix used in their cell naming +COMMON_PLATFORMS_PREFIX_MAP = { + "sky130hd": "sky130_fd_sc_hd__", + "sky130hs": "sky130_fd_sc_hs__", + "sky130hvl": "sky130_fd_sc_hvl__", + "sky130osu12Ths": "sky130_osu_sc_12T_hs__", + "sky130osu12Tms": "sky130_osu_sc_12T_ms__", + "sky130osu12Tls": "sky130_osu_sc_12T_ls__", + "sky130osu15Ths": "sky130_osu_sc_15T_hs__", + "sky130osu15Tms": "sky130_osu_sc_15T_ms__", + "sky130osu15Tls": "sky130_osu_sc_15T_ls__", + "sky130osu18Ths": "sky130_osu_sc_18T_hs__", + "sky130osu18Tms": "sky130_osu_sc_18T_ms__", + "sky130osu18Tls": "sky130_osu_sc_18T_ls__" +} \ No newline at end of file From 07eab484fea42a87e51f0ba2dd31bf6b981f722e Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Fri, 9 Jun 2023 15:34:50 +0530 Subject: [PATCH 29/32] feat: used the exported prefix map in temp sensor --- openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py index fed2a3e9e..ab31b61e0 100755 --- a/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py +++ b/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py @@ -12,7 +12,7 @@ # TODO: Find a better way to import modules from parent directory sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..')) -from common.verilog_generation import generate_verilog +from common.verilog_generation import generate_verilog, COMMON_PLATFORMS_PREFIX_MAP genDir = os.path.join(os.path.dirname(os.path.relpath(__file__)), "../") srcDir = genDir + "src/" @@ -105,7 +105,7 @@ generate_verilog( parameters={ "design_name": designName, - "cell_prefix": "sky130_fd_sc_hd__" if args.platform == "sky130hd" else "sky130_fd_sc_hs__", + "cell_prefix": COMMON_PLATFORMS_PREFIX_MAP[args.platform], "cell_suffix": "_1", "header_cell": "HEADER" if args.platform == "sky130hd" else "HEADER_hs", "slc_cell": "SLC" if args.platform == "sky130hd" else "SLC_hs", From 32f6336a166df12a1de710275b5f5f3f8e046122 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Fri, 9 Jun 2023 15:36:48 +0530 Subject: [PATCH 30/32] docs: added docstrings for the prefix map --- openfasoc/generators/common/__init__.py | 1 + openfasoc/generators/common/verilog_generation.py | 1 + 2 files changed, 2 insertions(+) diff --git a/openfasoc/generators/common/__init__.py b/openfasoc/generators/common/__init__.py index 145fdcdbc..ae57c6291 100644 --- a/openfasoc/generators/common/__init__.py +++ b/openfasoc/generators/common/__init__.py @@ -4,6 +4,7 @@ - `common.verilog_generation` 1. `generate_verilog(parameters: dict, src_dir: str, out_dir: str) -> None`: Used to generate synthesizable Verilog files (for OpenROAD flow) from source Mako-based Verilog templates. + 2. `COMMON_PLATFORMS_PREFIX_MAP` (dict): This is a dictionary of common platforms (currently sky130) and their cell naming prefixes. See individual function documentation for more information on a particular function. """ \ No newline at end of file diff --git a/openfasoc/generators/common/verilog_generation.py b/openfasoc/generators/common/verilog_generation.py index ce5fdc3f7..90689c8c3 100644 --- a/openfasoc/generators/common/verilog_generation.py +++ b/openfasoc/generators/common/verilog_generation.py @@ -85,6 +85,7 @@ def generate_verilog( _generate_subdirectory(src_dir, out_dir, parameters) # A dictionary of commonly used platforms and the prefix used in their cell naming +# Currently includes only sky130 platform prefixes COMMON_PLATFORMS_PREFIX_MAP = { "sky130hd": "sky130_fd_sc_hd__", "sky130hs": "sky130_fd_sc_hs__", From d8cd281fde375120dd25e0ed1a23e1acf5d58536 Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Wed, 21 Jun 2023 15:28:50 +0530 Subject: [PATCH 31/32] docs: added common python module docs to sphinx documentation --- docs/source/common-python-api.rst | 90 +++++++++++++++++++++++++++++++ docs/source/index.rst | 1 + 2 files changed, 91 insertions(+) create mode 100644 docs/source/common-python-api.rst diff --git a/docs/source/common-python-api.rst b/docs/source/common-python-api.rst new file mode 100644 index 000000000..3afab7188 --- /dev/null +++ b/docs/source/common-python-api.rst @@ -0,0 +1,90 @@ +Common Python API +================= + +.. contents:: Contents + :local: + +Introduction +------------ + +OpenFASoC generators have a Python script that runs the generator flow (See `Generators `_ for more information). Many of the steps in the Python script are common across generators. + +A common Python module is exported in ``openfasoc/generators/common/``to reduce code duplication and simplify the creation of new generators. This module exports various functions and constants which may be used in generators. + +Importing +--------- +Since the common Python module is in the ``openfasoc/generators/common/`` directory, which is a parent directory, the path to this directory must be added using ``sys.path.append()``. + +.. code-block:: python + + import sys + sys.path.append( + # This is the relative path to the `openfasoc/generators/common/` directory. + os.path.join(os.path.dirname(__file__), '..', '..') + ) + +Once the directory is added to the path, the exported modules can be imported using the standard Python import syntax. + +.. code-block:: python + + from common.verilog_generation import generate_verilog + +See `Exported Modules`_ for a list of exported modules and their respective functions and constants. + +Exported Modules +---------------- +The top level module ``common`` exports the following submodules. + +1. Verilog Generation (``common.verilog_generation``) +##################################################### +This module exports functions and constants used in the Verilog generation step. See `Temperature Sensor Generator `_ for more about Verilog generation. + +This module uses the `Mako `_ templating library to convert source Verilog templates into final Verilog files used in the OpenROAD flow. + +Functions +^^^^^^^^^ +1. ``generate_verilog(parameters: dict, src_dir: str, out_dir: str) -> None`` + + Reads source Verilog files from ``src_dir`` and generates output Verilog files for synthesis in the OpenROAD flow. The source files are `Mako `_ templates. + + The ``parameters`` argument is a dictionary of all the parameters used in the source Verilog Mako templates. Use the ``${parameter}}`` syntax in the source files to insert parameters. For example, the number of inverters in the `Temperature Sensor Generator `_ is a parameter. + + This function maintains the source directory (``src_dir``) structure in the output directory (``out_dir``). i.e., source files from a subdirectory of the ``src_dir`` will be generated in a subdirectory in ``out_dir`` with the same name. + + Arguments: + - ``src_dir`` (str): Path to the directory with the source Verilog templates. (default: ``src/``) + - ``out_dir`` (str): Path to the directory in which the output will be generated. (default: ``flow/design/src/``) + - ``parameters`` (dict): Dictionary of all the parameters used in the `Mako templates `_. + + Example: + .. code-block:: python + + generate_verilog( + # Generates the output in flow/design/src/ + out_dir=os.path.join('flow', 'design', 'src', 'tempsense'), + # Sets the parameters used in the design + parameters={ + "ninv": 6, + "nhead": 3, + "design_name": "tempsenseInst_error", + } + ) + + See the generators' Python files in ``tools/`` for more examples. + + This function also appends (can be directly used in the source Verilog files) the following Mako `defs `_: + - ``cell(name)`` + + This def returns the name of a standard cell for a given platform. Currently, it only supports the sky130 platform. The naming scheme for sky130 is ``${cell_prefix}${name}${cell_suffix}``. + + Here ``name`` is an argument passed to the ``cell()`` def, and ``cell_prefix`` and ``cell_suffix`` are set in the ``parameters`` argument passed to the ``generate_verilog()`` function. + + For example, an inverter cell can be inserted using the syntax ``${cell('inv')}``. If the prefix is ``sky130_fd_sc_hd__`` (sky130hd) and the suffix is ``_1``, the cell will be replaced with ``sky130_fd_sc_hd__inv_1``. The same statement will be replaced with ``sky130_fd_sc_hs__inv_1`` for the sky130hs platform. + + Use the constant ``COMMON_PLATFORMS_PREFIX_MAP`` for mapping a sky130 platform to its platform. + +Constants +^^^^^^^^^ +1. ``COMMON_PLATFORMS_PREFIX_MAP`` + + This is a dictionary of common platforms (currently sky130) and their cell naming prefixes. See the ``cell()`` def in the ``generate_verilog()`` function for more information on how to use it. \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst index 424cc05ba..c0dbe238e 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -32,6 +32,7 @@ If you are willing to contribute, please visit the :doc:`developers-guide` secti getting-started generators + common-python-api tapeouts examples developers-guide From cbf43811cadef22b4fdff104f5953e87d202388e Mon Sep 17 00:00:00 2001 From: Harsh Khandeparkar Date: Wed, 21 Jun 2023 15:31:15 +0530 Subject: [PATCH 32/32] docs: mention the Common Python API in tempsense docs --- docs/source/flow-tempsense.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/flow-tempsense.rst b/docs/source/flow-tempsense.rst index 08f2448f3..f72e216cf 100644 --- a/docs/source/flow-tempsense.rst +++ b/docs/source/flow-tempsense.rst @@ -49,6 +49,8 @@ Running ``make sky130hd_temp`` (temp for "temperature sensor") executes the `tem The generator starts from a Verilog template of the temperature sensor circuit, located in `temp-sense-gen/src/ `_. The ``.v`` templates follow `Mako `_ syntax. For example, ``${param}`` is replaced with the value of the parameter ``param``. +See `Common Python API `_ for more information. + Example: In `counter.v line 31 `_, ``${cell('buf')}`` with the buffer cell which is ``sky130_fd_sc_hd__buf_1`` for sky130hd. .. code-block:: verilog