fixed merge conflict

This commit is contained in:
jsowash 2019-07-04 11:14:32 -07:00
commit 02a0cd71ac
130 changed files with 2394 additions and 957 deletions

View File

@ -214,7 +214,13 @@ class layout():
return self.pin_map[text]
else:
return set()
def get_pin_names(self):
"""
Return a pin list of all pins
"""
return self.pin_map.keys()
def copy_layout_pin(self, instance, pin_name, new_name=""):
"""
Create a copied version of the layout pin at the current level.
@ -226,6 +232,16 @@ class layout():
new_name = pin.name
self.add_layout_pin(new_name, pin.layer, pin.ll(), pin.width(), pin.height())
def copy_layout_pins(self, instance, prefix=""):
"""
Create a copied version of the layout pin at the current level.
You can optionally rename the pin to a new name.
"""
for pin_name in self.pin_map.keys():
pins=instance.get_pins(pin_name)
for pin in pins:
self.add_layout_pin(prefix+pin_name, pin.layer, pin.ll(), pin.width(), pin.height())
def add_layout_pin_segment_center(self, text, layer, start, end):
"""
Creates a path like pin with center-line convention
@ -880,10 +896,10 @@ class layout():
"""
self.create_channel_route(netlist, offset, layer_stack, pitch, vertical=False)
def add_boundary(self):
def add_boundary(self, offset=vector(0,0)):
""" Add boundary for debugging dimensions """
self.add_rect(layer="boundary",
offset=vector(0,0),
offset=offset,
height=self.height,
width=self.width)

View File

@ -114,6 +114,12 @@ class spice():
output_list.append(pin)
return output_list
def copy_pins(self, other_module, suffix=""):
""" This will copy all of the pins from the other module and add an optional suffix."""
for pin in other_module.pins:
self.add_pin(pin+suffix, other_module.get_pin_type(pin))
def get_inouts(self):
""" These use pin types to determine pin lists. These
may be over-ridden by submodules that didn't use pin directions yet."""

View File

@ -42,15 +42,6 @@ class bitcell(design.design):
cin = 3 #Assumes always a minimum sizes inverter. Could be specified in the tech.py file.
return logical_effort.logical_effort('bitline', size, cin, load, parasitic_delay, False)
def list_bitcell_pins(self, col, row):
""" Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """
bitcell_pins = ["bl_{0}".format(col),
"br_{0}".format(col),
"wl_{0}".format(row),
"vdd",
"gnd"]
return bitcell_pins
def list_all_wl_names(self):
""" Creates a list of all wordline pin names """
row_pins = ["wl"]

View File

@ -0,0 +1,48 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import design
import debug
import utils
from tech import GDS,layer,parameter,drc
import logical_effort
class dummy_bitcell(design.design):
"""
A single bit cell (6T, 8T, etc.) This module implements the
single memory cell used in the design. It is a hand-made cell, so
the layout and netlist should be available in the technology
library.
"""
pin_names = ["bl", "br", "wl", "vdd", "gnd"]
(width,height) = utils.get_libcell_size("dummy_cell_6t", GDS["unit"], layer["boundary"])
pin_map = utils.get_libcell_pins(pin_names, "dummy_cell_6t", GDS["unit"])
def __init__(self, name=""):
# Ignore the name argument
design.design.__init__(self, "dummy_cell_6t")
debug.info(2, "Create dummy bitcell")
self.width = dummy_bitcell.width
self.height = dummy_bitcell.height
self.pin_map = dummy_bitcell.pin_map
def analytical_power(self, corner, load):
"""Bitcell power in nW. Only characterizes leakage."""
from tech import spice
leakage = spice["bitcell_leakage"]
dynamic = 0 #temporary
total_power = self.return_power(dynamic, leakage)
return total_power
def get_wl_cin(self):
"""Return the relative capacitance of the access transistor gates"""
#This is a handmade cell so the value must be entered in the tech.py file or estimated.
#Calculated in the tech file by summing the widths of all the related gates and dividing by the minimum width.
access_tx_cin = parameter["6T_access_size"]/drc["minwidth_tx"]
return 2*access_tx_cin

View File

@ -32,6 +32,14 @@ class replica_bitcell(design.design):
self.pin_map = replica_bitcell.pin_map
self.add_pin_types(self.type_list)
def analytical_power(self, corner, load):
"""Bitcell power in nW. Only characterizes leakage."""
from tech import spice
leakage = spice["bitcell_leakage"]
dynamic = 0 #temporary
total_power = self.return_power(dynamic, leakage)
return total_power
def get_wl_cin(self):
"""Return the relative capacitance of the access transistor gates"""
#This is a handmade cell so the value must be entered in the tech.py file or estimated.

View File

@ -28,6 +28,7 @@ class bank(design.design):
def __init__(self, sram_config, name=""):
self.sram_config = sram_config
sram_config.set_local_config(self)
if name == "":
@ -120,41 +121,22 @@ class bank(design.design):
def route_bitlines(self, port):
""" Route the bitlines depending on the port type rw, w, or r. """
if port in self.write_ports:
self.route_port_data_in(port)
if port in self.read_ports:
self.route_port_data_out(port)
self.route_port_data_to_bitcell_array(port)
if port in self.readwrite_ports:
# write_driver -> sense_amp -> (column_mux) -> precharge -> bitcell_array
self.route_write_driver_in(port)
self.route_sense_amp_out(port)
self.route_write_driver_to_sense_amp(port)
self.route_sense_amp_to_column_mux_or_precharge_array(port)
self.route_column_mux_to_precharge_array(port)
self.route_precharge_to_bitcell_array(port)
elif port in self.read_ports:
# sense_amp -> (column_mux) -> precharge -> bitcell_array
self.route_sense_amp_out(port)
self.route_sense_amp_to_column_mux_or_precharge_array(port)
self.route_column_mux_to_precharge_array(port)
self.route_precharge_to_bitcell_array(port)
else:
# write_driver -> (column_mux) -> bitcell_array
self.route_write_driver_in(port)
self.route_write_driver_to_column_mux_or_bitcell_array(port)
self.route_column_mux_to_bitcell_array(port)
def create_instances(self):
""" Create the instances of the netlist. """
self.create_bitcell_array()
self.create_precharge_array()
self.create_column_mux_array()
self.create_sense_amp_array()
self.create_write_driver_array()
self.create_port_data()
self.create_row_decoder()
self.create_wordline_driver()
self.create_column_decoder()
self.create_bank_select()
def compute_instance_offsets(self):
@ -162,39 +144,21 @@ class bank(design.design):
Compute the empty instance offsets for port0 and port1 (if needed)
"""
# These are created even if the port type (e.g. read only)
# doesn't need the instance (e.g. write driver).
# Create the bottom-up and left to right order of components in each port
# which deepends on the port type rw, w, r
self.vertical_port_order = []
self.vertical_port_offsets = []
for port in self.all_ports:
self.vertical_port_order.append([])
self.vertical_port_offsets.append([None]*4)
# For later placement, these are fixed in the order: write driver,
# sense amp, clumn mux, precharge, even if the item is not used
# in a given port (it will be None then)
self.vertical_port_order[port].append(self.write_driver_array_inst[port])
self.vertical_port_order[port].append(self.sense_amp_array_inst[port])
self.vertical_port_order[port].append(self.column_mux_array_inst[port])
self.vertical_port_order[port].append(self.precharge_array_inst[port])
# For the odd ones they will go on top, so reverse in place
if port%2:
self.vertical_port_order[port]=self.vertical_port_order[port][::-1]
self.write_driver_offsets = [None]*len(self.all_ports)
self.sense_amp_offsets = [None]*len(self.all_ports)
self.column_mux_offsets = [None]*len(self.all_ports)
self.precharge_offsets = [None]*len(self.all_ports)
self.port_data_offsets = [None]*len(self.all_ports)
self.wordline_driver_offsets = [None]*len(self.all_ports)
self.row_decoder_offsets = [None]*len(self.all_ports)
self.column_decoder_offsets = [None]*len(self.all_ports)
self.bank_select_offsets = [None]*len(self.all_ports)
# The center point for these cells are the upper-right corner of
# the bitcell array.
# The decoder/driver logic is placed on the right and mirrored on Y-axis.
# The write/sense/precharge/mux is placed on the top and mirrored on the X-axis.
self.bitcell_array_top = self.bitcell_array.height
self.bitcell_array_right = self.bitcell_array.width + self.m1_width + self.m2_gap
self.compute_instance_port0_offsets()
if len(self.all_ports)==2:
@ -214,23 +178,7 @@ class bank(design.design):
# LOWER RIGHT QUADRANT
# Below the bitcell array
y_height = 0
for p in self.vertical_port_order[port]:
if p==None:
continue
y_height += p.height + self.m2_gap
y_offset = -y_height
for i,p in enumerate(self.vertical_port_order[port]):
if p==None:
continue
self.vertical_port_offsets[port][i]=vector(0,y_offset)
y_offset += (p.height + self.m2_gap)
self.write_driver_offsets[port] = self.vertical_port_offsets[port][0]
self.sense_amp_offsets[port] = self.vertical_port_offsets[port][1]
self.column_mux_offsets[port] = self.vertical_port_offsets[port][2]
self.precharge_offsets[port] = self.vertical_port_offsets[port][3]
self.port_data_offsets[port] = vector(0,0)
# UPPER LEFT QUADRANT
# To the left of the bitcell array
@ -255,7 +203,7 @@ class bank(design.design):
# Bank select gets placed below the column decoder (x_offset doesn't change)
if self.col_addr_size > 0:
y_offset = min(self.column_decoder_offsets[port].y, self.column_mux_offsets[port].y)
y_offset = min(self.column_decoder_offsets[port].y, self.port_data[port].column_mux_offset.y)
else:
y_offset = self.row_decoder_offsets[port].y
if self.num_banks > 1:
@ -269,33 +217,17 @@ class bank(design.design):
port=1
# The center point for these cells are the upper-right corner of
# the bitcell array.
# The decoder/driver logic is placed on the right and mirrored on Y-axis.
# The write/sense/precharge/mux is placed on the top and mirrored on the X-axis.
# LOWER LEFT QUADRANT
# Bitcell array is placed at (0,0)
# UPPER LEFT QUADRANT
# Above the bitcell array
y_offset = self.bitcell_array.height + self.m2_gap
for i,p in enumerate(self.vertical_port_order[port]):
if p==None:
continue
y_offset += (p.height + self.m2_gap)
self.vertical_port_offsets[port][i]=vector(0,y_offset)
# Reversed order
self.write_driver_offsets[port] = self.vertical_port_offsets[port][3]
self.sense_amp_offsets[port] = self.vertical_port_offsets[port][2]
self.column_mux_offsets[port] = self.vertical_port_offsets[port][1]
self.precharge_offsets[port] = self.vertical_port_offsets[port][0]
self.port_data_offsets[port] = vector(0,self.bitcell_array_top)
# LOWER RIGHT QUADRANT
# To the left of the bitcell array
# The wordline driver is placed to the right of the main decoder width.
x_offset = self.bitcell_array.width + self.m2_gap + self.wordline_driver.width
x_offset = self.bitcell_array_right + self.wordline_driver.width
self.wordline_driver_offsets[port] = vector(x_offset,0)
x_offset += self.row_decoder.width + self.m2_gap
self.row_decoder_offsets[port] = vector(x_offset,0)
@ -303,19 +235,19 @@ class bank(design.design):
# UPPER RIGHT QUADRANT
# Place the col decoder right aligned with wordline driver plus halfway under row decoder
# Above the bitcell array with a well spacing
x_offset = self.bitcell_array.width + self.central_bus_width[port] + self.wordline_driver.width
x_offset = self.bitcell_array_right + self.central_bus_width[port] + self.wordline_driver.width
if self.col_addr_size > 0:
x_offset += self.column_decoder.width + self.col_addr_bus_width
y_offset = self.bitcell_array.height + self.column_decoder.height + self.m2_gap
y_offset = self.bitcell_array_top + self.m2_gap + self.column_decoder.height
else:
y_offset = self.bitcell_array.height
y_offset = self.bitcell_array_top
y_offset += 2*drc("well_to_well")
self.column_decoder_offsets[port] = vector(x_offset,y_offset)
# Bank select gets placed above the column decoder (x_offset doesn't change)
if self.col_addr_size > 0:
y_offset = max(self.column_decoder_offsets[port].y + self.column_decoder.height,
self.column_mux_offsets[port].y + self.column_mux_array[port].height)
self.port_data[port].column_mux_offset.y + self.port_data[port].column_mux_array.height)
else:
y_offset = self.row_decoder_offsets[port].y
self.bank_select_offsets[port] = vector(x_offset,y_offset)
@ -329,12 +261,7 @@ class bank(design.design):
self.place_bitcell_array(self.bitcell_array_offset)
# LOWER RIGHT QUADRANT
# These are fixed in the order: write driver, sense amp, clumn mux, precharge,
# even if the item is not used in a given port (it will be None then)
self.place_write_driver_array(self.write_driver_offsets)
self.place_sense_amp_array(self.sense_amp_offsets)
self.place_column_mux_array(self.column_mux_offsets)
self.place_precharge_array(self.precharge_offsets)
self.place_port_data(self.port_data_offsets)
# UPPER LEFT QUADRANT
self.place_row_decoder(self.row_decoder_offsets)
@ -417,39 +344,13 @@ class bank(design.design):
rows=self.num_rows)
self.add_mod(self.bitcell_array)
self.precharge_array = []
self.port_data = []
for port in self.all_ports:
if port in self.read_ports:
temp_pre = factory.create(module_type="precharge_array",
columns=self.num_cols,
bitcell_bl=self.bl_names[port],
bitcell_br=self.br_names[port])
self.precharge_array.append(temp_pre)
self.add_mod(self.precharge_array[port])
else:
self.precharge_array.append(None)
if self.col_addr_size > 0:
self.column_mux_array = []
for port in self.all_ports:
temp_col = factory.create(module_type="column_mux_array",
columns=self.num_cols,
word_size=self.word_size,
bitcell_bl=self.bl_names[port],
bitcell_br=self.br_names[port])
self.column_mux_array.append(temp_col)
self.add_mod(self.column_mux_array[port])
self.sense_amp_array = factory.create(module_type="sense_amp_array",
word_size=self.word_size,
words_per_row=self.words_per_row)
self.add_mod(self.sense_amp_array)
self.write_driver_array = factory.create(module_type="write_driver_array",
columns=self.num_cols,
word_size=self.word_size)
self.add_mod(self.write_driver_array)
temp_pre = factory.create(module_type="port_data",
sram_config=self.sram_config,
port=port)
self.port_data.append(temp_pre)
self.add_mod(self.port_data[port])
self.row_decoder = factory.create(module_type="decoder",
rows=self.num_rows)
@ -492,142 +393,48 @@ class bank(design.design):
self.bitcell_array_inst.place(offset)
def create_precharge_array(self):
""" Creating Precharge """
self.precharge_array_inst = [None]*len(self.all_ports)
for port in self.read_ports:
self.precharge_array_inst[port]=self.add_inst(name="precharge_array{}".format(port),
mod=self.precharge_array[port])
temp = []
for i in range(self.num_cols):
temp.append(self.bl_names[port]+"_{0}".format(i))
temp.append(self.br_names[port]+"_{0}".format(i))
temp.extend([self.prefix+"p_en_bar{0}".format(port), "vdd"])
self.connect_inst(temp)
def place_precharge_array(self, offsets):
""" Placing Precharge """
debug.check(len(offsets)>=len(self.all_ports), "Insufficient offsets to place precharge array.")
for port in self.read_ports:
if port%2 == 1:
mirror = "MX"
else:
mirror = "R0"
self.precharge_array_inst[port].place(offset=offsets[port], mirror=mirror)
def create_column_mux_array(self):
""" Creating Column Mux when words_per_row > 1 . """
self.column_mux_array_inst = [None]*len(self.all_ports)
if self.col_addr_size == 0:
return
def create_port_data(self):
""" Creating Port Data """
self.port_data_inst = [None]*len(self.all_ports)
for port in self.all_ports:
self.column_mux_array_inst[port] = self.add_inst(name="column_mux_array{}".format(port),
mod=self.column_mux_array[port])
self.port_data_inst[port]=self.add_inst(name="port_data{}".format(port),
mod=self.port_data[port])
temp = []
for col in range(self.num_cols):
temp.append(self.bl_names[port]+"_{0}".format(col))
temp.append(self.br_names[port]+"_{0}".format(col))
for word in range(self.words_per_row):
temp.append("sel{0}_{1}".format(port,word))
for bit in range(self.word_size):
temp.append(self.bl_names[port]+"_out_{0}".format(bit))
temp.append(self.br_names[port]+"_out_{0}".format(bit))
temp.append("gnd")
for col in range(self.num_cols):
temp.append("{0}_{1}".format(self.bl_names[port],col))
temp.append("{0}_{1}".format(self.br_names[port],col))
if port in self.read_ports:
for bit in range(self.word_size):
temp.append("dout{0}_{1}".format(port,bit))
if port in self.write_ports:
for bit in range(self.word_size):
temp.append("din{0}_{1}".format(port,bit))
# Will be empty if no col addr lines
sel_names = ["sel{0}_{1}".format(port,x) for x in range(self.num_col_addr_lines)]
temp.extend(sel_names)
if port in self.read_ports:
temp.append("s_en{0}".format(port))
if port in self.read_ports:
temp.append("p_en_bar{0}".format(port))
if port in self.write_ports:
temp.append("w_en{0}".format(port))
temp.extend(["vdd","gnd"])
self.connect_inst(temp)
def place_column_mux_array(self, offsets):
""" Placing Column Mux when words_per_row > 1 . """
if self.col_addr_size == 0:
return
debug.check(len(offsets)>=len(self.all_ports), "Insufficient offsets to place column mux array.")
def place_port_data(self, offsets):
""" Placing Port Data """
for port in self.all_ports:
# Top one is unflipped, bottom is flipped along X direction
if port%2 == 1:
mirror = "MX"
else:
mirror = "R0"
self.column_mux_array_inst[port].place(offset=offsets[port], mirror=mirror)
def create_sense_amp_array(self):
""" Creating Sense amp """
self.sense_amp_array_inst = [None]*len(self.all_ports)
for port in self.read_ports:
self.sense_amp_array_inst[port] = self.add_inst(name="sense_amp_array{}".format(port),
mod=self.sense_amp_array)
temp = []
for bit in range(self.word_size):
temp.append("dout{0}_{1}".format(port,bit))
if self.words_per_row == 1:
temp.append(self.bl_names[port]+"_{0}".format(bit))
temp.append(self.br_names[port]+"_{0}".format(bit))
else:
temp.append(self.bl_names[port]+"_out_{0}".format(bit))
temp.append(self.br_names[port]+"_out_{0}".format(bit))
temp.extend([self.prefix+"s_en{}".format(port), "vdd", "gnd"])
self.connect_inst(temp)
def place_sense_amp_array(self, offsets):
""" Placing Sense amp """
debug.check(len(offsets)>=len(self.read_ports), "Insufficient offsets to place sense amp array.")
for port in self.read_ports:
if port%2 == 1:
mirror = "MX"
else:
mirror = "R0"
self.sense_amp_array_inst[port].place(offset=offsets[port], mirror=mirror)
def create_write_driver_array(self):
""" Creating Write Driver """
self.write_driver_array_inst = [None]*len(self.all_ports)
for port in self.write_ports:
self.write_driver_array_inst[port] = self.add_inst(name="write_driver_array{}".format(port),
mod=self.write_driver_array)
temp = []
for bit in range(self.word_size):
temp.append("din{0}_{1}".format(port,bit))
for bit in range(self.word_size):
if (self.words_per_row == 1):
temp.append(self.bl_names[port]+"_{0}".format(bit))
temp.append(self.br_names[port]+"_{0}".format(bit))
else:
temp.append(self.bl_names[port]+"_out_{0}".format(bit))
temp.append(self.br_names[port]+"_out_{0}".format(bit))
temp.extend([self.prefix+"w_en{0}".format(port), "vdd", "gnd"])
self.connect_inst(temp)
def place_write_driver_array(self, offsets):
""" Placing Write Driver """
debug.check(len(offsets)>=len(self.write_ports), "Insufficient offsets to place write driver array.")
for port in self.write_ports:
if port%2 == 1:
mirror = "MX"
else:
mirror = "R0"
self.write_driver_array_inst[port].place(offset=offsets[port], mirror=mirror)
self.port_data_inst[port].place(offset=offsets[port], mirror=mirror)
def create_row_decoder(self):
""" Create the hierarchical row decoder """
@ -862,8 +669,8 @@ class bank(design.design):
# Port 1
if len(self.all_ports)==2:
# The other control bus is routed up to two pitches above the bitcell array
control_bus_length = self.max_y_offset - self.bitcell_array.height - 2*self.m1_pitch
control_bus_offset = vector(self.bitcell_array.width + self.m2_width,
control_bus_length = self.max_y_offset - self.bitcell_array_top - 2*self.m1_pitch
control_bus_offset = vector(self.bitcell_array_right,
self.max_y_offset - control_bus_length)
self.bus_xoffset[1] = self.create_bus(layer="metal2",
@ -875,10 +682,10 @@ class bank(design.design):
make_pins=(self.num_banks==1))
def route_precharge_to_bitcell_array(self, port):
""" Routing of BL and BR between pre-charge and bitcell array """
def route_port_data_to_bitcell_array(self, port):
""" Routing of BL and BR between port data and bitcell array """
inst2 = self.precharge_array_inst[port]
inst2 = self.port_data_inst[port]
inst1 = self.bitcell_array_inst
inst1_bl_name = self.bl_names[port]+"_{}"
inst1_br_name = self.br_names[port]+"_{}"
@ -886,96 +693,17 @@ class bank(design.design):
inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name)
def route_port_data_out(self, port):
""" Add pins for the port data out """
def route_column_mux_to_precharge_array(self, port):
""" Routing of BL and BR between col mux and precharge array """
# Only do this if we have a column mux!
if self.col_addr_size==0:
return
inst1 = self.column_mux_array_inst[port]
inst2 = self.precharge_array_inst[port]
self.connect_bitlines(inst1, inst2, self.num_cols)
def route_column_mux_to_bitcell_array(self, port):
""" Routing of BL and BR between col mux bitcell array """
# Only do this if we have a column mux!
if self.col_addr_size==0:
return
inst2 = self.column_mux_array_inst[port]
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)
def route_sense_amp_to_column_mux_or_precharge_array(self, port):
""" Routing of BL and BR between sense_amp and column mux or precharge array """
inst2 = self.sense_amp_array_inst[port]
if self.col_addr_size>0:
# Sense amp is connected to the col mux
inst1 = self.column_mux_array_inst[port]
inst1_bl_name = "bl_out_{}"
inst1_br_name = "br_out_{}"
else:
# Sense amp is directly connected to the precharge array
inst1 = self.precharge_array_inst[port]
inst1_bl_name = "bl_{}"
inst1_br_name = "br_{}"
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 """
inst2 = self.write_driver_array_inst[port]
if self.col_addr_size>0:
# Write driver is connected to the col mux
inst1 = self.column_mux_array_inst[port]
inst1_bl_name = "bl_out_{}"
inst1_br_name = "br_out_{}"
else:
# Write driver is directly connected to the bitcell array
inst1 = self.bitcell_array_inst
inst1_bl_name = self.bl_names[port]+"_{}"
inst1_br_name = self.br_names[port]+"_{}"
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_sense_amp(self, port):
""" Routing of BL and BR between write driver and sense amp """
inst1 = self.write_driver_array_inst[port]
inst2 = self.sense_amp_array_inst[port]
# 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):
""" Add pins for the sense amp output """
for bit in range(self.word_size):
data_pin = self.sense_amp_array_inst[port].get_pin("data_{}".format(bit))
data_pin = self.port_data_inst[port].get_pin("dout_{0}".format(bit))
self.add_layout_pin_rect_center(text="dout{0}_{1}".format(port,bit),
layer=data_pin.layer,
offset=data_pin.center(),
height=data_pin.height(),
width=data_pin.width())
def route_row_decoder(self, port):
""" Routes the row decoder inputs and supplies """
@ -988,13 +716,13 @@ class bank(design.design):
self.copy_layout_pin(self.row_decoder_inst[port], decoder_name, addr_name)
def route_write_driver_in(self, port):
""" Connecting write driver """
def route_port_data_in(self, port):
""" Connecting port data in """
for row in range(self.word_size):
data_name = "data_{}".format(row)
data_name = "din_{}".format(row)
din_name = "din{0}_{1}".format(port,row)
self.copy_layout_pin(self.write_driver_array_inst[port], data_name, din_name)
self.copy_layout_pin(self.port_data_inst[port], data_name, din_name)
def channel_route_bitlines(self, inst1, inst2, num_bits,
inst1_bl_name="bl_{}", inst1_br_name="br_{}",
@ -1129,7 +857,7 @@ class bank(design.design):
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]
column_mux_pins = [self.port_data_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)
@ -1192,13 +920,13 @@ class bank(design.design):
connection = []
if port in self.read_ports:
connection.append((self.prefix+"p_en_bar{}".format(port), self.precharge_array_inst[port].get_pin("en_bar").lc()))
connection.append((self.prefix+"p_en_bar{}".format(port), self.port_data_inst[port].get_pin("p_en_bar").lc()))
if port in self.write_ports:
connection.append((self.prefix+"w_en{}".format(port), self.write_driver_array_inst[port].get_pin("en").lc()))
connection.append((self.prefix+"w_en{}".format(port), self.port_data_inst[port].get_pin("w_en").lc()))
if port in self.read_ports:
connection.append((self.prefix+"s_en{}".format(port), self.sense_amp_array_inst[port].get_pin("en").lc()))
connection.append((self.prefix+"s_en{}".format(port), self.port_data_inst[port].get_pin("s_en").lc()))
for (control_signal, pin_pos) in connection:
control_pos = vector(self.bus_xoffset[port][control_signal].x ,pin_pos.y)
@ -1230,26 +958,26 @@ class bank(design.design):
#FIXME: Array delay is the same for every port.
word_driver_slew = 0
if self.words_per_row > 1:
bitline_ext_load = self.column_mux_array[port].get_drain_cin()
bitline_ext_load = self.port_data[port].column_mux_array.get_drain_cin()
else:
bitline_ext_load = self.sense_amp_array.get_drain_cin()
bitline_ext_load = self.port_data[port].sense_amp_array.get_drain_cin()
bitcell_array_delay = self.bitcell_array.analytical_delay(corner, word_driver_slew, bitline_ext_load)
bitcell_array_slew = 0
#This also essentially creates the same delay for each port. Good structure, no substance
if self.words_per_row > 1:
sa_load = self.sense_amp_array.get_drain_cin()
column_mux_delay = self.column_mux_array[port].analytical_delay(corner,
bitcell_array_slew,
sa_load)
sa_load = self.port_data[port].sense_amp_array.get_drain_cin()
column_mux_delay = self.port_data[port].column_mux_array.analytical_delay(corner,
bitcell_array_slew,
sa_load)
else:
column_mux_delay = []
column_mux_slew = 0
sense_amp_delay = self.sense_amp_array.analytical_delay(corner,
column_mux_slew,
load)
sense_amp_delay = self.port_data[port].sense_amp_array.analytical_delay(corner,
column_mux_slew,
load)
# output load of bitcell_array is set to be only small part of bl for sense amp.
return bitcell_array_delay + column_mux_delay + sense_amp_delay
@ -1270,7 +998,8 @@ class bank(design.design):
def get_w_en_cin(self):
"""Get the relative capacitance of all the clk connections in the bank"""
#wl_en only used in the wordline driver.
return self.write_driver.get_w_en_cin()
port = self.write_ports[0]
return self.port_data[port].write_driver.get_w_en_cin()
def get_clk_bar_cin(self):
"""Get the relative capacitance of all the clk_bar connections in the bank"""
@ -1278,19 +1007,21 @@ class bank(design.design):
#Precharges are the all the same in Mulitport, one is picked
port = self.read_ports[0]
return self.precharge_array[port].get_en_cin()
return self.port_data[port].precharge_array.get_en_cin()
def get_sen_cin(self):
"""Get the relative capacitance of all the sense amp enable connections in the bank"""
#Current bank only uses sen as an enable for the sense amps.
return self.sense_amp_array.get_en_cin()
port = self.read_ports[0]
return self.port_data[port].sense_amp_array.get_en_cin()
def graph_exclude_precharge(self):
"""Precharge adds a loop between bitlines, can be excluded to reduce complexity"""
for inst in self.precharge_array_inst:
if inst != None:
self.graph_inst_exclude.add(inst)
for port in self.read_ports:
if self.port_data[port]:
self.port_data[port].graph_exclude_precharge()
def get_cell_name(self, inst_name, row, col):
"""Gets the spice name of the target bitcell."""
return self.bitcell_array_inst.mod.get_cell_name(inst_name+'.x'+self.bitcell_array_inst.name, row, col)
return self.bitcell_array_inst.mod.get_cell_name(inst_name+'.x'+self.bitcell_array_inst.name, row, col)

View File

@ -89,7 +89,7 @@ class bank_select(design.design):
self.inv4x_nor = factory.create(module_type="pinv", height=height, size=4)
self.add_mod(self.inv4x_nor)
self.nand2 = factory.create(module_type="pnand2")
self.nand2 = factory.create(module_type="pnand2", height=height)
self.add_mod(self.nand2)
def calculate_module_offsets(self):

View File

@ -45,8 +45,8 @@ class bitcell_array(design.design):
def create_layout(self):
# We increase it by a well enclosure so the precharges don't overlap our wells
self.height = self.row_size*self.cell.height + drc("well_enclosure_active") + self.m1_width
self.width = self.column_size*self.cell.width + self.m1_width
self.height = self.row_size*self.cell.height
self.width = self.column_size*self.cell.width
xoffset = 0.0
for col in range(self.column_size):
@ -89,6 +89,24 @@ class bitcell_array(design.design):
self.cell = factory.create(module_type="bitcell")
self.add_mod(self.cell)
def list_bitcell_pins(self, col, row):
""" Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array """
bitcell_pins = []
pin_names = self.cell.list_all_bitline_names()
for pin in pin_names:
bitcell_pins.append(pin+"_{0}".format(col))
pin_names = self.cell.list_all_wl_names()
for pin in pin_names:
bitcell_pins.append(pin+"_{0}".format(row))
bitcell_pins.append("vdd")
bitcell_pins.append("gnd")
return bitcell_pins
def create_instances(self):
""" Create the module instances used in this design """
self.cell_inst = {}
@ -97,7 +115,7 @@ class bitcell_array(design.design):
name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row,col]=self.add_inst(name=name,
mod=self.cell)
self.connect_inst(self.cell.list_bitcell_pins(col, row))
self.connect_inst(self.list_bitcell_pins(col, row))
def add_layout_pins(self):
""" Add the layout pins """
@ -105,32 +123,24 @@ class bitcell_array(design.design):
row_list = self.cell.list_all_wl_names()
column_list = self.cell.list_all_bitline_names()
offset = vector(0.0, 0.0)
for col in range(self.column_size):
for cell_column in column_list:
bl_pin = self.cell_inst[0,col].get_pin(cell_column)
self.add_layout_pin(text=cell_column+"_{0}".format(col),
layer="metal2",
offset=bl_pin.ll(),
layer=bl_pin.layer,
offset=bl_pin.ll().scale(1,0),
width=bl_pin.width(),
height=self.height)
# increments to the next column width
offset.x += self.cell.width
offset.x = 0.0
for row in range(self.row_size):
for cell_row in row_list:
wl_pin = self.cell_inst[row,0].get_pin(cell_row)
self.add_layout_pin(text=cell_row+"_{0}".format(row),
layer="metal1",
offset=wl_pin.ll(),
layer=wl_pin.layer,
offset=wl_pin.ll().scale(0,1),
width=self.width,
height=wl_pin.height())
# increments to the next row height
offset.y += self.cell.height
# For every second row and column, add a via for gnd and vdd
for row in range(self.row_size):
for col in range(self.column_size):

View File

@ -0,0 +1,156 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
import debug
import design
from tech import drc
import contact
from sram_factory import factory
from vector import vector
from globals import OPTS
class dummy_array(design.design):
"""
Generate a dummy row/column for the replica array.
"""
def __init__(self, cols, rows, name):
design.design.__init__(self, name)
debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols))
self.add_comment("rows: {0} cols: {1}".format(rows, cols))
self.column_size = cols
self.row_size = rows
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
""" Create and connect the netlist """
self.add_modules()
self.add_pins()
self.create_instances()
def create_layout(self):
# We increase it by a well enclosure so the precharges don't overlap our wells
self.height = self.row_size*self.dummy_cell.height
self.width = self.column_size*self.dummy_cell.width
xoffset = 0.0
for col in range(self.column_size):
yoffset = 0.0
for row in range(self.row_size):
name = "dummy_r{0}_c{1}".format(row, col)
if row % 2:
tempy = yoffset + self.dummy_cell.height
dir_key = "MX"
else:
tempy = yoffset
dir_key = ""
self.cell_inst[row,col].place(offset=[xoffset, tempy],
mirror=dir_key)
yoffset += self.dummy_cell.height
xoffset += self.dummy_cell.width
self.add_layout_pins()
self.add_boundary()
self.DRC_LVS()
def add_pins(self):
row_list = self.cell.list_all_wl_names()
column_list = self.cell.list_all_bitline_names()
for col in range(self.column_size):
for cell_column in column_list:
self.add_pin(cell_column+"_{0}".format(col))
for row in range(self.row_size):
for cell_row in row_list:
self.add_pin(cell_row+"_{0}".format(row))
self.add_pin("vdd")
self.add_pin("gnd")
def add_modules(self):
""" Add the modules used in this design """
self.dummy_cell = factory.create(module_type="dummy_bitcell")
self.add_mod(self.dummy_cell)
self.cell = factory.create(module_type="bitcell")
def list_bitcell_pins(self, col, row):
""" Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array """
bitcell_pins = []
pin_names = self.cell.list_all_bitline_names()
for pin in pin_names:
bitcell_pins.append(pin+"_{0}".format(col))
pin_names = self.cell.list_all_wl_names()
for pin in pin_names:
bitcell_pins.append(pin+"_{0}".format(row))
bitcell_pins.append("vdd")
bitcell_pins.append("gnd")
return bitcell_pins
def create_instances(self):
""" Create the module instances used in this design """
self.cell_inst = {}
for col in range(self.column_size):
for row in range(self.row_size):
name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row,col]=self.add_inst(name=name,
mod=self.dummy_cell)
self.connect_inst(self.list_bitcell_pins(col, row))
def add_layout_pins(self):
""" Add the layout pins """
row_list = self.cell.list_all_wl_names()
column_list = self.cell.list_all_bitline_names()
for col in range(self.column_size):
for cell_column in column_list:
bl_pin = self.cell_inst[0,col].get_pin(cell_column)
self.add_layout_pin(text=cell_column+"_{0}".format(col),
layer="metal2",
offset=bl_pin.ll(),
width=bl_pin.width(),
height=self.height)
for row in range(self.row_size):
for cell_row in row_list:
wl_pin = self.cell_inst[row,0].get_pin(cell_row)
self.add_layout_pin(text=cell_row+"_{0}".format(row),
layer="metal1",
offset=wl_pin.ll(),
width=self.width,
height=wl_pin.height())
# For every second row and column, add a via for gnd and vdd
for row in range(self.row_size):
for col in range(self.column_size):
inst = self.cell_inst[row,col]
for pin_name in ["vdd", "gnd"]:
for pin in inst.get_pins(pin_name):
self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer)
def input_load(self):
wl_wire = self.gen_wl_wire()
return wl_wire.return_input_cap()
def get_wordline_cin(self):
"""Get the relative input capacitance from the wordline connections in all the bitcell"""
#A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns
bitcell_wl_cin = self.cell.get_wl_cin()
total_cin = bitcell_wl_cin * self.column_size
return total_cin

View File

@ -0,0 +1,500 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import sys
from tech import drc, parameter
import debug
import design
from sram_factory import factory
from vector import vector
from globals import OPTS
class port_data(design.design):
"""
Create the data port (column mux, sense amps, write driver, etc.)
"""
def __init__(self, sram_config, port, name=""):
sram_config.set_local_config(self)
self.port = port
if name == "":
name = "bank_{0}_{1}".format(self.word_size, self.num_words)
design.design.__init__(self, name)
debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words))
self.create_netlist()
if not OPTS.netlist_only:
debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.")
self.create_layout()
self.add_boundary()
def create_netlist(self):
self.compute_sizes()
self.add_pins()
self.add_modules()
self.create_instances()
def create_instances(self):
if self.precharge_array:
self.create_precharge_array()
else:
self.precharge_array_inst = None
if self.sense_amp_array:
self.create_sense_amp_array()
else:
self.sense_amp_array_inst = None
if self.write_driver_array:
self.create_write_driver_array()
else:
self.write_driver_array_inst = None
if self.column_mux_array:
self.create_column_mux_array()
else:
self.column_mux_array_inst = None
def create_layout(self):
self.compute_instance_offsets()
self.place_instances()
self.route_layout()
self.DRC_LVS()
def add_pins(self):
""" Adding pins for Bank module"""
for bit in range(self.num_cols):
self.add_pin(self.bl_names[self.port]+"_{0}".format(bit),"INOUT")
self.add_pin(self.br_names[self.port]+"_{0}".format(bit),"INOUT")
if self.port in self.read_ports:
for bit in range(self.word_size):
self.add_pin("dout_{}".format(bit),"OUTPUT")
if self.port in self.write_ports:
for bit in range(self.word_size):
self.add_pin("din_{}".format(bit),"INPUT")
# Will be empty if no col addr lines
sel_names = ["sel_{}".format(x) for x in range(self.num_col_addr_lines)]
for pin_name in sel_names:
self.add_pin(pin_name,"INPUT")
if self.port in self.read_ports:
self.add_pin("s_en", "INPUT")
if self.port in self.read_ports:
self.add_pin("p_en_bar", "INPUT")
if self.port in self.write_ports:
self.add_pin("w_en", "INPUT")
self.add_pin("vdd","POWER")
self.add_pin("gnd","GROUND")
def route_layout(self):
""" Create routing amoung the modules """
self.route_data_lines()
self.route_layout_pins()
self.route_supplies()
def route_layout_pins(self):
""" Add the pins """
self.route_bitline_pins()
self.route_control_pins()
def route_data_lines(self):
""" Route the bitlines depending on the port type rw, w, or r. """
if self.port in self.readwrite_ports:
# write_driver -> sense_amp -> (column_mux) -> precharge -> bitcell_array
self.route_write_driver_in(self.port)
self.route_sense_amp_out(self.port)
self.route_write_driver_to_sense_amp(self.port)
self.route_sense_amp_to_column_mux_or_precharge_array(self.port)
self.route_column_mux_to_precharge_array(self.port)
elif self.port in self.read_ports:
# sense_amp -> (column_mux) -> precharge -> bitcell_array
self.route_sense_amp_out(self.port)
self.route_sense_amp_to_column_mux_or_precharge_array(self.port)
self.route_column_mux_to_precharge_array(self.port)
else:
# write_driver -> (column_mux) -> bitcell_array
self.route_write_driver_in(self.port)
self.route_write_driver_to_column_mux_or_bitcell_array(self.port)
def route_supplies(self):
""" Propagate all vdd/gnd pins up to this level for all modules """
for inst in self.insts:
self.copy_power_pins(inst,"vdd")
self.copy_power_pins(inst,"gnd")
def add_modules(self):
if self.port in self.read_ports:
self.precharge_array = factory.create(module_type="precharge_array",
columns=self.num_cols,
bitcell_bl=self.bl_names[self.port],
bitcell_br=self.br_names[self.port])
self.add_mod(self.precharge_array)
self.sense_amp_array = factory.create(module_type="sense_amp_array",
word_size=self.word_size,
words_per_row=self.words_per_row)
self.add_mod(self.sense_amp_array)
else:
self.precharge_array = None
self.sense_amp_array = None
if self.col_addr_size > 0:
self.column_mux_array = factory.create(module_type="column_mux_array",
columns=self.num_cols,
word_size=self.word_size,
bitcell_bl=self.bl_names[self.port],
bitcell_br=self.br_names[self.port])
self.add_mod(self.column_mux_array)
else:
self.column_mux_array = None
if self.port in self.write_ports or self.port in self.readwrite_ports:
self.write_driver_array = factory.create(module_type="write_driver_array",
columns=self.num_cols,
word_size=self.word_size)
self.add_mod(self.write_driver_array)
else:
self.write_driver_array = None
def compute_sizes(self):
""" Computes the required sizes to create the bank """
self.num_cols = int(self.words_per_row*self.word_size)
self.num_rows = int(self.num_words / self.words_per_row)
# The central bus is the column address (one hot) and row address (binary)
if self.col_addr_size>0:
self.num_col_addr_lines = 2**self.col_addr_size
else:
self.num_col_addr_lines = 0
# A space for wells or jogging m2 between modules
self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclosure_active"),
3*self.m2_pitch)
# create arrays of bitline and bitline_bar names for read, write, or all ports
self.bitcell = factory.create(module_type="bitcell")
self.bl_names = self.bitcell.list_all_bl_names()
self.br_names = self.bitcell.list_all_br_names()
self.wl_names = self.bitcell.list_all_wl_names()
def create_precharge_array(self):
""" Creating Precharge """
if not self.precharge_array:
self.precharge_array_inst = None
return
self.precharge_array_inst = self.add_inst(name="precharge_array{}".format(self.port),
mod=self.precharge_array)
temp = []
for bit in range(self.num_cols):
temp.append(self.bl_names[self.port]+"_{0}".format(bit))
temp.append(self.br_names[self.port]+"_{0}".format(bit))
temp.extend(["p_en_bar", "vdd"])
self.connect_inst(temp)
def place_precharge_array(self, offset):
""" Placing Precharge """
self.precharge_array_inst.place(offset=offset, mirror="MX")
def create_column_mux_array(self):
""" Creating Column Mux when words_per_row > 1 . """
self.column_mux_array_inst = self.add_inst(name="column_mux_array{}".format(self.port),
mod=self.column_mux_array)
temp = []
for col in range(self.num_cols):
temp.append(self.bl_names[self.port]+"_{0}".format(col))
temp.append(self.br_names[self.port]+"_{0}".format(col))
for word in range(self.words_per_row):
temp.append("sel_{}".format(word))
for bit in range(self.word_size):
temp.append(self.bl_names[self.port]+"_out_{0}".format(bit))
temp.append(self.br_names[self.port]+"_out_{0}".format(bit))
temp.append("gnd")
self.connect_inst(temp)
def place_column_mux_array(self, offset):
""" Placing Column Mux when words_per_row > 1 . """
if self.col_addr_size == 0:
return
self.column_mux_array_inst.place(offset=offset, mirror="MX")
def create_sense_amp_array(self):
""" Creating Sense amp """
self.sense_amp_array_inst = self.add_inst(name="sense_amp_array{}".format(self.port),
mod=self.sense_amp_array)
temp = []
for bit in range(self.word_size):
temp.append("dout_{}".format(bit))
if self.words_per_row == 1:
temp.append(self.bl_names[self.port]+"_{0}".format(bit))
temp.append(self.br_names[self.port]+"_{0}".format(bit))
else:
temp.append(self.bl_names[self.port]+"_out_{0}".format(bit))
temp.append(self.br_names[self.port]+"_out_{0}".format(bit))
temp.extend(["s_en", "vdd", "gnd"])
self.connect_inst(temp)
def place_sense_amp_array(self, offset):
""" Placing Sense amp """
self.sense_amp_array_inst.place(offset=offset, mirror="MX")
def create_write_driver_array(self):
""" Creating Write Driver """
self.write_driver_array_inst = self.add_inst(name="write_driver_array{}".format(self.port),
mod=self.write_driver_array)
temp = []
for bit in range(self.word_size):
temp.append("din_{}".format(bit))
for bit in range(self.word_size):
if (self.words_per_row == 1):
temp.append(self.bl_names[self.port]+"_{0}".format(bit))
temp.append(self.br_names[self.port]+"_{0}".format(bit))
else:
temp.append(self.bl_names[self.port]+"_out_{0}".format(bit))
temp.append(self.br_names[self.port]+"_out_{0}".format(bit))
temp.extend(["w_en", "vdd", "gnd"])
self.connect_inst(temp)
def place_write_driver_array(self, offset):
""" Placing Write Driver """
self.write_driver_array_inst.place(offset=offset, mirror="MX")
def compute_instance_offsets(self):
"""
Compute the empty instance offsets for port0 and port1 (if needed)
"""
vertical_port_order = []
vertical_port_order.append(self.precharge_array_inst)
vertical_port_order.append(self.column_mux_array_inst)
vertical_port_order.append(self.sense_amp_array_inst)
vertical_port_order.append(self.write_driver_array_inst)
vertical_port_offsets = 4*[None]
self.width = 0
self.height = 0
for i,p in enumerate(vertical_port_order):
if p==None:
continue
self.height += (p.height + self.m2_gap)
self.width = max(self.width, p.width)
vertical_port_offsets[i]=vector(0,self.height)
# Reversed order
self.write_driver_offset = vertical_port_offsets[3]
self.sense_amp_offset = vertical_port_offsets[2]
self.column_mux_offset = vertical_port_offsets[1]
self.precharge_offset = vertical_port_offsets[0]
def place_instances(self):
""" Place the instances. """
# These are fixed in the order: write driver, sense amp, clumn mux, precharge,
# even if the item is not used in a given port (it will be None then)
if self.write_driver_offset:
self.place_write_driver_array(self.write_driver_offset)
if self.sense_amp_offset:
self.place_sense_amp_array(self.sense_amp_offset)
if self.precharge_offset:
self.place_precharge_array(self.precharge_offset)
if self.column_mux_offset:
self.place_column_mux_array(self.column_mux_offset)
def route_sense_amp_out(self, port):
""" Add pins for the sense amp output """
for bit in range(self.word_size):
data_pin = self.sense_amp_array_inst.get_pin("data_{}".format(bit))
self.add_layout_pin_rect_center(text="dout_{0}".format(bit),
layer=data_pin.layer,
offset=data_pin.center(),
height=data_pin.height(),
width=data_pin.width())
def route_write_driver_in(self, port):
""" Connecting write driver """
for row in range(self.word_size):
data_name = "data_{}".format(row)
din_name = "din_{}".format(row)
self.copy_layout_pin(self.write_driver_array_inst, data_name, din_name)
def route_column_mux_to_precharge_array(self, port):
""" Routing of BL and BR between col mux and precharge array """
# Only do this if we have a column mux!
if self.col_addr_size==0:
return
inst1 = self.column_mux_array_inst
inst2 = self.precharge_array_inst
self.connect_bitlines(inst1, inst2, self.num_cols)
def route_sense_amp_to_column_mux_or_precharge_array(self, port):
""" Routing of BL and BR between sense_amp and column mux or precharge array """
inst2 = self.sense_amp_array_inst
if self.col_addr_size>0:
# Sense amp is connected to the col mux
inst1 = self.column_mux_array_inst
inst1_bl_name = "bl_out_{}"
inst1_br_name = "br_out_{}"
else:
# Sense amp is directly connected to the precharge array
inst1 = self.precharge_array_inst
inst1_bl_name = "bl_{}"
inst1_br_name = "br_{}"
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 """
inst2 = self.write_driver_array_inst
if self.col_addr_size>0:
# Write driver is connected to the col mux
inst1 = self.column_mux_array_inst
inst1_bl_name = "bl_out_{}"
inst1_br_name = "br_out_{}"
else:
# Write driver is directly connected to the bitcell array
return
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_sense_amp(self, port):
""" Routing of BL and BR between write driver and sense amp """
inst1 = self.write_driver_array_inst
inst2 = self.sense_amp_array_inst
# 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_bitline_pins(self):
""" Add the bitline pins for the given port """
for bit in range(self.num_cols):
if self.port in self.read_ports:
self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(bit))
self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(bit))
elif self.column_mux_array_inst:
self.copy_layout_pin(self.column_mux_array_inst, "bl_{}".format(bit))
self.copy_layout_pin(self.column_mux_array_inst, "br_{}".format(bit))
else:
self.copy_layout_pin(self.write_driver_array_inst, "bl_{}".format(bit))
self.copy_layout_pin(self.write_driver_array_inst, "br_{}".format(bit))
def route_control_pins(self):
""" Add the control pins: s_en, p_en_bar, w_en """
if self.precharge_array_inst:
self.copy_layout_pin(self.precharge_array_inst, "en_bar", "p_en_bar")
if self.column_mux_array_inst:
sel_names = ["sel_{}".format(x) for x in range(self.num_col_addr_lines)]
for pin_name in sel_names:
self.copy_layout_pin(self.column_mux_array_inst, pin_name)
if self.sense_amp_array_inst:
self.copy_layout_pin(self.sense_amp_array_inst, "en", "s_en")
if self.write_driver_array_inst:
self.copy_layout_pin(self.write_driver_array_inst, "en", "w_en")
def channel_route_bitlines(self, inst1, inst2, num_bits,
inst1_bl_name="bl_{}", inst1_br_name="br_{}",
inst2_bl_name="bl_{}", inst2_br_name="br_{}"):
"""
Route the bl and br of two modules using the channel router.
"""
# determine top and bottom automatically.
# since they don't overlap, we can just check the bottom y coordinate.
if inst1.by() < inst2.by():
(bottom_inst, bottom_bl_name, bottom_br_name) = (inst1, inst1_bl_name, inst1_br_name)
(top_inst, top_bl_name, top_br_name) = (inst2, inst2_bl_name, inst2_br_name)
else:
(bottom_inst, bottom_bl_name, bottom_br_name) = (inst2, inst2_bl_name, inst2_br_name)
(top_inst, top_bl_name, top_br_name) = (inst1, inst1_bl_name, inst1_br_name)
# Channel route each mux separately since we don't minimize the number
# 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_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))
self.create_horizontal_channel_route(route_map, offset)
def connect_bitlines(self, inst1, inst2, num_bits,
inst1_bl_name="bl_{}", inst1_br_name="br_{}",
inst2_bl_name="bl_{}", inst2_br_name="br_{}"):
"""
Connect the bl and br of two modules.
This assumes that they have sufficient space to create a jog
in the middle between the two modules (if needed).
"""
# determine top and bottom automatically.
# since they don't overlap, we can just check the bottom y coordinate.
if inst1.by() < inst2.by():
(bottom_inst, bottom_bl_name, bottom_br_name) = (inst1, inst1_bl_name, inst1_br_name)
(top_inst, top_bl_name, top_br_name) = (inst2, inst2_bl_name, inst2_br_name)
else:
(bottom_inst, bottom_bl_name, bottom_br_name) = (inst2, inst2_bl_name, inst2_br_name)
(top_inst, top_bl_name, top_br_name) = (inst1, inst1_bl_name, inst1_br_name)
for col in range(num_bits):
bottom_bl = bottom_inst.get_pin(bottom_bl_name.format(col)).uc()
bottom_br = bottom_inst.get_pin(bottom_br_name.format(col)).uc()
top_bl = top_inst.get_pin(top_bl_name.format(col)).bc()
top_br = top_inst.get_pin(top_br_name.format(col)).bc()
yoffset = 0.5*(top_bl.y+bottom_bl.y)
self.add_path("metal2",[bottom_bl, vector(bottom_bl.x,yoffset),
vector(top_bl.x,yoffset), top_bl])
self.add_path("metal2",[bottom_br, vector(bottom_br.x,yoffset),
vector(top_br.x,yoffset), top_br])
def graph_exclude_precharge(self):
"""Precharge adds a loop between bitlines, can be excluded to reduce complexity"""
if self.precharge_array_inst:
self.graph_inst_exclude.add(self.precharge_array_inst)

View File

@ -0,0 +1,366 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
import debug
import design
from tech import drc, spice
from vector import vector
from globals import OPTS
from sram_factory import factory
import logical_effort
import bitcell_array
import replica_column
import dummy_array
class replica_bitcell_array(design.design):
"""
Creates a bitcell arrow of cols x rows and then adds the replica and dummy columns
and rows for one or two read ports. Replica columns are on the left and right, respectively.
Dummy are the outside columns/rows with WL and BL tied to gnd.
Requires a regular bitcell array, replica bitcell, and dummy bitcell (Bl/BR disconnected).
"""
def __init__(self, cols, rows, name):
design.design.__init__(self, name)
debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols))
self.add_comment("rows: {0} cols: {1}".format(rows, cols))
self.column_size = cols
self.row_size = rows
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
# We don't offset this because we need to align
# the replica bitcell in the control logic
#self.offset_all_coordinates()
def create_netlist(self):
""" Create and connect the netlist """
self.add_modules()
self.add_pins()
self.create_instances()
def add_modules(self):
""" Array and dummy/replica columns
d or D = dummy cell (caps to distinguish grouping)
r or R = replica cell (caps to distinguish grouping)
b or B = bitcell
replica columns 1
v v
bdDDDDDDDDDDDDDDdb <- Dummy row
bdDDDDDDDDDDDDDDrb <- Dummy row
br--------------rb
br| Array |rb
br| row x col |rb
br--------------rb
brDDDDDDDDDDDDDDdb <- Dummy row
bdDDDDDDDDDDDDDDdb <- Dummy row
^^^^^^^^^^^^^^^
dummy rows cols x 1
^ dummy columns ^
1 x (rows + 4)
"""
# Bitcell for port names only
self.cell = factory.create(module_type="bitcell")
# Bitcell array
self.bitcell_array = factory.create(module_type="bitcell_array",
cols=self.column_size,
rows=self.row_size)
self.add_mod(self.bitcell_array)
# Replica bitline
self.replica_column = factory.create(module_type="replica_column",
rows=self.row_size + 4)
self.add_mod(self.replica_column)
# Dummy row
self.dummy_row = factory.create(module_type="dummy_array",
rows=1,
cols=self.column_size)
self.add_mod(self.dummy_row)
# Dummy col
self.dummy_col = factory.create(module_type="dummy_array",
cols=1,
rows=self.row_size + 4)
self.add_mod(self.dummy_col)
def add_pins(self):
self.wl_names = [x for x in self.bitcell_array.pins if x.startswith("w")]
self.bl_names = [x for x in self.bitcell_array.pins if x.startswith("b")]
# top/bottom rows (in the middle)
self.replica_wl_names = ["replica_"+x for x in self.cell.pins if x.startswith("w")]
self.dummy_wl_names = ["dummy_"+x for x in self.cell.pins if x.startswith("w")]
self.dummy_bl_names = ["dummy_"+x for x in self.cell.pins if x.startswith("b")]
self.dummy_row_bl_names = self.bl_names
# dummy row and replica on each side of the bitcell rows
self.replica_col_wl_names = [x+"_0" for x in self.dummy_wl_names] \
+ ["replica_"+x+"_0" for x in self.cell.list_all_wl_names()] \
+ self.wl_names \
+ ["replica_"+x+"_1" for x in self.cell.list_all_wl_names()] \
+ [x+"_1" for x in self.dummy_wl_names]
self.replica_bl_names = ["replica_"+x for x in self.cell.pins if x.startswith("b")]
# left/right rows
self.dummy_col_wl_names = self.replica_col_wl_names
self.add_pin_list(self.bl_names)
self.add_pin_list([x+"_0" for x in self.replica_bl_names])
self.add_pin_list([x+"_1" for x in self.replica_bl_names])
self.add_pin_list([x for x in self.replica_col_wl_names if not x.startswith("dummy")])
self.add_pin("vdd")
self.add_pin("gnd")
def create_instances(self):
""" Create the module instances used in this design """
supplies = ["vdd", "gnd"]
# Main array
self.bitcell_array_inst=self.add_inst(name="bitcell_array",
mod=self.bitcell_array)
self.connect_inst(self.bitcell_array.pins)
# Replica columns (two even if one port for now)
self.replica_col_left_inst=self.add_inst(name="replica_col_left",
mod=self.replica_column)
self.connect_inst([x+"_0" for x in self.replica_bl_names] + self.replica_col_wl_names + supplies)
self.replica_col_right_inst=self.add_inst(name="replica_col_right",
mod=self.replica_column)
self.connect_inst([x+"_1" for x in self.replica_bl_names] + self.replica_col_wl_names[::-1] + supplies)
# Replica rows with replica bitcell
self.dummy_row_bottop_inst=self.add_inst(name="dummy_row_bottop",
mod=self.dummy_row)
self.connect_inst(self.dummy_row_bl_names + [x+"_0" for x in self.replica_wl_names] + supplies)
self.dummy_row_topbot_inst=self.add_inst(name="dummy_row_topbot",
mod=self.dummy_row)
self.connect_inst(self.dummy_row_bl_names + [x+"_1" for x in self.replica_wl_names] + supplies)
# Dummy rows without replica bitcell
self.dummy_row_botbot_inst=self.add_inst(name="dummy_row_botbot",
mod=self.dummy_row)
self.connect_inst(self.dummy_row_bl_names + [x+"_0" for x in self.dummy_wl_names] + supplies)
self.dummy_row_toptop_inst=self.add_inst(name="dummy_row_toptop",
mod=self.dummy_row)
self.connect_inst(self.dummy_row_bl_names + [x+"_1" for x in self.dummy_wl_names] + supplies)
# Dummy columns
self.dummy_col_left_inst=self.add_inst(name="dummy_col_left",
mod=self.dummy_col)
self.connect_inst([x+"_0" for x in self.dummy_bl_names] + self.dummy_col_wl_names + supplies)
self.dummy_col_right_inst=self.add_inst(name="dummy_col_right",
mod=self.dummy_col)
self.connect_inst([x+"_1" for x in self.dummy_bl_names] + self.dummy_col_wl_names + supplies)
def create_layout(self):
self.height = (self.row_size+4)*self.dummy_row.height
self.width = (self.column_size+4)*self.replica_column.width
# This is a bitcell x bitcell offset to scale
offset = vector(self.replica_column.width, self.dummy_row.height)
self.bitcell_array_inst.place(offset=[0,0])
self.replica_col_left_inst.place(offset=offset.scale(-1,-2))
self.replica_col_right_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ur(),
mirror="MX")
self.dummy_row_toptop_inst.place(offset=offset.scale(0,2)+self.bitcell_array_inst.ul(),
mirror="MX")
self.dummy_row_topbot_inst.place(offset=offset.scale(0,0)+self.bitcell_array_inst.ul())
self.dummy_row_bottop_inst.place(offset=offset.scale(0,0),
mirror="MX")
self.dummy_row_botbot_inst.place(offset=offset.scale(0,-2))
self.dummy_col_left_inst.place(offset=offset.scale(-2,-2))
self.dummy_col_right_inst.place(offset=offset.scale(1,-2)+self.bitcell_array_inst.lr())
self.translate_all(offset.scale(-2,-2))
self.add_layout_pins()
self.add_boundary()
self.DRC_LVS()
def add_layout_pins(self):
""" Add the layout pins """
# Main array wl and bl/br
pin_names = self.bitcell_array.get_pin_names()
for pin_name in pin_names:
if pin_name.startswith("wl"):
pin_list = self.bitcell_array_inst.get_pins(pin_name)
for pin in pin_list:
self.add_layout_pin_rect_center(text=pin_name,
layer=pin.layer,
offset=pin.center(),
width=self.width,
height=pin.height())
elif pin_name.startswith("bl") or pin_name.startswith("br"):
pin_list = self.bitcell_array_inst.get_pins(pin_name)
for pin in pin_list:
self.add_layout_pin_rect_center(text=pin_name,
layer=pin.layer,
offset=pin.center(),
width=pin.width(),
height=self.height)
for index,(side1,side2) in enumerate([("bottop","left"),("topbot","right")]):
inst = getattr(self, "dummy_row_{}_inst".format(side1))
pin_names = inst.mod.get_pin_names()
for pin_name in pin_names:
if pin_name.startswith("wl"):
pin_list = inst.get_pins(pin_name)
for pin in pin_list:
name = "replica_{0}_{1}".format(pin_name,index)
self.add_layout_pin_rect_center(text=name,
layer=pin.layer,
offset=pin.center(),
width=self.width,
height=pin.height())
# Replica columns
for index,side in enumerate(["left","right"]):
inst = getattr(self, "replica_col_{}_inst".format(side))
pin_names = inst.mod.get_pin_names()
for pin_name in pin_names:
if pin_name.startswith("bl") or pin_name.startswith("br"):
pin_list = inst.get_pins(pin_name)
for pin in pin_list:
name = "replica_{0}_{1}".format(pin_name,index)
self.add_layout_pin(text=name,
layer=pin.layer,
offset=pin.ll().scale(1,0),
width=pin.width(),
height=self.height)
for pin_name in ["vdd","gnd"]:
for inst in [self.bitcell_array_inst,
self.replica_col_left_inst, self.replica_col_right_inst,
self.dummy_col_left_inst, self.dummy_col_right_inst,
self.dummy_row_toptop_inst, self.dummy_row_topbot_inst,
self.dummy_row_bottop_inst, self.dummy_row_botbot_inst]:
pin_list = inst.get_pins(pin_name)
for pin in pin_list:
self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer)
# Non-pins
for side in ["botbot", "toptop"]:
inst = getattr(self, "dummy_row_{}_inst".format(side))
pin_names = inst.mod.get_pin_names()
for pin_name in pin_names:
if pin_name.startswith("wl"):
pin_list = inst.get_pins(pin_name)
for pin in pin_list:
self.add_rect_center(layer=pin.layer,
offset=pin.center(),
width=self.width,
height=pin.height())
for side in ["left", "right"]:
inst = getattr(self, "dummy_col_{}_inst".format(side))
pin_names = inst.mod.get_pin_names()
for pin_name in pin_names:
if pin_name.startswith("b"):
pin_list = inst.get_pins(pin_name)
for pin in pin_list:
self.add_rect_center(layer=pin.layer,
offset=pin.center(),
width=pin.width(),
height=self.height)
def analytical_delay(self, corner, slew, load):
"""Returns relative delay of the bitline in the bitcell array"""
from tech import parameter
#The load being driven/drained is mostly the bitline but could include the sense amp or the column mux.
#The load from the bitlines is due to the drain capacitances from all the other bitlines and wire parasitics.
drain_load = logical_effort.convert_farad_to_relative_c(parameter['bitcell_drain_cap'])
wire_unit_load = .05 * drain_load #Wires add 5% to this.
bitline_load = (drain_load+wire_unit_load)*self.row_size
return [self.cell.analytical_delay(corner, slew, load+bitline_load)]
def analytical_power(self, corner, load):
"""Power of Bitcell array and bitline in nW."""
from tech import drc, parameter
# Dynamic Power from Bitline
bl_wire = self.gen_bl_wire()
cell_load = 2 * bl_wire.return_input_cap()
bl_swing = parameter["rbl_height_percentage"]
freq = spice["default_event_rate"]
bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing)
#Calculate the bitcell power which currently only includes leakage
cell_power = self.cell.analytical_power(corner, load)
#Leakage power grows with entire array and bitlines.
total_power = self.return_power(cell_power.dynamic + bitline_dynamic * self.column_size,
cell_power.leakage * self.column_size * self.row_size)
return total_power
def gen_wl_wire(self):
if OPTS.netlist_only:
width = 0
else:
width = self.width
wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_metal1"))
wl_wire.wire_c = 2*spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell
return wl_wire
def gen_bl_wire(self):
if OPTS.netlist_only:
height = 0
else:
height = self.height
bl_pos = 0
bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), height, drc("minwidth_metal1"))
bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell
return bl_wire
def output_load(self, bl_pos=0):
bl_wire = self.gen_bl_wire()
return bl_wire.wire_c # sense amp only need to charge small portion of the bl
# set as one segment for now
def input_load(self):
wl_wire = self.gen_wl_wire()
return wl_wire.return_input_cap()
def get_wordline_cin(self):
"""Get the relative input capacitance from the wordline connections in all the bitcell"""
#A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns
bitcell_wl_cin = self.cell.get_wl_cin()
total_cin = bitcell_wl_cin * self.column_size
return total_cin

View File

@ -0,0 +1,141 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
import debug
import design
from tech import drc
import contact
from sram_factory import factory
from vector import vector
from globals import OPTS
class replica_column(design.design):
"""
Generate a replica bitline column for the replica array.
"""
def __init__(self, name, rows):
design.design.__init__(self, name)
self.row_size = rows
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_modules()
self.add_pins()
self.create_instances()
def create_layout(self):
self.place_instances()
self.add_layout_pins()
self.height = self.row_size*self.cell.height
self.width = self.cell.width
self.add_boundary()
self.DRC_LVS()
def add_pins(self):
column_list = self.cell.list_all_bitline_names()
for cell_column in column_list:
self.add_pin("{0}_{1}".format(cell_column,0))
row_list = self.cell.list_all_wl_names()
for row in range(self.row_size):
for cell_row in row_list:
self.add_pin("{0}_{1}".format(cell_row,row))
self.add_pin("vdd")
self.add_pin("gnd")
def add_modules(self):
self.replica_cell = factory.create(module_type="replica_bitcell")
self.add_mod(self.replica_cell)
self.dummy_cell = factory.create(module_type="dummy_bitcell")
self.add_mod(self.dummy_cell)
# Used for pin names only
self.cell = factory.create(module_type="bitcell")
def create_instances(self):
self.cell_inst = {}
for row in range(self.row_size):
name="rbc_{0}".format(row)
if row>0 and row<self.row_size-2:
self.cell_inst[row]=self.add_inst(name=name,
mod=self.replica_cell)
else:
self.cell_inst[row]=self.add_inst(name=name,
mod=self.dummy_cell)
self.connect_inst(self.list_bitcell_pins(0, row))
def place_instances(self):
yoffset = 0
for row in range(self.row_size):
name = "bit_r{0}_{1}".format(row,"rbl")
# This is opposite of a bitcell array since we will be 1 row off
if not row % 2:
tempy = yoffset
dir_key = ""
else:
tempy = yoffset + self.cell.height
dir_key = "MX"
self.cell_inst[row].place(offset=[0.0, tempy],
mirror=dir_key)
yoffset += self.cell.height
def add_layout_pins(self):
""" Add the layout pins """
row_list = self.cell.list_all_wl_names()
column_list = self.cell.list_all_bitline_names()
col = "0"
for cell_column in column_list:
bl_pin = self.cell_inst[0].get_pin(cell_column)
self.add_layout_pin(text=cell_column+"_{0}".format(col),
layer="metal2",
offset=bl_pin.ll(),
width=bl_pin.width(),
height=self.height)
for row in range(self.row_size):
for cell_row in row_list:
wl_pin = self.cell_inst[row].get_pin(cell_row)
self.add_layout_pin(text=cell_row+"_{0}".format(row),
layer="metal1",
offset=wl_pin.ll(),
width=self.width,
height=wl_pin.height())
# For every second row and column, add a via for gnd and vdd
for row in range(self.row_size):
inst = self.cell_inst[row]
for pin_name in ["vdd", "gnd"]:
self.copy_layout_pin(inst, pin_name)
def list_bitcell_pins(self, col, row):
""" Creates a list of connections in the bitcell,
indexed by column and row, for instance use in bitcell_array """
bitcell_pins = []
pin_names = self.cell.list_all_bitline_names()
for pin in pin_names:
bitcell_pins.append(pin+"_{0}".format(col))
pin_names = self.cell.list_all_wl_names()
for pin in pin_names:
bitcell_pins.append(pin+"_{0}".format(row))
bitcell_pins.append("vdd")
bitcell_pins.append("gnd")
return bitcell_pins

View File

@ -26,7 +26,7 @@ class ptx(design.design):
# will use the last record with a given name. I.e., you will
# over-write a design in GDS if one has and the other doesn't
# have poly connected, for example.
name = "{0}_m{1}_w{2}".format(tx_type, mults, width)
name = "{0}_m{1}_w{2:.3f}".format(tx_type, mults, width)
if connect_active:
name += "_a"
if connect_poly:

View File

@ -48,6 +48,7 @@ class sram_1bank(sram_base):
if (self.write_size != self.word_size):
self.wmask_dff_insts = self.create_wmask_dff()
def place_instances(self):
"""
@ -76,8 +77,27 @@ class sram_1bank(sram_base):
# Port 0
port = 0
# 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.
if port in self.write_ports:
data_pos[port] = vector(self.bank.bank_array_ll.x,
-max_gap_size - self.dff.height)
self.data_dff_insts[port].place(data_pos[port])
else:
data_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:
col_addr_pos[port] = vector(self.bank.bank_array_ll.x - self.col_addr_dff_insts[port].width - self.bank.m2_gap,
-max_gap_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.
# It is also placed to align with the column decoder (if it exists hence the bank gap)
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 - self.bank.m2_gap)
self.control_logic_insts[port].place(control_pos[port])
@ -117,33 +137,14 @@ class sram_1bank(sram_base):
# Port 1
port = 1
# This includes 2 M2 pitches for the row addr clock line
# It is also placed to align with the column decoder (if it exists hence the bank gap)
control_pos[port] = vector(self.bank_inst.rx() + 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 + self.bank.m2_gap)
self.control_logic_insts[port].place(control_pos[port], mirror="MY")
# The row address bits are placed above the control logic aligned on the left.
x_offset = control_pos[port].x - self.control_logic_insts[port].width + self.row_addr_dff_insts[port].width
# It is above the control logic but below the top of the bitcell array
y_offset = max(self.control_logic_insts[port].uy(), self.bank.bank_array_ur.y - self.row_addr_dff_insts[port].height)
row_addr_pos[port] = vector(x_offset, y_offset)
self.row_addr_dff_insts[port].place(row_addr_pos[port], mirror="MY")
# Add the col address flops above the bank to the right of the upper-right of bank array
if self.col_addr_dff:
col_addr_pos[port] = vector(self.bank.bank_array_ur.x + self.bank.m2_gap,
self.bank.height + max_gap_size + self.col_addr_dff_insts[port].height)
self.col_addr_dff_insts[port].place(col_addr_pos[port], mirror="MX")
# 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.
# sense amps.
if port in self.write_ports:
data_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width,
self.bank.height + max_gap_size + self.data_dff_insts[port].height)
self.bank.height + max_gap_size + self.dff.height)
self.data_dff_insts[port].place(data_pos[port], mirror="MX")
# Add the write mask flops to the left of the din flops.
@ -152,8 +153,31 @@ class sram_1bank(sram_base):
wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width,
self.bank.height + max_gap_size + self.data_dff_insts[port].height)
self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX")
else:
data_pos[port] = self.bank_inst.ur()
# Add the col address flops above the bank to the right of the upper-right of bank array
if self.col_addr_dff:
col_addr_pos[port] = vector(self.bank.bank_array_ur.x + self.bank.m2_gap,
self.bank.height + max_gap_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,
self.bank.bank_array_ur.y + self.control_logic_insts[port].mod.control_logic_center.y + self.bank.m2_gap)
self.control_logic_insts[port].place(control_pos[port], mirror="XY")
# The row address bits are placed above the control logic aligned on the left.
x_offset = control_pos[port].x - self.control_logic_insts[port].width + self.row_addr_dff_insts[port].width
# It is above the control logic but below the top of the bitcell array
y_offset = min(self.control_logic_insts[port].by(), self.bank.bank_array_ll.y - self.row_addr_dff_insts[port].height)
row_addr_pos[port] = vector(x_offset, y_offset)
self.row_addr_dff_insts[port].place(row_addr_pos[port], mirror="XY")
def add_layout_pins(self):
"""
Add the top-level pins for a single bank SRAM with control.
@ -278,10 +302,15 @@ class sram_1bank(sram_base):
def route_col_addr_dff(self):
""" Connect the output of the row flops to the bank pins """
for port in self.all_ports:
if port%2:
offset = self.col_addr_dff_insts[port].ll() - vector(0, (self.word_size+2)*self.m1_pitch)
else:
offset = self.col_addr_dff_insts[port].ul() + vector(0, 2*self.m1_pitch)
bus_names = ["addr_{}".format(x) for x in range(self.col_addr_size)]
col_addr_bus_offsets = self.create_horizontal_bus(layer="metal1",
pitch=self.m1_pitch,
offset=self.col_addr_dff_insts[port].ul() + vector(0, self.m1_pitch),
offset=offset,
names=bus_names,
length=self.col_addr_dff_insts[port].width)

View File

@ -262,6 +262,7 @@ class sram_base(design, verilog, lef):
def add_modules(self):
self.bitcell = factory.create(module_type=OPTS.bitcell)
self.dff = factory.create(module_type="dff")
# Create the address and control flops (but not the clk)
from dff_array import dff_array
@ -279,6 +280,7 @@ class sram_base(design, verilog, lef):
self.wmask_dff = dff_array(name="wmask_dff", rows=1, columns=int(self.word_size/self.write_size))
self.add_mod(self.wmask_dff)
# Create the bank module (up to four are instantiated)
from bank import bank

View File

@ -6,8 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"Run a regression test the library cells for DRC"
import unittest
from testutils import *
import sys,os,re

View File

@ -6,8 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"Run a regression test the library cells for LVS"
import unittest
from testutils import *
import sys,os,re

View File

@ -6,8 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"Run a regression test for DRC on basic contacts of different array sizes"
import unittest
from testutils import *
import sys,os

View File

@ -6,8 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"Run a regression test on a basic path"
import unittest
from testutils import *
import sys,os

View File

@ -6,8 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"Run a regression test on a basic parameterized transistors"
import unittest
from testutils import *
import sys,os

View File

@ -6,8 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"Run a regression test on a basic parameterized transistors"
import unittest
from testutils import *
import sys,os

View File

@ -6,8 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"Run a regression test on a basic parameterized transistors"
import unittest
from testutils import *
import sys,os

View File

@ -6,8 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"Run a regression test on a basic parameterized transistors"
import unittest
from testutils import *
import sys,os

View File

@ -6,8 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"Run a regression test on a basic parameterized transistors"
import unittest
from testutils import *
import sys,os

View File

@ -6,8 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"Run a regression test on a basic parameterized transistors"
import unittest
from testutils import *
import sys,os

View File

@ -6,8 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"Run a regression test on a basic wire"
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a pand2 cell
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run regresion tests on a parameterized bitcell
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 2-row buffer cell
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 2-row buffer cell
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run regression tests on a parameterized inverter
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run regression tests on a parameterized inverter
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,9 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run regression tests on a parameterized inverter
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run regression tests on a parameterized inverter
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 2-row buffer cell
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,12 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run regression tests on a parameterized nand 2. This module doesn't
generate a multi_finger 2-input nand gate. It generates only a minimum
size 2-input nand gate.
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,12 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run regression tests on a parameterized pnand3.
This module doesn't generate a multi-finger 3-input nand gate.
It generates only a minimum size 3-input nand gate.
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,12 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run regression tests on a parameterized nor 2. This module doesn't
generate a multi_finger 2-input nor gate. It generates only a minimum
size 2-input nor gate.
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a precharge cell
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a replica pbitcell
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a wordline_driver array
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a basic array
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a basic array
"""
import unittest
from testutils import *
import sys,os

View File

@ -0,0 +1,36 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class dummy_row_test(openram_test):
def runTest(self):
globals.init_openram("config_{0}".format(OPTS.tech_name))
debug.info(2, "Testing dummy row for 6t_cell")
a = factory.create(module_type="dummy_array", rows=1, cols=4)
self.local_check(a)
debug.info(2, "Testing dummy column for 6t_cell")
a = factory.create(module_type="dummy_array", rows=4, cols=1)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a basic array
"""
import unittest
from testutils import *
import sys,os

View File

@ -0,0 +1,32 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class replica_bitcell_array_test(openram_test):
def runTest(self):
globals.init_openram("config_{0}".format(OPTS.tech_name))
debug.info(2, "Testing 4x4 array for 6t_cell")
a = factory.create(module_type="replica_bitcell_array", cols=4, rows=4)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -0,0 +1,32 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class replica_column_test(openram_test):
def runTest(self):
globals.init_openram("config_{0}".format(OPTS.tech_name))
debug.info(2, "Testing replica column for 6t_cell")
a = factory.create(module_type="replica_column", rows=4)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a hierarchical_decoder.
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a hierarchical_predecode2x4.
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a hierarchical_predecode3x8.
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a single transistor column_mux.
"""
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a precharge array
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a wordline_driver array
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a sense amp array
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a write driver array
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a dff_array.
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a dff_array.
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a dff_buf.
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a tri_gate_array.
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a test on a delay chain
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a test on a multiport replica bitline
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a test on a replica bitline
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a control_logic
"""
import unittest
from testutils import *
import sys,os

View File

@ -0,0 +1,112 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class port_data_test(openram_test):
def runTest(self):
globals.init_openram("config_{0}".format(OPTS.tech_name))
from sram_config import sram_config
c = sram_config(word_size=4,
num_words=16)
c.words_per_row=1
factory.reset()
c.recompute_sizes()
debug.info(1, "No column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
c.num_words=32
c.words_per_row=2
factory.reset()
c.recompute_sizes()
debug.info(1, "Two way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
c.num_words=64
c.words_per_row=4
factory.reset()
c.recompute_sizes()
debug.info(1, "Four way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
c.word_size=2
c.num_words=128
c.words_per_row=8
factory.reset()
c.recompute_sizes()
debug.info(1, "Eight way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
OPTS.bitcell = "bitcell_1w_1r"
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 0
c.num_words=16
c.words_per_row=1
factory.reset()
c.recompute_sizes()
debug.info(1, "No column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.num_words=32
c.words_per_row=2
factory.reset()
c.recompute_sizes()
debug.info(1, "Two way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.num_words=64
c.words_per_row=4
factory.reset()
c.recompute_sizes()
debug.info(1, "Four way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
c.word_size=2
c.num_words=128
c.words_per_row=8
factory.reset()
c.recompute_sizes()
debug.info(1, "Eight way column mux")
a = factory.create("port_data", sram_config=c, port=0)
self.local_check(a)
a = factory.create("port_data", sram_config=c, port=1)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on 1rw 1r sram bank
"""
import unittest
from testutils import *
import sys,os

View File

@ -0,0 +1,71 @@
#!/usr/bin/env python3
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import unittest
from testutils import *
import sys,os
sys.path.append(os.getenv("OPENRAM_HOME"))
import globals
from globals import OPTS
from sram_factory import factory
import debug
class single_bank_1w_1r_test(openram_test):
def runTest(self):
globals.init_openram("config_{0}".format(OPTS.tech_name))
OPTS.bitcell = "bitcell_1w_1r"
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 1
OPTS.num_w_ports = 0
from sram_config import sram_config
c = sram_config(word_size=4,
num_words=16)
c.words_per_row=1
factory.reset()
c.recompute_sizes()
debug.info(1, "No column mux")
a = factory.create(module_type="bank", sram_config=c)
self.local_check(a)
c.num_words=32
c.words_per_row=2
factory.reset()
c.recompute_sizes()
debug.info(1, "Two way column mux")
a = factory.create(module_type="bank", sram_config=c)
self.local_check(a)
c.num_words=64
c.words_per_row=4
factory.reset()
c.recompute_sizes()
debug.info(1, "Four way column mux")
a = factory.create(module_type="bank", sram_config=c)
self.local_check(a)
c.word_size=2
c.num_words=128
c.words_per_row=8
factory.reset()
c.recompute_sizes()
debug.info(1, "Eight way column mux")
a = factory.create(module_type="bank", sram_config=c)
self.local_check(a)
globals.end_openram()
# run the test from the command line
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main(testRunner=debugTestRunner())

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank, 2 port SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank, 2 port SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on a 2 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a functioal test on 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a regression test on various srams
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a functioal test on 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Run a functioal test on 1 bank SRAM
"""
import unittest
from testutils import *
import sys,os

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Check the .lib file for an SRAM
"""
import unittest
from testutils import *
import sys,os,re

View File

@ -6,10 +6,6 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
"""
Check the .lib file for an SRAM
"""
import unittest
from testutils import *
import sys,os,re

Some files were not shown because too many files have changed in this diff Show More