Add input pin rails to hierarchical decoder for easier connections at SRAM level.

This commit is contained in:
Matt Guthaus 2018-07-09 13:16:38 -07:00
parent 5cf62e82cf
commit e60d157310
1 changed files with 83 additions and 42 deletions

View File

@ -45,7 +45,8 @@ class hierarchical_decoder(design.design):
self.add_pins() self.add_pins()
self.create_pre_decoder() self.create_pre_decoder()
self.create_row_decoder() self.create_row_decoder()
self.create_vertical_rail() self.create_input_rail()
self.create_predecode_rail()
self.route_vdd_gnd() self.route_vdd_gnd()
def add_modules(self): def add_modules(self):
@ -89,6 +90,7 @@ class hierarchical_decoder(design.design):
debug.error("Invalid number of inputs for hierarchical decoder",-1) debug.error("Invalid number of inputs for hierarchical decoder",-1)
def setup_layout_constants(self): def setup_layout_constants(self):
self.m1_pitch = contact.m1m2.height + max(self.m1_space,self.m2_space)
self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space) self.m2_pitch = contact.m2m3.height + max(self.m2_space,self.m3_space)
self.predec_groups = [] # This array is a 2D array. self.predec_groups = [] # This array is a 2D array.
@ -115,7 +117,77 @@ class hierarchical_decoder(design.design):
self.calculate_dimensions() self.calculate_dimensions()
def create_input_rail(self):
""" Create input rails for the predecoders """
# input bus width plus a spacing track
input_width = (self.num_inputs+1) * self.m2_pitch
# inputs should be as high as the decoders
input_height = self.no_of_pre2x4*self.pre2_4.height + self.no_of_pre2x4*self.pre3_8.height
# Find the left-most predecoder
min_x = 0
if self.no_of_pre2x4 > 0:
min_x = min(min_x, -self.pre2_4.width)
if self.no_of_pre3x8 > 0:
min_x = min(min_x, -self.pre3_8.width)
for i in range(self.num_inputs):
x_offset = min_x - input_width + i*self.m2_pitch
pin_offset = vector(x_offset,0)
self.add_layout_pin(text="A[{0}]".format(i),
layer="metal2",
offset=vector(x_offset,0),
height=input_height)
self.connect_input_to_predecodes()
def connect_input_to_predecodes(self):
""" Connect the vertical input rail to the predecoders """
for pre_num in range(self.no_of_pre2x4):
for i in range(2):
index = pre_num * 2 + i
input_pin = self.get_pin("A[{}]".format(index))
in_name = "in[{}]".format(i)
decoder_pin = self.pre2x4_inst[pre_num].get_pin(in_name)
# Offset each decoder pin up so they don't conflit
decoder_offset = decoder_pin.center() + vector(0,i*self.m2_pitch)
input_offset = input_pin.center().scale(1,0) + decoder_offset.scale(0,1)
self.connect_input_rail(decoder_offset, input_offset)
for pre_num in range(self.no_of_pre3x8):
for i in range(3):
index = pre_num * 3 + i + self.no_of_pre2x4 * 2
input_pin = self.get_pin("A[{}]".format(index))
in_name = "in[{}]".format(i)
decoder_pin = self.pre3x8_inst[pre_num].get_pin(in_name)
# Offset each decoder pin up so they don't conflit
decoder_offset = decoder_pin.center() + vector(0,i*self.m2_pitch)
input_offset = input_pin.center().scale(1,0) + decoder_offset.scale(0,1)
self.connect_input_rail(decoder_offset, input_offset)
def connect_input_rail(self, input_offset, output_offset):
""" Connect a vertical M2 coordinate to another vertical M2 coordinate to the predecode inputs """
self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=input_offset,
rotate=90)
self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=output_offset,
rotate=90)
self.add_path(("metal3"), [input_offset, output_offset])
def add_pins(self): def add_pins(self):
""" Add the module pins """ """ Add the module pins """
@ -189,23 +261,6 @@ class hierarchical_decoder(design.design):
offset=base)) offset=base))
self.connect_inst(pins) self.connect_inst(pins)
self.add_pre2x4_pins(num)
def add_pre2x4_pins(self,num):
""" Add the input pins to the 2x4 predecoder """
for i in range(2):
pin = self.pre2x4_inst[num].get_pin("in[{}]".format(i))
pin_offset = pin.ll()
pin = self.pre2_4.get_pin("in[{}]".format(i))
self.add_layout_pin(text="A[{0}]".format(i + 2*num ),
layer="metal2",
offset=pin_offset,
width=pin.width(),
height=pin.height())
def add_pre3x8(self,num): def add_pre3x8(self,num):
""" Add 3x8 predecoder to the left of the origin and above any 2x4 decoders """ """ Add 3x8 predecoder to the left of the origin and above any 2x4 decoders """
@ -233,20 +288,6 @@ class hierarchical_decoder(design.design):
offset=offset)) offset=offset))
self.connect_inst(pins) self.connect_inst(pins)
# The 3x8 predecoders will be stacked, so use yoffset
self.add_pre3x8_pins(num,offset)
def add_pre3x8_pins(self,num,offset):
""" Add the input pins to the 3x8 predecoder at the given offset """
for i in range(3):
pin = self.pre3x8_inst[num].get_pin("in[{}]".format(i))
pin_offset = pin.ll()
self.add_layout_pin(text="A[{0}]".format(i + 3*num + 2*self.no_of_pre2x4),
layer="metal2",
offset=pin_offset,
width=pin.width(),
height=pin.height())
@ -372,7 +413,7 @@ class hierarchical_decoder(design.design):
def create_vertical_rail(self): def create_predecode_rail(self):
""" Creates vertical metal 2 rails to connect predecoder and decoder stages.""" """ Creates vertical metal 2 rails to connect predecoder and decoder stages."""
# This is not needed for inputs <4 since they have no pre/decode stages. # This is not needed for inputs <4 since they have no pre/decode stages.
@ -401,7 +442,7 @@ class hierarchical_decoder(design.design):
index = pre_num * 4 + i index = pre_num * 4 + i
out_name = "out[{}]".format(i) out_name = "out[{}]".format(i)
pin = self.pre2x4_inst[pre_num].get_pin(out_name) pin = self.pre2x4_inst[pre_num].get_pin(out_name)
self.connect_rail_m3(index, pin) self.connect_predecode_rail_m3(index, pin)
for pre_num in range(self.no_of_pre3x8): for pre_num in range(self.no_of_pre3x8):
@ -409,7 +450,7 @@ class hierarchical_decoder(design.design):
index = pre_num * 8 + i + self.no_of_pre2x4 * 4 index = pre_num * 8 + i + self.no_of_pre2x4 * 4
out_name = "out[{}]".format(i) out_name = "out[{}]".format(i)
pin = self.pre3x8_inst[pre_num].get_pin(out_name) pin = self.pre3x8_inst[pre_num].get_pin(out_name)
self.connect_rail_m3(index, pin) self.connect_predecode_rail_m3(index, pin)
@ -425,17 +466,17 @@ class hierarchical_decoder(design.design):
if (self.num_inputs == 4 or self.num_inputs == 5): if (self.num_inputs == 4 or self.num_inputs == 5):
for index_A in self.predec_groups[0]: for index_A in self.predec_groups[0]:
for index_B in self.predec_groups[1]: for index_B in self.predec_groups[1]:
self.connect_rail(index_A, self.nand_inst[row_index].get_pin("A")) self.connect_predecode_rail(index_A, self.nand_inst[row_index].get_pin("A"))
self.connect_rail(index_B, self.nand_inst[row_index].get_pin("B")) self.connect_predecode_rail(index_B, self.nand_inst[row_index].get_pin("B"))
row_index = row_index + 1 row_index = row_index + 1
elif (self.num_inputs > 5): elif (self.num_inputs > 5):
for index_A in self.predec_groups[0]: for index_A in self.predec_groups[0]:
for index_B in self.predec_groups[1]: for index_B in self.predec_groups[1]:
for index_C in self.predec_groups[2]: for index_C in self.predec_groups[2]:
self.connect_rail(index_A, self.nand_inst[row_index].get_pin("A")) self.connect_predecode_rail(index_A, self.nand_inst[row_index].get_pin("A"))
self.connect_rail(index_B, self.nand_inst[row_index].get_pin("B")) self.connect_predecode_rail(index_B, self.nand_inst[row_index].get_pin("B"))
self.connect_rail(index_C, self.nand_inst[row_index].get_pin("C")) self.connect_predecode_rail(index_C, self.nand_inst[row_index].get_pin("C"))
row_index = row_index + 1 row_index = row_index + 1
def route_vdd_gnd(self): def route_vdd_gnd(self):
@ -471,7 +512,7 @@ class hierarchical_decoder(design.design):
self.copy_layout_pin(pre, "gnd") self.copy_layout_pin(pre, "gnd")
def connect_rail(self, rail_index, pin): def connect_predecode_rail(self, rail_index, pin):
""" Connect the routing rail to the given metal1 pin """ """ Connect the routing rail to the given metal1 pin """
rail_pos = vector(self.rail_x_offsets[rail_index],pin.lc().y) rail_pos = vector(self.rail_x_offsets[rail_index],pin.lc().y)
self.add_path("metal1", [rail_pos, pin.lc()]) self.add_path("metal1", [rail_pos, pin.lc()])
@ -480,7 +521,7 @@ class hierarchical_decoder(design.design):
rotate=90) rotate=90)
def connect_rail_m3(self, rail_index, pin): def connect_predecode_rail_m3(self, rail_index, pin):
""" Connect the routing rail to the given metal1 pin """ """ Connect the routing rail to the given metal1 pin """
mid_point = vector(pin.cx(), pin.cy()+self.inv.height/2) mid_point = vector(pin.cx(), pin.cy()+self.inv.height/2)
rail_pos = vector(self.rail_x_offsets[rail_index],mid_point.y) rail_pos = vector(self.rail_x_offsets[rail_index],mid_point.y)