mirror of https://github.com/VLSIDA/OpenRAM.git
Connect data and column DFF clocks in 1 bank.
This commit is contained in:
parent
5ff49d322d
commit
3420b1002c
|
|
@ -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"""
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -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 """
|
||||
|
|
|
|||
|
|
@ -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 """
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue