mirror of https://github.com/VLSIDA/OpenRAM.git
Modifications for min area metal.
Made add_via_stack_center iterative instead of recursive. Removed add_via_stack (non-center) since it isn't used. Add min area metal during iterative via insertion.
This commit is contained in:
parent
011ac2fc05
commit
c1fedda575
|
|
@ -13,6 +13,7 @@ from tech import drc, GDS
|
||||||
from tech import layer as techlayer
|
from tech import layer as techlayer
|
||||||
from tech import layer_indices
|
from tech import layer_indices
|
||||||
from tech import layer_stacks
|
from tech import layer_stacks
|
||||||
|
from tech import preferred_directions
|
||||||
import os
|
import os
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
from vector import vector
|
from vector import vector
|
||||||
|
|
@ -521,7 +522,6 @@ class layout():
|
||||||
|
|
||||||
def get_preferred_direction(self, layer):
|
def get_preferred_direction(self, layer):
|
||||||
""" Return the preferred routing directions """
|
""" Return the preferred routing directions """
|
||||||
from tech import preferred_directions
|
|
||||||
return preferred_directions[layer]
|
return preferred_directions[layer]
|
||||||
|
|
||||||
def add_via(self, layers, offset, size=[1, 1], directions=None, implant_type=None, well_type=None):
|
def add_via(self, layers, offset, size=[1, 1], directions=None, implant_type=None, well_type=None):
|
||||||
|
|
@ -567,24 +567,6 @@ class layout():
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
return inst
|
return inst
|
||||||
|
|
||||||
def add_via_stack(self, offset, from_layer, to_layer,
|
|
||||||
directions=None,
|
|
||||||
size=[1, 1],
|
|
||||||
implant_type=None,
|
|
||||||
well_type=None):
|
|
||||||
"""
|
|
||||||
Punch a stack of vias from a start layer to a target layer.
|
|
||||||
"""
|
|
||||||
return self.__add_via_stack_internal(offset=offset,
|
|
||||||
directions=directions,
|
|
||||||
from_layer=from_layer,
|
|
||||||
to_layer=to_layer,
|
|
||||||
via_func=self.add_via,
|
|
||||||
last_via=None,
|
|
||||||
size=size,
|
|
||||||
implant_type=implant_type,
|
|
||||||
well_type=well_type)
|
|
||||||
|
|
||||||
def add_via_stack_center(self,
|
def add_via_stack_center(self,
|
||||||
offset,
|
offset,
|
||||||
from_layer,
|
from_layer,
|
||||||
|
|
@ -594,24 +576,7 @@ class layout():
|
||||||
implant_type=None,
|
implant_type=None,
|
||||||
well_type=None):
|
well_type=None):
|
||||||
"""
|
"""
|
||||||
Punch a stack of vias from a start layer to a target layer by the center
|
Punch a stack of vias from a start layer to a target layer by the center.
|
||||||
coordinate accounting for mirroring and rotation.
|
|
||||||
"""
|
|
||||||
return self.__add_via_stack_internal(offset=offset,
|
|
||||||
directions=directions,
|
|
||||||
from_layer=from_layer,
|
|
||||||
to_layer=to_layer,
|
|
||||||
via_func=self.add_via_center,
|
|
||||||
last_via=None,
|
|
||||||
size=size,
|
|
||||||
implant_type=implant_type,
|
|
||||||
well_type=well_type)
|
|
||||||
|
|
||||||
def __add_via_stack_internal(self, offset, directions, from_layer, to_layer,
|
|
||||||
via_func, last_via, size, implant_type=None, well_type=None):
|
|
||||||
"""
|
|
||||||
Punch a stack of vias from a start layer to a target layer. Here we
|
|
||||||
figure out whether to punch it up or down the stack.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if from_layer == to_layer:
|
if from_layer == to_layer:
|
||||||
|
|
@ -619,39 +584,66 @@ class layout():
|
||||||
# a metal enclosure. This helps with center-line path routing.
|
# a metal enclosure. This helps with center-line path routing.
|
||||||
self.add_rect_center(layer=from_layer,
|
self.add_rect_center(layer=from_layer,
|
||||||
offset=offset)
|
offset=offset)
|
||||||
return last_via
|
return None
|
||||||
|
|
||||||
from_id = layer_indices[from_layer]
|
via = None
|
||||||
to_id = layer_indices[to_layer]
|
cur_layer = from_layer
|
||||||
|
while cur_layer != to_layer:
|
||||||
|
from_id = layer_indices[cur_layer]
|
||||||
|
to_id = layer_indices[to_layer]
|
||||||
|
|
||||||
if from_id < to_id: # grow the stack up
|
if from_id < to_id: # grow the stack up
|
||||||
search_id = 0
|
search_id = 0
|
||||||
next_id = 2
|
next_id = 2
|
||||||
else: # grow the stack down
|
else: # grow the stack down
|
||||||
search_id = 2
|
search_id = 2
|
||||||
next_id = 0
|
next_id = 0
|
||||||
|
|
||||||
curr_stack = next(filter(lambda stack: stack[search_id] == from_layer, layer_stacks), None)
|
curr_stack = next(filter(lambda stack: stack[search_id] == cur_layer, layer_stacks), None)
|
||||||
if curr_stack is None:
|
|
||||||
raise ValueError("Cannot create via from '{0}' to '{1}'."
|
|
||||||
"Layer '{0}' not defined".format(from_layer, to_layer))
|
|
||||||
|
|
||||||
via = via_func(layers=curr_stack,
|
via = self.add_via_center(layers=curr_stack,
|
||||||
size=size,
|
size=size,
|
||||||
offset=offset,
|
offset=offset,
|
||||||
directions=directions,
|
directions=directions,
|
||||||
implant_type=implant_type,
|
implant_type=implant_type,
|
||||||
well_type=well_type)
|
well_type=well_type)
|
||||||
|
|
||||||
|
if cur_layer != from_layer:
|
||||||
|
self.add_min_area_rect_center(cur_layer,
|
||||||
|
offset,
|
||||||
|
via.mod.first_layer_width,
|
||||||
|
via.mod.first_layer_height)
|
||||||
|
|
||||||
|
cur_layer = curr_stack[next_id]
|
||||||
|
|
||||||
via = self.__add_via_stack_internal(offset=offset,
|
|
||||||
directions=directions,
|
|
||||||
from_layer=curr_stack[next_id],
|
|
||||||
to_layer=to_layer,
|
|
||||||
via_func=via_func,
|
|
||||||
last_via=via,
|
|
||||||
size=size)
|
|
||||||
return via
|
return via
|
||||||
|
|
||||||
|
def add_min_area_rect_center(self,
|
||||||
|
layer,
|
||||||
|
offset,
|
||||||
|
width=None,
|
||||||
|
height=None):
|
||||||
|
"""
|
||||||
|
Add a minimum area retcangle at the given point.
|
||||||
|
Either width or height should be fixed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
min_area = drc("minarea_{}".format(layer))
|
||||||
|
if min_area == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
min_width = drc("minwidth_{}".format(layer))
|
||||||
|
|
||||||
|
if preferred_directions[layer] == "V":
|
||||||
|
height = max(min_area / width, min_width)
|
||||||
|
else:
|
||||||
|
width = max(min_area / height, min_width)
|
||||||
|
|
||||||
|
self.add_rect_center(layer=layer,
|
||||||
|
offset=offset,
|
||||||
|
width=width,
|
||||||
|
height=height)
|
||||||
|
|
||||||
def add_ptx(self, offset, mirror="R0", rotate=0, width=1, mults=1, tx_type="nmos"):
|
def add_ptx(self, offset, mirror="R0", rotate=0, width=1, mults=1, tx_type="nmos"):
|
||||||
"""Adds a ptx module to the design."""
|
"""Adds a ptx module to the design."""
|
||||||
import ptx
|
import ptx
|
||||||
|
|
@ -1181,12 +1173,8 @@ class layout():
|
||||||
self.add_path(layer,
|
self.add_path(layer,
|
||||||
[pin_loc, peri_pin_loc])
|
[pin_loc, peri_pin_loc])
|
||||||
|
|
||||||
self.add_via_stack_center(from_layer=layer,
|
|
||||||
to_layer="m4",
|
|
||||||
offset=peri_pin_loc)
|
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text=name,
|
self.add_layout_pin_rect_center(text=name,
|
||||||
layer="m4",
|
layer=layer,
|
||||||
offset=peri_pin_loc)
|
offset=peri_pin_loc)
|
||||||
|
|
||||||
def add_power_ring(self, bbox):
|
def add_power_ring(self, bbox):
|
||||||
|
|
|
||||||
|
|
@ -160,11 +160,11 @@ class pwrite_driver(design.design):
|
||||||
track_xoff = self.get_m2_track(1)
|
track_xoff = self.get_m2_track(1)
|
||||||
|
|
||||||
din_loc = self.din_inst.get_pin("A").center()
|
din_loc = self.din_inst.get_pin("A").center()
|
||||||
self.add_via_stack("m1", "m2", din_loc)
|
self.add_via_stack_center("m1", "m2", din_loc)
|
||||||
din_track = vector(track_xoff,din_loc.y)
|
din_track = vector(track_xoff,din_loc.y)
|
||||||
|
|
||||||
br_in = self.br_inst.get_pin("in").center()
|
br_in = self.br_inst.get_pin("in").center()
|
||||||
self.add_via_stack("m1", "m2", br_in)
|
self.add_via_stack_center("m1", "m2", br_in)
|
||||||
br_track = vector(track_xoff,br_in.y)
|
br_track = vector(track_xoff,br_in.y)
|
||||||
|
|
||||||
din_in = vector(track_xoff,0)
|
din_in = vector(track_xoff,0)
|
||||||
|
|
@ -181,11 +181,11 @@ class pwrite_driver(design.design):
|
||||||
track_xoff = self.get_m4_track(self.din_bar_track)
|
track_xoff = self.get_m4_track(self.din_bar_track)
|
||||||
|
|
||||||
din_bar_in = self.din_inst.get_pin("Z").center()
|
din_bar_in = self.din_inst.get_pin("Z").center()
|
||||||
self.add_via_stack("m1", "m3", din_bar_in)
|
self.add_via_stack_center("m1", "m3", din_bar_in)
|
||||||
din_bar_track = vector(track_xoff,din_bar_in.y)
|
din_bar_track = vector(track_xoff,din_bar_in.y)
|
||||||
|
|
||||||
bl_in = self.bl_inst.get_pin("in").center()
|
bl_in = self.bl_inst.get_pin("in").center()
|
||||||
self.add_via_stack("m1", "m3", bl_in)
|
self.add_via_stack_center("m1", "m3", bl_in)
|
||||||
bl_track = vector(track_xoff,bl_in.y)
|
bl_track = vector(track_xoff,bl_in.y)
|
||||||
|
|
||||||
din_in = vector(track_xoff,0)
|
din_in = vector(track_xoff,0)
|
||||||
|
|
@ -204,15 +204,15 @@ class pwrite_driver(design.design):
|
||||||
# This M2 pitch is a hack since the A and Z pins align horizontally
|
# This M2 pitch is a hack since the A and Z pins align horizontally
|
||||||
en_bar_loc = self.en_inst.get_pin("Z").uc()
|
en_bar_loc = self.en_inst.get_pin("Z").uc()
|
||||||
en_bar_track = vector(track_xoff, en_bar_loc.y)
|
en_bar_track = vector(track_xoff, en_bar_loc.y)
|
||||||
self.add_via_stack("m1", "m3", en_bar_loc)
|
self.add_via_stack_center("m1", "m3", en_bar_loc)
|
||||||
|
|
||||||
# This is a U route to the right down then left
|
# This is a U route to the right down then left
|
||||||
bl_en_loc = self.bl_inst.get_pin("en_bar").center()
|
bl_en_loc = self.bl_inst.get_pin("en_bar").center()
|
||||||
bl_en_track = vector(track_xoff, bl_en_loc.y)
|
bl_en_track = vector(track_xoff, bl_en_loc.y)
|
||||||
self.add_via_stack("m1", "m3", bl_en_loc)
|
self.add_via_stack_center("m1", "m3", bl_en_loc)
|
||||||
br_en_loc = self.br_inst.get_pin("en_bar").center()
|
br_en_loc = self.br_inst.get_pin("en_bar").center()
|
||||||
br_en_track = vector(track_xoff, bl_en_loc.y)
|
br_en_track = vector(track_xoff, bl_en_loc.y)
|
||||||
self.add_via_stack("m1", "m3", br_en_loc)
|
self.add_via_stack_center("m1", "m3", br_en_loc)
|
||||||
|
|
||||||
|
|
||||||
# L shape
|
# L shape
|
||||||
|
|
@ -237,21 +237,21 @@ class pwrite_driver(design.design):
|
||||||
|
|
||||||
en_loc = self.en_inst.get_pin("A").center()
|
en_loc = self.en_inst.get_pin("A").center()
|
||||||
en_rail = vector(en_loc.x, vdd_yloc)
|
en_rail = vector(en_loc.x, vdd_yloc)
|
||||||
self.add_via_stack("m1", "m2", en_loc)
|
self.add_via_stack_center("m1", "m2", en_loc)
|
||||||
self.add_path("m2", [en_loc, en_rail])
|
self.add_path("m2", [en_loc, en_rail])
|
||||||
self.add_via_stack("m2", "m3", en_rail)
|
self.add_via_stack_center("m2", "m3", en_rail)
|
||||||
|
|
||||||
# Start point in the track on the pin rail
|
# Start point in the track on the pin rail
|
||||||
en_track = vector(track_xoff, vdd_yloc)
|
en_track = vector(track_xoff, vdd_yloc)
|
||||||
self.add_via_stack("m3", "m4", en_track)
|
self.add_via_stack_center("m3", "m4", en_track)
|
||||||
|
|
||||||
# This is a U route to the right down then left
|
# This is a U route to the right down then left
|
||||||
bl_en_loc = self.bl_inst.get_pin("en").center()
|
bl_en_loc = self.bl_inst.get_pin("en").center()
|
||||||
bl_en_track = vector(track_xoff, bl_en_loc.y)
|
bl_en_track = vector(track_xoff, bl_en_loc.y)
|
||||||
self.add_via_stack("m1", "m3", bl_en_loc)
|
self.add_via_stack_center("m1", "m3", bl_en_loc)
|
||||||
br_en_loc = self.br_inst.get_pin("en").center()
|
br_en_loc = self.br_inst.get_pin("en").center()
|
||||||
br_en_track = vector(track_xoff, bl_en_loc.y)
|
br_en_track = vector(track_xoff, bl_en_loc.y)
|
||||||
self.add_via_stack("m1", "m3", br_en_loc)
|
self.add_via_stack_center("m1", "m3", br_en_loc)
|
||||||
|
|
||||||
# U shape
|
# U shape
|
||||||
self.add_wire(self.m3_stack,
|
self.add_wire(self.m3_stack,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue