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 all 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
90 changes: 90 additions & 0 deletions docs/source/common-python-api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
Common Python API
=================

.. contents:: Contents
:local:

Introduction
------------

OpenFASoC generators have a Python script that runs the generator flow (See `Generators <generators.html>`_ 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 <flow-tempsense.html#verilog-generation>`_ for more about Verilog generation.

This module uses the `Mako <https://www.makotemplates.org/>`_ 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 <https://makotemplates.org>`_ 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 <flow-tempsense.html>`_ 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 <https://makotemplates.org>`_.

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 <https://docs.makotemplates.org/en/latest/defs.html>`_:
- ``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.
27 changes: 15 additions & 12 deletions docs/source/flow-tempsense.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,23 @@ Verilog generation
Running ``make sky130hd_temp`` (temp for "temperature sensor") executes the `temp-sense-gen.py <https://github.com/idea-fasoc/OpenFASOC/blob/main/openfasoc/generators/temp-sense-gen/tools/temp-sense-gen.py>`_ script from temp-sense-gen/tools/. This file takes the input specifications from `test.json <https://github.com/idea-fasoc/OpenFASOC/blob/main/openfasoc/generators/temp-sense-gen/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 <https://github.com/idea-fasoc/OpenFASOC/blob/main/openfasoc/generators/temp-sense-gen/tools/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 <https://github.com/idea-fasoc/OpenFASOC/blob/main/openfasoc/generators/temp-sense-gen/tools/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/ <https://github.com/idea-fasoc/OpenFASOC/tree/main/openfasoc/generators/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/ <https://github.com/idea-fasoc/OpenFASOC/tree/main/openfasoc/generators/temp-sense-gen/src>`_. The ``.v`` templates follow `Mako <https://makotemplates.org>`_ syntax. For example, ``${param}`` is replaced with the value of the parameter ``param``.

Example: `counter_generic.v line 31 <https://github.com/idea-fasoc/OpenFASOC/blob/main/openfasoc/generators/temp-sense-gen/src/counter_generic.v#L31>`_ is replaced during Verilog generation.
See `Common Python API <common-python-api.html#verilog-generation-common-verilog-generation>`_ for more information.

Example: In `counter.v line 31 <https://github.com/idea-fasoc/OpenFASOC/blob/main/openfasoc/generators/temp-sense-gen/src/counter.v#L32>`_, ``${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)
Expand Down Expand Up @@ -87,15 +90,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 <https://openroad.readthedocs.io/en/latest/user/GettingStarted.html>`_.

Expand Down
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions openfasoc/generators/common/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""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.
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.
"""
102 changes: 102 additions & 0 deletions openfasoc/generators/common/verilog_generation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
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)

# 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__",
"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__"
}
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
Loading