mirror of https://github.com/VLSIDA/OpenRAM.git
Port address with vertical power stripes
This commit is contained in:
parent
4fac069c3c
commit
51ba88d896
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Reference in New Issue