mirror of
https://github.com/The-OpenROAD-Project/OpenLane.git
synced 2026-05-29 00:23:55 +08:00
* Add scripts/pdk-linker.py for ORFS/OL integration Signed-off-by: Matt Liberty <mliberty@eng.ucsd.edu> * Add *~ to .gitignore Signed-off-by: Matt Liberty <mliberty@eng.ucsd.edu> * Update ioplacer.tcl to use proper tcl commands Also allow skipping the calls Signed-off-by: Matt Liberty <mliberty@eng.ucsd.edu> * black format pdk-linker.py Signed-off-by: Matt Liberty <mliberty@eng.ucsd.edu>
106 lines
4.3 KiB
Python
Executable File
106 lines
4.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
###############################################################################
|
|
## BSD 3-Clause License
|
|
##
|
|
## Copyright (c) 2022, The Regents of the University of California
|
|
## All rights reserved.
|
|
##
|
|
## Redistribution and use in source and binary forms, with or without
|
|
## modification, are permitted provided that the following conditions are met:
|
|
##
|
|
## * Redistributions of source code must retain the above copyright notice, this
|
|
## list of conditions and the following disclaimer.
|
|
##
|
|
## * Redistributions in binary form must reproduce the above copyright notice,
|
|
## this list of conditions and the following disclaimer in the documentation
|
|
## and/or other materials provided with the distribution.
|
|
##
|
|
## * Neither the name of the copyright holder nor the names of its
|
|
## contributors may be used to endorse or promote products derived from
|
|
## this software without specific prior written permission.
|
|
##
|
|
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
## AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
## IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
## ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
## LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
## SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
## INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
## ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
## POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
# The purpose of this script is to build a symbolic link farm from a
|
|
# source PDK according to a JSON mapping file. This is to adapt a PDK
|
|
# from a vendor into the form expected by OpenLane without actually
|
|
# modifying the source PDK. This is in opposition to the open_pdks
|
|
# approach which modifies the vendor PDK to fit.
|
|
|
|
# This is a transitional tool. Eventually OpenLane scripts will use
|
|
# the mapping file to directly access the files without needing the
|
|
# link farm. This will free OL from any dependency on PDK organization.
|
|
|
|
import argparse
|
|
import glob
|
|
import json
|
|
import os
|
|
|
|
parser = argparse.ArgumentParser(
|
|
description="""Builds a link farm from <source> in <dest> according to <mappings>"""
|
|
)
|
|
parser.add_argument("-s", "--source", required=True)
|
|
parser.add_argument("-d", "--destination", required=True)
|
|
parser.add_argument("-m", "--mappings", required=True)
|
|
parser.add_argument("-v", "--verbose", action="store_true")
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
def link_files(source_path, destination_path):
|
|
"""Create a link from source_path to destination path unless
|
|
one already exists. If it exists but is different then the
|
|
arguments imply an exception is raised."""
|
|
|
|
destination_dir = os.path.dirname(destination_path)
|
|
if not os.path.isdir(destination_dir):
|
|
os.makedirs(destination_dir)
|
|
if os.path.exists(destination_path):
|
|
if (
|
|
os.path.islink(destination_path)
|
|
and os.path.realpath(destination_path) == source_path
|
|
):
|
|
if args.verbose:
|
|
print(f" Skip {source_path} -> {destination_path}")
|
|
return
|
|
else:
|
|
raise Exception(f"File {destination_path} already exists")
|
|
os.symlink(source_path, destination_path)
|
|
if args.verbose:
|
|
print(f" Link {source_path} -> {destination_path}")
|
|
|
|
|
|
with open(args.mappings) as f:
|
|
mappings = json.load(f)
|
|
|
|
if not os.path.isdir(args.source):
|
|
raise Exception(f"{args.source} is not a directory")
|
|
|
|
source = os.path.abspath(f"{args.source}")
|
|
destination = os.path.abspath(f"{args.destination}")
|
|
|
|
for category, mapping in mappings.items():
|
|
print(f"Linking {category}")
|
|
pdk = mapping["pdk"]
|
|
openlane = mapping["openlane"]
|
|
for pattern in mapping["files"]:
|
|
pattern = f"{source}/{pdk}/{pattern}"
|
|
paths = glob.glob(pattern)
|
|
if len(paths) == 0:
|
|
raise Exception(f"No matches for {pattern}")
|
|
for source_path in paths:
|
|
file_name = os.path.basename(source_path)
|
|
destination_path = f"{destination}/{openlane}/{file_name}"
|
|
link_files(source_path, destination_path)
|