Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
aaf7a9387This file is pinned to the selected release. Download the original to open it in your design tool.
# Copyright 2025 LibreLane Contributors
#
# Adapted from OpenLane
#
# Copyright 2020-2024 Efabless Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import re
import sys
from typing import Iterable, List, Optional, Tuple, Union
try:
from pyosys import libyosys as ys
except ImportError:
try:
# flake8: noqa F401
import libyosys
print(
"Current versions of LibreLane require Yosys 0.59.1 or higher.",
file=sys.stderr,
)
exit(-1)
except ImportError:
print(
"Failed to import pyosys -- make sure Yosys is compiled with ENABLE_PYTHON set to 1.",
file=sys.stderr,
)
exit(-1)
_yosys_version_extracted: Optional[Tuple[int, int]] = None
def yosys_version_at_least(*target: Tuple[int, ...]) -> Tuple[int, int]:
"""
check if version is >= the target components, i.e.
yosys_version_at_least(0, 68) checks if the verison >= 0.68
"""
global _yosys_version_extracted
yosys_version_rx = re.compile(r"^\s*Yosys (\d+)\.(\d+)")
if _yosys_version_extracted is None:
_yosys_version_extracted = (999, 999)
try:
match = yosys_version_rx.search(ys.Globals.yosys_version_str)
_yosys_version_extracted = (int(match.group(1)), int(match.group(2)))
except Exception:
ys.log_warning(
"Could not identify Yosys version. "
"Defaulting to the latest version's behavior on all code.\n"
)
return _yosys_version_extracted >= target
def _Design_run_pass(self, *command):
ys.Pass.call(self, command)
ys.Design.run_pass = _Design_run_pass # type: ignore
def _Design_tee(self, *command: Union[List[str], str], o: str):
self.run_pass("tee", "-o", o, *command)
ys.Design.tee = _Design_tee # type: ignore
def _Design_read_verilog_files(
self: ys.Design,
files: Iterable[str],
*,
top: str,
synth_parameters: Iterable[str],
includes: Iterable[str],
defines: Iterable[str],
use_slang: bool = False,
slang_arguments: Iterable[str],
):
files = list(files) # for easier concatenation
include_args = [f"-I{dir}" for dir in includes]
define_args = [f"-D{define}" for define in defines]
chparams = {}
slang_chparam_args = []
for chparam in synth_parameters:
param, value = chparam.split("=", maxsplit=1) # validate
chparams[param] = value
slang_chparam_args.append(f"-G{param}={value}")
if use_slang:
if not yosys_version_at_least(0, 67):
self.run_pass("plugin", "-i", "slang")
self.run_pass(
"read_slang",
"--top",
top,
*define_args,
*include_args,
*slang_chparam_args,
*slang_arguments,
*files,
)
else:
for file in files:
self.run_pass(
"read_verilog",
"-defer",
"-noautowire",
"-sv",
*include_args,
*define_args,
file,
)
for param, value in chparams.items():
self.run_pass("chparam", "-set", param, value, top)
ys.Design.read_verilog_files = _Design_read_verilog_files # type: ignore
def _Design_add_blackbox_models(
self,
models: Iterable[str],
*,
includes: Iterable[str],
defines: Iterable[str],
):
include_args = [f"-I{dir}" for dir in includes]
define_args = [f"-D{define}" for define in defines]
for model in models:
model_path, ext = os.path.splitext(model)
if ext == ".gz":
# Yosys transparently handles gzip compression
model_path, ext = os.path.splitext(model_path)
if ext in [".v", ".sv", ".vh"]:
self.run_pass(
"read_verilog",
"-sv",
"-setattr",
"keep_hierarchy",
"-lib",
*include_args,
*define_args,
model,
)
elif ext in [".lib"]:
self.run_pass(
"read_liberty",
"-lib",
"-ignore_miss_dir",
"-setattr",
"blackbox",
"-setattr",
"keep_hierarchy",
model,
)
else:
ys.log_error(
f"Black-box model '{model}' has an unrecognized file extension: '{ext}'.",
file=sys.stderr,
)
sys.stderr.flush()
exit(-1)
ys.Design.add_blackbox_models = _Design_add_blackbox_models # type: ignore