mirror of https://github.com/VLSIDA/OpenRAM.git
Use channel for dffs all at once
This commit is contained in:
parent
c10a6a29c0
commit
66ea559209
|
|
@ -108,8 +108,21 @@ class write_mask_and_array(design.design):
|
|||
end=vector(self.width, en_pin.cy()))
|
||||
|
||||
for i in range(self.num_wmasks):
|
||||
# Route the A pin over to the left so that it doesn't conflict with the sense
|
||||
# amp output which is usually in the center
|
||||
a_pin = self.and2_insts[i].get_pin("A")
|
||||
a_pos = a_pin.center()
|
||||
in_pos = vector(self.and2_insts[i].lx(),
|
||||
a_pos.y)
|
||||
self.add_via_stack_center(from_layer=a_pin.layer,
|
||||
to_layer="m2",
|
||||
offset=in_pos)
|
||||
self.add_layout_pin_rect_center(text="wmask_in_{0}".format(i),
|
||||
layer="m2",
|
||||
offset=in_pos)
|
||||
self.add_path(a_pin.layer, [in_pos, a_pos])
|
||||
|
||||
# Copy remaining layout pins
|
||||
self.copy_layout_pin(self.and2_insts[i], "A", "wmask_in_{0}".format(i))
|
||||
self.copy_layout_pin(self.and2_insts[i], "Z", "wmask_out_{0}".format(i))
|
||||
|
||||
# Add via connections to metal3 for AND array's B pin
|
||||
|
|
@ -122,7 +135,7 @@ class write_mask_and_array(design.design):
|
|||
for supply in ["gnd", "vdd"]:
|
||||
supply_pin=self.and2_insts[i].get_pin(supply)
|
||||
if "li" in layer:
|
||||
self.add_power_pin(supply, supply_pin.center(), start_layer="li", directions = ("H", "H"))
|
||||
self.add_power_pin(supply, supply_pin.center(), start_layer="li", directions=("H", "H"))
|
||||
else:
|
||||
self.add_power_pin(supply, supply_pin.center())
|
||||
|
||||
|
|
|
|||
|
|
@ -70,93 +70,12 @@ class sram_1bank(sram_base):
|
|||
# If a horizontal channel, they rely on the vertical channel non-preferred (contacted) pitch.
|
||||
# If a vertical channel, they rely on the horizontal channel non-preferred (contacted) pitch.
|
||||
# So, m3 non-pref pitch means that this is routed on the m2 layer.
|
||||
if self.write_size:
|
||||
self.data_bus_gap = self.m4_nonpref_pitch * 2
|
||||
self.data_bus_size = self.m4_nonpref_pitch * (self.word_size + self.num_spare_cols) + self.data_bus_gap
|
||||
self.wmask_bus_gap = self.m2_nonpref_pitch * 2
|
||||
self.wmask_bus_size = self.m2_nonpref_pitch * (max(self.num_wmasks + 1, self.col_addr_size + 1)) + self.wmask_bus_gap
|
||||
if self.num_spare_cols:
|
||||
self.spare_wen_bus_gap = self.m2_nonpref_pitch * 2
|
||||
self.spare_wen_bus_size = self.m2_nonpref_pitch * (max(self.num_spare_cols + 1, self.col_addr_size + 1)) + self.spare_wen_bus_gap
|
||||
else:
|
||||
self.spare_wen_bus_size = 0
|
||||
|
||||
elif self.num_spare_cols and not self.write_size:
|
||||
self.data_bus_gap = self.m4_nonpref_pitch * 2
|
||||
self.data_bus_size = self.m4_nonpref_pitch * (self.word_size + self.num_spare_cols) + self.data_bus_gap
|
||||
self.spare_wen_bus_gap = self.m2_nonpref_pitch * 2
|
||||
self.spare_wen_bus_size = self.m2_nonpref_pitch * (max(self.num_spare_cols + 1, self.col_addr_size + 1)) + self.spare_wen_bus_gap
|
||||
|
||||
else:
|
||||
self.data_bus_gap = self.m3_nonpref_pitch * 2
|
||||
self.data_bus_size = self.m3_nonpref_pitch * (max(self.word_size + 1, self.col_addr_size + 1)) + self.data_bus_gap
|
||||
|
||||
self.col_addr_bus_gap = self.m2_nonpref_pitch * 2
|
||||
self.col_addr_bus_size = self.m2_nonpref_pitch * (self.col_addr_size) + self.col_addr_bus_gap
|
||||
self.data_bus_gap = self.m4_nonpref_pitch * 2
|
||||
self.data_bus_size = self.m4_nonpref_pitch * (self.word_size + self.num_spare_cols + self.num_wmasks + self.col_addr_size + self.num_spare_cols) + self.data_bus_gap
|
||||
|
||||
# Port 0
|
||||
port = 0
|
||||
|
||||
if port in self.write_ports:
|
||||
if self.write_size:
|
||||
bus_size = max(self.wmask_bus_size, self.spare_wen_bus_size)
|
||||
# Add the write mask flops below the write mask AND array.
|
||||
wmask_pos[port] = vector(self.bank.bank_array_ll.x,
|
||||
- bus_size - self.dff.height)
|
||||
self.wmask_dff_insts[port].place(wmask_pos[port])
|
||||
|
||||
# Add the data flops below the write mask flops.
|
||||
data_pos[port] = vector(self.bank.bank_array_ll.x,
|
||||
- self.data_bus_size - bus_size - 2 * self.dff.height)
|
||||
self.data_dff_insts[port].place(data_pos[port])
|
||||
|
||||
#Add spare write enable flops to the right of write mask flops
|
||||
if self.num_spare_cols:
|
||||
spare_wen_pos[port] = vector(self.bank.bank_array_ll.x + self.wmask_dff_insts[port].width + self.bank.m2_gap,
|
||||
- bus_size - self.dff.height)
|
||||
self.spare_wen_dff_insts[port].place(spare_wen_pos[port])
|
||||
|
||||
elif self.num_spare_cols and not self.write_size:
|
||||
# Add spare write enable flops below bank (lower right)
|
||||
spare_wen_pos[port] = vector(self.bank.bank_array_ll.x,
|
||||
- self.spare_wen_bus_size - self.dff.height)
|
||||
self.spare_wen_dff_insts[port].place(spare_wen_pos[port])
|
||||
|
||||
# Add the data flops below the spare write enable flops.
|
||||
data_pos[port] = vector(self.bank.bank_array_ll.x,
|
||||
- self.data_bus_size - self.spare_wen_bus_size - 2 * self.dff.height)
|
||||
self.data_dff_insts[port].place(data_pos[port])
|
||||
|
||||
else:
|
||||
# Add the data flops below the bank to the right of the lower-left of bank array
|
||||
# This relies on the lower-left of the array 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
|
||||
# sense amps.
|
||||
data_pos[port] = vector(self.bank.bank_array_ll.x,
|
||||
-self.data_bus_size - self.dff.height)
|
||||
self.data_dff_insts[port].place(data_pos[port])
|
||||
|
||||
else:
|
||||
wmask_pos[port] = vector(self.bank.bank_array_ll.x, 0)
|
||||
data_pos[port] = vector(self.bank.bank_array_ll.x, 0)
|
||||
spare_wen_pos[port] = vector(self.bank.bank_array_ll.x, 0)
|
||||
|
||||
# Add the col address flops below the bank to the left of the lower-left of bank array
|
||||
if self.col_addr_dff:
|
||||
if self.write_size:
|
||||
col_addr_pos[port] = vector(self.bank.bank_array_ll.x - self.col_addr_dff_insts[port].width - self.bank.m2_gap,
|
||||
-bus_size - self.col_addr_dff_insts[port].height)
|
||||
elif self.num_spare_cols and not self.write_size:
|
||||
col_addr_pos[port] = vector(self.bank.bank_array_ll.x - self.col_addr_dff_insts[port].width - self.bank.m2_gap,
|
||||
-self.spare_wen_bus_size - self.col_addr_dff_insts[port].height)
|
||||
else:
|
||||
col_addr_pos[port] = vector(self.bank.bank_array_ll.x - self.col_addr_dff_insts[port].width - self.bank.m2_gap,
|
||||
-self.data_bus_size - self.col_addr_dff_insts[port].height)
|
||||
self.col_addr_dff_insts[port].place(col_addr_pos[port])
|
||||
else:
|
||||
col_addr_pos[port] = vector(self.bank.bank_array_ll.x, 0)
|
||||
|
||||
# This includes 2 M2 pitches for the row addr clock line.
|
||||
control_pos[port] = vector(-self.control_logic_insts[port].width - 2 * self.m2_pitch,
|
||||
self.bank.bank_array_ll.y - self.control_logic_insts[port].mod.control_logic_center.y - 2 * self.bank.m2_gap)
|
||||
|
|
@ -169,64 +88,45 @@ class sram_1bank(sram_base):
|
|||
row_addr_pos[port] = vector(x_offset, y_offset)
|
||||
self.row_addr_dff_insts[port].place(row_addr_pos[port])
|
||||
|
||||
# Add the col address flops below the bank to the right of the control logic
|
||||
x_offset = self.control_logic_insts[port].rx() + self.dff.width
|
||||
y_offset = - self.data_bus_size - self.dff.height
|
||||
if self.col_addr_dff:
|
||||
col_addr_pos[port] = vector(x_offset,
|
||||
y_offset)
|
||||
self.col_addr_dff_insts[port].place(col_addr_pos[port])
|
||||
x_offset = self.col_addr_dff_insts[port].rx()
|
||||
else:
|
||||
col_addr_pos[port] = vector(x_offset, 0)
|
||||
|
||||
if port in self.write_ports:
|
||||
if self.write_size:
|
||||
# Add the write mask flops below the write mask AND array.
|
||||
wmask_pos[port] = vector(x_offset,
|
||||
y_offset)
|
||||
self.wmask_dff_insts[port].place(wmask_pos[port])
|
||||
x_offset = self.wmask_dff_insts[port].rx()
|
||||
|
||||
# Add spare write enable flops to the right of write mask flops
|
||||
if self.num_spare_cols:
|
||||
spare_wen_pos[port] = vector(x_offset,
|
||||
y_offset)
|
||||
self.spare_wen_dff_insts[port].place(spare_wen_pos[port])
|
||||
x_offset = self.spare_wen_dff_insts[port].rx()
|
||||
|
||||
# Add the data flops below the write mask flops.
|
||||
data_pos[port] = vector(x_offset,
|
||||
y_offset)
|
||||
self.data_dff_insts[port].place(data_pos[port])
|
||||
|
||||
else:
|
||||
wmask_pos[port] = vector(x_offset, y_offset)
|
||||
data_pos[port] = vector(x_offset, y_offset)
|
||||
spare_wen_pos[port] = vector(x_offset, y_offset)
|
||||
|
||||
if len(self.all_ports)>1:
|
||||
# Port 1
|
||||
port = 1
|
||||
|
||||
if port in self.write_ports:
|
||||
if self.write_size:
|
||||
bus_size = max(self.wmask_bus_size, self.spare_wen_bus_size)
|
||||
# Add the write mask flops above the write mask AND array.
|
||||
wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.wmask_dff_insts[port].width,
|
||||
self.bank.height + bus_size + self.dff.height)
|
||||
self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX")
|
||||
|
||||
# Add the data flops above the write mask flops
|
||||
data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width,
|
||||
self.bank.height + bus_size + self.data_bus_size + 2 * self.dff.height)
|
||||
self.data_dff_insts[port].place(data_pos[port], mirror="MX")
|
||||
|
||||
if self.num_spare_cols:
|
||||
spare_wen_pos[port] = vector(self.bank.bank_array_ur.x - self.wmask_dff_insts[port].width
|
||||
- self.spare_wen_dff_insts[port].width - self.bank.m2_gap,
|
||||
self.bank.height + bus_size + self.dff.height)
|
||||
self.spare_wen_dff_insts[port].place(spare_wen_pos[port], mirror="MX")
|
||||
|
||||
# Place dffs when spare cols is enabled
|
||||
elif self.num_spare_cols and not self.write_size:
|
||||
# Spare wen flops on the upper right, below data flops
|
||||
spare_wen_pos[port] = vector(self.bank.bank_array_ur.x - self.spare_wen_dff_insts[port].width,
|
||||
self.bank.height + self.spare_wen_bus_size + self.dff.height)
|
||||
self.spare_wen_dff_insts[port].place(spare_wen_pos[port], mirror="MX")
|
||||
# Add the data flops above the spare write enable flops
|
||||
data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width,
|
||||
self.bank.height + self.spare_wen_bus_size + self.data_bus_size + 2 * self.dff.height)
|
||||
self.data_dff_insts[port].place(data_pos[port], mirror="MX")
|
||||
|
||||
else:
|
||||
# Add the data flops above the bank to the left of the upper-right of bank array
|
||||
# This relies on the upper-right of the array 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
|
||||
# sense amps.
|
||||
data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width,
|
||||
self.bank.height + self.data_bus_size + self.dff.height)
|
||||
self.data_dff_insts[port].place(data_pos[port], mirror="MX")
|
||||
|
||||
# Add the col address flops above the bank to the right of the upper-right of bank array
|
||||
if self.col_addr_dff:
|
||||
if self.write_size:
|
||||
col_addr_pos[port] = vector(self.bank.bank_array_ur.x + self.bank.m2_gap,
|
||||
self.bank.height + bus_size + self.dff.height)
|
||||
elif self.num_spare_cols and not self.write_size:
|
||||
col_addr_pos[port] = vector(self.bank.bank_array_ur.x + self.bank.m2_gap,
|
||||
self.bank.height + self.spare_wen_bus_size + self.dff.height)
|
||||
else:
|
||||
col_addr_pos[port] = vector(self.bank.bank_array_ur.x + self.bank.m2_gap,
|
||||
self.bank.height + self.data_bus_size + self.dff.height)
|
||||
self.col_addr_dff_insts[port].place(col_addr_pos[port], mirror="MX")
|
||||
else:
|
||||
col_addr_pos[port] = self.bank_inst.ur()
|
||||
|
||||
# This includes 2 M2 pitches for the row addr clock line
|
||||
control_pos[port] = vector(self.bank_inst.rx() + self.control_logic_insts[port].width + 2 * self.m2_pitch,
|
||||
|
|
@ -242,6 +142,42 @@ class sram_1bank(sram_base):
|
|||
row_addr_pos[port] = vector(x_offset, y_offset)
|
||||
self.row_addr_dff_insts[port].place(row_addr_pos[port], mirror="XY")
|
||||
|
||||
# Add the col address flops below the bank to the right of the control logic
|
||||
x_offset = self.control_logic_insts[port].lx() - 2 * self.dff.width
|
||||
y_offset = self.bank.height + self.data_bus_size + self.dff.height
|
||||
if self.col_addr_dff:
|
||||
col_addr_pos[port] = vector(x_offset - self.col_addr_dff_insts[port].width,
|
||||
y_offset)
|
||||
self.col_addr_dff_insts[port].place(col_addr_pos[port], mirror="MX")
|
||||
x_offset = self.col_addr_dff_insts[port].lx()
|
||||
else:
|
||||
col_addr_pos[port] = vector(x_offset, y_offset)
|
||||
|
||||
if port in self.write_ports:
|
||||
if self.write_size:
|
||||
# Add the write mask flops below the write mask AND array.
|
||||
wmask_pos[port] = vector(x_offset - self.wmask_dff_insts[port].width,
|
||||
y_offset)
|
||||
self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX")
|
||||
x_offset = self.wmask_dff_insts[port].lx()
|
||||
|
||||
# Add spare write enable flops to the right of write mask flops
|
||||
if self.num_spare_cols:
|
||||
spare_wen_pos[port] = vector(x_offset - self.spare_wen_dff_insts[port].width,
|
||||
y_offset)
|
||||
self.spare_wen_dff_insts[port].place(spare_wen_pos[port], mirror="MX")
|
||||
x_offset = self.spare_wen_dff_insts[port].lx()
|
||||
|
||||
# Add the data flops below the write mask flops.
|
||||
data_pos[port] = vector(x_offset - self.data_dff_insts[port].width,
|
||||
y_offset)
|
||||
self.data_dff_insts[port].place(data_pos[port], mirror="MX")
|
||||
|
||||
else:
|
||||
wmask_pos[port] = vector(x_offset, y_offset)
|
||||
data_pos[port] = vector(x_offset, y_offset)
|
||||
spare_wen_pos[port] = vector(x_offset, y_offset)
|
||||
|
||||
def add_layout_pins(self):
|
||||
"""
|
||||
Add the top-level pins for a single bank SRAM with control.
|
||||
|
|
@ -250,7 +186,6 @@ class sram_1bank(sram_base):
|
|||
lowest_coord = self.find_lowest_coords()
|
||||
bbox = [lowest_coord, highest_coord]
|
||||
|
||||
|
||||
for port in self.all_ports:
|
||||
# Depending on the port, use the bottom/top or left/right sides
|
||||
# Port 0 is left/bottom
|
||||
|
|
@ -370,17 +305,83 @@ class sram_1bank(sram_base):
|
|||
|
||||
self.route_row_addr_dff()
|
||||
|
||||
if self.col_addr_dff:
|
||||
self.route_col_addr_dff()
|
||||
# if self.col_addr_dff:
|
||||
# self.route_col_addr_dff()
|
||||
|
||||
self.route_data_dff()
|
||||
# self.route_data_dff()
|
||||
|
||||
if self.write_size:
|
||||
self.route_wmask_dff()
|
||||
# if self.write_size:
|
||||
# self.route_wmask_dff()
|
||||
|
||||
if self.num_spare_cols:
|
||||
self.route_spare_wen_dff()
|
||||
# if self.num_spare_cols:
|
||||
# self.route_spare_wen_dff()
|
||||
for port in self.all_ports:
|
||||
self.route_dff(port)
|
||||
|
||||
def route_dff(self, port):
|
||||
|
||||
route_map = []
|
||||
|
||||
# column mux dff
|
||||
if self.col_addr_size > 0:
|
||||
dff_names = ["dout_{}".format(x) for x in range(self.col_addr_size)]
|
||||
dff_pins = [self.col_addr_dff_insts[port].get_pin(x) for x in dff_names]
|
||||
bank_names = ["addr{0}_{1}".format(port, x) for x in range(self.col_addr_size)]
|
||||
bank_pins = [self.bank_inst.get_pin(x) for x in bank_names]
|
||||
route_map.extend(list(zip(bank_pins, dff_pins)))
|
||||
|
||||
# spare wen dff
|
||||
if self.num_spare_cols > 0 and port in self.write_ports:
|
||||
dff_names = ["dout_{}".format(x) for x in range(self.num_spare_cols)]
|
||||
dff_pins = [self.spare_wen_dff_insts[port].get_pin(x) for x in dff_names]
|
||||
bank_names = ["bank_spare_wen{0}_{1}".format(port, x) for x in range(self.num_spare_cols)]
|
||||
bank_pins = [self.bank_inst.get_pin(x) for x in bank_names]
|
||||
route_map.extend(list(zip(bank_pins, dff_pins)))
|
||||
|
||||
# wmask dff
|
||||
if self.num_wmasks > 0 and port in self.write_ports:
|
||||
dff_names = ["dout_{}".format(x) for x in range(self.num_wmasks)]
|
||||
dff_pins = [self.wmask_dff_insts[port].get_pin(x) for x in dff_names]
|
||||
bank_names = ["bank_wmask{0}_{1}".format(port, x) for x in range(self.num_wmasks)]
|
||||
bank_pins = [self.bank_inst.get_pin(x) for x in bank_names]
|
||||
route_map.extend(list(zip(bank_pins, dff_pins)))
|
||||
|
||||
if port in self.write_ports:
|
||||
# data dff
|
||||
dff_names = ["dout_{}".format(x) for x in range(self.word_size + self.num_spare_cols)]
|
||||
dff_pins = [self.data_dff_insts[port].get_pin(x) for x in dff_names]
|
||||
bank_names = ["din{0}_{1}".format(port, x) for x in range(self.word_size + self.num_spare_cols)]
|
||||
bank_pins = [self.bank_inst.get_pin(x) for x in bank_names]
|
||||
route_map.extend(list(zip(bank_pins, dff_pins)))
|
||||
|
||||
if self.num_wmasks > 0 and port in self.write_ports:
|
||||
vertical_layer = "m4"
|
||||
layer_stack = self.m3_stack
|
||||
else:
|
||||
vertical_layer = "m2"
|
||||
layer_stack = self.m1_stack
|
||||
for (pin1, pin2) in route_map:
|
||||
if pin1.layer != vertical_layer:
|
||||
self.add_via_stack_center(from_layer=pin1.layer,
|
||||
to_layer=vertical_layer,
|
||||
offset=pin1.center())
|
||||
if pin2.layer != vertical_layer:
|
||||
self.add_via_stack_center(from_layer=pin2.layer,
|
||||
to_layer=vertical_layer,
|
||||
offset=pin2.center())
|
||||
|
||||
if port == 0:
|
||||
offset = vector(self.control_logic_insts[port].rx() + self.dff.width,
|
||||
- self.data_bus_size + 2 * self.m1_pitch)
|
||||
else:
|
||||
offset = vector(0,
|
||||
self.bank.height + 2 * self.m1_space)
|
||||
|
||||
if len(route_map) > 0:
|
||||
self.create_horizontal_channel_route(netlist=route_map,
|
||||
offset=offset,
|
||||
layer_stack=layer_stack)
|
||||
|
||||
def route_clk(self):
|
||||
""" Route the clock network """
|
||||
|
||||
|
|
@ -423,8 +424,7 @@ class sram_1bank(sram_base):
|
|||
mid_pos = vector(clk_steiner_pos.x, dff_clk_pos.y)
|
||||
self.add_wire(self.m2_stack[::-1],
|
||||
[dff_clk_pos, mid_pos, clk_steiner_pos])
|
||||
|
||||
if port in self.write_ports:
|
||||
elif port in self.write_ports:
|
||||
data_dff_clk_pin = self.data_dff_insts[port].get_pin("clk")
|
||||
data_dff_clk_pos = data_dff_clk_pin.center()
|
||||
mid_pos = vector(clk_steiner_pos.x, data_dff_clk_pos.y)
|
||||
|
|
@ -436,24 +436,6 @@ class sram_1bank(sram_base):
|
|||
self.add_wire(self.m2_stack[::-1],
|
||||
[data_dff_clk_pos, mid_pos, clk_steiner_pos])
|
||||
|
||||
if self.write_size:
|
||||
wmask_dff_clk_pin = self.wmask_dff_insts[port].get_pin("clk")
|
||||
wmask_dff_clk_pos = wmask_dff_clk_pin.center()
|
||||
mid_pos = vector(clk_steiner_pos.x, wmask_dff_clk_pos.y)
|
||||
# In some designs, the steiner via will be too close to the mid_pos via
|
||||
# so make the wire as wide as the contacts
|
||||
self.add_path("m2", [mid_pos, clk_steiner_pos], width=max(m2_via.width, m2_via.height))
|
||||
self.add_wire(self.m2_stack[::-1], [wmask_dff_clk_pos, mid_pos, clk_steiner_pos])
|
||||
|
||||
if self.num_spare_cols:
|
||||
spare_wen_dff_clk_pin = self.spare_wen_dff_insts[port].get_pin("clk")
|
||||
spare_wen_dff_clk_pos = spare_wen_dff_clk_pin.center()
|
||||
mid_pos = vector(clk_steiner_pos.x, spare_wen_dff_clk_pos.y)
|
||||
# In some designs, the steiner via will be too close to the mid_pos via
|
||||
# so make the wire as wide as the contacts
|
||||
self.add_path("m2", [mid_pos, clk_steiner_pos], width=max(m2_via.width, m2_via.height))
|
||||
self.add_wire(self.m2_stack[::-1], [spare_wen_dff_clk_pos, mid_pos, clk_steiner_pos])
|
||||
|
||||
def route_control_logic(self):
|
||||
""" Route the control logic pins that are not inputs """
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue