blob: 9efb07fb4d20971f453443efdadfc944e7f08f81 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2020 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 argparse
import os
import odb
parser = argparse.ArgumentParser(
description="Places macros in positions and orientations specified by a config file"
)
parser.add_argument(
"--lef",
"-l",
nargs="+",
type=str,
default=None,
required=True,
help="Input LEF file(s)",
)
parser.add_argument(
"--input-def",
"-id",
required=True,
help="DEF view of the design that needs to have its instances placed",
)
parser.add_argument("--output-def", "-o", required=True, help="Output placed DEF file")
parser.add_argument("--config", "-c", required=True, help="Configuration file")
parser.add_argument(
"--fixed",
"-f",
action="store_true",
default=False,
help="a flag to signal whether the placement should be fixed or placed",
)
args = parser.parse_args()
input_lef_file_names = args.lef
input_def_file_name = args.input_def
output_def_file_name = args.output_def
config_file_name = args.config
fixed_flag = args.fixed
LEF2OA_MAP = {
"N": "R0",
"S": "R180",
"W": "R90",
"E": "R270",
"FN": "MY",
"FS": "MX",
"FW": "MXR90",
"FE": "MYR90",
}
def lef_rot_to_oa_rot(rot):
if rot in LEF2OA_MAP:
return LEF2OA_MAP[rot]
else:
assert rot in [item[1] for item in LEF2OA_MAP.items()], rot
return rot
def gridify(n, f):
"""
e.g., (1.1243, 0.005) -> 1.120
"""
return round(n / f) * f
# read config
macros = {}
with open(config_file_name, "r") as config_file:
for line in config_file:
# Discard comments and empty lines
line = line.split("#")[0].strip()
if not line:
continue
line = line.split()
macros[line[0]] = [
str(int(float(line[1]) * 1000)),
str(int(float(line[2]) * 1000)),
line[3],
]
print("Placing the following macros:")
print(macros)
db_design = odb.dbDatabase.create()
for lef in input_lef_file_names:
odb.read_lef(db_design, lef)
odb.read_def(db_design, input_def_file_name)
chip_design = db_design.getChip()
block_design = chip_design.getBlock()
top_design_name = block_design.getName()
print("Design name:", top_design_name)
macros_cnt = len(macros)
for inst in block_design.getInsts():
inst_name = inst.getName()
if inst.isFixed():
assert inst_name not in macros, inst_name
continue
if inst_name in macros:
print("Placing", inst_name)
macro_data = macros[inst_name]
x = gridify(int(macro_data[0]), 5)
y = gridify(int(macro_data[1]), 5)
inst.setOrient(lef_rot_to_oa_rot(macro_data[2]))
inst.setLocation(x, y)
if fixed_flag:
inst.setPlacementStatus("FIRM")
else:
inst.setPlacementStatus("PLACED")
del macros[inst_name]
assert not macros, ("Macros not found:", macros)
print("Successfully placed", macros_cnt, "instances")
odb.write_def(block_design, output_def_file_name)
assert os.path.exists(output_def_file_name), "Output not written successfully"