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 and ioplacer update (#897)
* 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>
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -3,7 +3,10 @@
|
||||
tags
|
||||
.vim
|
||||
|
||||
# Flow Artefacts
|
||||
# emacs backup files
|
||||
*~
|
||||
|
||||
# Flow Artifacts
|
||||
dummy.guide
|
||||
lefRWarning.log
|
||||
run.param
|
||||
|
||||
@@ -27,14 +27,20 @@ if {[catch {read_def $::env(CURRENT_DEF)} errmsg]} {
|
||||
exit 1
|
||||
}
|
||||
|
||||
set_pin_length -hor_length $::env(FP_IO_HLENGTH) \
|
||||
-ver_length $::env(FP_IO_VLENGTH)
|
||||
if {$::env(FP_IO_HLENGTH) != "" && $::env(FP_IO_HLENGTH) != ""} {
|
||||
set_pin_length -hor_length $::env(FP_IO_HLENGTH) \
|
||||
-ver_length $::env(FP_IO_VLENGTH)
|
||||
}
|
||||
|
||||
set_pin_length_extension -hor_extension $::env(FP_IO_HEXTEND) \
|
||||
-ver_extension $::env(FP_IO_VEXTEND)
|
||||
if {$::env(FP_IO_HLENGTH) != "" && $::env(FP_IO_HLENGTH) != ""} {
|
||||
set_pin_length_extension -hor_extension $::env(FP_IO_HEXTEND) \
|
||||
-ver_extension $::env(FP_IO_VEXTEND)
|
||||
}
|
||||
|
||||
set_pin_thick_multiplier -hor_multiplier $::env(FP_IO_HTHICKNESS_MULT) \
|
||||
-ver_multiplier $::env(FP_IO_VTHICKNESS_MULT)
|
||||
if {$::env(FP_IO_HLENGTH) != "" && $::env(FP_IO_HLENGTH) != ""} {
|
||||
set_pin_thick_multiplier -hor_multiplier $::env(FP_IO_HTHICKNESS_MULT) \
|
||||
-ver_multiplier $::env(FP_IO_VTHICKNESS_MULT)
|
||||
}
|
||||
|
||||
set arg_list [list]
|
||||
if { $::env(FP_IO_MODE) == 1 } {
|
||||
|
||||
105
scripts/pdk-linker.py
Executable file
105
scripts/pdk-linker.py
Executable file
@@ -0,0 +1,105 @@
|
||||
#!/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)
|
||||
Reference in New Issue
Block a user