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()))
|
end=vector(self.width, en_pin.cy()))
|
||||||
|
|
||||||
for i in range(self.num_wmasks):
|
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
|
# 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))
|
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
|
# 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"]:
|
for supply in ["gnd", "vdd"]:
|
||||||
supply_pin=self.and2_insts[i].get_pin(supply)
|
supply_pin=self.and2_insts[i].get_pin(supply)
|
||||||
if "li" in layer:
|
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:
|
else:
|
||||||
self.add_power_pin(supply, supply_pin.center())
|
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 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.
|
# 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.
|
# 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_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
|
||||||
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
|
|
||||||
|
|
||||||
# Port 0
|
# Port 0
|
||||||
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.
|
# 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,
|
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)
|
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)
|
row_addr_pos[port] = vector(x_offset, y_offset)
|
||||||
self.row_addr_dff_insts[port].place(row_addr_pos[port])
|
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:
|
if len(self.all_ports)>1:
|
||||||
# Port 1
|
# Port 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
|
# 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,
|
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)
|
row_addr_pos[port] = vector(x_offset, y_offset)
|
||||||
self.row_addr_dff_insts[port].place(row_addr_pos[port], mirror="XY")
|
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):
|
def add_layout_pins(self):
|
||||||
"""
|
"""
|
||||||
Add the top-level pins for a single bank SRAM with control.
|
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()
|
lowest_coord = self.find_lowest_coords()
|
||||||
bbox = [lowest_coord, highest_coord]
|
bbox = [lowest_coord, highest_coord]
|
||||||
|
|
||||||
|
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
# Depending on the port, use the bottom/top or left/right sides
|
# Depending on the port, use the bottom/top or left/right sides
|
||||||
# Port 0 is left/bottom
|
# Port 0 is left/bottom
|
||||||
|
|
@ -370,17 +305,83 @@ class sram_1bank(sram_base):
|
||||||
|
|
||||||
self.route_row_addr_dff()
|
self.route_row_addr_dff()
|
||||||
|
|
||||||
if self.col_addr_dff:
|
# if self.col_addr_dff:
|
||||||
self.route_col_addr_dff()
|
# self.route_col_addr_dff()
|
||||||
|
|
||||||
self.route_data_dff()
|
# self.route_data_dff()
|
||||||
|
|
||||||
if self.write_size:
|
# if self.write_size:
|
||||||
self.route_wmask_dff()
|
# self.route_wmask_dff()
|
||||||
|
|
||||||
if self.num_spare_cols:
|
# if self.num_spare_cols:
|
||||||
self.route_spare_wen_dff()
|
# 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):
|
def route_clk(self):
|
||||||
""" Route the clock network """
|
""" Route the clock network """
|
||||||
|
|
||||||
|
|
@ -423,8 +424,7 @@ class sram_1bank(sram_base):
|
||||||
mid_pos = vector(clk_steiner_pos.x, dff_clk_pos.y)
|
mid_pos = vector(clk_steiner_pos.x, dff_clk_pos.y)
|
||||||
self.add_wire(self.m2_stack[::-1],
|
self.add_wire(self.m2_stack[::-1],
|
||||||
[dff_clk_pos, mid_pos, clk_steiner_pos])
|
[dff_clk_pos, mid_pos, clk_steiner_pos])
|
||||||
|
elif port in self.write_ports:
|
||||||
if port in self.write_ports:
|
|
||||||
data_dff_clk_pin = self.data_dff_insts[port].get_pin("clk")
|
data_dff_clk_pin = self.data_dff_insts[port].get_pin("clk")
|
||||||
data_dff_clk_pos = data_dff_clk_pin.center()
|
data_dff_clk_pos = data_dff_clk_pin.center()
|
||||||
mid_pos = vector(clk_steiner_pos.x, data_dff_clk_pos.y)
|
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],
|
self.add_wire(self.m2_stack[::-1],
|
||||||
[data_dff_clk_pos, mid_pos, clk_steiner_pos])
|
[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):
|
def route_control_logic(self):
|
||||||
""" Route the control logic pins that are not inputs """
|
""" Route the control logic pins that are not inputs """
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue