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_offset=vector(min_x - self.input_routing_width,0)
input_bus_names = ["A[{0}]".format(i) for i in range(self.num_inputs)] input_bus_names = ["A[{0}]".format(i) for i in range(self.num_inputs)]
self.create_vertical_pin_bus(layer="metal2", self.input_rails = self.create_vertical_pin_bus(layer="metal2",
pitch=self.m2_pitch, pitch=self.m2_pitch,
offset=input_offset, offset=input_offset,
names=input_bus_names, names=input_bus_names,
length=input_height) length=input_height)
self.connect_input_to_predecodes() self.connect_input_to_predecodes()
@ -143,14 +143,15 @@ class hierarchical_decoder(design.design):
for i in range(2): for i in range(2):
index = pre_num * 2 + i 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) in_name = "in[{}]".format(i)
decoder_pin = self.pre2x4_inst[pre_num].get_pin(in_name) decoder_pin = self.pre2x4_inst[pre_num].get_pin(in_name)
# Offset each decoder pin up so they don't conflit # To prevent conflicts, we will offset each input connect so
decoder_offset = decoder_pin.center() + vector(0,i*self.m2_pitch) # that it aligns with the vdd/gnd rails
input_offset = input_pin.center().scale(1,0) + decoder_offset.scale(0,1) 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) self.connect_input_rail(decoder_offset, input_offset)
@ -159,14 +160,15 @@ class hierarchical_decoder(design.design):
for i in range(3): for i in range(3):
index = pre_num * 3 + i + self.no_of_pre2x4 * 2 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) in_name = "in[{}]".format(i)
decoder_pin = self.pre3x8_inst[pre_num].get_pin(in_name) decoder_pin = self.pre3x8_inst[pre_num].get_pin(in_name)
# Offset each decoder pin up so they don't conflit # To prevent conflicts, we will offset each input connect so
decoder_offset = decoder_pin.center() + vector(0,i*self.m2_pitch) # that it aligns with the vdd/gnd rails
input_offset = input_pin.center().scale(1,0) + decoder_offset.scale(0,1) 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) 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. # This is not needed for inputs <4 since they have no pre/decode stages.
if (self.num_inputs >= 4): if (self.num_inputs >= 4):
# Array for saving the X offsets of the vertical rails. These rail input_offset = vector(0.5*self.m2_width,0)
# offsets are accessed with indices. input_bus_names = ["predecode[{0}]".format(i) for i in range(self.total_number_of_predecoder_outputs)]
self.rail_x_offsets = [] self.predecode_rails = self.create_vertical_pin_bus(layer="metal2",
for i in range(self.total_number_of_predecoder_outputs): pitch=self.m2_pitch,
# The offsets go into the negative x direction offset=input_offset,
# assuming the predecodes are placed at (self.internal_routing_width,0) names=input_bus_names,
x_offset = self.m2_pitch * i length=self.height)
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)
self.connect_rails_to_predecodes() self.connect_rails_to_predecodes()
self.connect_rails_to_decoder() self.connect_rails_to_decoder()
@ -434,20 +432,22 @@ class hierarchical_decoder(design.design):
def connect_rails_to_predecodes(self): def connect_rails_to_predecodes(self):
""" Iterates through all of the predecodes and connects to the rails including the offsets """ """ 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 pre_num in range(self.no_of_pre2x4):
for i in range(4): for i in range(4):
index = pre_num * 4 + i predecode_name = "predecode[{}]".format(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_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 pre_num in range(self.no_of_pre3x8):
for i in range(8): 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) 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_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): 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_predecode_rail(index_A, self.nand_inst[row_index].get_pin("A")) # FIXME: convert to connect_bus?
self.connect_predecode_rail(index_B, self.nand_inst[row_index].get_pin("B")) 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 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_predecode_rail(index_A, self.nand_inst[row_index].get_pin("A")) # FIXME: convert to connect_bus?
self.connect_predecode_rail(index_B, self.nand_inst[row_index].get_pin("B")) predecode_name = "predecode[{}]".format(index_A)
self.connect_predecode_rail(index_C, self.nand_inst[row_index].get_pin("C")) 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 row_index = row_index + 1
def route_vdd_gnd(self): def route_vdd_gnd(self):
@ -509,19 +516,21 @@ class hierarchical_decoder(design.design):
self.copy_layout_pin(pre, "gnd") 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 """ """ 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_path("metal1", [rail_pos, pin.lc()])
self.add_via_center(layers=("metal1", "via1", "metal2"), self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=rail_pos, offset=rail_pos,
rotate=90) 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 """ """ 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) 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"), self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=pin.center(), offset=pin.center(),
rotate=90) rotate=90)