mirror of
https://github.com/The-OpenROAD-Project/OpenLane.git
synced 2026-05-29 00:23:55 +08:00
+ Added linting rules for flake8, formatting with black + Added a GitHub Action to enforce lint/format rules
138 lines
4.3 KiB
Python
138 lines
4.3 KiB
Python
#!/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 odb
|
|
|
|
|
|
def remove_buffers(block_design, dont_buffer):
|
|
design_nets = block_design.getNets()
|
|
dont_buffer_nets = [net for net in design_nets if net.getConstName() in dont_buffer]
|
|
|
|
for net in dont_buffer_nets:
|
|
# get the cells driving the dont buffer net
|
|
master_cells = get_master_cells(net)
|
|
|
|
assert (
|
|
len(master_cells) == 1
|
|
), f"Net {net.getConstName()} is driven by multiple cells."
|
|
|
|
cell_name = master_cells[0].getMaster().getConstName()
|
|
assert (
|
|
"buf" in cell_name
|
|
), f"{net.getConstName()} isn't driven by a buffer cell. It is driven by {cell_name}. "
|
|
|
|
# get the net connected to the input pin of this buffer
|
|
input_nets, output_nets = get_nets(master_cells[0])
|
|
|
|
assert (
|
|
len(output_nets) == 1
|
|
), f"{cell_name} has more than one output port. Please make sure that {cell_name} is a buffer cell."
|
|
assert (
|
|
len(input_nets) == 1
|
|
), f"{cell_name} has more than one input port. Please make sure that {cell_name} is a buffer cell."
|
|
assert (
|
|
output_nets[0].getConstName() in dont_buffer
|
|
), f"{cell_name} isn't driving any of the dont buffer nets."
|
|
|
|
# remove the buffer cell instance
|
|
master_cells[0].destroy(master_cells[0])
|
|
|
|
# connect buffer cell input net to the dont buffer port
|
|
for input_net in input_nets:
|
|
input_net_master_cell = get_master_cells(input_net)[0]
|
|
_, output_nets_2 = get_nets(input_net_master_cell)
|
|
output_net_it = output_nets_2[0].getITerms()[0]
|
|
output_net_it.connect(net)
|
|
|
|
|
|
def get_master_cells(net):
|
|
master_cells = []
|
|
for it in net.getITerms():
|
|
master_instance = it.getInst().getMaster()
|
|
master_cells.append(it.getInst())
|
|
cell_type = master_instance.getConstName()
|
|
cell_pin = it.getMTerm().getConstName()
|
|
print(f"Net {net.getConstName()} is connected to {cell_type}, pin {cell_pin}")
|
|
|
|
return master_cells
|
|
|
|
|
|
def get_nets(master_instance):
|
|
input_nets = []
|
|
output_nets = []
|
|
for iterm in master_instance.getITerms():
|
|
if iterm.isSpecial(): # Skip special nets
|
|
continue
|
|
|
|
if iterm.isInputSignal():
|
|
input_pin_net = iterm.getNet()
|
|
input_nets.append(input_pin_net)
|
|
|
|
if iterm.isOutputSignal():
|
|
output_pin_net = iterm.getNet()
|
|
output_nets.append(output_pin_net)
|
|
|
|
return input_nets, output_nets
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="DEF to Liberty.")
|
|
|
|
parser.add_argument(
|
|
"--input_lef",
|
|
"-l",
|
|
nargs="+",
|
|
type=str,
|
|
default=None,
|
|
required=True,
|
|
help="Input LEF file(s)",
|
|
)
|
|
parser.add_argument(
|
|
"--input_def", "-i", required=True, help="DEF view of the design."
|
|
)
|
|
parser.add_argument("--output_def", "-o", required=True, help="Output DEF file")
|
|
parser.add_argument(
|
|
"--dont_buffer", "-d", required=True, help="Dont Buffer list of output ports."
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
input_lef_files = args.input_lef
|
|
input_def_file = args.input_def
|
|
output_def = args.output_def
|
|
dont_buffer_list = args.dont_buffer
|
|
|
|
# parse input def/lef files
|
|
db_design = odb.dbDatabase.create()
|
|
|
|
for lef in input_lef_files:
|
|
odb.read_lef(db_design, lef)
|
|
|
|
odb.read_def(db_design, input_def_file)
|
|
|
|
chip_design = db_design.getChip()
|
|
block_design = chip_design.getBlock()
|
|
|
|
# remove buffers connected to the dont buffer nets
|
|
remove_buffers(block_design, dont_buffer_list)
|
|
|
|
# write output def
|
|
odb.write_def(block_design, output_def)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|