blob: b09452fdeab47741b61fc0bae582728bf597a9bd [file] [log] [blame]
import pya
from random import random, seed
seed(a=0)
app = pya.Application.instance()
win = app.main_window()
# design_name = 'manual_macro_placement_test'
# from_cell_prefix = 'sky130_fd_sc_hd__decap'
# to_cell_prefix = 'sky130_fd_sc_hd__fill'
# library_gds = '/home/xrex/usr/devel/pdks/sky130A/libs.ref/sky130_fd_sc_hd/gds/sky130_fd_sc_hd.gds'
# user_gds = '/home/xrex/usr/devel/openlane_develop/designs/manual_macro_placement_test/runs/test/results/magic/manual_macro_placement_test.gds'
# output_gds = '/home/xrex/usr/devel/openlane_develop/designs/manual_macro_placement_test/runs/test/results/magic/out.gds'
# probability = 1.0
#######
library_gds = library_gds.split(',')
from_cell_prefix = from_cell_prefix.split(',')
to_cell_prefix = to_cell_prefix.split(',')
from_cells = []
to_cells = []
user_layout = pya.Layout()
for gds in library_gds:
print("Reading", gds)
user_layout.read(gds)
# find the cells we're interested in (flat cell list)
for cell in user_layout.each_cell():
cell_name = cell.name
for prefix in from_cell_prefix:
if cell_name.startswith(prefix):
if cell not in from_cells:
from_cells.append(cell)
for prefix in to_cell_prefix:
if cell_name.startswith(prefix):
if cell not in to_cells:
to_cells.append(cell)
print("From:", [c.name for c in from_cells])
print("To:", [c.name for c in to_cells])
subst_dict = {}
for cell_from in from_cells:
cell_from_width = cell_from.bbox().width()
for cell_to in to_cells:
cell_to_width = cell_to.bbox().width()
if cell_to_width == cell_from_width:
subst_dict[cell_from.name] = cell_to
break
subst_dict.setdefault(cell_from.name, None)
print('-'*10)
for k, v in subst_dict.items():
if v:
print("Found a substitution", k, "->", v.name)
print('-'*10)
##############################
matching_insts = []
def add_if_matching_cell(inst):
cell_name = inst.cell.name
# print("DBUG: Checking", cell_name)
for prefix in from_cell_prefix:
if cell_name.startswith(prefix):
matching_insts.append(inst)
def print_cell_name(inst):
pass
def substitute_matching_cell(inst):
cell_name = inst.cell.name
# assert cell_name in subst_dict
for prefix in from_cell_prefix:
if cell_name.startswith(prefix) and prefix in subst_dict and subst_dict[prefix] is not None:
# print("DBUG: Replacing", cell_name, end=' ')
# print("with", subst_dict[prefix].name)
inst.cell = subst_dict[prefix]
def exec_for_each_inst(cell, func):
# print("DBUG_CELL:", cell.name)
for inst in cell.each_inst():
# print(" DBUG_INST:", inst.cell.name)
assert inst is not None
# for cells that have no hierarchy beneath (standard cells in this case)
if inst.cell.hierarchy_levels() == 0:
func(inst)
# for macros
for child_idx in cell.each_child_cell():
cell = user_layout.cell(child_idx)
if cell.hierarchy_levels() > 0:
# print("DBUG_CHILD:", cell.name)
exec_for_each_inst(cell, func)
user_layout.read(user_gds)
top_cell = user_layout.cell(design_name)
print("Top-cell name:", top_cell.name)
exec_for_each_inst(top_cell, add_if_matching_cell)
subst_cnt = 0
tot = len(matching_insts)
for inst in matching_insts:
if random() <= float(probability):
subst_cnt += 1
substitute_matching_cell(inst)
print("Substituted", subst_cnt, "out of", tot, "substitutable cells")
# delete the rest of the top-level cells
####### revise this:
for cell in user_layout.top_cells():
if cell.name != design_name:
cell.delete()
for cell in user_layout.top_cells():
if cell.name != design_name:
cell.delete()
user_layout.write(output_gds)
print("Successfully wrote", output_gds)