mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into fix_rbl_cell_connections
This commit is contained in:
commit
c01f0f5274
|
|
@ -0,0 +1,23 @@
|
||||||
|
import design
|
||||||
|
import debug
|
||||||
|
import utils
|
||||||
|
from tech import GDS,layer
|
||||||
|
|
||||||
|
class replica_bitcell_1rw_1r(design.design):
|
||||||
|
"""
|
||||||
|
A single bit cell which is forced to store a 0.
|
||||||
|
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 = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"]
|
||||||
|
(width,height) = utils.get_libcell_size("replica_cell_1rw_1r", GDS["unit"], layer["boundary"])
|
||||||
|
pin_map = utils.get_libcell_pins(pin_names, "replica_cell_1rw_1r", GDS["unit"], layer["boundary"])
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
design.design.__init__(self, "replica_cell_1rw_1r")
|
||||||
|
debug.info(2, "Create replica bitcell 1rw+1r object")
|
||||||
|
|
||||||
|
self.width = replica_bitcell_1rw_1r.width
|
||||||
|
self.height = replica_bitcell_1rw_1r.height
|
||||||
|
self.pin_map = replica_bitcell_1rw_1r.pin_map
|
||||||
|
|
@ -36,6 +36,14 @@ class functional(simulation):
|
||||||
self.write_check = []
|
self.write_check = []
|
||||||
self.read_check = []
|
self.read_check = []
|
||||||
|
|
||||||
|
def set_spice_constants(self):
|
||||||
|
"""Spice constants for functional test"""
|
||||||
|
simulation.set_spice_constants(self)
|
||||||
|
#Heuristic increase for functional period. Base feasible period typically does not pass the functional test
|
||||||
|
#for column mux of this size. Increase the feasible period by 20% for this case.
|
||||||
|
if self.sram.words_per_row >= 4:
|
||||||
|
self.period = self.period*1.2
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
# Generate a random sequence of reads and writes
|
# Generate a random sequence of reads and writes
|
||||||
self.write_random_memory_sequence()
|
self.write_random_memory_sequence()
|
||||||
|
|
|
||||||
|
|
@ -208,14 +208,14 @@ class simulation():
|
||||||
t_current,
|
t_current,
|
||||||
t_current+self.period)
|
t_current+self.period)
|
||||||
elif op == "write":
|
elif op == "write":
|
||||||
comment = "\tWriting {0} to address {1} (from port {2}) during cylce {3} ({4}ns - {5}ns)".format(word,
|
comment = "\tWriting {0} to address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word,
|
||||||
addr,
|
addr,
|
||||||
port,
|
port,
|
||||||
int(t_current/self.period),
|
int(t_current/self.period),
|
||||||
t_current,
|
t_current,
|
||||||
t_current+self.period)
|
t_current+self.period)
|
||||||
else:
|
else:
|
||||||
comment = "\tReading {0} from address {1} (from port {2}) during cylce {3} ({4}ns - {5}ns)".format(word,
|
comment = "\tReading {0} from address {1} (from port {2}) during cycle {3} ({4}ns - {5}ns)".format(word,
|
||||||
addr,
|
addr,
|
||||||
port,
|
port,
|
||||||
int(t_current/self.period),
|
int(t_current/self.period),
|
||||||
|
|
|
||||||
|
|
@ -18,13 +18,14 @@ class control_logic(design.design):
|
||||||
Dynamically generated Control logic for the total SRAM circuit.
|
Dynamically generated Control logic for the total SRAM circuit.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, num_rows, port_type="rw"):
|
def __init__(self, num_rows, words_per_row, port_type="rw"):
|
||||||
""" Constructor """
|
""" Constructor """
|
||||||
name = "control_logic_" + port_type
|
name = "control_logic_" + port_type
|
||||||
design.design.__init__(self, name)
|
design.design.__init__(self, name)
|
||||||
debug.info(1, "Creating {}".format(name))
|
debug.info(1, "Creating {}".format(name))
|
||||||
|
|
||||||
self.num_rows = num_rows
|
self.num_rows = num_rows
|
||||||
|
self.words_per_row = words_per_row
|
||||||
self.port_type = port_type
|
self.port_type = port_type
|
||||||
|
|
||||||
if self.port_type == "rw":
|
if self.port_type == "rw":
|
||||||
|
|
@ -92,13 +93,24 @@ class control_logic(design.design):
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
c = reload(__import__(OPTS.replica_bitline))
|
c = reload(__import__(OPTS.replica_bitline))
|
||||||
replica_bitline = getattr(c, OPTS.replica_bitline)
|
replica_bitline = getattr(c, OPTS.replica_bitline)
|
||||||
# FIXME: These should be tuned according to the size!
|
|
||||||
delay_stages = 4 # Must be non-inverting
|
delay_stages, delay_fanout = self.get_delay_chain_size()
|
||||||
delay_fanout = 3 # This can be anything >=2
|
|
||||||
bitcell_loads = int(math.ceil(self.num_rows / 2.0))
|
bitcell_loads = int(math.ceil(self.num_rows / 2.0))
|
||||||
self.replica_bitline = replica_bitline(delay_stages, delay_fanout, bitcell_loads, name="replica_bitline_"+self.port_type)
|
self.replica_bitline = replica_bitline(delay_stages, delay_fanout, bitcell_loads, name="replica_bitline_"+self.port_type)
|
||||||
self.add_mod(self.replica_bitline)
|
self.add_mod(self.replica_bitline)
|
||||||
|
|
||||||
|
def get_delay_chain_size(self):
|
||||||
|
"""Determine the size of the delay chain used for the Sense Amp Enable """
|
||||||
|
# FIXME: These should be tuned according to the additional size parameters
|
||||||
|
delay_fanout = 3 # This can be anything >=2
|
||||||
|
# Delay stages Must be non-inverting
|
||||||
|
if self.words_per_row >= 8:
|
||||||
|
delay_stages = 8
|
||||||
|
elif self.words_per_row == 4:
|
||||||
|
delay_stages = 6
|
||||||
|
else:
|
||||||
|
delay_stages = 4
|
||||||
|
return (delay_stages, delay_fanout)
|
||||||
|
|
||||||
def setup_signal_busses(self):
|
def setup_signal_busses(self):
|
||||||
""" Setup bus names, determine the size of the busses etc """
|
""" Setup bus names, determine the size of the busses etc """
|
||||||
|
|
|
||||||
|
|
@ -189,15 +189,65 @@ class replica_bitline(design.design):
|
||||||
|
|
||||||
if pin.layer != "metal1":
|
if pin.layer != "metal1":
|
||||||
continue
|
continue
|
||||||
self.add_path("metal1", [pin_right, pin_extension])
|
pin_width_ydir = pin.uy()-pin.by()
|
||||||
|
#Width is set to pin y width to avoid DRC issues with m1 gaps
|
||||||
|
self.add_path("metal1", [pin_right, pin_extension], pin_width_ydir)
|
||||||
self.add_power_pin("gnd", pin_extension)
|
self.add_power_pin("gnd", pin_extension)
|
||||||
|
|
||||||
# for multiport, need to short wordlines to each other so they all connect to gnd
|
# for multiport, need to short wordlines to each other so they all connect to gnd.
|
||||||
wl_last = self.wl_list[self.total_ports-1]+"_{}".format(row)
|
wl_last = self.wl_list[self.total_ports-1]+"_{}".format(row)
|
||||||
pin_last = self.rbl_inst.get_pin(wl_last)
|
pin_last = self.rbl_inst.get_pin(wl_last)
|
||||||
|
self.short_wordlines(pin, pin_last, "right", False, row, vector(self.m3_pitch,0))
|
||||||
|
|
||||||
|
def short_wordlines(self, wl_pin_a, wl_pin_b, pin_side, is_replica_cell, cell_row=0, offset_x_vec=None):
|
||||||
|
"""Connects the word lines together for a single bitcell. Also requires which side of the bitcell to short the pins."""
|
||||||
|
#Assumes input pins are wordlines. Also assumes the word lines are horizontal in metal1. Also assumes pins have same x coord.
|
||||||
|
#This is my (Hunter) first time editing layout in openram so this function is likely not optimal.
|
||||||
|
if self.total_ports > 1:
|
||||||
|
#1. Create vertical metal for all the bitlines to connect to
|
||||||
|
#m1 needs to be extended in the y directions, direction needs to be determined as every other cell is flipped
|
||||||
|
correct_y = vector(0, 0.5*drc("minwidth_metal1"))
|
||||||
|
#x spacing depends on the side being drawn. Unknown to me (Hunter) why the size of the space differs by the side.
|
||||||
|
#I assume this is related to how a wire is draw, but I have not investigated the issue.
|
||||||
|
if pin_side == "right":
|
||||||
|
correct_x = vector(0.5*drc("minwidth_metal1"), 0)
|
||||||
|
if offset_x_vec != None:
|
||||||
|
correct_x = offset_x_vec
|
||||||
|
else:
|
||||||
|
correct_x = vector(1.5*drc("minwidth_metal1"), 0)
|
||||||
|
|
||||||
|
if wl_pin_a.uy() > wl_pin_b.uy():
|
||||||
|
self.add_path("metal1", [wl_pin_a.rc()+correct_x+correct_y, wl_pin_b.rc()+correct_x-correct_y])
|
||||||
|
else:
|
||||||
|
self.add_path("metal1", [wl_pin_a.rc()+correct_x-correct_y, wl_pin_b.rc()+correct_x+correct_y])
|
||||||
|
elif pin_side == "left":
|
||||||
|
if offset_x_vec != None:
|
||||||
|
correct_x = offset_x_vec
|
||||||
|
else:
|
||||||
|
correct_x = vector(1.5*drc("minwidth_metal1"), 0)
|
||||||
|
|
||||||
|
if wl_pin_a.uy() > wl_pin_b.uy():
|
||||||
|
self.add_path("metal1", [wl_pin_a.lc()-correct_x+correct_y, wl_pin_b.lc()-correct_x-correct_y])
|
||||||
|
else:
|
||||||
|
self.add_path("metal1", [wl_pin_a.lc()-correct_x-correct_y, wl_pin_b.lc()-correct_x+correct_y])
|
||||||
|
else:
|
||||||
|
debug.error("Could not connect wordlines on specified input side={}".format(pin_side),1)
|
||||||
|
|
||||||
|
#2. Connect word lines horizontally. Only replica cell needs. Bitline loads currently already do this.
|
||||||
|
for port in range(self.total_ports):
|
||||||
|
if is_replica_cell:
|
||||||
|
wl = self.wl_list[port]
|
||||||
|
pin = self.rbc_inst.get_pin(wl)
|
||||||
|
else:
|
||||||
|
wl = self.wl_list[port]+"_{}".format(cell_row)
|
||||||
|
pin = self.rbl_inst.get_pin(wl)
|
||||||
|
|
||||||
|
if pin_side == "left":
|
||||||
|
self.add_path("metal1", [pin.lc()-correct_x, pin.lc()])
|
||||||
|
elif pin_side == "right":
|
||||||
|
self.add_path("metal1", [pin.rc()+correct_x, pin.rc()])
|
||||||
|
|
||||||
|
|
||||||
correct = vector(0.5*drc("minwidth_metal1"), 0)
|
|
||||||
self.add_path("metal1", [pin.rc()-correct, pin_last.rc()-correct])
|
|
||||||
|
|
||||||
def route_supplies(self):
|
def route_supplies(self):
|
||||||
""" Propagate all vdd/gnd pins up to this level for all modules """
|
""" Propagate all vdd/gnd pins up to this level for all modules """
|
||||||
|
|
@ -217,8 +267,13 @@ class replica_bitline(design.design):
|
||||||
|
|
||||||
# Replica bitcell needs to be routed up to M3
|
# Replica bitcell needs to be routed up to M3
|
||||||
pin=self.rbc_inst.get_pin("vdd")
|
pin=self.rbc_inst.get_pin("vdd")
|
||||||
# Don't rotate this via to vit in FreePDK45
|
# Don't rotate this via to vit in FreePDK45. In the custom cell, the pin cannot be placed
|
||||||
self.add_power_pin("vdd", pin.center(), rotate=0)
|
# directly on vdd or there will be a drc error with a wordline. Place the pin slightly farther
|
||||||
|
# away then route to it. A better solution would be to rotate the m1 in the via or move the pin
|
||||||
|
# a m1_pitch below the entire cell.
|
||||||
|
pin_extension = pin.center() - vector(0,self.m1_pitch)
|
||||||
|
self.add_power_pin("vdd", pin_extension, rotate=0)
|
||||||
|
self.add_path("metal1", [pin.center(), pin_extension])
|
||||||
|
|
||||||
for pin in self.rbc_inst.get_pins("gnd"):
|
for pin in self.rbc_inst.get_pins("gnd"):
|
||||||
self.add_power_pin("gnd", pin.center())
|
self.add_power_pin("gnd", pin.center())
|
||||||
|
|
@ -267,9 +322,10 @@ class replica_bitline(design.design):
|
||||||
wl_last = self.wl_list[self.total_ports-1]
|
wl_last = self.wl_list[self.total_ports-1]
|
||||||
pin = self.rbc_inst.get_pin(wl)
|
pin = self.rbc_inst.get_pin(wl)
|
||||||
pin_last = self.rbc_inst.get_pin(wl_last)
|
pin_last = self.rbc_inst.get_pin(wl_last)
|
||||||
|
x_offset = self.short_wordlines(pin, pin_last, "left", True)
|
||||||
|
|
||||||
correct = vector(0.5*drc("minwidth_metal1"), 0)
|
#correct = vector(0.5*drc("minwidth_metal1"), 0)
|
||||||
self.add_path("metal1", [pin.lc()+correct, pin_last.lc()+correct])
|
#self.add_path("metal1", [pin.lc()+correct, pin_last.lc()+correct])
|
||||||
|
|
||||||
# DRAIN ROUTE
|
# DRAIN ROUTE
|
||||||
# Route the drain to the vdd rail
|
# Route the drain to the vdd rail
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ class sense_amp(design.design):
|
||||||
|
|
||||||
def input_load(self):
|
def input_load(self):
|
||||||
#Input load for the bitlines which are connected to the source/drain of a TX. Not the selects.
|
#Input load for the bitlines which are connected to the source/drain of a TX. Not the selects.
|
||||||
|
from tech import spice, parameter
|
||||||
bitline_pmos_size = 8 #FIXME: This should be set somewhere and referenced. Probably in tech file.
|
bitline_pmos_size = 8 #FIXME: This should be set somewhere and referenced. Probably in tech file.
|
||||||
return spice["min_tx_drain_c"]*(bitline_pmos_size/parameter["min_tx_size"])#ff
|
return spice["min_tx_drain_c"]*(bitline_pmos_size/parameter["min_tx_size"])#ff
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ class single_level_column_mux_array(design.design):
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
||||||
def analytical_delay(self, vdd, slew, load=0.0):
|
def analytical_delay(self, vdd, slew, load=0.0):
|
||||||
from tech import spice
|
from tech import spice, parameter
|
||||||
r = spice["min_tx_r"]/(self.mux.ptx_width/parameter["min_tx_size"])
|
r = spice["min_tx_r"]/(self.mux.ptx_width/parameter["min_tx_size"])
|
||||||
#Drains of mux transistors make up capacitance.
|
#Drains of mux transistors make up capacitance.
|
||||||
c_para = spice["min_tx_drain_c"]*(self.mux.ptx_width/parameter["min_tx_size"])*self.words_per_row#ff
|
c_para = spice["min_tx_drain_c"]*(self.mux.ptx_width/parameter["min_tx_size"])*self.words_per_row#ff
|
||||||
|
|
|
||||||
|
|
@ -223,13 +223,13 @@ class sram_base(design):
|
||||||
from control_logic import control_logic
|
from control_logic import control_logic
|
||||||
# Create the control logic module for each port type
|
# Create the control logic module for each port type
|
||||||
if OPTS.num_rw_ports>0:
|
if OPTS.num_rw_ports>0:
|
||||||
self.control_logic = self.control_logic_rw = control_logic(num_rows=self.num_rows, port_type="rw")
|
self.control_logic = self.control_logic_rw = control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, port_type="rw")
|
||||||
self.add_mod(self.control_logic_rw)
|
self.add_mod(self.control_logic_rw)
|
||||||
if OPTS.num_w_ports>0:
|
if OPTS.num_w_ports>0:
|
||||||
self.control_logic_w = control_logic(num_rows=self.num_rows, port_type="w")
|
self.control_logic_w = control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, port_type="w")
|
||||||
self.add_mod(self.control_logic_w)
|
self.add_mod(self.control_logic_w)
|
||||||
if OPTS.num_r_ports>0:
|
if OPTS.num_r_ports>0:
|
||||||
self.control_logic_r = control_logic(num_rows=self.num_rows, port_type="r")
|
self.control_logic_r = control_logic(num_rows=self.num_rows, words_per_row=self.words_per_row, port_type="r")
|
||||||
self.add_mod(self.control_logic_r)
|
self.add_mod(self.control_logic_r)
|
||||||
|
|
||||||
# Create the address and control flops (but not the clk)
|
# Create the address and control flops (but not the clk)
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ class replica_bitline_test(openram_test):
|
||||||
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
#debug.error("Exiting...", 1)
|
||||||
|
|
||||||
stages=8
|
stages=8
|
||||||
rows=100
|
rows=100
|
||||||
|
|
@ -31,7 +32,26 @@ class replica_bitline_test(openram_test):
|
||||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
# check replica bitline in multi-port
|
#check replica bitline in handmade multi-port 1rw+1r cell
|
||||||
|
OPTS.bitcell = "bitcell_1rw_1r"
|
||||||
|
OPTS.replica_bitcell = "replica_bitcell_1rw_1r"
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
stages=4
|
||||||
|
fanout=4
|
||||||
|
rows=13
|
||||||
|
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||||
|
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||||
|
self.local_check(a)
|
||||||
|
|
||||||
|
stages=8
|
||||||
|
rows=100
|
||||||
|
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||||
|
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||||
|
self.local_check(a)
|
||||||
|
|
||||||
|
# check replica bitline in pbitcell multi-port
|
||||||
OPTS.bitcell = "pbitcell"
|
OPTS.bitcell = "pbitcell"
|
||||||
OPTS.replica_bitcell = "replica_pbitcell"
|
OPTS.replica_bitcell = "replica_pbitcell"
|
||||||
OPTS.num_rw_ports = 1
|
OPTS.num_rw_ports = 1
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ class control_logic_test(openram_test):
|
||||||
|
|
||||||
# check control logic for single port
|
# check control logic for single port
|
||||||
debug.info(1, "Testing sample for control_logic")
|
debug.info(1, "Testing sample for control_logic")
|
||||||
a = control_logic.control_logic(num_rows=128)
|
a = control_logic.control_logic(num_rows=128, words_per_row=1)
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
# check control logic for multi-port
|
# check control logic for multi-port
|
||||||
|
|
@ -31,7 +31,7 @@ class control_logic_test(openram_test):
|
||||||
OPTS.num_r_ports = 0
|
OPTS.num_r_ports = 0
|
||||||
|
|
||||||
debug.info(1, "Testing sample for control_logic for multiport")
|
debug.info(1, "Testing sample for control_logic for multiport")
|
||||||
a = control_logic.control_logic(num_rows=128)
|
a = control_logic.control_logic(num_rows=128, words_per_row=1)
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
# Check port specific control logic
|
# Check port specific control logic
|
||||||
|
|
@ -40,15 +40,15 @@ class control_logic_test(openram_test):
|
||||||
OPTS.num_r_ports = 1
|
OPTS.num_r_ports = 1
|
||||||
|
|
||||||
debug.info(1, "Testing sample for control_logic for multiport, only write control logic")
|
debug.info(1, "Testing sample for control_logic for multiport, only write control logic")
|
||||||
a = control_logic.control_logic(num_rows=128, port_type="rw")
|
a = control_logic.control_logic(num_rows=128, words_per_row=1, port_type="rw")
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
debug.info(1, "Testing sample for control_logic for multiport, only write control logic")
|
debug.info(1, "Testing sample for control_logic for multiport, only write control logic")
|
||||||
a = control_logic.control_logic(num_rows=128, port_type="w")
|
a = control_logic.control_logic(num_rows=128, words_per_row=1, port_type="w")
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
debug.info(1, "Testing sample for control_logic for multiport, only read control logic")
|
debug.info(1, "Testing sample for control_logic for multiport, only read control logic")
|
||||||
a = control_logic.control_logic(num_rows=128, port_type="r")
|
a = control_logic.control_logic(num_rows=128, words_per_row=1, port_type="r")
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ class psram_1bank_2mux_func_test(openram_test):
|
||||||
OPTS.netlist_only = True
|
OPTS.netlist_only = True
|
||||||
OPTS.bitcell = "pbitcell"
|
OPTS.bitcell = "pbitcell"
|
||||||
OPTS.replica_bitcell="replica_pbitcell"
|
OPTS.replica_bitcell="replica_pbitcell"
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 1
|
||||||
|
|
||||||
# This is a hack to reload the characterizer __init__ with the spice version
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import globals
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
@unittest.skip("SKIPPING 22_psram_1bank_4mux_func_test")
|
#@unittest.skip("SKIPPING 22_psram_1bank_4mux_func_test")
|
||||||
class psram_1bank_4mux_func_test(openram_test):
|
class psram_1bank_4mux_func_test(openram_test):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
|
|
@ -20,6 +20,9 @@ class psram_1bank_4mux_func_test(openram_test):
|
||||||
OPTS.netlist_only = True
|
OPTS.netlist_only = True
|
||||||
OPTS.bitcell = "pbitcell"
|
OPTS.bitcell = "pbitcell"
|
||||||
OPTS.replica_bitcell="replica_pbitcell"
|
OPTS.replica_bitcell="replica_pbitcell"
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 1
|
||||||
|
|
||||||
# This is a hack to reload the characterizer __init__ with the spice version
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import globals
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
@unittest.skip("SKIPPING 22_psram_1bank_8mux_func_test")
|
#@unittest.skip("SKIPPING 22_psram_1bank_8mux_func_test")
|
||||||
class psram_1bank_8mux_func_test(openram_test):
|
class psram_1bank_8mux_func_test(openram_test):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
|
|
@ -20,6 +20,9 @@ class psram_1bank_8mux_func_test(openram_test):
|
||||||
OPTS.netlist_only = True
|
OPTS.netlist_only = True
|
||||||
OPTS.bitcell = "pbitcell"
|
OPTS.bitcell = "pbitcell"
|
||||||
OPTS.replica_bitcell="replica_pbitcell"
|
OPTS.replica_bitcell="replica_pbitcell"
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 1
|
||||||
|
|
||||||
# This is a hack to reload the characterizer __init__ with the spice version
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
|
|
@ -29,7 +32,7 @@ class psram_1bank_8mux_func_test(openram_test):
|
||||||
from sram import sram
|
from sram import sram
|
||||||
from sram_config import sram_config
|
from sram_config import sram_config
|
||||||
c = sram_config(word_size=4,
|
c = sram_config(word_size=4,
|
||||||
num_words=512,
|
num_words=256,
|
||||||
num_banks=1)
|
num_banks=1)
|
||||||
c.words_per_row=8
|
c.words_per_row=8
|
||||||
debug.info(1, "Functional test for psram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
debug.info(1, "Functional test for psram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,9 @@ class psram_1bank_nomux_func_test(openram_test):
|
||||||
OPTS.netlist_only = True
|
OPTS.netlist_only = True
|
||||||
OPTS.bitcell = "pbitcell"
|
OPTS.bitcell = "pbitcell"
|
||||||
OPTS.replica_bitcell="replica_pbitcell"
|
OPTS.replica_bitcell="replica_pbitcell"
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
OPTS.num_w_ports = 1
|
||||||
|
|
||||||
# This is a hack to reload the characterizer __init__ with the spice version
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
from importlib import reload
|
from importlib import reload
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import globals
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
@unittest.skip("SKIPPING 22_sram_1bank_4mux_func_test")
|
#@unittest.skip("SKIPPING 22_sram_1bank_4mux_func_test")
|
||||||
class sram_1bank_4mux_func_test(openram_test):
|
class sram_1bank_4mux_func_test(openram_test):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import globals
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
@unittest.skip("SKIPPING 22_sram_1bank_8mux_func_test")
|
#@unittest.skip("SKIPPING 22_sram_1bank_8mux_func_test")
|
||||||
class sram_1bank_8mux_func_test(openram_test):
|
class sram_1bank_8mux_func_test(openram_test):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
|
|
@ -30,7 +30,7 @@ class sram_1bank_8mux_func_test(openram_test):
|
||||||
from sram import sram
|
from sram import sram
|
||||||
from sram_config import sram_config
|
from sram_config import sram_config
|
||||||
c = sram_config(word_size=4,
|
c = sram_config(word_size=4,
|
||||||
num_words=512,
|
num_words=256,
|
||||||
num_banks=1)
|
num_banks=1)
|
||||||
c.words_per_row=8
|
c.words_per_row=8
|
||||||
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
|
@ -39,6 +39,7 @@ class sram_1bank_8mux_func_test(openram_test):
|
||||||
c.num_banks))
|
c.num_banks))
|
||||||
s = sram(c, name="sram")
|
s = sram(c, name="sram")
|
||||||
tempspice = OPTS.openram_temp + "temp.sp"
|
tempspice = OPTS.openram_temp + "temp.sp"
|
||||||
|
tempspice = OPTS.openram_temp + "temp.sp"
|
||||||
s.sp_write(tempspice)
|
s.sp_write(tempspice)
|
||||||
|
|
||||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Run a functioal test on 1 bank SRAM
|
||||||
|
"""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from testutils import header,openram_test
|
||||||
|
import sys,os
|
||||||
|
sys.path.append(os.path.join(sys.path[0],".."))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
import debug
|
||||||
|
|
||||||
|
#@unittest.skip("SKIPPING 22_sram_1rw_1r_1bank_nomux_func_test")
|
||||||
|
class psram_1bank_nomux_func_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.netlist_only = True
|
||||||
|
OPTS.bitcell = "bitcell_1rw_1r"
|
||||||
|
OPTS.replica_bitcell = "replica_bitcell_1rw_1r"
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_w_ports = 0
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
|
||||||
|
# This is a hack to reload the characterizer __init__ with the spice version
|
||||||
|
from importlib import reload
|
||||||
|
import characterizer
|
||||||
|
reload(characterizer)
|
||||||
|
from characterizer import functional
|
||||||
|
from sram import sram
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=4,
|
||||||
|
num_words=32,
|
||||||
|
num_banks=1)
|
||||||
|
c.words_per_row=1
|
||||||
|
debug.info(1, "Functional test for sram 1rw,1r with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
|
||||||
|
c.num_words,
|
||||||
|
c.words_per_row,
|
||||||
|
c.num_banks))
|
||||||
|
s = sram(c, name="sram")
|
||||||
|
tempspice = OPTS.openram_temp + "temp.sp"
|
||||||
|
s.sp_write(tempspice)
|
||||||
|
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
|
||||||
|
f = functional(s.s, tempspice, corner)
|
||||||
|
f.num_cycles = 10
|
||||||
|
(fail, error) = f.run()
|
||||||
|
self.assertTrue(fail,error)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copy of the class to actually run the test
|
||||||
|
if __name__ == "__main__":
|
||||||
|
(OPTS, args) = globals.parse_args()
|
||||||
|
del sys.argv[1:]
|
||||||
|
header(__file__, OPTS.tech_name)
|
||||||
|
unittest.main()
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
.SUBCKT replica_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd
|
||||||
|
MM9 RA_to_R_right wl1 br1 gnd NMOS_VTG W=180.0n L=50n m=1
|
||||||
|
MM8 RA_to_R_right Q gnd gnd NMOS_VTG W=180.0n L=50n m=1
|
||||||
|
MM7 RA_to_R_left vdd gnd gnd NMOS_VTG W=180.0n L=50n m=1
|
||||||
|
MM6 RA_to_R_left wl1 bl1 gnd NMOS_VTG W=180.0n L=50n m=1
|
||||||
|
MM5 Q wl0 bl0 gnd NMOS_VTG W=135.00n L=50n m=1
|
||||||
|
MM4 vdd wl0 br0 gnd NMOS_VTG W=135.00n L=50n m=1
|
||||||
|
MM1 Q vdd gnd gnd NMOS_VTG W=270.0n L=50n m=1
|
||||||
|
MM0 vdd Q gnd gnd NMOS_VTG W=270.0n L=50n m=1
|
||||||
|
MM3 Q vdd vdd vdd PMOS_VTG W=90n L=50n m=1
|
||||||
|
MM2 vdd Q vdd vdd PMOS_VTG W=90n L=50n m=1
|
||||||
|
.ENDS
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,6 +1,6 @@
|
||||||
magic
|
magic
|
||||||
tech scmos
|
tech scmos
|
||||||
timestamp 1540504134
|
timestamp 1541193956
|
||||||
<< nwell >>
|
<< nwell >>
|
||||||
rect 0 50 54 79
|
rect 0 50 54 79
|
||||||
<< pwell >>
|
<< pwell >>
|
||||||
|
|
@ -139,10 +139,10 @@ rect 0 0 54 74
|
||||||
<< labels >>
|
<< labels >>
|
||||||
rlabel metal1 27 4 27 4 1 wl1
|
rlabel metal1 27 4 27 4 1 wl1
|
||||||
rlabel psubstratepcontact 27 11 27 11 1 gnd
|
rlabel psubstratepcontact 27 11 27 11 1 gnd
|
||||||
rlabel m2contact 27 74 27 74 5 vdd
|
|
||||||
rlabel metal1 19 67 19 67 1 wl0
|
rlabel metal1 19 67 19 67 1 wl0
|
||||||
rlabel metal2 4 7 4 7 2 bl0
|
rlabel metal2 4 7 4 7 2 bl0
|
||||||
rlabel metal2 11 7 11 7 1 bl1
|
rlabel metal2 11 7 11 7 1 bl1
|
||||||
rlabel metal2 43 7 43 7 1 br1
|
rlabel metal2 43 7 43 7 1 br1
|
||||||
rlabel metal2 50 7 50 7 8 br0
|
rlabel metal2 50 7 50 7 8 br0
|
||||||
|
rlabel metal1 19 74 19 74 5 vdd
|
||||||
<< end >>
|
<< end >>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
magic
|
||||||
|
tech scmos
|
||||||
|
timestamp 1541194096
|
||||||
|
<< nwell >>
|
||||||
|
rect 0 50 54 79
|
||||||
|
<< pwell >>
|
||||||
|
rect 0 0 54 50
|
||||||
|
<< ntransistor >>
|
||||||
|
rect 14 35 16 41
|
||||||
|
rect 22 29 24 41
|
||||||
|
rect 30 29 32 41
|
||||||
|
rect 38 35 40 41
|
||||||
|
rect 14 17 16 25
|
||||||
|
rect 22 17 24 25
|
||||||
|
rect 30 17 32 25
|
||||||
|
rect 38 17 40 25
|
||||||
|
<< ptransistor >>
|
||||||
|
rect 22 58 24 62
|
||||||
|
rect 30 58 32 62
|
||||||
|
<< ndiffusion >>
|
||||||
|
rect 9 39 14 41
|
||||||
|
rect 13 35 14 39
|
||||||
|
rect 16 35 17 41
|
||||||
|
rect 21 33 22 41
|
||||||
|
rect 17 29 22 33
|
||||||
|
rect 24 29 25 41
|
||||||
|
rect 29 29 30 41
|
||||||
|
rect 32 33 33 41
|
||||||
|
rect 37 35 38 41
|
||||||
|
rect 40 39 45 41
|
||||||
|
rect 40 35 41 39
|
||||||
|
rect 32 29 37 33
|
||||||
|
rect 9 23 14 25
|
||||||
|
rect 13 19 14 23
|
||||||
|
rect 9 17 14 19
|
||||||
|
rect 16 17 22 25
|
||||||
|
rect 24 17 25 25
|
||||||
|
rect 29 17 30 25
|
||||||
|
rect 32 17 38 25
|
||||||
|
rect 40 23 45 25
|
||||||
|
rect 40 19 41 23
|
||||||
|
rect 40 17 45 19
|
||||||
|
<< pdiffusion >>
|
||||||
|
rect 21 58 22 62
|
||||||
|
rect 24 58 25 62
|
||||||
|
rect 29 58 30 62
|
||||||
|
rect 32 58 33 62
|
||||||
|
<< ndcontact >>
|
||||||
|
rect 9 35 13 39
|
||||||
|
rect 17 33 21 41
|
||||||
|
rect 25 29 29 41
|
||||||
|
rect 33 33 37 41
|
||||||
|
rect 41 35 45 39
|
||||||
|
rect 9 19 13 23
|
||||||
|
rect 25 17 29 25
|
||||||
|
rect 41 19 45 23
|
||||||
|
<< pdcontact >>
|
||||||
|
rect 17 58 21 62
|
||||||
|
rect 25 58 29 62
|
||||||
|
rect 33 58 37 62
|
||||||
|
<< psubstratepcontact >>
|
||||||
|
rect 25 9 29 13
|
||||||
|
<< nsubstratencontact >>
|
||||||
|
rect 25 72 29 76
|
||||||
|
<< polysilicon >>
|
||||||
|
rect 22 62 24 64
|
||||||
|
rect 30 62 32 64
|
||||||
|
rect 22 48 24 58
|
||||||
|
rect 30 55 32 58
|
||||||
|
rect 31 51 32 55
|
||||||
|
rect 14 41 16 46
|
||||||
|
rect 22 44 23 48
|
||||||
|
rect 22 41 24 44
|
||||||
|
rect 30 41 32 51
|
||||||
|
rect 38 41 40 46
|
||||||
|
rect 14 33 16 35
|
||||||
|
rect 38 33 40 35
|
||||||
|
rect 14 25 16 26
|
||||||
|
rect 22 25 24 29
|
||||||
|
rect 30 25 32 29
|
||||||
|
rect 38 25 40 26
|
||||||
|
rect 14 15 16 17
|
||||||
|
rect 22 15 24 17
|
||||||
|
rect 30 15 32 17
|
||||||
|
rect 38 15 40 17
|
||||||
|
<< polycontact >>
|
||||||
|
rect 27 51 31 55
|
||||||
|
rect 10 42 14 46
|
||||||
|
rect 23 44 27 48
|
||||||
|
rect 40 42 44 46
|
||||||
|
rect 12 26 16 30
|
||||||
|
rect 38 26 42 30
|
||||||
|
<< metal1 >>
|
||||||
|
rect 0 72 25 76
|
||||||
|
rect 29 72 54 76
|
||||||
|
rect 0 65 54 69
|
||||||
|
rect 10 46 14 65
|
||||||
|
rect 29 58 33 62
|
||||||
|
rect 17 55 20 58
|
||||||
|
rect 17 51 27 55
|
||||||
|
rect 17 41 20 51
|
||||||
|
rect 34 48 37 58
|
||||||
|
rect 27 44 37 48
|
||||||
|
rect 34 41 37 44
|
||||||
|
rect 40 46 44 65
|
||||||
|
rect 6 35 9 39
|
||||||
|
rect 45 35 48 39
|
||||||
|
rect 25 25 29 29
|
||||||
|
rect 25 13 29 17
|
||||||
|
rect 0 9 25 13
|
||||||
|
rect 29 9 54 13
|
||||||
|
rect 0 2 16 6
|
||||||
|
rect 20 2 34 6
|
||||||
|
rect 38 2 54 6
|
||||||
|
<< m2contact >>
|
||||||
|
rect 25 72 29 76
|
||||||
|
rect 25 58 29 62
|
||||||
|
rect 2 35 6 39
|
||||||
|
rect 16 26 20 30
|
||||||
|
rect 48 35 52 39
|
||||||
|
rect 34 26 38 30
|
||||||
|
rect 9 19 13 23
|
||||||
|
rect 41 19 45 23
|
||||||
|
rect 16 2 20 6
|
||||||
|
rect 34 2 38 6
|
||||||
|
<< metal2 >>
|
||||||
|
rect 2 39 6 76
|
||||||
|
rect 2 0 6 35
|
||||||
|
rect 9 23 13 76
|
||||||
|
rect 25 62 29 72
|
||||||
|
rect 9 0 13 19
|
||||||
|
rect 16 6 20 26
|
||||||
|
rect 34 6 38 26
|
||||||
|
rect 41 23 45 76
|
||||||
|
rect 41 0 45 19
|
||||||
|
rect 48 39 52 76
|
||||||
|
rect 48 0 52 35
|
||||||
|
<< bb >>
|
||||||
|
rect 0 0 54 74
|
||||||
|
<< labels >>
|
||||||
|
rlabel metal1 27 4 27 4 1 wl1
|
||||||
|
rlabel psubstratepcontact 27 11 27 11 1 gnd
|
||||||
|
rlabel metal1 19 67 19 67 1 wl0
|
||||||
|
rlabel metal2 4 7 4 7 2 bl0
|
||||||
|
rlabel metal2 11 7 11 7 1 bl1
|
||||||
|
rlabel metal2 43 7 43 7 1 br1
|
||||||
|
rlabel metal2 50 7 50 7 8 br0
|
||||||
|
rlabel metal1 19 74 19 74 5 vdd
|
||||||
|
<< end >>
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
.SUBCKT replica_cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd
|
||||||
|
MM9 RA_to_R_right wl1 br1 gnd n w=1.6u l=0.4u
|
||||||
|
MM8 RA_to_R_right Q gnd gnd n w=1.6u l=0.4u
|
||||||
|
MM7 RA_to_R_left vdd gnd gnd n w=1.6u l=0.4u
|
||||||
|
MM6 RA_to_R_left wl1 bl1 gnd n w=1.6u l=0.4u
|
||||||
|
MM5 Q wl0 bl0 gnd n w=1.2u l=0.4u
|
||||||
|
MM4 vdd wl0 br0 gnd n w=1.2u l=0.4u
|
||||||
|
MM1 Q vdd gnd gnd n w=2.4u l=0.4u
|
||||||
|
MM0 vdd Q gnd gnd n w=2.4u l=0.4u
|
||||||
|
MM3 Q vdd vdd vdd p w=0.8u l=0.4u
|
||||||
|
MM2 vdd Q vdd vdd p w=0.8u l=0.4u
|
||||||
|
.ENDS
|
||||||
|
|
||||||
Loading…
Reference in New Issue