refactor(logo): move pdk specific code to tech.py

This commit is contained in:
htfab
2025-11-06 13:33:10 +02:00
committed by Uri Shaked
parent eebefdd779
commit ce6e5d19eb
2 changed files with 38 additions and 56 deletions
+18 -56
View File
@@ -2,59 +2,23 @@
import argparse import argparse
import sys import sys
from typing import Dict, TypedDict
import gdstk import gdstk
from git.repo import Repo from git.repo import Repo
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from config import Config from config import Config
from tech import TechName, tech_map
class TechDef(TypedDict):
PRBOUNDARY_LAYER: int
PRBOUNDARY_DATATYPE: int
LOGO_LAYER: int
LOGO_DATATYPE: int
OBS_LAYER_NAME: str
PIXEL_SIZE: float
tech: Dict[str, TechDef] = {
"gf180mcuD": {
"PRBOUNDARY_LAYER": 0, # PR_bndry
"PRBOUNDARY_DATATYPE": 0, #
"LOGO_LAYER": 46, # Metal4
"LOGO_DATATYPE": 0, #
"OBS_LAYER_NAME": "Metal4",
"PIXEL_SIZE": 0.5, # um
},
"ihp-sg13g2": {
"PRBOUNDARY_LAYER": 189, # prBoundary
"PRBOUNDARY_DATATYPE": 4, # .boundary
"LOGO_LAYER": 67, # Metal5
"LOGO_DATATYPE": 0, # .drawing
"OBS_LAYER_NAME": "Metal5",
"PIXEL_SIZE": 0.25, # um
},
"sky130A": {
"PRBOUNDARY_LAYER": 235, # prBoundary
"PRBOUNDARY_DATATYPE": 4, # .boundary
"LOGO_LAYER": 71, # Metal4
"LOGO_DATATYPE": 20, # .drawing
"OBS_LAYER_NAME": "met4",
"PIXEL_SIZE": 0.5, # um
},
}
LOGO_WIDTH = 200 LOGO_WIDTH = 200
LOGO_HEIGHT = 200 LOGO_HEIGHT = 200
class LogoGenerator: class LogoGenerator:
def __init__(self, tt_dir, pdk: str, config: Config | None = None): def __init__(self, tt_dir, pdk: TechName, config: Config | None = None):
self.tt_dir = tt_dir self.tt_dir = tt_dir
self.pdk = pdk self.pdk = pdk
self.tech = tech_map[pdk]
self.config = config self.config = config
def gen_logo(self, variant: str, gds_file: str, shuttle=None, commit=None): def gen_logo(self, variant: str, gds_file: str, shuttle=None, commit=None):
@@ -96,19 +60,14 @@ class LogoGenerator:
draw.text((1, 137), commit[18:29], fill=255, font=font(32)) draw.text((1, 137), commit[18:29], fill=255, font=font(32))
draw.text((1, 165), commit[29:], fill=255, font=font(32)) draw.text((1, 165), commit[29:], fill=255, font=font(32))
PRBOUNDARY_LAYER = tech[self.pdk]["PRBOUNDARY_LAYER"] pixel_size = self.tech.logo_pixel_size
PRBOUNDARY_DATATYPE = tech[self.pdk]["PRBOUNDARY_DATATYPE"]
MET4_LAYER = tech[self.pdk]["LOGO_LAYER"]
DRAWING_DATATYPE = tech[self.pdk]["LOGO_DATATYPE"]
PIXEL_SIZE = tech[self.pdk]["PIXEL_SIZE"]
lib = gdstk.Library() lib = gdstk.Library()
cell = lib.new_cell(f"tt_logo_{variant}") cell = lib.new_cell(f"tt_logo_{variant}")
boundary = gdstk.rectangle( boundary = gdstk.rectangle(
(0, 0), (0, 0),
(img.width * PIXEL_SIZE, img.height * PIXEL_SIZE), (img.width * pixel_size, img.height * pixel_size),
layer=PRBOUNDARY_LAYER, layer=self.tech.prboundary_layer[0],
datatype=PRBOUNDARY_DATATYPE, datatype=self.tech.prboundary_layer[1],
) )
cell.add(boundary) cell.add(boundary)
@@ -118,10 +77,10 @@ class LogoGenerator:
if color >= 128: if color >= 128:
flipped_y = img.height - y - 1 # flip vertically flipped_y = img.height - y - 1 # flip vertically
rect = gdstk.rectangle( rect = gdstk.rectangle(
(x * PIXEL_SIZE, flipped_y * PIXEL_SIZE), (x * pixel_size, flipped_y * pixel_size),
((x + 1) * PIXEL_SIZE, (flipped_y + 1) * PIXEL_SIZE), ((x + 1) * pixel_size, (flipped_y + 1) * pixel_size),
layer=MET4_LAYER, layer=self.tech.logo_layer[0],
datatype=DRAWING_DATATYPE, datatype=self.tech.logo_layer[1],
) )
cell.add(rect) cell.add(rect)
@@ -129,8 +88,8 @@ class LogoGenerator:
def gen_lef(self, variant: str, lef_file: str): def gen_lef(self, variant: str, lef_file: str):
assert variant in ("top", "bottom") assert variant in ("top", "bottom")
width = tech[self.pdk]["PIXEL_SIZE"] * LOGO_WIDTH width = self.tech.logo_pixel_size * LOGO_WIDTH
height = tech[self.pdk]["PIXEL_SIZE"] * LOGO_HEIGHT height = self.tech.logo_pixel_size * LOGO_HEIGHT
lef_lines = [ lef_lines = [
f"VERSION 5.7 ;", f"VERSION 5.7 ;",
f" NOWIREEXTENSIONATPIN ON ;", f" NOWIREEXTENSIONATPIN ON ;",
@@ -142,7 +101,7 @@ class LogoGenerator:
f" ORIGIN 0.000 0.000 ;", f" ORIGIN 0.000 0.000 ;",
f" SIZE {width:.3f} BY {height:.3f} ;", f" SIZE {width:.3f} BY {height:.3f} ;",
f" OBS", f" OBS",
f' LAYER {tech[self.pdk]["OBS_LAYER_NAME"]} ;', f" LAYER {self.tech.logo_layer_name} ;",
f" RECT 0.000 0.000 {width:.3f} {height:.3f} ;", f" RECT 0.000 0.000 {width:.3f} {height:.3f} ;",
f" END", f" END",
f"END tt_logo_{variant}", f"END tt_logo_{variant}",
@@ -157,7 +116,10 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser(description="TT logo generator") parser = argparse.ArgumentParser(description="TT logo generator")
parser.add_argument( parser.add_argument(
"--pdk", type=str, default="sky130A", choices=["sky130A", "ihp-sg13g2"] "--pdk",
type=str,
default="sky130A",
choices=["sky130A", "ihp-sg13g2", "gf180mcuD"],
) )
parser.add_argument("--top", action="store_true") parser.add_argument("--top", action="store_true")
parser.add_argument("--bottom", action="store_true") parser.add_argument("--bottom", action="store_true")
+20
View File
@@ -41,6 +41,14 @@ class Tech(Protocol):
mux_macros: List[str] mux_macros: List[str]
""" Lists all of the extra logo macros that need to be copied to the tt_top directory. """ """ Lists all of the extra logo macros that need to be copied to the tt_top directory. """
extra_logo_macros: List[str] extra_logo_macros: List[str]
""" GDS layer/datatype for the place&route boundary marker layer """
prboundary_layer: Tuple[int, int]
""" GDS layer/datatype for the metal layer used in the logo """
logo_layer: Tuple[int, int]
""" LEF layer name for the metal layer used in the logo """
logo_layer_name: str
""" Logo pixel size in microns """
logo_pixel_size: float
def read_pdk_version(self, pdk_root: str) -> PDKVersionInfo: def read_pdk_version(self, pdk_root: str) -> PDKVersionInfo:
raise NotImplementedError() raise NotImplementedError()
@@ -96,6 +104,10 @@ class Sky130Tech(Tech):
"asw/sky130/tt_asw_3v3", "asw/sky130/tt_asw_3v3",
] ]
extra_logo_macros = [] extra_logo_macros = []
prboundary_layer = (235, 4) # prBoundary.boundary
logo_layer = (71, 20) # met4.drawing
logo_layer_name = "met4"
logo_pixel_size = 0.5 # um
def read_pdk_version(self, pdk_root: str) -> PDKVersionInfo: def read_pdk_version(self, pdk_root: str) -> PDKVersionInfo:
pdk_sources_file = os.path.join(pdk_root, "sky130A", "SOURCES") pdk_sources_file = os.path.join(pdk_root, "sky130A", "SOURCES")
@@ -145,6 +157,10 @@ class IHPTech(Tech):
extra_logo_macros = [ extra_logo_macros = [
"tech/ihp-sg13g2/tt_logo_corner", "tech/ihp-sg13g2/tt_logo_corner",
] ]
prboundary_layer = (189, 4) # prBoundary.boundary
logo_layer = (67, 0) # Metal5.drawing
logo_layer_name = "Metal5"
logo_pixel_size = 0.25 # um
def read_pdk_version(self, pdk_root: str) -> PDKVersionInfo: def read_pdk_version(self, pdk_root: str) -> PDKVersionInfo:
pdk_repo = Repo(pdk_root) pdk_repo = Repo(pdk_root)
@@ -219,6 +235,10 @@ class GF180MCUDTech(Tech):
"pg/gf180mcuD/tt_pg_1v8_ll_4", "pg/gf180mcuD/tt_pg_1v8_ll_4",
] ]
extra_logo_macros = [] extra_logo_macros = []
prboundary_layer = (0, 0) # PR_bndry
logo_layer = (46, 0) # Metal4
logo_layer_name = "Metal4"
logo_pixel_size = 0.5 # um
def read_pdk_version(self, pdk_root: str) -> PDKVersionInfo: def read_pdk_version(self, pdk_root: str) -> PDKVersionInfo:
pdk_sources_file = os.path.join(pdk_root, "gf180mcuD", "SOURCES") pdk_sources_file = os.path.join(pdk_root, "gf180mcuD", "SOURCES")