mirror of https://github.com/VLSIDA/OpenRAM.git
Move pin name mapping to layout class.
This commit is contained in:
parent
93e94e26ec
commit
1d729e8f02
|
|
@ -8,30 +8,28 @@
|
|||
|
||||
class _cell:
|
||||
def __init__(self, port_order, port_types, port_map=None, hard_cell=True, boundary_layer="boundary"):
|
||||
|
||||
# Specifies if this is a hard (i.e. GDS) cell
|
||||
self._hard_cell = hard_cell
|
||||
self._boundary_layer = boundary_layer
|
||||
|
||||
# Specifies the port directions
|
||||
self._port_types_map = {x: y for (x, y) in zip(port_order, port_types)}
|
||||
|
||||
# Specifies a map from OpenRAM names to cell names
|
||||
# by default it is 1:1
|
||||
if not port_map:
|
||||
port_map = {x: x for x in port_order}
|
||||
self._port_map = {x: x for x in port_order}
|
||||
|
||||
# Update mapping of names
|
||||
self._pins = _pins(port_map)
|
||||
self._port_order = port_order
|
||||
|
||||
# Update ordered name list
|
||||
self._port_names = [getattr(self._pins, x) for x in self._port_order]
|
||||
self._port_names = [self._port_map[x] for x in self._port_order]
|
||||
|
||||
# Update ordered type list
|
||||
self._port_types = [self._port_types_map[x] for x in port_order]
|
||||
self._port_types = [self._port_types_map[x] for x in self._port_order]
|
||||
|
||||
@property
|
||||
def pin(self):
|
||||
return self._pins
|
||||
|
||||
@property
|
||||
def hard_cell(self):
|
||||
return self._hard_cell
|
||||
|
|
|
|||
|
|
@ -35,9 +35,11 @@ class design(hierarchy_design):
|
|||
# This means it is a custom cell.
|
||||
# It could have properties and not be a hard cell too (e.g. dff_buf)
|
||||
if prop and prop.hard_cell:
|
||||
# The pins get added from the spice file
|
||||
# The pins get added from the spice file, so just check
|
||||
# that they matched here
|
||||
debug.check(prop.port_names == self.pins,
|
||||
"Custom cell pin names do not match spice file:\n{0} vs {1}".format(prop.port_names, self.pins))
|
||||
self.add_pin_names(prop.port_map)
|
||||
self.add_pin_types(prop.port_types)
|
||||
|
||||
(width, height) = utils.get_libcell_size(self.cell_name,
|
||||
|
|
|
|||
|
|
@ -39,12 +39,21 @@ class layout():
|
|||
self.width = None
|
||||
self.height = None
|
||||
self.bounding_box = None
|
||||
self.insts = [] # Holds module/cell layout instances
|
||||
self.inst_names = set() # Set of names to check for duplicates
|
||||
self.objs = [] # Holds all other objects (labels, geometries, etc)
|
||||
self.pin_map = {} # Holds name->pin_layout map for all pins
|
||||
self.visited = [] # List of modules we have already visited
|
||||
self.is_library_cell = False # Flag for library cells
|
||||
# Holds module/cell layout instances
|
||||
self.insts = []
|
||||
# Set of names to check for duplicates
|
||||
self.inst_names = set()
|
||||
# Holds all other objects (labels, geometries, etc)
|
||||
self.objs = []
|
||||
# This is a mapping of internal pin names to cell pin names
|
||||
# If the key is not found, the internal pin names is assumed
|
||||
self.pin_names = {}
|
||||
# Holds name->pin_layout map for all pins
|
||||
self.pin_map = {}
|
||||
# List of modules we have already visited
|
||||
self.visited = []
|
||||
# Flag for library cells
|
||||
self.is_library_cell = False
|
||||
|
||||
self.gds_read()
|
||||
|
||||
|
|
@ -54,8 +63,13 @@ class layout():
|
|||
except ImportError:
|
||||
self.pwr_grid_layer = "m3"
|
||||
|
||||
|
||||
|
||||
def add_pin_names(self, pin_dict):
|
||||
"""
|
||||
Create a mapping from internal pin names to external pin names.
|
||||
"""
|
||||
self.pin_names = pin_dict
|
||||
|
||||
|
||||
############################################################
|
||||
# GDS layout
|
||||
############################################################
|
||||
|
|
@ -311,23 +325,33 @@ class layout():
|
|||
"""
|
||||
Return the pin or list of pins
|
||||
"""
|
||||
if text in self.pin_names:
|
||||
name = self.pin_names[text]
|
||||
else:
|
||||
name = text
|
||||
|
||||
try:
|
||||
if len(self.pin_map[text]) > 1:
|
||||
if len(self.pin_map[name]) > 1:
|
||||
debug.error("Should use a pin iterator since more than one pin {}".format(text), -1)
|
||||
# If we have one pin, return it and not the list.
|
||||
# Otherwise, should use get_pins()
|
||||
any_pin = next(iter(self.pin_map[text]))
|
||||
any_pin = next(iter(self.pin_map[name]))
|
||||
return any_pin
|
||||
except Exception:
|
||||
self.gds_write("missing_pin.gds")
|
||||
debug.error("No pin found with name {0} on {1}. Saved as missing_pin.gds.".format(text, self.cell_name), -1)
|
||||
debug.error("No pin found with name {0} on {1}. Saved as missing_pin.gds.".format(name, self.cell_name), -1)
|
||||
|
||||
def get_pins(self, text):
|
||||
"""
|
||||
Return a pin list (instead of a single pin)
|
||||
"""
|
||||
if text in self.pin_map.keys():
|
||||
return self.pin_map[text]
|
||||
if text in self.pin_names:
|
||||
name = self.pin_names[text]
|
||||
else:
|
||||
name = text
|
||||
|
||||
if name in self.pin_map.keys():
|
||||
return self.pin_map[name]
|
||||
else:
|
||||
return set()
|
||||
|
||||
|
|
|
|||
|
|
@ -24,37 +24,35 @@ class bitcell_1port(bitcell_base.bitcell_base):
|
|||
|
||||
def get_all_wl_names(self):
|
||||
""" Creates a list of all wordline pin names """
|
||||
row_pins = [props.bitcell_1port.pin.wl]
|
||||
row_pins = ["wl"]
|
||||
return row_pins
|
||||
|
||||
def get_all_bitline_names(self):
|
||||
""" Creates a list of all bitline pin names (both bl and br) """
|
||||
pin = props.bitcell_1port.pin
|
||||
column_pins = [pin.bl, pin.br]
|
||||
return column_pins
|
||||
return ["bl", "br"]
|
||||
|
||||
def get_all_bl_names(self):
|
||||
""" Creates a list of all bl pins names """
|
||||
return [props.bitcell_1port.pin.bl]
|
||||
return ["bl"]
|
||||
|
||||
def get_all_br_names(self):
|
||||
""" Creates a list of all br pins names """
|
||||
return [props.bitcell_1port.pin.br]
|
||||
return ["br"]
|
||||
|
||||
def get_bl_name(self, port=0):
|
||||
"""Get bl name"""
|
||||
debug.check(port == 0, "One port for bitcell only.")
|
||||
return props.bitcell_1port.pin.bl
|
||||
return "bl"
|
||||
|
||||
def get_br_name(self, port=0):
|
||||
"""Get bl name"""
|
||||
debug.check(port == 0, "One port for bitcell only.")
|
||||
return props.bitcell_1port.pin.br
|
||||
return "br"
|
||||
|
||||
def get_wl_name(self, port=0):
|
||||
"""Get wl name"""
|
||||
debug.check(port == 0, "One port for bitcell only.")
|
||||
return props.bitcell_1port.pin.wl
|
||||
return "wl"
|
||||
|
||||
def build_graph(self, graph, inst_name, port_nets):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -22,65 +22,56 @@ class bitcell_2port(bitcell_base.bitcell_base):
|
|||
super().__init__(name, prop=props.bitcell_2port)
|
||||
debug.info(2, "Create bitcell with 2 ports")
|
||||
|
||||
self.bl_names = [props.bitcell_2port.pin.bl0, props.bitcell_2port.pin.bl1]
|
||||
self.br_names = [props.bitcell_2port.pin.br0, props.bitcell_2port.pin.br1]
|
||||
self.wl_names = [props.bitcell_2port.pin.wl0, props.bitcell_2port.pin.wl1]
|
||||
self.bl_names = ["bl0", "bl1"]
|
||||
self.br_names = ["br0", "br1"]
|
||||
self.wl_names = ["wl0", "wl1"]
|
||||
|
||||
def get_bitcell_pins(self, col, row):
|
||||
"""
|
||||
Creates a list of connections in the bitcell,
|
||||
indexed by column and row, for instance use in bitcell_array
|
||||
"""
|
||||
pin_name = props.bitcell_2port.pin
|
||||
bitcell_pins = ["{0}_{1}".format(pin_name.bl0, col),
|
||||
"{0}_{1}".format(pin_name.br0, col),
|
||||
"{0}_{1}".format(pin_name.bl1, col),
|
||||
"{0}_{1}".format(pin_name.br1, col),
|
||||
"{0}_{1}".format(pin_name.wl0, row),
|
||||
"{0}_{1}".format(pin_name.wl1, row),
|
||||
bitcell_pins = ["bl0_{0}".format(col),
|
||||
"br0_{0}".format(col),
|
||||
"bl1_{0}".format(col),
|
||||
"br1_{0}".format(col),
|
||||
"wl0_{0}".format(row),
|
||||
"wl1_{0}".format(row),
|
||||
"vdd",
|
||||
"gnd"]
|
||||
return bitcell_pins
|
||||
|
||||
def get_all_wl_names(self):
|
||||
""" Creates a list of all wordline pin names """
|
||||
return [props.bitcell_2port.pin.wl0,
|
||||
props.bitcell_2port.pin.wl1]
|
||||
return self.wl_names
|
||||
|
||||
def get_all_bitline_names(self):
|
||||
""" Creates a list of all bitline pin names (both bl and br) """
|
||||
return [props.bitcell_2port.pin.bl0,
|
||||
props.bitcell_2port.pin.br0,
|
||||
props.bitcell_2port.pin.bl1,
|
||||
props.bitcell_2port.pin.br1]
|
||||
return ["bl0", "br0", "bl1", "br1"]
|
||||
|
||||
def get_all_bl_names(self):
|
||||
""" Creates a list of all bl pins names """
|
||||
return [props.bitcell_2port.pin.bl0,
|
||||
props.bitcell_2port.pin.bl1]
|
||||
return ["bl0", "bl1"]
|
||||
|
||||
def get_all_br_names(self):
|
||||
""" Creates a list of all br pins names """
|
||||
return [props.bitcell_2port.pin.br0,
|
||||
props.bitcell_2port.pin.br1]
|
||||
return ["br0", "br1"]
|
||||
|
||||
def get_read_bl_names(self):
|
||||
""" Creates a list of bl pin names associated with read ports """
|
||||
return [props.bitcell_2port.pin.bl0,
|
||||
props.bitcell_2port.pin.bl1]
|
||||
return ["bl0", "bl1"]
|
||||
|
||||
def get_read_br_names(self):
|
||||
""" Creates a list of br pin names associated with read ports """
|
||||
return [props.bitcell_2port.pin.br0,
|
||||
props.bitcell_2port.pin.br1]
|
||||
return ["br0", "br1"]
|
||||
|
||||
def get_write_bl_names(self):
|
||||
""" Creates a list of bl pin names associated with write ports """
|
||||
return [props.bitcell_2port.pin.bl0]
|
||||
return ["bl0"]
|
||||
|
||||
def get_write_br_names(self):
|
||||
""" Creates a list of br pin names asscociated with write ports"""
|
||||
return [props.bitcell_2port.pin.br1]
|
||||
return ["br1"]
|
||||
|
||||
def get_bl_name(self, port=0):
|
||||
"""Get bl name by port"""
|
||||
|
|
|
|||
|
|
@ -26,9 +26,8 @@ class bitcell_base(design.design):
|
|||
self.nets_match = self.do_nets_exist(prop.storage_nets)
|
||||
self.mirror = prop.mirror
|
||||
self.end_caps = prop.end_caps
|
||||
self.supplies = [prop.pin.vdd, prop.pin.gnd]
|
||||
else:
|
||||
self.supplies = ["vdd", "gnd"]
|
||||
|
||||
self.supplies = ["vdd", "gnd"]
|
||||
|
||||
def get_stage_effort(self, load):
|
||||
parasitic_delay = 1
|
||||
|
|
|
|||
|
|
@ -42,11 +42,10 @@ class replica_bitcell_2port(bitcell_base.bitcell_base):
|
|||
"""Adds edges to graph. Multiport bitcell timing graph is too complex
|
||||
to use the add_graph_edges function."""
|
||||
pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)}
|
||||
pins = props.bitcell_2port.pin
|
||||
# Edges hardcoded here. Essentially wl->bl/br for both ports.
|
||||
# Port 0 edges
|
||||
graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.bl0], self)
|
||||
graph.add_edge(pin_dict[pins.wl0], pin_dict[pins.br0], self)
|
||||
graph.add_edge(pin_dict["wl0"], pin_dict["bl0"], self)
|
||||
graph.add_edge(pin_dict["wl0"], pin_dict["br0"], self)
|
||||
# Port 1 edges
|
||||
graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.bl1], self)
|
||||
graph.add_edge(pin_dict[pins.wl1], pin_dict[pins.br1], self)
|
||||
graph.add_edge(pin_dict["wl1"], pin_dict["bl1"], self)
|
||||
graph.add_edge(pin_dict["wl1"], pin_dict["br1"], self)
|
||||
|
|
|
|||
|
|
@ -25,18 +25,18 @@ class sense_amp(design.design):
|
|||
debug.info(2, "Create sense_amp")
|
||||
|
||||
def get_bl_names(self):
|
||||
return props.sense_amp.pin.bl
|
||||
return "bl"
|
||||
|
||||
def get_br_names(self):
|
||||
return props.sense_amp.pin.br
|
||||
return "br"
|
||||
|
||||
@property
|
||||
def dout_name(self):
|
||||
return props.sense_amp.pin.dout
|
||||
return "dout"
|
||||
|
||||
@property
|
||||
def en_name(self):
|
||||
return props.sense_amp.pin.en
|
||||
return "en"
|
||||
|
||||
def get_cin(self):
|
||||
|
||||
|
|
|
|||
|
|
@ -23,18 +23,18 @@ class write_driver(design.design):
|
|||
debug.info(2, "Create write_driver")
|
||||
|
||||
def get_bl_names(self):
|
||||
return props.write_driver.pin.bl
|
||||
return "bl"
|
||||
|
||||
def get_br_names(self):
|
||||
return props.write_driver.pin.br
|
||||
return "br"
|
||||
|
||||
@property
|
||||
def din_name(self):
|
||||
return props.write_driver.pin.din
|
||||
return "din"
|
||||
|
||||
@property
|
||||
def en_name(self):
|
||||
return props.write_driver.pin.en
|
||||
return "en"
|
||||
|
||||
def get_w_en_cin(self):
|
||||
"""Get the relative capacitance of a single input"""
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
# All rights reserved.
|
||||
#
|
||||
import design
|
||||
from tech import cell_properties as props
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
import math
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#
|
||||
import debug
|
||||
import design
|
||||
from tech import cell_properties as props
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
|
@ -138,7 +137,7 @@ class dff_array(design.design):
|
|||
height=dout_pin.height())
|
||||
|
||||
# Create vertical spines to a single horizontal rail
|
||||
clk_pin = self.dff_insts[0, 0].get_pin(props.dff.pin.clk)
|
||||
clk_pin = self.dff_insts[0, 0].get_pin("clk")
|
||||
clk_ypos = 2 * self.m3_pitch + self.m3_width
|
||||
debug.check(clk_pin.layer == "m2", "DFF clk pin not on metal2")
|
||||
self.add_layout_pin_segment_center(text="clk",
|
||||
|
|
@ -146,7 +145,7 @@ class dff_array(design.design):
|
|||
start=vector(0, clk_ypos),
|
||||
end=vector(self.width, clk_ypos))
|
||||
for col in range(self.columns):
|
||||
clk_pin = self.dff_insts[0, col].get_pin(props.dff.pin.clk)
|
||||
clk_pin = self.dff_insts[0, col].get_pin("clk")
|
||||
# Make a vertical strip for each column
|
||||
self.add_rect(layer="m2",
|
||||
offset=clk_pin.ll().scale(1, 0),
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ class dff_buf(design.design):
|
|||
self.add_mod(self.inv2)
|
||||
|
||||
def add_pins(self):
|
||||
self.add_pin_names(props.dff_buf.port_map)
|
||||
self.add_pin_list(props.dff_buf.port_names,
|
||||
props.dff_buf.port_types)
|
||||
|
||||
|
|
@ -79,15 +80,15 @@ class dff_buf(design.design):
|
|||
self.dff_inst=self.add_inst(name="dff_buf_dff",
|
||||
mod=self.dff)
|
||||
|
||||
self.connect_inst([props.dff_buf.pin.D, "qint", props.dff_buf.pin.clk, props.dff_buf.pin.vdd, props.dff_buf.pin.gnd])
|
||||
self.connect_inst(["D", "qint", "clk", "vdd", "gnd"])
|
||||
|
||||
self.inv1_inst=self.add_inst(name="dff_buf_inv1",
|
||||
mod=self.inv1)
|
||||
self.connect_inst(["qint", "Qb", props.dff_buf.pin.vdd, props.dff_buf.pin.gnd])
|
||||
self.connect_inst(["qint", "Qb", "vdd", "gnd"])
|
||||
|
||||
self.inv2_inst=self.add_inst(name="dff_buf_inv2",
|
||||
mod=self.inv2)
|
||||
self.connect_inst(["Qb", props.dff_buf.pin.Q, props.dff_buf.pin.vdd, props.dff_buf.pin.gnd])
|
||||
self.connect_inst(["Qb", "Q", "vdd", "gnd"])
|
||||
|
||||
def place_instances(self):
|
||||
# Add the DFF
|
||||
|
|
@ -121,7 +122,7 @@ class dff_buf(design.design):
|
|||
self.route_layer = "m1"
|
||||
|
||||
# Route dff q to inv1 a
|
||||
q_pin = self.dff_inst.get_pin(props.dff.pin.Q)
|
||||
q_pin = self.dff_inst.get_pin("Q")
|
||||
a1_pin = self.inv1_inst.get_pin("A")
|
||||
mid1 = vector(a1_pin.cx(), q_pin.cy())
|
||||
self.add_path(q_pin.layer, [q_pin.center(), mid1, a1_pin.center()], width=q_pin.height())
|
||||
|
|
@ -138,30 +139,30 @@ class dff_buf(design.design):
|
|||
def add_layout_pins(self):
|
||||
|
||||
# Continous vdd rail along with label.
|
||||
vdd_pin=self.dff_inst.get_pin(props.dff.pin.vdd)
|
||||
self.add_layout_pin(text=props.dff_buf.pin.vdd,
|
||||
vdd_pin=self.dff_inst.get_pin("vdd")
|
||||
self.add_layout_pin(text="vdd",
|
||||
layer=vdd_pin.layer,
|
||||
offset=vdd_pin.ll(),
|
||||
width=self.width,
|
||||
height=vdd_pin.height())
|
||||
|
||||
# Continous gnd rail along with label.
|
||||
gnd_pin=self.dff_inst.get_pin(props.dff.pin.gnd)
|
||||
self.add_layout_pin(text=props.dff_buf.pin.gnd,
|
||||
gnd_pin=self.dff_inst.get_pin("gnd")
|
||||
self.add_layout_pin(text="gnd",
|
||||
layer=gnd_pin.layer,
|
||||
offset=gnd_pin.ll(),
|
||||
width=self.width,
|
||||
height=vdd_pin.height())
|
||||
|
||||
clk_pin = self.dff_inst.get_pin(props.dff.pin.clk)
|
||||
self.add_layout_pin(text=props.dff_buf.pin.clk,
|
||||
clk_pin = self.dff_inst.get_pin("clk")
|
||||
self.add_layout_pin(text="clk",
|
||||
layer=clk_pin.layer,
|
||||
offset=clk_pin.ll(),
|
||||
width=clk_pin.width(),
|
||||
height=clk_pin.height())
|
||||
|
||||
din_pin = self.dff_inst.get_pin(props.dff_buf.pin.D)
|
||||
self.add_layout_pin(text=props.dff_buf.pin.D,
|
||||
din_pin = self.dff_inst.get_pin("D")
|
||||
self.add_layout_pin(text="D",
|
||||
layer=din_pin.layer,
|
||||
offset=din_pin.ll(),
|
||||
width=din_pin.width(),
|
||||
|
|
@ -170,7 +171,7 @@ class dff_buf(design.design):
|
|||
dout_pin = self.inv2_inst.get_pin("Z")
|
||||
mid_pos = dout_pin.center() + vector(self.m2_nonpref_pitch, 0)
|
||||
q_pos = mid_pos - vector(0, 2 * self.m2_nonpref_pitch)
|
||||
self.add_layout_pin_rect_center(text=props.dff_buf.pin.Q,
|
||||
self.add_layout_pin_rect_center(text="Q",
|
||||
layer="m2",
|
||||
offset=q_pos)
|
||||
self.add_path(self.route_layer, [dout_pin.center(), mid_pos, q_pos])
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#
|
||||
import debug
|
||||
import design
|
||||
from tech import cell_properties as props
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from sram_factory import factory
|
||||
|
|
@ -148,7 +147,7 @@ class dff_buf_array(design.design):
|
|||
|
||||
def route_supplies(self):
|
||||
for row in range(self.rows):
|
||||
vdd0_pin=self.dff_insts[row, 0].get_pin(props.dff.pin.vdd)
|
||||
vdd0_pin=self.dff_insts[row, 0].get_pin("vdd")
|
||||
vddn_pin=self.dff_insts[row, self.columns - 1].get_pin("vdd")
|
||||
self.add_path(vdd0_pin.layer, [vdd0_pin.lc(), vddn_pin.rc()], width=vdd0_pin.height())
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue