Port address with vertical power stripes

This commit is contained in:
mrg 2022-03-02 16:29:43 -08:00
parent 4fac069c3c
commit 51ba88d896
5 changed files with 89 additions and 69 deletions

View File

@ -422,25 +422,36 @@ class layout():
for pin_name in self.pin_map.keys():
self.copy_layout_pin(instance, pin_name, prefix + pin_name)
def route_vertical_pins(self, name, layer=None):
def route_vertical_pins(self, name, insts=None, layer=None, side=None):
"""
Route together all of the pins of a given name that vertically align.
Uses local_insts if insts not specified.
Uses center of pin by default, or right or left if specified.
"""
bins = {}
if not insts:
insts = self.local_insts
for i in range(len(self.local_insts)):
inst = self.local_insts[i]
for inst in insts:
for pin in inst.get_pins(name):
if side == "right":
x = pin.rx()
elif side == "left":
x = pin.lx()
else:
x = pin.cx()
try:
bins[pin.cx()].append((inst,pin))
bins[x].append((inst,pin))
except KeyError:
bins[pin.cx()] = [(inst,pin)]
bins[x] = [(inst,pin)]
for x, v in bins.items():
bot_x = min([inst.by() for (inst,pin) in v])
top_x = max([inst.uy() for (inst,pin) in v])
bot_y = min([inst.by() for (inst,pin) in v])
top_y = max([inst.uy() for (inst,pin) in v])
last_via = None
for inst,pin in v:
@ -450,7 +461,7 @@ class layout():
pin_layer = self.supply_stack[2]
last_via = self.add_via_stack_center(from_layer=pin.layer,
to_layer=pin_layer,
offset=pin.center(),
offset=vector(x, pin.cy()),
min_area=True)
if last_via:
@ -464,21 +475,31 @@ class layout():
end=vector(x, top_y),
width=via_width)
def route_horizontal_pins(self, name, layer=None):
def route_horizontal_pins(self, name, insts=None, layer=None, side=None):
"""
Route together all of the pins of a given name that horizontally align.
Uses local_insts if insts not specified.
Uses center of pin by default, or top or botom if specified.
"""
bins = {}
if not insts:
insts = self.local_insts
for i in range(len(self.local_insts)):
inst = self.local_insts[i]
for inst in insts:
for pin in inst.get_pins(name):
if side == "top":
y = pin.uy()
elif side == "bottom":
y = pin.by()
else:
y = pin.cy()
try:
bins[pin.cy()].append((inst,pin))
bins[y].append((inst,pin))
except KeyError:
bins[pin.cy()] = [(inst,pin)]
bins[y] = [(inst,pin)]
for y, v in bins.items():
left_x = min([inst.lx() for (inst,pin) in v])
@ -492,7 +513,7 @@ class layout():
pin_layer = self.supply_stack[0]
last_via = self.add_via_stack_center(from_layer=pin.layer,
to_layer=pin_layer,
offset=pin.center(),
offset=vector(pin.cx(), y),
min_area=True)
if last_via:

View File

@ -28,6 +28,7 @@ class hierarchical_decoder(design.design):
self.pre2x4_inst = []
self.pre3x8_inst = []
self.pre4x16_inst = []
self.local_insts = []
b = factory.create(module_type=OPTS.bitcell)
self.cell_height = b.height
@ -57,11 +58,12 @@ class hierarchical_decoder(design.design):
self.route_inputs()
self.route_outputs()
self.route_decoder_bus()
self.route_vdd_gnd()
self.offset_x_coordinates()
self.width = self.and_inst[0].rx() + 0.5 * self.m1_width
self.width = self.and_inst[0].rx()
self.route_vdd_gnd()
self.add_boundary()
self.DRC_LVS()
@ -188,7 +190,7 @@ class hierarchical_decoder(design.design):
self.output_layer_pitch = getattr(self, self.output_layer + "_pitch")
# Two extra pitches between modules on left and right
self.internal_routing_width = self.total_number_of_predecoder_outputs * self.bus_pitch + self.bus_pitch
self.internal_routing_width = self.total_number_of_predecoder_outputs * self.bus_pitch + 2 * self.bus_pitch
self.row_decoder_height = self.and2.height * self.num_outputs
# Extra bus space for supply contacts
@ -592,8 +594,13 @@ class hierarchical_decoder(design.design):
Add a pin for each row of vdd/gnd which are
must-connects next level up.
"""
if layer_props.hierarchical_decoder.vertical_supply:
pre_insts = self.pre2x4_inst + self.pre3x8_inst + self.pre4x16_inst
self.route_vertical_pins("vdd", insts=pre_insts)
self.route_vertical_pins("gnd", insts=pre_insts)
self.route_vertical_pins("vdd", insts=self.and_inst)
self.route_vertical_pins("gnd", insts=self.and_inst)
return
for n in ["vdd", "gnd"]:
pins = self.and_inst[0].get_pins(n)
for pin in pins:
@ -612,19 +619,20 @@ class hierarchical_decoder(design.design):
for i in self.pre2x4_inst + self.pre3x8_inst:
self.copy_layout_pin(i, n)
else:
# The vias will be placed at the right of the cells.
xoffset = max(x.rx() for x in self.and_inst) + 0.5 * self.m1_space
for row in range(0, self.num_outputs):
for pin_name in ["vdd", "gnd"]:
# The nand and inv are the same height rows...
supply_pin = self.and_inst[row].get_pin(pin_name)
pin_pos = vector(xoffset, supply_pin.cy())
self.copy_power_pin(supply_pin, loc=pin_pos)
pre_insts = self.pre2x4_inst + self.pre3x8_inst + self.pre4x16_inst
self.route_vertical_pins("vdd", insts=pre_insts)
self.route_vertical_pins("gnd", insts=pre_insts)
self.route_vertical_pins("vdd", insts=self.and_inst, side="right")
self.route_vertical_pins("gnd", insts=self.and_inst, side="left")
# Widen the rails to cover any gap
for inst in self.and_inst:
for name in ["vdd", "gnd"]:
supply_pin = inst.get_pin(name)
self.add_segment_center(layer=supply_pin.layer,
start=vector(0, supply_pin.cy()),
end=vector(self.width, supply_pin.cy()))
# Copy the pins from the predecoders
for pre in self.pre2x4_inst + self.pre3x8_inst + self.pre4x16_inst:
for pin_name in ["vdd", "gnd"]:
self.copy_layout_pin(pre, pin_name)
def route_predecode_bus_outputs(self, rail_name, pin, row):
"""

View File

@ -413,7 +413,9 @@ class hierarchical_predecode(design.design):
end=vector(self.width, and_pin.cy()))
# Add pins in two locations
for xoffset in [self.inv_inst[0].lx() - self.bus_space,
self.and_inst[0].lx() - self.bus_space]:
pin_pos = vector(xoffset, and_pin.cy())
self.copy_power_pin(and_pin, loc=pin_pos)
if n == "vdd":
xoffset = self.and_inst[0].lx() - self.bus_space
else:
xoffset = self.inv_inst[0].lx() - self.bus_space
pin_pos = vector(xoffset, and_pin.cy())
self.copy_power_pin(and_pin, loc=pin_pos)

View File

@ -77,8 +77,8 @@ class port_address(design.design):
def route_supplies(self):
""" Propagate all vdd/gnd pins up to this level for all modules """
for inst in [self.wordline_driver_array_inst, self.row_decoder_inst]:
self.copy_power_pins(inst, "vdd")
self.copy_power_pins(inst, "gnd")
self.copy_layout_pin(inst, "vdd")
self.copy_layout_pin(inst, "gnd")
for rbl_vdd_pin in self.rbl_driver_inst.get_pins("vdd"):
if layer_props.port_address.supply_offset:

View File

@ -44,9 +44,9 @@ class wordline_driver_array(design.design):
self.route_layer = "m1"
self.place_drivers()
self.route_layout()
self.route_vdd_gnd()
self.offset_x_coordinates()
self.add_boundary()
self.route_vdd_gnd()
self.DRC_LVS()
def add_pins(self):
@ -67,35 +67,23 @@ class wordline_driver_array(design.design):
def route_vdd_gnd(self):
"""
Add a pin for each row of vdd/gnd which
are must-connects next level up.
Add vertical power rails.
"""
if layer_props.wordline_driver.vertical_supply:
for name in ["vdd", "gnd"]:
supply_pins = self.wld_inst[0].get_pins(name)
for pin in supply_pins:
self.add_layout_pin_segment_center(text=name,
layer=pin.layer,
start=pin.bc(),
end=vector(pin.cx(), self.height))
self.route_vertical_pins("vdd", insts=self.wld_inst)
self.route_vertical_pins("gnd", insts=self.wld_inst)
else:
# Find the x offsets for where the vias/pins should be placed
xoffset_list = [self.wld_inst[0].rx()]
for num in range(self.rows):
# this will result in duplicate polygons for rails, but who cares
self.route_vertical_pins("vdd", insts=self.wld_inst, side="left")
self.route_vertical_pins("gnd", insts=self.wld_inst, side="right")
# use the inverter offset even though it will be the and's too
(gate_offset, y_dir) = self.get_gate_offset(0,
self.wl_driver.height,
num)
# Route both supplies
# Widen the rails to cover any gap
for num in range(self.rows):
for name in ["vdd", "gnd"]:
supply_pin = self.wld_inst[num].get_pin(name)
self.add_segment_center(layer=supply_pin.layer,
start=vector(0, supply_pin.cy()),
end=vector(self.width, supply_pin.cy()))
# Add pins in two locations
for xoffset in xoffset_list:
pin_pos = vector(xoffset, supply_pin.cy())
self.copy_power_pin(supply_pin, loc=pin_pos)
def create_drivers(self):
self.wld_inst = []
@ -105,8 +93,8 @@ class wordline_driver_array(design.design):
# add and2
self.wld_inst.append(self.add_inst(name=name_and,
mod=self.wl_driver))
self.connect_inst(["in_{0}".format(row),
"en",
self.connect_inst(["en",
"in_{0}".format(row),
"wl_{0}".format(row),
"vdd", "gnd"])
@ -135,24 +123,25 @@ class wordline_driver_array(design.design):
""" Route all of the signals """
# Wordline enable connection
en_pin = self.wld_inst[0].get_pin("B")
en_bottom_pos = vector(en_pin.lx(), 0)
en_pin = self.add_layout_pin(text="en",
layer="m2",
offset=en_bottom_pos,
height=self.height)
en_pin = self.wld_inst[0].get_pin("A")
en_bottom_pos = vector(en_pin.cx(), 0)
en_top_pos = vector(en_pin.cx(), self.height)
en_pin = self.add_layout_pin_segment_center(text="en",
layer="m2",
start=en_bottom_pos,
end=en_top_pos)
for row in range(self.rows):
and_inst = self.wld_inst[row]
# Drop a via
b_pin = and_inst.get_pin("B")
b_pin = and_inst.get_pin("A")
self.add_via_stack_center(from_layer=b_pin.layer,
to_layer="m2",
offset=b_pin.center())
# connect the decoder input pin to and2 A
self.copy_layout_pin(and_inst, "A", "in_{0}".format(row))
self.copy_layout_pin(and_inst, "B", "in_{0}".format(row))
# output each WL on the right
wl_offset = and_inst.get_pin("Z").rc()