Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GSoC] Common Verilog Generation API and Implementation in temp-sense-gen #212

Merged
merged 32 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
832f830
feat: added mako to Python requirements.txt
harshkhandeparkar May 27, 2023
45d2c60
feat: exported a verilog generation function
harshkhandeparkar May 28, 2023
7c58dbd
doc: added code hints to verilog generation functions
harshkhandeparkar May 28, 2023
60d11e9
feat: use the new verilog generation function in temp-sense-gen.
harshkhandeparkar May 29, 2023
5b4363e
feat: converted temp-sense-gen Verilog to Mako templates
harshkhandeparkar May 29, 2023
d305499
fix: fixed typos in TEMP_ANALOG_lv.v
harshkhandeparkar May 29, 2023
98fb956
fix: changed placeholder port nbout to X
harshkhandeparkar May 29, 2023
688859b
feat: updated gitignore files
harshkhandeparkar May 29, 2023
5e18789
fix: removed unused imports in temp-sense-gen.py
harshkhandeparkar May 29, 2023
ac85fb9
fix: removed extra tabs in Verilog source
harshkhandeparkar May 29, 2023
1a3bbd6
fix: removed a statement which incremented ninv
harshkhandeparkar May 29, 2023
ef5a28f
feat: commented unused code
harshkhandeparkar May 29, 2023
9524faf
feat: added designName as a parameter in the Verilog source
harshkhandeparkar May 29, 2023
3d74ba4
feat: designName parameter code
harshkhandeparkar May 29, 2023
835b9b6
feat: removed previous code
harshkhandeparkar May 29, 2023
441f004
feat: removed `.template` replacement
harshkhandeparkar May 29, 2023
a55f30f
refactor: rename counter_generic.v to counter.v
harshkhandeparkar May 29, 2023
eef004f
feat: clean the generated verilog files in make clean
harshkhandeparkar May 29, 2023
70c120e
docs: added docstrings to common API
harshkhandeparkar May 30, 2023
115747f
feat: pre-imported common defs
harshkhandeparkar May 30, 2023
67660e9
feat: removed old commented Verilog code
harshkhandeparkar May 31, 2023
c8e8518
fix: fixed generation of `blocks/sky130hd/*.txt`
harshkhandeparkar Jun 3, 2023
6d38d10
refactor: convert all class privates to module privates
harshkhandeparkar Jun 5, 2023
677bf9f
test: added unit tests for the _generate_file function
harshkhandeparkar Jun 5, 2023
d97616b
test: added better error message in asserts
harshkhandeparkar Jun 5, 2023
2e5dda3
test: added tests for files in subdirectory
harshkhandeparkar Jun 7, 2023
cc0f3b5
docs: update flow-tempsense.rst to reflect the changes
harshkhandeparkar Jun 7, 2023
a0e4ee4
feat: export a map of common platform prefixes in verilog_generation …
harshkhandeparkar Jun 9, 2023
07eab48
feat: used the exported prefix map in temp sensor
harshkhandeparkar Jun 9, 2023
32f6336
docs: added docstrings for the prefix map
harshkhandeparkar Jun 9, 2023
d8cd281
docs: added common python module docs to sphinx documentation
harshkhandeparkar Jun 21, 2023
cbf4381
docs: mention the Common Python API in tempsense docs
harshkhandeparkar Jun 21, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions openfasoc/generators/common/__init__.py
Original file line number Diff line number Diff line change
@@ -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.
"""
85 changes: 85 additions & 0 deletions openfasoc/generators/common/verilog_generation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
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>
'''

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.

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.
"""

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

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):
input_filepath = path.join(src_dir, filename)
output_filepath = path.join(out_dir, filename)

if path.isdir(input_filepath):
# if the path is a subdirectory, recursively call the function
__generate_subdirectory(
input_filepath,
output_filepath,
parameters
)
else:
# if the path is a fine, generate the output
__generate_file(
input_filepath,
output_filepath,
parameters
)

def generate_verilog(
parameters: dict,
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)
1 change: 1 addition & 0 deletions openfasoc/generators/temp-sense-gen/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tempsense/

This file was deleted.

4 changes: 0 additions & 4 deletions openfasoc/generators/temp-sense-gen/src/.gitignore

This file was deleted.

9 changes: 6 additions & 3 deletions openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_hv.v
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,11 @@ counter async_counter_0(
);

(* keep *)
@@ @nf a_header_@nh(.VIN(VIN));
SLC
@@ @no a_buffer_0 (.A(lc_0), .nbout(lc_out));
% 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
29 changes: 19 additions & 10 deletions openfasoc/generators/temp-sense-gen/src/TEMP_ANALOG_lv.v
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,25 @@ module TEMP_ANALOG_lv (EN, OUT, OUTB);
// inout in_vin;
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));
@@ @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));

${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
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ 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));

${cell('buf')} Buf_DONE(.A(done_pre), .X(DONE));
//assign RESET_CLK_REF = ~q1;

always @ (*) begin
Expand Down
2 changes: 1 addition & 1 deletion openfasoc/generators/temp-sense-gen/src/tempsenseInst.v
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module tempsenseInst_error
module ${design_name}
(
input CLK_REF,
input RESET_COUNTERn,
Expand Down
68 changes: 24 additions & 44 deletions openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,18 @@

import json
import os
import re
import shutil
import subprocess as sp
import sys
import time
import re

import TEMP_netlist
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__)), "../")
srcDir = genDir + "src/"
flowDir = genDir + "flow/"
Expand Down Expand Up @@ -98,46 +100,38 @@
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,
"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=verilog_gen_dir
)

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"

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:
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(srcDir + "TEMP_ANALOG_lv.nl.v", "r") as rf:
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(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(
Expand All @@ -146,20 +140,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("#----------------------------------------------------------------------")
Expand Down Expand Up @@ -262,7 +242,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
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ nbsphinx
cairosvg
scipy
ltspice
mako