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:
Matt Liberty
2022-02-02 16:44:10 -08:00
committed by GitHub
parent aac68a0ca1
commit f01acb5c2e
3 changed files with 121 additions and 7 deletions

5
.gitignore vendored
View File

@@ -3,7 +3,10 @@
tags
.vim
# Flow Artefacts
# emacs backup files
*~
# Flow Artifacts
dummy.guide
lefRWarning.log
run.param

View File

@@ -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
View 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)