Push create bus functions down into layout class.

This commit is contained in:
Matt Guthaus 2018-07-10 10:06:59 -07:00
parent 98f1914e9f
commit 25cf57ede5
3 changed files with 114 additions and 99 deletions

View File

@ -524,6 +524,62 @@ class layout(lef.lef):
return blockages
def create_horizontal_pin_bus(self, layer, pitch, offset, names, length):
""" Create a horizontal bus of pins. """
self.create_bus(layer,pitch,offset,names,length,vertical=False,make_pins=True)
def create_vertical_pin_bus(self, layer, pitch, offset, names, length):
""" Create a horizontal bus of pins. """
self.create_bus(layer,pitch,offset,names,length,vertical=True,make_pins=True)
def create_vertical_bus(self, layer, pitch, offset, names, length):
""" Create a horizontal bus. """
self.create_bus(layer,pitch,offset,names,length,vertical=True,make_pins=False)
def create_horiontal_bus(self, layer, pitch, offset, names, length):
""" Create a horizontal bus. """
self.create_bus(layer,pitch,offset,names,length,vertical=False,make_pins=False)
def create_bus(self, layer, pitch, offset, names, length, vertical, make_pins):
"""
Create a horizontal or vertical bus. It can be either just rectangles, or actual
layout pins. It returns an map of line center line positions indexed by name.
"""
# half minwidth so we can return the center line offsets
half_minwidth = 0.5*drc["minwidth_{}".format(layer)]
line_positions = {}
if vertical:
for i in range(len(names)):
line_offset = offset + vector(i*pitch,0)
if make_pins:
self.add_layout_pin(text=names[i],
layer=layer,
offset=line_offset,
height=length)
else:
self.add_rect(layer=layer,
offset=line_offset,
height=length)
line_positions[names[i]]=line_offset+vector(half_minwidth,0)
else:
for i in range(len(names)):
line_offset = offset + vector(0,i*pitch + half_minwidth)
if make_pins:
self.add_layout_pin(text=names[i],
layer=layer,
offset=line_offset,
width=length)
else:
self.add_rect(layer=layer,
offset=line_offset,
width=length)
line_positions[names[i]]=line_offset+vector(0,half_minwidth)
return line_positions
def add_enclosure(self, insts, layer="nwell"):
""" Add a layer that surrounds the given instances. Useful
for creating wells, for example. Doesn't check for minimum widths or

View File

@ -125,16 +125,15 @@ class hierarchical_decoder(design.design):
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 - self.input_routing_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),
width=self.m2_width,
height=input_height)
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.connect_input_to_predecodes()

View File

@ -103,8 +103,10 @@ class sram(design.design):
debug.info(1,"Words per row: {}".format(self.words_per_row))
def estimate_words_per_row(self,tentative_num_cols, word_size):
"""This provides a heuristic rounded estimate for the number of words
per row."""
"""
This provides a heuristic rounded estimate for the number of words
per row.
"""
if tentative_num_cols < 1.5*word_size:
return 1
@ -114,7 +116,8 @@ class sram(design.design):
return 2
def amend_words_per_row(self,tentative_num_rows, words_per_row):
"""This picks the number of words per row more accurately by limiting
"""
This picks the number of words per row more accurately by limiting
it to a minimum and maximum.
"""
# Recompute the words per row given a hard max
@ -319,7 +322,8 @@ class sram(design.design):
self.supply_bus_width = self.data_bus_width
# Sanity check to ensure we can fit the control logic above a single bank (0.9 is a hack really)
debug.check(self.bank.width + self.vertical_bus_width > 0.9*self.control_logic.width, "Bank is too small compared to control logic.")
debug.check(self.bank.width + self.vertical_bus_width > 0.9*self.control_logic.width,
"Bank is too small compared to control logic.")
def compute_four_bank_offsets(self):
@ -336,7 +340,8 @@ class sram(design.design):
self.vertical_bus_offset = vector(self.bank.width + self.bank_to_bus_distance, 0)
self.data_bus_offset = vector(0, self.bank.height + self.bank_to_bus_distance)
self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height + self.bank.height + 2*self.bank_to_bus_distance)
self.supply_bus_offset = vector(0, self.data_bus_offset.y + self.data_bus_height \
+ self.bank.height + 2*self.bank_to_bus_distance)
self.control_bus_offset = vector(0, self.supply_bus_offset.y + self.supply_bus_height)
self.bank_sel_bus_offset = self.vertical_bus_offset + vector(self.m2_pitch*self.control_size,0)
self.addr_bus_offset = self.bank_sel_bus_offset.scale(1,0) + vector(self.m2_pitch*self.num_banks,0)
@ -347,7 +352,8 @@ class sram(design.design):
# Bank select flops get put to the right of control logic above bank1 and the buses
# Leave a pitch to get the vdd rails up to M2
self.msb_address_position = vector(self.bank_inst[1].lx() + 3*self.supply_rail_pitch,
self.supply_bus_offset.y + self.supply_bus_height + 2*self.m1_pitch + self.msb_address.width)
self.supply_bus_offset.y + self.supply_bus_height \
+ 2*self.m1_pitch + self.msb_address.width)
# Decoder goes above the MSB address flops, and is flipped in Y
# separate the two by a bank to bus distance for nwell rules, just in case
@ -375,73 +381,65 @@ class sram(design.design):
# Bank select flops get put to the right of control logic above bank1 and the buses
# Leave a pitch to get the vdd rails up to M2
self.msb_address_position = vector(self.bank_inst[1].lx() + 3*self.supply_rail_pitch,
self.supply_bus_offset.y+self.supply_bus_height + 2*self.m1_pitch + self.msb_address.width)
self.supply_bus_offset.y + self.supply_bus_height \
+ 2*self.m1_pitch + self.msb_address.width)
def add_busses(self):
""" Add the horizontal and vertical busses """
# Vertical bus
# The order of the control signals on the control bus:
self.control_bus_names = ["clk_buf", "tri_en_bar", "tri_en", "clk_buf_bar", "w_en", "s_en"]
self.vert_control_bus_positions = self.create_bus(layer="metal2",
pitch=self.m2_pitch,
offset=self.vertical_bus_offset,
names=self.control_bus_names,
length=self.vertical_bus_height,
vertical=True)
self.vert_control_bus_positions = self.create_vertical_bus(layer="metal2",
pitch=self.m2_pitch,
offset=self.vertical_bus_offset,
names=self.control_bus_names,
length=self.vertical_bus_height))
self.addr_bus_names=["A[{}]".format(i) for i in range(self.addr_size)]
self.vert_control_bus_positions.update(self.create_bus(layer="metal2",
pitch=self.m2_pitch,
offset=self.addr_bus_offset,
names=self.addr_bus_names,
length=self.addr_bus_height,
vertical=True,
make_pins=True))
self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="metal2",
pitch=self.m2_pitch,
offset=self.addr_bus_offset,
names=self.addr_bus_names,
length=self.addr_bus_height))
self.bank_sel_bus_names = ["bank_sel[{}]".format(i) for i in range(self.num_banks)]
self.vert_control_bus_positions.update(self.create_bus(layer="metal2",
pitch=self.m2_pitch,
offset=self.bank_sel_bus_offset,
names=self.bank_sel_bus_names,
length=self.vertical_bus_height,
vertical=True,
make_pins=True))
self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="metal2",
pitch=self.m2_pitch,
offset=self.bank_sel_bus_offset,
names=self.bank_sel_bus_names,
length=self.vertical_bus_height))
# Horizontal data bus
self.data_bus_names = ["DATA[{}]".format(i) for i in range(self.word_size)]
self.data_bus_positions = self.create_bus(layer="metal3",
pitch=self.m3_pitch,
offset=self.data_bus_offset,
names=self.data_bus_names,
length=self.data_bus_width,
vertical=False,
make_pins=True)
self.data_bus_positions = self.create_horizontal_pin_bus(layer="metal3",
pitch=self.m3_pitch,
offset=self.data_bus_offset,
names=self.data_bus_names,
length=self.data_bus_width)
# Horizontal control logic bus
# vdd/gnd in bus go along whole SRAM
# FIXME: Fatten these wires?
self.horz_control_bus_positions = self.create_bus(layer="metal1",
pitch=self.m1_pitch,
offset=self.supply_bus_offset,
names=["vdd"],
length=self.supply_bus_width,
vertical=False)
self.horz_control_bus_positions = self.create_horizontal_bus(layer="metal1",
pitch=self.m1_pitch,
offset=self.supply_bus_offset,
names=["vdd"],
length=self.supply_bus_width)
# The gnd rail must not be the entire width since we protrude the right-most vdd rail up for
# the decoder in 4-bank SRAMs
self.horz_control_bus_positions.update(self.create_bus(layer="metal1",
pitch=self.m1_pitch,
offset=self.supply_bus_offset+vector(0,self.m1_pitch),
names=["gnd"],
length=self.supply_bus_width,
vertical=False))
self.horz_control_bus_positions.update(self.create_bus(layer="metal1",
pitch=self.m1_pitch,
offset=self.control_bus_offset,
names=self.control_bus_names,
length=self.control_bus_width,
vertical=False))
self.horz_control_bus_positions.update(self.create_horizontal_bus(layer="metal1",
pitch=self.m1_pitch,
offset=self.supply_bus_offset+vector(0,self.m1_pitch),
names=["gnd"],
length=self.supply_bus_width))
self.horz_control_bus_positions.update(self.create_horizontal_bus(layer="metal1",
pitch=self.m1_pitch,
offset=self.control_bus_offset,
names=self.control_bus_names,
length=self.control_bus_width))
def add_two_bank_logic(self):
""" Add the control and MSB logic """
@ -848,44 +846,6 @@ class sram(design.design):
return bank_inst
# FIXME: This should be in geometry.py or it's own class since it is
# reusable
def create_bus(self, layer, pitch, offset, names, length, vertical=False, make_pins=False):
""" Create a horizontal or vertical bus. It can be either just rectangles, or actual
layout pins. It returns an map of line center line positions indexed by name. """
# half minwidth so we can return the center line offsets
half_minwidth = 0.5*drc["minwidth_{}".format(layer)]
line_positions = {}
if vertical:
for i in range(len(names)):
line_offset = offset + vector(i*pitch,0)
if make_pins:
self.add_layout_pin(text=names[i],
layer=layer,
offset=line_offset,
height=length)
else:
self.add_rect(layer=layer,
offset=line_offset,
height=length)
line_positions[names[i]]=line_offset+vector(half_minwidth,0)
else:
for i in range(len(names)):
line_offset = offset + vector(0,i*pitch + half_minwidth)
if make_pins:
self.add_layout_pin(text=names[i],
layer=layer,
offset=line_offset,
width=length)
else:
self.add_rect(layer=layer,
offset=line_offset,
width=length)
line_positions[names[i]]=line_offset+vector(0,half_minwidth)
return line_positions
def add_addr_dff(self, position):