mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-08-29 09:30:38 +02:00
Power routing changes.
Make the power rails an "experimental_power" option and conditional. Rename route_vdd_gnd to route_supplies everywhere for consistency.
This commit is contained in:
@@ -63,7 +63,7 @@ class hierarchical_decoder(design.design):
|
||||
|
||||
self.width = self.and_inst[0].rx()
|
||||
|
||||
self.route_vdd_gnd()
|
||||
self.route_supplies()
|
||||
|
||||
self.add_boundary()
|
||||
self.DRC_LVS()
|
||||
@@ -589,50 +589,67 @@ class hierarchical_decoder(design.design):
|
||||
output_index)
|
||||
output_index = output_index + 1
|
||||
|
||||
def route_vdd_gnd(self):
|
||||
def route_supplies(self):
|
||||
"""
|
||||
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, yside="by")
|
||||
self.route_vertical_pins("gnd", insts=pre_insts, yside="by")
|
||||
self.route_vertical_pins("vdd", insts=self.and_inst, yside="by")
|
||||
self.route_vertical_pins("gnd", insts=self.and_inst, yside="by")
|
||||
return
|
||||
for n in ["vdd", "gnd"]:
|
||||
pins = self.and_inst[0].get_pins(n)
|
||||
for pin in pins:
|
||||
self.add_rect(layer=pin.layer,
|
||||
offset=pin.ll() + vector(0, self.bus_space),
|
||||
width=pin.width(),
|
||||
height=self.height - 2 * self.bus_space)
|
||||
|
||||
# This adds power vias at the top of each cell
|
||||
# (except the last to keep them inside the boundary)
|
||||
for i in self.and_inst[:-1]:
|
||||
pins = i.get_pins(n)
|
||||
for pin in pins:
|
||||
self.copy_power_pin(pin, loc=pin.uc())
|
||||
# This is an experiment with power rails
|
||||
if OPTS.experimental_power:
|
||||
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, yside="by")
|
||||
self.route_vertical_pins("gnd", insts=pre_insts, yside="by")
|
||||
self.route_vertical_pins("vdd", insts=self.and_inst, yside="by")
|
||||
self.route_vertical_pins("gnd", insts=self.and_inst, yside="by")
|
||||
else:
|
||||
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, xside="rx")
|
||||
self.route_vertical_pins("gnd", insts=self.and_inst, xside="lx")
|
||||
|
||||
for i in self.pre2x4_inst + self.pre3x8_inst:
|
||||
self.copy_layout_pin(i, n)
|
||||
# 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()))
|
||||
else:
|
||||
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, xside="rx")
|
||||
self.route_vertical_pins("gnd", insts=self.and_inst, xside="lx")
|
||||
if layer_props.hierarchical_decoder.vertical_supply:
|
||||
for n in ["vdd", "gnd"]:
|
||||
pins = self.and_inst[0].get_pins(n)
|
||||
for pin in pins:
|
||||
self.add_rect(layer=pin.layer,
|
||||
offset=pin.ll() + vector(0, self.bus_space),
|
||||
width=pin.width(),
|
||||
height=self.height - 2 * self.bus_space)
|
||||
|
||||
# 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()))
|
||||
# This adds power vias at the top of each cell
|
||||
# (except the last to keep them inside the boundary)
|
||||
for i in self.and_inst[:-1]:
|
||||
pins = i.get_pins(n)
|
||||
for pin in pins:
|
||||
self.copy_power_pin(pin, loc=pin.uc())
|
||||
|
||||
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)
|
||||
|
||||
# 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):
|
||||
"""
|
||||
|
||||
@@ -189,7 +189,7 @@ class hierarchical_predecode(design.design):
|
||||
self.route_output_inverters()
|
||||
self.route_inputs_to_rails()
|
||||
self.route_output_ands()
|
||||
self.route_vdd_gnd()
|
||||
self.route_supplies()
|
||||
|
||||
def route_inputs_to_rails(self):
|
||||
""" Route the uninverted inputs to the second set of rails """
|
||||
@@ -378,7 +378,7 @@ class hierarchical_predecode(design.design):
|
||||
offset=pin_pos,
|
||||
directions=direction)
|
||||
|
||||
def route_vdd_gnd(self):
|
||||
def route_supplies(self):
|
||||
""" Add a pin for each row of vdd/gnd which are must-connects next level up. """
|
||||
|
||||
# We may ahve vertical power supply rails
|
||||
|
||||
@@ -230,7 +230,7 @@ class port_address(design.design):
|
||||
|
||||
# This m4_pitch corresponds to the offset space for jog routing in the
|
||||
# wordline_driver_array
|
||||
rbl_driver_offset = wordline_driver_array_offset + vector(self.m4_pitch, 0)
|
||||
rbl_driver_offset = wordline_driver_array_offset + vector(2 * self.m4_pitch, 0)
|
||||
|
||||
if self.port == 0:
|
||||
self.rbl_driver_inst.place(rbl_driver_offset, "MX")
|
||||
|
||||
@@ -68,6 +68,7 @@ class precharge_array(design.design):
|
||||
self.height = self.pc_cell.height
|
||||
|
||||
self.add_layout_pins()
|
||||
self.route_supplies()
|
||||
self.add_boundary()
|
||||
self.DRC_LVS()
|
||||
|
||||
@@ -81,14 +82,24 @@ class precharge_array(design.design):
|
||||
|
||||
def add_layout_pins(self):
|
||||
|
||||
en_pin = self.pc_cell.get_pin("en_bar")
|
||||
self.route_horizontal_pins("en_bar", layer=self.en_bar_layer)
|
||||
self.route_horizontal_pins("vdd")
|
||||
for inst in self.local_insts:
|
||||
self.add_via_stack_center(from_layer=en_pin.layer,
|
||||
to_layer=self.en_bar_layer,
|
||||
offset=inst.get_pin("en_bar").center())
|
||||
|
||||
for i in range(len(self.local_insts)):
|
||||
inst = self.local_insts[i]
|
||||
self.copy_layout_pin(inst, "bl", "bl_{0}".format(i))
|
||||
self.copy_layout_pin(inst, "br", "br_{0}".format(i))
|
||||
|
||||
def route_supplies(self):
|
||||
if OPTS.experimental_power:
|
||||
self.route_horizontal_pins("vdd")
|
||||
else:
|
||||
for inst in self.local_insts:
|
||||
self.copy_layout_pin(inst, "vdd")
|
||||
|
||||
def create_insts(self):
|
||||
"""Creates a precharge array by horizontally tiling the precharge cell"""
|
||||
|
||||
@@ -462,20 +462,33 @@ class replica_bitcell_array(bitcell_base_array):
|
||||
# replica column should only have a vdd/gnd in the dummy cell on top/bottom
|
||||
supply_insts = self.dummy_col_insts + self.dummy_row_insts
|
||||
|
||||
for pin_name in self.supplies:
|
||||
#self.route_vertical_pins(name=pin_name, insts=supply_insts)
|
||||
self.route_horizontal_pins(name=pin_name, insts=supply_insts)
|
||||
|
||||
#self.route_vertical_pins(name=pin_name, insts=self.replica_col_insts)
|
||||
#self.route_horizontal_pins(name=pin_name, insts=self.replica_col_insts)
|
||||
for inst in supply_insts:
|
||||
pin_list = inst.get_pins(pin_name)
|
||||
for pin in pin_list:
|
||||
self.copy_power_pin(pin)
|
||||
if OPTS.experimental_power:
|
||||
for pin_name in self.supplies:
|
||||
#self.route_vertical_pins(name=pin_name, insts=supply_insts)
|
||||
self.route_horizontal_pins(name=pin_name, insts=supply_insts)
|
||||
|
||||
#self.route_vertical_pins(name=pin_name, insts=self.replica_col_insts)
|
||||
#self.route_horizontal_pins(name=pin_name, insts=self.replica_col_insts)
|
||||
for inst in supply_insts:
|
||||
pin_list = inst.get_pins(pin_name)
|
||||
for pin in pin_list:
|
||||
self.copy_power_pin(pin)
|
||||
|
||||
for inst in self.replica_col_insts:
|
||||
if inst:
|
||||
self.copy_layout_pin(inst, pin_name)
|
||||
else:
|
||||
for pin_name in self.supplies:
|
||||
for inst in supply_insts:
|
||||
pin_list = inst.get_pins(pin_name)
|
||||
for pin in pin_list:
|
||||
self.copy_power_pin(pin)
|
||||
|
||||
for inst in self.replica_col_insts:
|
||||
if inst:
|
||||
self.copy_layout_pin(inst, pin_name)
|
||||
|
||||
for inst in self.replica_col_insts:
|
||||
if inst:
|
||||
self.copy_layout_pin(inst, pin_name)
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Power of Bitcell array and bitline in nW."""
|
||||
|
||||
@@ -75,8 +75,8 @@ class sense_amp_array(design.design):
|
||||
self.width = self.local_insts[-1].rx()
|
||||
|
||||
self.add_layout_pins()
|
||||
self.route_horizontal_pins("vdd")
|
||||
self.route_horizontal_pins("gnd")
|
||||
|
||||
self.route_supplies()
|
||||
self.route_rails()
|
||||
|
||||
self.add_boundary()
|
||||
@@ -173,6 +173,20 @@ class sense_amp_array(design.design):
|
||||
width=dout_pin.width(),
|
||||
height=dout_pin.height())
|
||||
|
||||
def route_supplies(self):
|
||||
if OPTS.experimental_power:
|
||||
self.route_horizontal_pins("vdd")
|
||||
self.route_horizontal_pins("gnd")
|
||||
else:
|
||||
for i in range(len(self.local_insts)):
|
||||
inst = self.local_insts[i]
|
||||
|
||||
for gnd_pin in inst.get_pins("gnd"):
|
||||
self.copy_power_pin(gnd_pin)
|
||||
|
||||
for vdd_pin in inst.get_pins("vdd"):
|
||||
self.copy_power_pin(vdd_pin)
|
||||
|
||||
def route_rails(self):
|
||||
# Add enable across the array
|
||||
en_pin = self.amp.get_pin(self.amp.en_name)
|
||||
|
||||
@@ -45,7 +45,7 @@ class wordline_driver_array(design.design):
|
||||
|
||||
self.place_drivers()
|
||||
self.route_layout()
|
||||
self.offset_x_coordinates(vector(-self.m4_pitch, 0))
|
||||
self.offset_x_coordinates(vector(-2*self.m4_pitch, 0))
|
||||
|
||||
# Leave a well gap to separate the bitcell array well from this well
|
||||
well_gap = 2 * drc("pwell_to_nwell") + drc("nwell_enclose_active")
|
||||
@@ -76,20 +76,50 @@ class wordline_driver_array(design.design):
|
||||
"""
|
||||
Add vertical power rails.
|
||||
"""
|
||||
if layer_props.wordline_driver.vertical_supply:
|
||||
self.route_vertical_pins("vdd", insts=self.wld_inst)
|
||||
self.route_vertical_pins("gnd", insts=self.wld_inst)
|
||||
else:
|
||||
self.route_vertical_pins("vdd", insts=self.wld_inst, xside="lx")
|
||||
self.route_vertical_pins("gnd", insts=self.wld_inst, xside="rx")
|
||||
|
||||
# Widen the rails to cover any gap
|
||||
for num in range(self.rows):
|
||||
# Experiment with power straps
|
||||
if OPTS.experimental_power:
|
||||
if layer_props.wordline_driver.vertical_supply:
|
||||
self.route_vertical_pins("vdd", insts=self.wld_inst)
|
||||
self.route_vertical_pins("gnd", insts=self.wld_inst)
|
||||
else:
|
||||
self.route_vertical_pins("vdd", insts=self.wld_inst, xside="lx")
|
||||
self.route_vertical_pins("gnd", insts=self.wld_inst, xside="rx")
|
||||
|
||||
# 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()))
|
||||
else:
|
||||
if layer_props.wordline_driver.vertical_supply:
|
||||
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()))
|
||||
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))
|
||||
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
|
||||
|
||||
# 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
|
||||
for name in ["vdd", "gnd"]:
|
||||
supply_pin = self.wld_inst[num].get_pin(name)
|
||||
|
||||
# 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):
|
||||
|
||||
@@ -72,6 +72,7 @@ class write_driver_array(design.design):
|
||||
self.width = self.local_insts[-1].rx()
|
||||
self.height = self.driver.height
|
||||
self.add_layout_pins()
|
||||
self.route_supplies()
|
||||
self.add_boundary()
|
||||
self.DRC_LVS()
|
||||
|
||||
@@ -204,9 +205,6 @@ class write_driver_array(design.design):
|
||||
width=br_pin.width(),
|
||||
height=br_pin.height())
|
||||
|
||||
self.route_horizontal_pins("vdd")
|
||||
self.route_horizontal_pins("gnd")
|
||||
|
||||
if self.write_size:
|
||||
for bit in range(self.num_wmasks):
|
||||
inst = self.local_insts[bit * self.write_size]
|
||||
@@ -256,3 +254,17 @@ class write_driver_array(design.design):
|
||||
layer="m1",
|
||||
offset=inst.get_pin(inst.mod.en_name).ll().scale(0, 1),
|
||||
width=self.width)
|
||||
|
||||
def route_supplies(self):
|
||||
if OPTS.experimental_power:
|
||||
self.route_horizontal_pins("vdd")
|
||||
self.route_horizontal_pins("gnd")
|
||||
else:
|
||||
for i in range(self.word_size + self.num_spare_cols):
|
||||
inst = self.local_insts[i]
|
||||
for n in ["vdd", "gnd"]:
|
||||
pin_list = inst.get_pins(n)
|
||||
for pin in pin_list:
|
||||
self.copy_power_pin(pin, directions=("V", "V"))
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user