Connect data and column DFF clocks in 1 bank.

This commit is contained in:
Matt Guthaus 2018-08-14 10:09:41 -07:00
parent 5ff49d322d
commit 3420b1002c
7 changed files with 69 additions and 97 deletions

View File

@ -101,7 +101,6 @@ class bank(design.design):
self.route_row_decoder()
self.route_column_address_lines()
self.route_control_lines()
self.add_control_pins()
if self.num_banks > 1:
self.route_bank_select()
@ -505,13 +504,15 @@ class bank(design.design):
# and control lines.
# The bank is at (0,0), so this is to the left of the y-axis.
# 2 pitches on the right for vias/jogs to access the inputs
control_bus_offset = vector(-self.m2_pitch * self.num_control_lines - self.m2_width, 0)
control_bus_length = self.bitcell_array_inst.uy()
self.bus_xoffset = self.create_vertical_bus(layer="metal2",
pitch=self.m2_pitch,
offset=control_bus_offset,
names=self.control_signals,
length=control_bus_length)
control_bus_offset = vector(-self.m2_pitch * self.num_control_lines - self.m2_width, self.min_y_offset)
control_bus_length = self.max_y_offset - self.min_y_offset
self.bus_xoffset = self.create_bus(layer="metal2",
pitch=self.m2_pitch,
offset=control_bus_offset,
names=self.control_signals,
length=control_bus_length,
vertical=True,
make_pins=(self.num_banks==1))
@ -750,52 +751,7 @@ class bank(design.design):
offset=control_via_pos,
rotate=90)
def add_control_pins(self):
""" Add the control signal input pins """
for ctrl in self.control_signals:
# xoffsets are the center of the rail
x_offset = self.bus_xoffset[ctrl].x - 0.5*self.m2_width
if self.num_banks > 1:
# it's not an input pin if we have multiple banks
self.add_label_pin(text=ctrl,
layer="metal2",
offset=vector(x_offset, self.min_y_offset),
width=self.m2_width,
height=self.max_y_offset-self.min_y_offset)
else:
self.add_layout_pin(text=ctrl,
layer="metal2",
offset=vector(x_offset, self.min_y_offset),
width=self.m2_width,
height=self.max_y_offset-self.min_y_offset)
def connect_rail_from_right(self,inst, pin, rail):
""" Helper routine to connect an unrotated/mirrored oriented instance to the rails """
in_pin = inst.get_pin(pin).lc()
rail_pos = vector(self.rail_1_x_offsets[rail], in_pin.y)
self.add_wire(("metal3","via2","metal2"),[in_pin, rail_pos, rail_pos - vector(0,self.m2_pitch)])
# Bring it up to M2 for M2/M3 routing
self.add_via(layers=("metal1","via1","metal2"),
offset=in_pin + contact.m1m2.offset,
rotate=90)
self.add_via(layers=("metal2","via2","metal3"),
offset=in_pin + self.m2m3_via_offset,
rotate=90)
def connect_rail_from_left(self,inst, pin, rail):
""" Helper routine to connect an unrotated/mirrored oriented instance to the rails """
in_pin = inst.get_pin(pin).rc()
rail_pos = vector(self.rail_1_x_offsets[rail], in_pin.y)
self.add_wire(("metal3","via2","metal2"),[in_pin, rail_pos, rail_pos - vector(0,self.m2_pitch)])
self.add_via(layers=("metal1","via1","metal2"),
offset=in_pin + contact.m1m2.offset,
rotate=90)
self.add_via(layers=("metal2","via2","metal3"),
offset=in_pin + self.m2m3_via_offset,
rotate=90)
def analytical_delay(self, slew, load):
""" return analytical delay of the bank"""

View File

@ -99,7 +99,7 @@ class control_logic(design.design):
self.internal_bus_list = ["clk_buf", "clk_buf_bar", "we", "cs"]
# leave space for the bus plus one extra space
self.internal_bus_width = (len(self.internal_bus_list)+1)*self.m2_pitch
# Ooutputs to the bank
# Outputs to the bank
self.output_list = ["s_en", "w_en", "clk_buf_bar", "clk_buf"]
self.supply_list = ["vdd", "gnd"]
@ -137,10 +137,11 @@ class control_logic(design.design):
# This offset is used for placement of the control logic in
# the SRAM level.
self.control_logic_center = vector(self.ctrl_dff_inst.rx(), self.rbl_inst.by())
self.height = self.rbl_inst.uy()
# Extra pitch on top and right
self.height = self.rbl_inst.uy() + self.m3_pitch
# Max of modules or logic rows
self.width = max(self.rbl_inst.rx(), max([inst.rx() for inst in self.row_end_inst]))
self.width = max(self.rbl_inst.rx(), max([inst.rx() for inst in self.row_end_inst])) + self.m2_pitch
def add_routing(self):

View File

@ -125,28 +125,21 @@ class dff_array(design.design):
# Create vertical spines to a single horizontal rail
clk_pin = self.dff_insts[0,0].get_pin("clk")
debug.check(clk_pin.layer=="metal2","DFF clk pin not on metal2")
if self.columns==1:
self.add_layout_pin(text="clk",
layer="metal2",
offset=clk_pin.ll().scale(1,0),
width=self.m2_width,
height=self.height)
else:
self.add_layout_pin_segment_center(text="clk",
layer="metal3",
start=vector(0,self.m3_pitch+self.m3_width),
end=vector(self.width,self.m3_pitch+self.m3_width))
for col in range(self.columns):
clk_pin = self.dff_insts[0,col].get_pin("clk")
# Make a vertical strip for each column
self.add_rect(layer="metal2",
offset=clk_pin.ll().scale(1,0),
width=self.m2_width,
height=self.height)
# Drop a via to the M3 pin
self.add_via_center(layers=("metal2","via2","metal3"),
offset=vector(clk_pin.cx(),self.m3_pitch+self.m3_width))
self.add_layout_pin_segment_center(text="clk",
layer="metal3",
start=vector(0,self.m3_pitch+self.m3_width),
end=vector(self.width,self.m3_pitch+self.m3_width))
for col in range(self.columns):
clk_pin = self.dff_insts[0,col].get_pin("clk")
# Make a vertical strip for each column
self.add_rect(layer="metal2",
offset=clk_pin.ll().scale(1,0),
width=self.m2_width,
height=self.height)
# Drop a via to the M3 pin
self.add_via_center(layers=("metal2","via2","metal3"),
offset=vector(clk_pin.cx(),self.m3_pitch+self.m3_width))
def analytical_delay(self, slew, load=0.0):

View File

@ -42,9 +42,9 @@ class replica_bitline(design.design):
#self.add_lvs_correspondence_points()
# Plus a pitch for the WL contacts on the RBL
self.width = self.rbl_inst.rx() - self.dc_inst.lx() + self.m1_pitch
self.height = max(self.rbl_inst.uy(), self.dc_inst.uy())
# Extra pitch on top and right
self.width = self.rbl_inst.rx() - self.dc_inst.lx() + self.m2_pitch
self.height = max(self.rbl_inst.uy(), self.dc_inst.uy()) + self.m3_pitch
self.DRC_LVS()

View File

@ -29,26 +29,29 @@ class sram_1bank(sram_base):
# No orientation or offset
self.bank_inst = self.add_bank(0, [0, 0], 1, 1)
# The control logic is placed such that the center (between the delay/RBL and
# the actual control logic is aligned with the center of the bank (between
# the sense amps/column mux and cell array)
control_pos = vector(-self.control_logic.width - self.m3_pitch,
self.bank.bank_center.y - self.control_logic.control_logic_center.y)
self.add_control_logic(position=control_pos)
# Leave room for the control routes to the left of the flops
# The row address bits are placed above the control logic aligned on the right.
row_addr_pos = vector(self.control_logic_inst.rx() - self.row_addr_dff.width,
control_pos.y + self.control_logic.height + self.m1_pitch)
self.control_logic_inst.uy())
self.add_row_addr_dff(row_addr_pos)
# This is M2 pitch even though it is on M1 to help stem via spacings on the trunk
data_gap = -self.m2_pitch*(self.word_size+1)
# Add the column address below the bank under the control
# Keep it aligned with the data flops
# The column address flops are aligned with the data flops
if self.col_addr_dff:
col_addr_pos = vector(self.bank.bank_center.x - self.col_addr_dff.width - self.bank.central_bus_width,
data_gap - self.col_addr_dff.height)
self.add_col_addr_dff(col_addr_pos)
# Add the data flops below the bank
# Add the data flops below the bank to the right of the center of bank:
# This relies on the center point of the bank:
# decoder in upper left, bank in upper right, sensing in lower right.
# These flops go below the sensing and leave a gap to channel route to the
@ -104,13 +107,34 @@ class sram_1bank(sram_base):
def route_clk(self):
""" Route the clock network """
debug.warning("Clock is top-level must connect.")
# For now, just have four clock pins for the address (x2), data, and control
if self.col_addr_dff:
self.copy_layout_pin(self.col_addr_dff_inst, "clk")
self.copy_layout_pin(self.row_addr_dff_inst, "clk")
self.copy_layout_pin(self.data_dff_inst, "clk")
# This is the actual input to the SRAM
self.copy_layout_pin(self.control_logic_inst, "clk")
debug.warning("Clock is top-level must connect.")
# Connect all of these clock pins to the clock in the central bus
# This is something like a "spine" clock distribution. The two spines
# are clk_buf and clk_buf_bar
bank_clk_buf_pin = self.bank_inst.get_pin("clk_buf")
bank_clk_buf_pos = bank_clk_buf_pin.center()
bank_clk_buf_bar_pin = self.bank_inst.get_pin("clk_buf_bar")
bank_clk_buf_bar_pos = bank_clk_buf_bar_pin.center()
if self.col_addr_dff:
dff_clk_pin = self.col_addr_dff_inst.get_pin("clk")
dff_clk_pos = dff_clk_pin.center()
mid_pos = vector(bank_clk_buf_pos.x, dff_clk_pos.y)
self.add_wire(("metal3","via2","metal2"),[dff_clk_pos, mid_pos, bank_clk_buf_pos])
self.copy_layout_pin(self.row_addr_dff_inst, "clk")
#self.copy_layout_pin(self.data_dff_inst, "clk")
data_dff_clk_pin = self.data_dff_inst.get_pin("clk")
data_dff_clk_pos = data_dff_clk_pin.center()
mid_pos = vector(bank_clk_buf_pos.x, data_dff_clk_pos.y)
self.add_wire(("metal3","via2","metal2"),[data_dff_clk_pos, mid_pos, bank_clk_buf_pos])
def route_vdd_gnd(self):
""" Propagate all vdd/gnd pins up to this level for all modules """

View File

@ -362,8 +362,7 @@ class sram_base(design):
inputs.append("ADDR[{}]".format(i))
outputs.append("A[{}]".format(i))
# FIXME clk->clk_buf
self.connect_inst(inputs + outputs + ["clk", "vdd", "gnd"])
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
def add_data_dff(self, position):
""" Add and place all data flops """
@ -377,8 +376,7 @@ class sram_base(design):
inputs.append("DIN[{}]".format(i))
outputs.append("BANK_DIN[{}]".format(i))
# FIXME clk->clk_buf_bar
self.connect_inst(inputs + outputs + ["clk", "vdd", "gnd"])
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
def add_control_logic(self, position):
""" Add and place control logic """

View File

@ -35,7 +35,7 @@ class sram_1bank_test(openram_test):
debug.info(1, "Single bank, eight way column mux with control logic")
a = sram(word_size=2, num_words=128, num_banks=1, name="sram4")
self.local_check(a, final_verification=True)
globals.end_openram()
# instantiate a copy of the class to actually run the test