2019-04-26 21:21:50 +02:00
|
|
|
# See LICENSE for licensing information.
|
|
|
|
|
#
|
2019-06-14 17:43:41 +02:00
|
|
|
# Copyright (c) 2016-2019 Regents of the University of California and The Board
|
|
|
|
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
|
|
|
|
# (acting for and on behalf of Oklahoma State University)
|
|
|
|
|
# All rights reserved.
|
2019-04-26 21:21:50 +02:00
|
|
|
#
|
2016-11-08 18:57:35 +01:00
|
|
|
import gdsMill
|
2017-12-13 00:50:45 +01:00
|
|
|
import tech
|
|
|
|
|
import math
|
2016-11-08 18:57:35 +01:00
|
|
|
import globals
|
2018-10-23 02:02:21 +02:00
|
|
|
import debug
|
2017-08-24 00:02:15 +02:00
|
|
|
from vector import vector
|
|
|
|
|
from pin_layout import pin_layout
|
2016-11-08 18:57:35 +01:00
|
|
|
|
|
|
|
|
OPTS = globals.OPTS
|
|
|
|
|
|
2019-11-14 19:17:20 +01:00
|
|
|
|
2017-12-13 00:50:45 +01:00
|
|
|
def ceil(decimal):
|
|
|
|
|
"""
|
|
|
|
|
Performs a ceiling function on the decimal place specified by the DRC grid.
|
|
|
|
|
"""
|
|
|
|
|
grid = tech.drc["grid"]
|
|
|
|
|
return math.ceil(decimal * 1 / grid) / (1 / grid)
|
|
|
|
|
|
2019-11-14 19:17:20 +01:00
|
|
|
|
2017-11-30 21:15:20 +01:00
|
|
|
def round_to_grid(number):
|
2016-11-08 18:57:35 +01:00
|
|
|
"""
|
2017-11-30 21:15:20 +01:00
|
|
|
Rounds an arbitrary number to the grid.
|
2016-11-08 18:57:35 +01:00
|
|
|
"""
|
2019-11-14 19:17:20 +01:00
|
|
|
grid = tech.drc["grid"]
|
2016-11-08 18:57:35 +01:00
|
|
|
# this gets the nearest integer value
|
2017-11-30 21:15:20 +01:00
|
|
|
number_grid = int(round(round((number / grid), 2), 0))
|
|
|
|
|
number_off = number_grid * grid
|
|
|
|
|
return number_off
|
|
|
|
|
|
2019-11-14 19:17:20 +01:00
|
|
|
|
2017-11-30 21:15:20 +01:00
|
|
|
def snap_to_grid(offset):
|
|
|
|
|
"""
|
|
|
|
|
Changes the coodrinate to match the grid settings
|
|
|
|
|
"""
|
2019-11-14 19:17:20 +01:00
|
|
|
return [round_to_grid(offset[0]),
|
|
|
|
|
round_to_grid(offset[1])]
|
|
|
|
|
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2017-08-24 00:02:15 +02:00
|
|
|
def pin_center(boundary):
|
2016-11-17 20:24:17 +01:00
|
|
|
"""
|
2017-08-24 00:02:15 +02:00
|
|
|
This returns the center of a pin shape in the vlsiLayout border format.
|
2016-11-17 20:24:17 +01:00
|
|
|
"""
|
2019-11-14 19:17:20 +01:00
|
|
|
return [0.5 * (boundary[0] + boundary[2]),
|
|
|
|
|
0.5 * (boundary[1] + boundary[3])]
|
|
|
|
|
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2019-10-25 19:03:25 +02:00
|
|
|
def auto_measure_libcell(pin_list, name, units, lpp):
|
2016-11-17 20:24:17 +01:00
|
|
|
"""
|
|
|
|
|
Open a GDS file and find the pins in pin_list as text on a given layer.
|
|
|
|
|
Return these as a set of properties including the cell width/height too.
|
|
|
|
|
"""
|
2016-11-08 18:57:35 +01:00
|
|
|
cell_gds = OPTS.openram_tech + "gds_lib/" + str(name) + ".gds"
|
|
|
|
|
cell_vlsi = gdsMill.VlsiLayout(units=units)
|
|
|
|
|
reader = gdsMill.Gds2reader(cell_vlsi)
|
|
|
|
|
reader.loadFromFile(cell_gds)
|
|
|
|
|
|
|
|
|
|
cell = {}
|
2019-10-25 19:03:25 +02:00
|
|
|
measure_result = cell_vlsi.getLayoutBorder(lpp[0])
|
2019-11-14 19:17:20 +01:00
|
|
|
if measure_result:
|
2016-11-08 18:57:35 +01:00
|
|
|
measure_result = cell_vlsi.measureSize(name)
|
|
|
|
|
[cell["width"], cell["height"]] = measure_result
|
|
|
|
|
|
|
|
|
|
for pin in pin_list:
|
2019-11-14 19:17:20 +01:00
|
|
|
(name, lpp, boundary) = cell_vlsi.getPinShapeByLabel(str(pin))
|
2017-08-24 00:02:15 +02:00
|
|
|
cell[str(pin)] = pin_center(boundary)
|
|
|
|
|
return cell
|
|
|
|
|
|
|
|
|
|
|
2019-10-25 19:03:25 +02:00
|
|
|
def get_gds_size(name, gds_filename, units, lpp):
|
2017-08-24 00:02:15 +02:00
|
|
|
"""
|
2018-08-22 20:37:24 +02:00
|
|
|
Open a GDS file and return the size from either the
|
2017-08-24 00:02:15 +02:00
|
|
|
bounding box or a border layer.
|
|
|
|
|
"""
|
2019-11-14 19:17:20 +01:00
|
|
|
debug.info(4, "Creating VLSI layout for {}".format(name))
|
2017-08-24 00:02:15 +02:00
|
|
|
cell_vlsi = gdsMill.VlsiLayout(units=units)
|
|
|
|
|
reader = gdsMill.Gds2reader(cell_vlsi)
|
2018-08-22 20:37:24 +02:00
|
|
|
reader.loadFromFile(gds_filename)
|
2017-08-24 00:02:15 +02:00
|
|
|
|
2019-10-25 19:03:25 +02:00
|
|
|
measure_result = cell_vlsi.getLayoutBorder(lpp)
|
2019-11-14 19:17:20 +01:00
|
|
|
if not measure_result:
|
|
|
|
|
debug.info(2, "Layout border failed. Trying to measure size for {}".format(name))
|
2017-08-24 00:02:15 +02:00
|
|
|
measure_result = cell_vlsi.measureSize(name)
|
|
|
|
|
# returns width,height
|
|
|
|
|
return measure_result
|
|
|
|
|
|
2019-11-14 19:17:20 +01:00
|
|
|
|
2019-10-25 19:03:25 +02:00
|
|
|
def get_libcell_size(name, units, lpp):
|
2018-08-22 20:37:24 +02:00
|
|
|
"""
|
|
|
|
|
Open a GDS file and return the library cell size from either the
|
|
|
|
|
bounding box or a border layer.
|
|
|
|
|
"""
|
2020-02-10 06:37:09 +01:00
|
|
|
|
|
|
|
|
cell_gds = OPTS.openram_tech + "gds_lib/" + str(name) + ".gds"
|
|
|
|
|
return(get_gds_size(name, cell_gds, units, lpp))
|
|
|
|
|
|
2018-08-22 20:37:24 +02:00
|
|
|
|
2017-08-24 00:02:15 +02:00
|
|
|
|
2018-11-07 20:31:44 +01:00
|
|
|
def get_gds_pins(pin_names, name, gds_filename, units):
|
2017-08-24 00:02:15 +02:00
|
|
|
"""
|
2018-11-07 20:31:44 +01:00
|
|
|
Open a GDS file and find the pins in pin_names as text on a given layer.
|
2017-08-24 00:02:15 +02:00
|
|
|
Return these as a rectangle layer pair for each pin.
|
|
|
|
|
"""
|
|
|
|
|
cell_vlsi = gdsMill.VlsiLayout(units=units)
|
|
|
|
|
reader = gdsMill.Gds2reader(cell_vlsi)
|
2018-08-22 20:37:24 +02:00
|
|
|
reader.loadFromFile(gds_filename)
|
2017-08-24 00:02:15 +02:00
|
|
|
|
|
|
|
|
cell = {}
|
2018-11-07 20:31:44 +01:00
|
|
|
for pin_name in pin_names:
|
2019-11-14 19:17:20 +01:00
|
|
|
cell[str(pin_name)] = []
|
|
|
|
|
pin_list = cell_vlsi.getPinShape(str(pin_name))
|
2018-11-07 22:05:13 +01:00
|
|
|
for pin_shape in pin_list:
|
2019-11-14 19:17:20 +01:00
|
|
|
(lpp, boundary) = pin_shape
|
|
|
|
|
rect = [vector(boundary[0], boundary[1]),
|
|
|
|
|
vector(boundary[2], boundary[3])]
|
|
|
|
|
# this is a list because other cells/designs
|
|
|
|
|
# may have must-connect pins
|
2019-10-25 19:03:25 +02:00
|
|
|
cell[str(pin_name)].append(pin_layout(pin_name, rect, lpp))
|
2016-11-08 18:57:35 +01:00
|
|
|
return cell
|
2016-11-11 18:41:43 +01:00
|
|
|
|
2019-11-14 19:17:20 +01:00
|
|
|
|
2018-11-07 20:31:44 +01:00
|
|
|
def get_libcell_pins(pin_list, name, units):
|
2018-08-22 20:37:24 +02:00
|
|
|
"""
|
|
|
|
|
Open a GDS file and find the pins in pin_list as text on a given layer.
|
|
|
|
|
Return these as a rectangle layer pair for each pin.
|
|
|
|
|
"""
|
2020-02-10 06:37:09 +01:00
|
|
|
|
|
|
|
|
cell_gds = OPTS.openram_tech + "gds_lib/" + str(name) + ".gds"
|
|
|
|
|
return(get_gds_pins(pin_list, name, cell_gds, units))
|
2018-08-22 20:37:24 +02:00
|
|
|
|
2016-11-11 18:41:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|