mirror of https://github.com/VLSIDA/OpenRAM.git
Space hier decoder input connections along rails to avoid conflicts
This commit is contained in:
parent
b8e3629923
commit
b8a3bc9b1a
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue