PyHDI / veriloggen

Veriloggen: A Mixed-Paradigm Hardware Construction Framework
Apache License 2.0
306 stars 58 forks source link

Add OpenLane Support #53

Open mu2519 opened 1 year ago

mu2519 commented 1 year ago

Adding Support for OpenLane

Introduction

Veriloggen has the potential to synthesize hardware for both FPGAs and ASICs. However, its design is not optimal for ASICs because it was originally designed for FPGAs. Recently, an open-source EDA tool called OpenLane has emerged, and I implemented some functionalities to help use Veriloggen with OpenLane.

Problem

Instantiating SRAMs with OpenLane is quite complicated, as tutorial shows. Additionally, this way of instantiating SRAMs does not match the high-level synthesis functionality of Veriloggen.

Solution

My approach is to have Veriloggen generate both Verilog and configuration files. OpenLane requires config.json for various configurations and macro_placement.cfg for the placement of SRAM macros. I wrote code to generate these files. Furthermore, I added class ASICSRAM to use SRAMs from the high-level synthesis functionality of Veriloggen.

Implementation

Question and Answer

Does the use of type hints break backward compatibility?

No. By using from __future__ import annotations, type annotations are not evaluated at runtime. By using if TYPE_CHECKING:, modules used only for type annotations are not imported at runtime. Hence, type hints don't affect the behavior of programs.

Known Problems and Limitations

Module Names

If we instantiate the same module more than once, underscores are appended to the module name. This is problematic when instantiating SRAM macros. I tried to solve this issue, but I couldn't understand why on earch underscores are appended. For the present, I work around by adding the argument named workaround.

class Module(vtypes.VeriloggenNode):
    """ Verilog Module class """
    def Instance(self, module, instname, params=None, ports=None, workaround=False):
        if isinstance(module, str):
            module = StubModule(module)
        if not isinstance(module, (Module, StubModule, str)):
            raise TypeError('"module" of Instance must be Module,'
                            ' StubModule, or str, not %s' % type(module))
        self.check_existing_identifier(instname)
        t = Instance(module, instname, params, ports)
        self.instance[instname] = t
        self.items.append(t)

        if workaround:
            return t

        mod = self.find_module(module.name)
        if mod is None:
            self.submodule[module.name] = module

        while mod is not None:
            if mod == module:
                break
            module.name = module.name + '_'
            self.submodule[module.name] = module
            mod = self.find_module(module.name)

        return t

Testing Requires Network Access

Network access is required for testing because it involves cloning some repositories (sky130_sram_macros and globalfoundries-pdk-ip-gf180mcu_fd_ip_sram).

Significant Changes

rectpack: An Additional Dependency

The rectpack package (PyPI) is used to place SRAM macros. This package is added to dependencies:

install_requires=['pyverilog>=1.3.0',
                  'numpy>=1.17',
                  'rectpack>=0.2.2']

pytest-pythonpath Is No Longer Necessary

According to PyPI, pytest-pathpath is obsolete as of pytest 7.0.0. I reflect this change:

pythonpath = .
extras_require={
    'test': ['pytest>=7.0.0'],
    'graph': ['pygraphviz>=1.3.1'],
}

Appendices

I created some notebooks that can be executed in Colab (veriloggen-sram-openlane.ipynb and veriloggen-matmul-openlane.ipynb). If you are interested, please run these notebooks. Please note that it takes tens of minutes to run the notebooks, so please be patient.