From 8c72b8a6c36228640f6751a210c1461d9059abdc Mon Sep 17 00:00:00 2001 From: Uri Shaked Date: Wed, 6 Nov 2024 21:02:56 +0200 Subject: [PATCH] fix: workaround for the sky130 poly density issue Replace 50% of the decap_12 cells with newfill_12 cells across all Wokwi designs. --- .github/workflows/gds.yaml | 8 ++ sky130_density_fix/README.txt | 1 + sky130_density_fix/replace_decap.py | 87 ++++++++++++++++++ .../sky130_ef_sc_hd__newfill_12.gds | Bin 0 -> 3458 bytes 4 files changed, 96 insertions(+) create mode 100644 sky130_density_fix/README.txt create mode 100644 sky130_density_fix/replace_decap.py create mode 100644 sky130_density_fix/sky130_ef_sc_hd__newfill_12.gds diff --git a/.github/workflows/gds.yaml b/.github/workflows/gds.yaml index cf65a958..f48c34c9 100644 --- a/.github/workflows/gds.yaml +++ b/.github/workflows/gds.yaml @@ -67,6 +67,14 @@ jobs: pdk_version: ${{ env.SKY130_PDK_VERSION }} pdk_root: ${{ env.PDK_ROOT }} + # Patch Wokwi designs to work around the poly density issue + - name: Patch Wokwi designs + working-directory: projects + run: | + for project in tt_um_wokwi_*; do + python ../sky130_density_fix/replace_decap.py --design $project --user-gds $project/$project.gds --replacement-gds ../sky130_density_fix/sky130_ef_sc_hd__newfill_12.gds + done + # run OpenLane to build the GDS - name: Harden Chip ROM run: nix-shell $GITHUB_WORKSPACE/openlane2/shell.nix --run "python -m openlane tt/rom/config.json" diff --git a/sky130_density_fix/README.txt b/sky130_density_fix/README.txt new file mode 100644 index 00000000..4581dd39 --- /dev/null +++ b/sky130_density_fix/README.txt @@ -0,0 +1 @@ +sky130_ef_sc_hd__newfill_12.gds retrieved from https://github.com/RTimothyEdwards/open_pdks/blob/320597ea84b2816eb2fcc4fbe10c3874f19c92fc/sky130/custom/sky130_fd_sc_hd/gds/sky130_ef_sc_hd__newfill_12.gds diff --git a/sky130_density_fix/replace_decap.py b/sky130_density_fix/replace_decap.py new file mode 100644 index 00000000..9dfc073b --- /dev/null +++ b/sky130_density_fix/replace_decap.py @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: Apache-2.0 +# Authors: David Lindley, Uri Shaked + +import argparse +from random import random, seed + +import klayout.db as pya + +# We want reproducible results: +seed(a=0) + +parser = argparse.ArgumentParser( + description="Replaces a given portion of a decap_12 cells with newfill_12 cells." +) + +parser.add_argument("--probability", "-p", type=float, default=0.5, help="") + +parser.add_argument("--design-name", "-n", required=True) + +parser.add_argument("--from-cell-name", "-f", default="sky130_ef_sc_hd__decap_12") +parser.add_argument("--to-cell-name", "-t", default="sky130_ef_sc_hd__newfill_12") + +parser.add_argument("--user-gds", "-i", required=True) +parser.add_argument("--replacement-gds", "-r", required=True) + +parser.add_argument("--output-gds", "-o", required=False) + + +args = parser.parse_args() + +probability = args.probability + +design_name = args.design_name + +from_cell_name = args.from_cell_name +to_cell_name = args.to_cell_name + +user_gds = args.user_gds +replacement_gds = args.replacement_gds +output_gds = args.output_gds or user_gds + +replacement_layout = pya.Layout() +replacement_layout.read(replacement_gds) + +user_layout = pya.Layout() +user_layout.read(user_gds) + +top_cell = user_layout.cell(design_name) +replacement_cell = user_layout.create_cell(to_cell_name) +replacement_cell.copy_tree(replacement_layout.cell(to_cell_name)) + + +def cell_dimensions_equal(cell1, cell2): + return ( + cell1.bbox().width() == cell2.bbox().width() + and cell1.bbox().height() == cell2.bbox().height() + ) + + +print("Top-cell name:", top_cell.name) +print("From-cell prefix:", from_cell_name) +print("Replacement-cell name:", replacement_cell.name) +matches = 0 +replacements = 0 + +for inst in top_cell.each_inst(): + assert inst is not None + + # Make sure we haven't already processed this gds + assert inst.cell.name != to_cell_name + + # For cells that have no hierarchy beneath (standard cells in this case) + if inst.cell.hierarchy_levels() == 0 and inst.cell.name == from_cell_name: + assert cell_dimensions_equal(inst.cell, replacement_cell) + matches += 1 + + if random() < probability: + continue + + inst.cell = replacement_cell + replacements += 1 + +print(f"Replaced {replacements} cells out of {matches} matches.") +print(f"Writing to {output_gds}...") + +user_layout.write(output_gds) +print("Done.") diff --git a/sky130_density_fix/sky130_ef_sc_hd__newfill_12.gds b/sky130_density_fix/sky130_ef_sc_hd__newfill_12.gds new file mode 100644 index 0000000000000000000000000000000000000000..afafbee2599501d74b7db7f0c4cb91dd4275c05c GIT binary patch literal 3458 zcmbuBziSj*6vxlb&dly6*<_;|B|Zxqi-6!SP(+ZZ0g*_aPt1ENBwP3!#YRx{4^UDF z+6fkljfI64DmE52c4A@oIxR$auh1e`#_#u>d)(R8J0!S}{cO&?pE>v5Id|qtE=h7s z)>o3+XKBcYjLL+J6@N=T$qyaeC(^EFd-g8uoPP7@%dV-Hn;+aeaa7i4ac@JOU%qf{ z>-H_3(`P!DPj=3o>U1uhzIx{T#fzP-+eFg3NZw3jQu5(M+OnxtU0PZ~qHNqaI4`nh zM#SmyY+TaOuD`eIi^xq}^iN~sxyV>U#OZOc)R+IvuObP3r^msfKi`udYW5ai_;B1~ zx4ZN>SoG)A-^BUTvbpnD^_%%dk1LD*z8?RHNc|mTuyIYKa=c5AgHgY|(|nSC`$L!X zLwnR`-pUQjpKP)GPLG38pVwzUk{KWT}%w$9x>W z)8k;=XZ=0KHTc1`SieS(D}VOAe(%_N3Au=Sxw}BFzqLpGWX^mg{A$g7CH&AH_0tLS zmGIN|<}2Zc_Nbr1;eA))cYfb|rN@6&KVkm0*XAqX*Dsi_gdf_Y`5U*)S8^=a2V6%b z{Lmit2eIEdekHsiJX7c^Jzg^Y=0@|C@S523^p)^Kdo=&>SM!zdM(&xfgdf_Ye(RO_ zO8BE^%~!$??NNW#g854LtGAo4gdf_YetXt@CH(f1`AYbqJ?hJyuuo9u+&8R$qsPnl zPcmoySm*Ru_ePJG`{{)BW1Z7u-5Wh#?q`eEFT>pFvF?o?FZXM&tsm>09_!xd@p8X$ z%lfg->9OvO9xwL?k6S<1KRwpH(c|TQbEEZRozr988$Dj`4}Z0OtaEy-d!xt8{njh% z$2zCSx;J{f++Vd|{aEMpSocPcm;3Em>&H5$$GSIq{3m~^|NYx|3J0G-ygTXQ=pX*)$S=m<3g@?#?|+;B58s|Y!uRB2`TH}Be{#9=_wnP1U0i?oIDh|c z{@u%7|Czr0*L(A8eF^8!x?9Hcb4GnXe?Ut=+MUOIwf>wQ2aEInOa0W(-{$h$J!iM2 P$Nyh_S-Fo#dz#93DL?5> literal 0 HcmV?d00001