mirror of https://github.com/VLSIDA/OpenRAM.git
Convert channel router to take netlist of pins rather than names.
This commit is contained in:
parent
a7bc9e0de0
commit
4df862d8af
|
|
@ -745,13 +745,14 @@ class layout(lef.lef):
|
|||
self.add_wire(layer_stack, [pin.center(), mid, trunk_mid])
|
||||
|
||||
|
||||
def create_channel_route(self, netlist, pins, offset,
|
||||
layer_stack=("metal1", "via1", "metal2"), pitch=None,
|
||||
def create_channel_route(self, netlist,
|
||||
offset,
|
||||
layer_stack=("metal1", "via1", "metal2"),
|
||||
pitch=None,
|
||||
vertical=False):
|
||||
"""
|
||||
The net list is a list of the nets. Each net is a list of pin
|
||||
names to be connected. Pins is a dictionary of the pin names
|
||||
to the pin structures. Offset is the lower-left of where the
|
||||
The net list is a list of the nets. Each net is a list of pins
|
||||
to be connected. Offset is the lower-left of where the
|
||||
routing channel will start. This does NOT try to minimize the
|
||||
number of tracks -- instead, it picks an order to avoid the
|
||||
vertical conflicts between pins.
|
||||
|
|
@ -786,7 +787,10 @@ class layout(lef.lef):
|
|||
|
||||
def vcg_pin_overlap(pin1, pin2, vertical):
|
||||
""" Check for vertical or horizontal overlap of the two pins """
|
||||
|
||||
# FIXME: If the pins are not in a row, this may break.
|
||||
# However, a top pin shouldn't overlap another top pin, for example, so the
|
||||
# extra comparison *shouldn't* matter.
|
||||
|
||||
# Pin 1 must be in the "BOTTOM" set
|
||||
x_overlap = pin1.by() < pin2.by() and abs(pin1.center().x-pin2.center().x)<pitch
|
||||
|
||||
|
|
@ -815,10 +819,7 @@ class layout(lef.lef):
|
|||
for pin_list in netlist:
|
||||
net_name = "n{}".format(index)
|
||||
index += 1
|
||||
nets[net_name] = []
|
||||
for pin_name in pin_list:
|
||||
pin = pins[pin_name]
|
||||
nets[net_name].append(pin)
|
||||
nets[net_name] = pin_list
|
||||
|
||||
# Find the vertical pin conflicts
|
||||
# FIXME: O(n^2) but who cares for now
|
||||
|
|
@ -868,23 +869,21 @@ class layout(lef.lef):
|
|||
offset += vector(0,pitch)
|
||||
|
||||
|
||||
def create_vertical_channel_route(self, netlist, pins, offset,
|
||||
def create_vertical_channel_route(self, netlist, offset,
|
||||
layer_stack=("metal1", "via1", "metal2"),
|
||||
pitch=None):
|
||||
"""
|
||||
Wrapper to create a vertical channel route
|
||||
"""
|
||||
self.create_channel_route(netlist, pins, offset, layer_stack,
|
||||
pitch, vertical=True)
|
||||
self.create_channel_route(netlist, offset, layer_stack, pitch, vertical=True)
|
||||
|
||||
def create_horizontal_channel_route(self, netlist, pins, offset,
|
||||
def create_horizontal_channel_route(self, netlist, offset,
|
||||
layer_stack=("metal1", "via1", "metal2"),
|
||||
pitch=None):
|
||||
"""
|
||||
Wrapper to create a horizontal channel route
|
||||
"""
|
||||
self.create_channel_route(netlist, pins, offset,
|
||||
layer_stack, pitch, vertical=False)
|
||||
self.create_channel_route(netlist, offset, layer_stack, pitch, vertical=False)
|
||||
|
||||
def add_enclosure(self, insts, layer="nwell"):
|
||||
""" Add a layer that surrounds the given instances. Useful
|
||||
|
|
|
|||
|
|
@ -907,6 +907,9 @@ class bank(design.design):
|
|||
inst1 = self.bitcell_array_inst
|
||||
inst1_bl_name = self.bl_names[port]+"_{}"
|
||||
inst1_br_name = self.br_names[port]+"_{}"
|
||||
|
||||
# The column mux is constructed to match the bitline pitch, so we can directly connect
|
||||
# here and not channel route the bitlines.
|
||||
self.connect_bitlines(inst1=inst1, inst2=inst2, num_bits=self.num_cols,
|
||||
inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name)
|
||||
|
||||
|
|
@ -927,8 +930,8 @@ class bank(design.design):
|
|||
inst1_bl_name = "bl_{}"
|
||||
inst1_br_name = "br_{}"
|
||||
|
||||
self.connect_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size,
|
||||
inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name)
|
||||
self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size,
|
||||
inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name)
|
||||
|
||||
def route_write_driver_to_column_mux_or_bitcell_array(self, port):
|
||||
""" Routing of BL and BR between sense_amp and column mux or bitcell array """
|
||||
|
|
@ -953,7 +956,11 @@ class bank(design.design):
|
|||
|
||||
inst1 = self.write_driver_array_inst[port]
|
||||
inst2 = self.sense_amp_array_inst[port]
|
||||
self.connect_bitlines(inst1, inst2, self.word_size)
|
||||
|
||||
# These should be pitch matched in the cell library,
|
||||
# but just in case, do a channel route.
|
||||
self.channel_route_bitlines(inst1=inst1, inst2=inst2, num_bits=self.word_size)
|
||||
|
||||
|
||||
|
||||
def route_sense_amp_out(self, port):
|
||||
|
|
@ -1008,14 +1015,10 @@ class bank(design.design):
|
|||
# of tracks in teh channel router yet. If we did, we could route all the bits at once!
|
||||
offset = bottom_inst.ul() + vector(0,self.m1_pitch)
|
||||
for bit in range(num_bits):
|
||||
bottom_names = [bottom_bl_name.format(bit), bottom_br_name.format(bit)]
|
||||
top_names = [top_bl_name.format(bit), top_br_name.format(bit)]
|
||||
bottom_names = [bottom_inst.get_pin(bottom_bl_name.format(bit)), bottom_inst.get_pin(bottom_br_name.format(bit))]
|
||||
top_names = [top_inst.get_pin(top_bl_name.format(bit)), top_inst.get_pin(top_br_name.format(bit))]
|
||||
route_map = list(zip(bottom_names, top_names))
|
||||
bottom_pins = {key: bottom_inst.get_pin(key) for key in bottom_names }
|
||||
top_pins = {key: top_inst.get_pin(key) for key in top_names }
|
||||
all_pins = {**bottom_pins, **top_pins}
|
||||
debug.check(len(all_pins)==len(bottom_pins)+len(top_pins),"Duplicate named pins in bitline channel route.")
|
||||
self.create_horizontal_channel_route(route_map, all_pins, offset)
|
||||
self.create_horizontal_channel_route(route_map, offset)
|
||||
|
||||
|
||||
def connect_bitlines(self, inst1, inst2, num_bits,
|
||||
|
|
@ -1093,79 +1096,81 @@ class bank(design.design):
|
|||
mid2 = driver_wl_pos.scale(0.5,0)+bitcell_wl_pos.scale(0.5,1)
|
||||
self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
||||
|
||||
# def route_column_address_lines(self, port):
|
||||
# if port%2:
|
||||
# self.route_column_address_lines_right(port)
|
||||
# else:
|
||||
# self.route_column_address_lines_left(port)
|
||||
|
||||
def route_column_address_lines(self, port):
|
||||
""" Connecting the select lines of column mux to the address bus """
|
||||
if not self.col_addr_size>0:
|
||||
return
|
||||
|
||||
if self.col_addr_size == 1:
|
||||
|
||||
# Connect to sel[0] and sel[1]
|
||||
decode_names = ["Zb", "Z"]
|
||||
|
||||
# The Address LSB
|
||||
self.copy_layout_pin(self.column_decoder_inst[port], "A", "addr{}_0".format(port))
|
||||
|
||||
elif self.col_addr_size > 1:
|
||||
decode_names = []
|
||||
for i in range(self.num_col_addr_lines):
|
||||
decode_names.append("out_{}".format(i))
|
||||
|
||||
for i in range(self.col_addr_size):
|
||||
decoder_name = "in_{}".format(i)
|
||||
addr_name = "addr{0}_{1}".format(port,i)
|
||||
self.copy_layout_pin(self.column_decoder_inst[port], decoder_name, addr_name)
|
||||
|
||||
if port%2:
|
||||
self.route_column_address_lines_right(port)
|
||||
offset = self.column_decoder_inst[port].ll() - vector(self.num_col_addr_lines*self.m2_pitch, 0)
|
||||
else:
|
||||
self.route_column_address_lines_left(port)
|
||||
|
||||
def route_column_address_lines_left(self, port):
|
||||
""" Connecting the select lines of column mux to the address bus """
|
||||
if not self.col_addr_size>0:
|
||||
return
|
||||
|
||||
if self.col_addr_size == 1:
|
||||
|
||||
# Connect to sel[0] and sel[1]
|
||||
decode_names = ["Zb", "Z"]
|
||||
|
||||
# The Address LSB
|
||||
self.copy_layout_pin(self.column_decoder_inst[port], "A", "addr{}_0".format(port))
|
||||
|
||||
elif self.col_addr_size > 1:
|
||||
decode_names = []
|
||||
for i in range(self.num_col_addr_lines):
|
||||
decode_names.append("out_{}".format(i))
|
||||
|
||||
for i in range(self.col_addr_size):
|
||||
decoder_name = "in_{}".format(i)
|
||||
addr_name = "addr{0}_{1}".format(port,i)
|
||||
self.copy_layout_pin(self.column_decoder_inst[port], decoder_name, addr_name)
|
||||
|
||||
offset = self.column_decoder_inst[port].lr() + vector(self.m2_pitch, 0)
|
||||
offset = self.column_decoder_inst[port].lr() + vector(self.m2_pitch, 0)
|
||||
|
||||
decode_pins = [self.column_decoder_inst[port].get_pin(x) for x in decode_names]
|
||||
|
||||
sel_names = ["sel_{}".format(x) for x in range(self.num_col_addr_lines)]
|
||||
column_mux_pins = [self.column_mux_array_inst[port].get_pin(x) for x in sel_names]
|
||||
|
||||
route_map = list(zip(decode_pins, column_mux_pins))
|
||||
self.create_vertical_channel_route(route_map, offset)
|
||||
|
||||
route_map = list(zip(decode_names, sel_names))
|
||||
decode_pins = {key: self.column_decoder_inst[port].get_pin(key) for key in decode_names }
|
||||
column_mux_pins = {key: self.column_mux_array_inst[port].get_pin(key) for key in sel_names }
|
||||
# Combine the dff and bank pins into a single dictionary of pin name to pin.
|
||||
all_pins = {**decode_pins, **column_mux_pins}
|
||||
self.create_vertical_channel_route(route_map, all_pins, offset)
|
||||
# def route_column_address_lines_right(self, port):
|
||||
# """ Connecting the select lines of column mux to the address bus """
|
||||
# if not self.col_addr_size>0:
|
||||
# return
|
||||
|
||||
def route_column_address_lines_right(self, port):
|
||||
""" Connecting the select lines of column mux to the address bus """
|
||||
if not self.col_addr_size>0:
|
||||
return
|
||||
|
||||
if self.col_addr_size == 1:
|
||||
# if self.col_addr_size == 1:
|
||||
|
||||
# Connect to sel[0] and sel[1]
|
||||
decode_names = ["Zb", "Z"]
|
||||
# # Connect to sel[0] and sel[1]
|
||||
# decode_names = ["Zb", "Z"]
|
||||
|
||||
# The Address LSB
|
||||
self.copy_layout_pin(self.column_decoder_inst[port], "A", "addr{}_0".format(port))
|
||||
# # The Address LSB
|
||||
# self.copy_layout_pin(self.column_decoder_inst[port], "A", "addr{}_0".format(port))
|
||||
|
||||
elif self.col_addr_size > 1:
|
||||
decode_names = []
|
||||
for i in range(self.num_col_addr_lines):
|
||||
decode_names.append("out_{}".format(i))
|
||||
# elif self.col_addr_size > 1:
|
||||
# decode_names = []
|
||||
# for i in range(self.num_col_addr_lines):
|
||||
# decode_names.append("out_{}".format(i))
|
||||
|
||||
for i in range(self.col_addr_size):
|
||||
decoder_name = "in_{}".format(i)
|
||||
addr_name = "addr{0}_{1}".format(port,i)
|
||||
self.copy_layout_pin(self.column_decoder_inst[port], decoder_name, addr_name)
|
||||
# for i in range(self.col_addr_size):
|
||||
# decoder_name = "in_{}".format(i)
|
||||
# addr_name = "addr{0}_{1}".format(port,i)
|
||||
# self.copy_layout_pin(self.column_decoder_inst[port], decoder_name, addr_name)
|
||||
|
||||
offset = self.column_decoder_inst[port].ll() - vector(self.num_col_addr_lines*self.m2_pitch, 0)
|
||||
# offset = self.column_decoder_inst[port].ll() - vector(self.num_col_addr_lines*self.m2_pitch, 0)
|
||||
|
||||
sel_names = ["sel_{}".format(x) for x in range(self.num_col_addr_lines)]
|
||||
# sel_names = ["sel_{}".format(x) for x in range(self.num_col_addr_lines)]
|
||||
|
||||
route_map = list(zip(decode_names, sel_names))
|
||||
decode_pins = {key: self.column_decoder_inst[port].get_pin(key) for key in decode_names }
|
||||
column_mux_pins = {key: self.column_mux_array_inst[port].get_pin(key) for key in sel_names }
|
||||
# Combine the dff and bank pins into a single dictionary of pin name to pin.
|
||||
all_pins = {**decode_pins, **column_mux_pins}
|
||||
self.create_vertical_channel_route(route_map, all_pins, offset)
|
||||
# route_map = list(zip(decode_names, sel_names))
|
||||
# decode_pins = {key: self.column_decoder_inst[port].get_pin(key) for key in decode_names }
|
||||
# column_mux_pins = {key: self.column_mux_array_inst[port].get_pin(key) for key in sel_names }
|
||||
# # Combine the dff and bank pins into a single dictionary of pin name to pin.
|
||||
# all_pins = {**decode_pins, **column_mux_pins}
|
||||
# self.create_vertical_channel_route(route_map, all_pins, offset)
|
||||
|
||||
|
||||
def add_lvs_correspondence_points(self):
|
||||
|
|
|
|||
|
|
@ -278,17 +278,20 @@ class sram_1bank(sram_base):
|
|||
""" Connect the output of the data flops to the write driver """
|
||||
# This is where the channel will start (y-dimension at least)
|
||||
for port in self.write_ports:
|
||||
offset = self.data_dff_insts[port].ul() + vector(0, 2*self.m1_pitch)
|
||||
if port%2:
|
||||
offset = self.data_dff_insts[port].ll() - vector(0, (self.word_size+2)*self.m1_pitch)
|
||||
else:
|
||||
offset = self.data_dff_insts[port].ul() + vector(0, 2*self.m1_pitch)
|
||||
|
||||
|
||||
dff_names = ["dout_{}".format(x) for x in range(self.word_size)]
|
||||
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)]
|
||||
|
||||
route_map = list(zip(bank_names, dff_names))
|
||||
dff_pins = {key: self.data_dff_insts[port].get_pin(key) for key in dff_names }
|
||||
bank_pins = {key: self.bank_inst.get_pin(key) for key in bank_names }
|
||||
# Combine the dff and bank pins into a single dictionary of pin name to pin.
|
||||
all_pins = {**dff_pins, **bank_pins}
|
||||
self.create_horizontal_channel_route(route_map, all_pins, offset)
|
||||
bank_pins = [self.bank_inst.get_pin(x) for x in bank_names]
|
||||
|
||||
route_map = list(zip(bank_pins, dff_pins))
|
||||
self.create_horizontal_channel_route(route_map, offset)
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue