diff --git a/docs/source/flow-ldo.rst b/docs/source/flow-ldo.rst index 000919738..fae0c673e 100644 --- a/docs/source/flow-ldo.rst +++ b/docs/source/flow-ldo.rst @@ -53,9 +53,9 @@ Running ``make sky130hvl_ldo`` (ldo for "digital ldo") executes the `ldo-gen.py .. note:: ldo-gen.py calls other modules from ldo-gen/tools/ during execution. For example, `configure_workspace.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 ldo circuit, located in `ldo-gen/src/ `_. The ``.v`` template file have a parameter ARRSZ , which updates according to the specifications. +The generator starts from a Verilog template of the ldo circuit, located in `ldo-gen/src/ `_. The ``.v`` template file have a parameter ``ARRSZ`` , which updates according to the specifications. -Example: `LDO_CONTROLLER_TEMPLATE.v line 5 `_ changes the value based on number of switches during Verilog generation. +Example: `LDO_CONTROLLER.v line 5 `_ changes the value based on number of switches during Verilog generation. .. note:: diff --git a/openfasoc/generators/ldo-gen/Makefile b/openfasoc/generators/ldo-gen/Makefile index ff9ba8a81..46c89eeaf 100644 --- a/openfasoc/generators/ldo-gen/Makefile +++ b/openfasoc/generators/ldo-gen/Makefile @@ -76,6 +76,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/ldo -cd flow && make nuke -rm -f blocks/sky130hvl/ldo_custom_net.txt blocks/sky130hvl/ldo_domain_insts.txt -rm -rf ../../common/drc-lvs-check/sky130A diff --git a/openfasoc/generators/ldo-gen/flow/design/src/.gitignore b/openfasoc/generators/ldo-gen/flow/design/src/.gitignore new file mode 100644 index 000000000..d9674a05e --- /dev/null +++ b/openfasoc/generators/ldo-gen/flow/design/src/.gitignore @@ -0,0 +1 @@ +ldo/ \ No newline at end of file diff --git a/openfasoc/generators/ldo-gen/flow/design/src/ldo/ldoInst.v b/openfasoc/generators/ldo-gen/flow/design/src/ldo/ldoInst.v deleted file mode 100644 index 1037c1dc2..000000000 --- a/openfasoc/generators/ldo-gen/flow/design/src/ldo/ldoInst.v +++ /dev/null @@ -1,72 +0,0 @@ -module ldoInst( - input clk, - input reset, - input trim1,trim2,trim3,trim4,trim5,trim6,trim7,trim8,trim9,trim10, - - input [1:0] mode_sel, // 2'b00 (Comparator & PT Array Test Mode) - // 2'b01 (Controller Test Mode) - // 2'b1X (LDO Run Mode) - - input std_ctrl_in, // Standalone Controller Test Input - input [8:0] std_pt_in_cnt, // Standalone PT Array Test Input - - output cmp_out, // Comparator Output - output [8:0] ctrl_out // Controller Output Count - - //input VREF // Reference Voltage -); - - parameter integer ARRSZ = 411; - - reg ctrl_in, mode; - reg [ARRSZ-1:0] pt_ctrl_word; - - wire VREF; - - LDO_COMPARATOR_LATCH cmp1 (.CLK(clk), - .VREF(VREF), - .OUT(cmp_out)); - - LDO_CONTROLLER #(.ARRSZ(ARRSZ)) - ctrl1 (.clk(clk), - .reset(reset), - .mode(mode), - .ctrl_in(ctrl_in), - .std_pt_in_cnt(std_pt_in_cnt), - .ctrl_word(pt_ctrl_word), - .ctrl_word_cnt(ctrl_out)); - - PT_UNIT_CELL pt_array_unit [ARRSZ-1:0] (.CTRL(pt_ctrl_word)); - - vref_gen_nmos_with_trim vref_gen (.trim1(trim1), - .trim2(trim2), - .trim3(trim3), - .trim4(trim4), - .trim5(trim5), - .trim6(trim6), - .trim7(trim7), - .trim8(trim8), - .trim9(trim9), - .trim10(trim10), - .vref(VREF) - ); - - PMOS pmos_1 (.cmp_out(cmp_out)); - PMOS pmos_2 (.cmp_out(cmp_out)); - - capacitor_test_nf cap_1 (.pin0(VREF)); - capacitor_test_nf cap_2 (.pin0(VREF)); - capacitor_test_nf cap_3 (.pin0(VREF)); - capacitor_test_nf cap_4 (.pin0(VREF)); - capacitor_test_nf cap_5 (.pin0(VREF)); - - always @(*) begin - mode = mode_sel[0] || mode_sel[1]; - - if (mode_sel[1]) - ctrl_in = cmp_out; - else - ctrl_in = std_ctrl_in; - end - -endmodule diff --git a/openfasoc/generators/ldo-gen/src/LDO_TEMPLATE.v b/openfasoc/generators/ldo-gen/src/LDO.v similarity index 97% rename from openfasoc/generators/ldo-gen/src/LDO_TEMPLATE.v rename to openfasoc/generators/ldo-gen/src/LDO.v index 11644d059..cfa4f6ff9 100644 --- a/openfasoc/generators/ldo-gen/src/LDO_TEMPLATE.v +++ b/openfasoc/generators/ldo-gen/src/LDO.v @@ -1,4 +1,4 @@ -module ldoInst( +module ${design_name}( input clk, input reset, input trim1,trim2,trim3,trim4,trim5,trim6,trim7,trim8,trim9,trim10, @@ -16,7 +16,7 @@ module ldoInst( //input VREF // Reference Voltage ); - parameter integer ARRSZ = 50; + parameter integer ARRSZ = ${arrSize}; reg ctrl_in, mode; reg [ARRSZ-1:0] pt_ctrl_word; diff --git a/openfasoc/generators/ldo-gen/flow/design/src/ldo/LDO_CONTROLLER.v b/openfasoc/generators/ldo-gen/src/LDO_CONTROLLER.v similarity index 85% rename from openfasoc/generators/ldo-gen/flow/design/src/ldo/LDO_CONTROLLER.v rename to openfasoc/generators/ldo-gen/src/LDO_CONTROLLER.v index aed5de3be..fad491196 100644 --- a/openfasoc/generators/ldo-gen/flow/design/src/ldo/LDO_CONTROLLER.v +++ b/openfasoc/generators/ldo-gen/src/LDO_CONTROLLER.v @@ -2,14 +2,14 @@ module LDO_CONTROLLER( clk, reset, mode, ctrl_in, std_pt_in_cnt, ctrl_word, ctrl_word_cnt); - parameter integer ARRSZ = 411; + parameter integer ARRSZ = ${arrSize}; input clk, reset, ctrl_in, mode; input [8:0] std_pt_in_cnt; output reg [8:0] ctrl_word_cnt; output reg [ARRSZ-1:0] ctrl_word; - wire [ARRSZ-1:0] ctrl_rst = 411'h7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + wire [ARRSZ-1:0] ctrl_rst = ${ctrlWdRst}; always @(posedge clk) begin if (reset) begin diff --git a/openfasoc/generators/ldo-gen/src/LDO_CONTROLLER_TEMPLATE.v b/openfasoc/generators/ldo-gen/src/LDO_CONTROLLER_TEMPLATE.v deleted file mode 100644 index 821812f49..000000000 --- a/openfasoc/generators/ldo-gen/src/LDO_CONTROLLER_TEMPLATE.v +++ /dev/null @@ -1,37 +0,0 @@ -module LDO_CONTROLLER( - clk, reset, mode, ctrl_in, - std_pt_in_cnt, ctrl_word, ctrl_word_cnt); - - parameter integer ARRSZ = 50; - - input clk, reset, ctrl_in, mode; - input [8:0] std_pt_in_cnt; - output reg [8:0] ctrl_word_cnt; - output reg [ARRSZ-1:0] ctrl_word; - - wire [ARRSZ-1:0] ctrl_rst = 50'h3ffffffffffff; - - always @(posedge clk) begin - if (reset) begin - ctrl_word <= ctrl_rst; - ctrl_word_cnt <= 9'h0; - end - else if (mode) begin - if (ctrl_in) begin - ctrl_word <= {1'b1, ctrl_word[ARRSZ-1:1]}; - if (~ctrl_word[0]) - ctrl_word_cnt <= ctrl_word_cnt - 1; - end - else begin - ctrl_word <= {ctrl_word[ARRSZ-2:0], 1'b0}; - if (ctrl_word[ARRSZ-1]) - ctrl_word_cnt <= ctrl_word_cnt + 1; - end - end - else begin - ctrl_word <= ctrl_rst << std_pt_in_cnt; - ctrl_word_cnt <= std_pt_in_cnt; - end - end - -endmodule diff --git a/openfasoc/generators/ldo-gen/tools/configure_workspace.py b/openfasoc/generators/ldo-gen/tools/configure_workspace.py index 107975239..462da5de4 100644 --- a/openfasoc/generators/ldo-gen/tools/configure_workspace.py +++ b/openfasoc/generators/ldo-gen/tools/configure_workspace.py @@ -1,10 +1,7 @@ # Utility functions to setup neccessary vars used in LDO-gen import subprocess as sp -import argparse import json -import math import os -import re import shutil import sys import time diff --git a/openfasoc/generators/ldo-gen/tools/generate_verilog.py b/openfasoc/generators/ldo-gen/tools/generate_verilog.py index 8867dff25..fa7489eb7 100644 --- a/openfasoc/generators/ldo-gen/tools/generate_verilog.py +++ b/openfasoc/generators/ldo-gen/tools/generate_verilog.py @@ -1,11 +1,7 @@ -import json import math -import re - INCLUDE_2_PMOS_ARRSIZE = int(40) - # model file contains polynomial coeficients # for a polynomial which represents max current "x" vs number of transistors in array "f(x)" def polynomial_output_at_point_from_coefficients(model_coefficients, polynomial_input): @@ -32,7 +28,7 @@ def update_ldo_domain_insts(blocksDir, arrSize): # write arrSize pt cells for i in range(arrSize): ldo_domain_insts.write("{pt_array_unit\[" + str(i) + "\]}\n") - + def update_ldo_place_insts(blocksDir, arrSize): """Writes arrSize pt unit cell instances to ldo_domain_insts.txt.""" with open(blocksDir + "/ldo_place.txt", "w") as ldo_place_insts: @@ -54,29 +50,8 @@ def update_custom_nets(blocksDir, arrSize): ldo_domain_insts.write("{pt_array_unit\[" + str(i) + "\]} VREG\n") -def generate_LDO_verilog(directories, outputDir, designName, arrSize): - """Writes specialized behavioral verilog to output dir and flow dir.""" - with open(directories["verilogDir"] + "/LDO_TEMPLATE.v", "r") as verilog_template: - filedata = verilog_template.read() - filedata = re.sub( - r"parameter integer ARRSZ = \d+;", - r"parameter integer ARRSZ = " + str(arrSize) + ";", - filedata, - ) - filedata = re.sub(r"module \S+", r"module " + designName + "(", filedata) - if arrSize > INCLUDE_2_PMOS_ARRSIZE: - filedata = filedata.replace("//COMMENTPMOS2 ", "", 1) - # write verilog src files to output dir and flow dir - with open(outputDir + "/" + designName + ".v", "w") as verilog_template: - verilog_template.write(filedata) - with open( - directories["flowDir"] + "/design/src/ldo/" + designName + ".v", "w" - ) as verilog_template: - verilog_template.write(filedata) - - -def generate_controller_verilog(directories, outputDir, arrSize): - """Writes specialized behavioral verilog to output dir and flow dir.""" +def get_ctrl_wd_rst(arrSize): + """Returns the value of the ctrlWdRst parameter used in the Verilog source.""" # Get ctrl word initialization in hex ctrlWordHexCntF = int(math.floor(arrSize / 4.0)) ctrlWordHexCntR = int(arrSize % 4.0) @@ -86,22 +61,7 @@ def generate_controller_verilog(directories, outputDir, arrSize): ctrlWordHex.append("f") ctrlWdRst = str(arrSize) + "'" + "".join(ctrlWordHex) - with open(directories["verilogDir"] + "/LDO_CONTROLLER_TEMPLATE.v", "r") as file: - filedata = file.read() - filedata = re.sub( - r"parameter integer ARRSZ = \d+;", - r"parameter integer ARRSZ = " + str(arrSize) + ";", - filedata, - ) - filedata = re.sub( - r"wire \[ARRSZ-1:0\] ctrl_rst = \S+", - r"wire " + "[ARRSZ-1:0] ctrl_rst = " + ctrlWdRst + ";", - filedata, - ) - with open(outputDir + "/LDO_CONTROLLER.v", "w") as file: - file.write(filedata) - with open(directories["flowDir"] + "/design/src/ldo/LDO_CONTROLLER.v", "w") as file: - file.write(filedata) + return ctrlWdRst def update_area_and_place_density(flowDir, arrSize): diff --git a/openfasoc/generators/ldo-gen/tools/ldo-gen.py b/openfasoc/generators/ldo-gen/tools/ldo-gen.py index 2c22e4204..d75aaa8fb 100644 --- a/openfasoc/generators/ldo-gen/tools/ldo-gen.py +++ b/openfasoc/generators/ldo-gen/tools/ldo-gen.py @@ -1,9 +1,6 @@ import argparse -import json import math import os -import re -import shutil import sys import subprocess as sp @@ -11,6 +8,10 @@ from generate_verilog import * from simulations import * +# 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 + print("#---------------------------------------------------------------------") print("# Parsing command line arguments...") print("#---------------------------------------------------------------------") @@ -112,8 +113,18 @@ update_area_and_place_density(directories["flowDir"], arrSize) # Generate the Behavioral Verilog -generate_LDO_verilog(directories, args.outputDir, user_specs["designName"], arrSize) -generate_controller_verilog(directories, args.outputDir, arrSize) +verilog_gen_dir = os.path.join('flow', 'design', 'src', 'ldo') +ctrlWdRst = get_ctrl_wd_rst(arrSize) + +generate_verilog( + parameters={ + "design_name": user_specs["designName"], + "arrSize": arrSize, + "ctrlWdRst": ctrlWdRst + }, + out_dir=verilog_gen_dir +) + if clean_work_dir: print("# LDO - Behavioural Verilog Generated") print("#----------------------------------------------------------------------") @@ -156,7 +167,7 @@ print("#----------------------------------------------------------------------") print("# LVS and DRC finished successfully") print("#----------------------------------------------------------------------") - + # function defined in configure_workspace.py copy_outputs(directories, args.outputDir, args.platform, user_specs["designName"]) @@ -220,7 +231,7 @@ else: print("simtool not supported") exit(1) - + if args.simtype == "prePEX": if jsonConfig["simTool"] == "ngspice": [sim, output_file_names] = ngspice_prepare_scripts( @@ -251,10 +262,10 @@ else: print("simtool not supported") exit(1) - + print("#----------------------------------------------------------------------") print("# Spice netlists created successfully") - print("#----------------------------------------------------------------------") + print("#----------------------------------------------------------------------") # ------------------------------------------------------------------------------ # run simulations @@ -275,13 +286,13 @@ for s in range (len(sim)): p = sp.Popen(sim[s],cwd=postPEX_sim_dir,shell=True) processes.append(p) - + for p in processes: p.wait() - + p = sp.Popen(["python3","processing.py","--file_path",postPEX_sim_dir,"--vref",str(vref),"--iload",str(iload),"--odir",odir, "--figs", "True", "--simType", "postPEX"],cwd=run_dir) p.wait() - + if args.simtype == "prePEX": run_dir = directories["genDir"] + "tools/" vref = user_specs["vin"] @@ -290,20 +301,20 @@ for s in range (len(sim)): p = sp.Popen(sim[s],cwd=prePEX_sim_dir,shell=True) processes.append(p) - + for p in processes: p.wait() - + p = sp.Popen(["python3","processing.py","--file_path",prePEX_sim_dir,"--vref",str(vref),"--iload",str(iload),"--odir",odir, "--figs", "True", "--simType", "prePEX"],cwd=run_dir) p.wait() """ for s in range (len(sim)): p = sp.Popen(sim[s],cwd=prePEX_sim_dir,shell=True) processes.append(p) - + for p in processes: p.wait() - + # perform post processing on simulation results and save figures to work dir raw_files = [(prePEX_sim_dir + ofile) for ofile in output_file_names] raw_to_csv(raw_files,user_specs["vin"],args.outputDir) diff --git a/openfasoc/generators/ldo-gen/tools/processing.py b/openfasoc/generators/ldo-gen/tools/processing.py index 435468c32..79980b2ca 100644 --- a/openfasoc/generators/ldo-gen/tools/processing.py +++ b/openfasoc/generators/ldo-gen/tools/processing.py @@ -36,7 +36,7 @@ ext = ('.raw',) for files in os.scandir(sim_dir): if files.path.endswith(ext) and "cap" in files.name: - output_file_names.append(files.name) + output_file_names.append(files.name) def fig_VREG_results(raw_files, vrefspec):