Space hier decoder input connections along rails to avoid conflicts

This commit is contained in:
Matt Guthaus 2018-07-18 10:21:58 -07:00
parent b8e3629923
commit b8a3bc9b1a
1 changed files with 47 additions and 38 deletions

View File

@ -128,11 +128,11 @@ class hierarchical_decoder(design.design):
input_offset=vector(min_x - self.input_routing_width,0)
input_bus_names = ["A[{0}]".format(i) for i in range(self.num_inputs)]
self.create_vertical_pin_bus(layer="metal2",
pitch=self.m2_pitch,
offset=input_offset,
names=input_bus_names,
length=input_height)
self.input_rails = self.create_vertical_pin_bus(layer="metal2",
pitch=self.m2_pitch,
offset=input_offset,
names=input_bus_names,
length=input_height)
self.connect_input_to_predecodes()
@ -143,14 +143,15 @@ class hierarchical_decoder(design.design):
for i in range(2):
index = pre_num * 2 + i
input_pin = self.get_pin("A[{}]".format(index))
input_pos = self.input_rails["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)
# To prevent conflicts, we will offset each input connect so
# that it aligns with the vdd/gnd rails
decoder_offset = decoder_pin.bc() + vector(0,(i+1)*self.inv.height)
input_offset = input_pos.scale(1,0) + decoder_offset.scale(0,1)
self.connect_input_rail(decoder_offset, input_offset)
@ -159,14 +160,15 @@ class hierarchical_decoder(design.design):
for i in range(3):
index = pre_num * 3 + i + self.no_of_pre2x4 * 2
input_pin = self.get_pin("A[{}]".format(index))
input_pos = self.input_rails["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)
# To prevent conflicts, we will offset each input connect so
# that it aligns with the vdd/gnd rails
decoder_offset = decoder_pin.bc() + vector(0,(i+1)*self.inv.height)
input_offset = input_pos.scale(1,0) + decoder_offset.scale(0,1)
self.connect_input_rail(decoder_offset, input_offset)
@ -415,18 +417,14 @@ class hierarchical_decoder(design.design):
# This is not needed for inputs <4 since they have no pre/decode stages.
if (self.num_inputs >= 4):
# Array for saving the X offsets of the vertical rails. These rail
# offsets are accessed with indices.
self.rail_x_offsets = []
for i in range(self.total_number_of_predecoder_outputs):
# The offsets go into the negative x direction
# assuming the predecodes are placed at (self.internal_routing_width,0)
x_offset = self.m2_pitch * i
self.rail_x_offsets.append(x_offset+0.5*self.m2_width)
self.add_rect(layer="metal2",
offset=vector(x_offset,0),
width=drc["minwidth_metal2"],
height=self.height)
input_offset = vector(0.5*self.m2_width,0)
input_bus_names = ["predecode[{0}]".format(i) for i in range(self.total_number_of_predecoder_outputs)]
self.predecode_rails = self.create_vertical_pin_bus(layer="metal2",
pitch=self.m2_pitch,
offset=input_offset,
names=input_bus_names,
length=self.height)
self.connect_rails_to_predecodes()
self.connect_rails_to_decoder()
@ -434,20 +432,22 @@ class hierarchical_decoder(design.design):
def connect_rails_to_predecodes(self):
""" Iterates through all of the predecodes and connects to the rails including the offsets """
# FIXME: convert to connect_bus
for pre_num in range(self.no_of_pre2x4):
for i in range(4):
index = pre_num * 4 + i
predecode_name = "predecode[{}]".format(pre_num * 4 + i)
out_name = "out[{}]".format(i)
pin = self.pre2x4_inst[pre_num].get_pin(out_name)
self.connect_predecode_rail_m3(index, pin)
self.connect_predecode_rail_m3(predecode_name, pin)
# FIXME: convert to connect_bus
for pre_num in range(self.no_of_pre3x8):
for i in range(8):
index = pre_num * 8 + i + self.no_of_pre2x4 * 4
predecode_name = "predecode[{}]".format(pre_num * 8 + i + self.no_of_pre2x4 * 4)
out_name = "out[{}]".format(i)
pin = self.pre3x8_inst[pre_num].get_pin(out_name)
self.connect_predecode_rail_m3(index, pin)
self.connect_predecode_rail_m3(predecode_name, pin)
@ -463,17 +463,24 @@ class hierarchical_decoder(design.design):
if (self.num_inputs == 4 or self.num_inputs == 5):
for index_A in self.predec_groups[0]:
for index_B in self.predec_groups[1]:
self.connect_predecode_rail(index_A, self.nand_inst[row_index].get_pin("A"))
self.connect_predecode_rail(index_B, self.nand_inst[row_index].get_pin("B"))
# FIXME: convert to connect_bus?
predecode_name = "predecode[{}]".format(index_A)
self.connect_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("A"))
predecode_name = "predecode[{}]".format(index_B)
self.connect_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("B"))
row_index = row_index + 1
elif (self.num_inputs > 5):
for index_A in self.predec_groups[0]:
for index_B in self.predec_groups[1]:
for index_C in self.predec_groups[2]:
self.connect_predecode_rail(index_A, self.nand_inst[row_index].get_pin("A"))
self.connect_predecode_rail(index_B, self.nand_inst[row_index].get_pin("B"))
self.connect_predecode_rail(index_C, self.nand_inst[row_index].get_pin("C"))
# FIXME: convert to connect_bus?
predecode_name = "predecode[{}]".format(index_A)
self.connect_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("A"))
predecode_name = "predecode[{}]".format(index_B)
self.connect_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("B"))
predecode_name = "predecode[{}]".format(index_C)
self.connect_predecode_rail(predecode_name, self.nand_inst[row_index].get_pin("C"))
row_index = row_index + 1
def route_vdd_gnd(self):
@ -509,19 +516,21 @@ class hierarchical_decoder(design.design):
self.copy_layout_pin(pre, "gnd")
def connect_predecode_rail(self, rail_index, pin):
def connect_predecode_rail(self, rail_name, 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.predecode_rails[rail_name].x,pin.lc().y)
self.add_path("metal1", [rail_pos, pin.lc()])
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=rail_pos,
rotate=90)
def connect_predecode_rail_m3(self, rail_index, pin):
def connect_predecode_rail_m3(self, rail_name, pin):
""" Connect the routing rail to the given metal1 pin """
# This routes the pin up to the rail, basically, to avoid conflicts.
# It would be fixed with a channel router.
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.predecode_rails[rail_name].x,mid_point.y)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=pin.center(),
rotate=90)