Merge branch 'supply_routing' of https://github.com/VLSIDA/PrivateRAM into supply_routing

This commit is contained in:
Matt Guthaus 2018-11-06 07:56:57 -08:00
commit 485590052a
33 changed files with 477 additions and 99 deletions

View File

@ -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

View File

@ -35,7 +35,15 @@ class functional(simulation):
self.stored_words = {}
self.write_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):
# Generate a random sequence of reads and writes
self.write_random_memory_sequence()

View File

@ -208,14 +208,14 @@ class simulation():
t_current,
t_current+self.period)
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,
port,
int(t_current/self.period),
t_current,
t_current+self.period)
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,
port,
int(t_current/self.period),

View File

@ -18,13 +18,14 @@ class control_logic(design.design):
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 """
name = "control_logic_" + port_type
design.design.__init__(self, name)
debug.info(1, "Creating {}".format(name))
self.num_rows = num_rows
self.words_per_row = words_per_row
self.port_type = port_type
if self.port_type == "rw":
@ -92,14 +93,25 @@ class control_logic(design.design):
from importlib import reload
c = reload(__import__(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_fanout = 3 # This can be anything >=2
delay_stages, delay_fanout = self.get_delay_chain_size()
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.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):
""" Setup bus names, determine the size of the busses etc """

View File

@ -189,16 +189,66 @@ class replica_bitline(design.design):
if pin.layer != "metal1":
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)
# 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)
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)
correct = vector(0.5*drc("minwidth_metal1"), 0)
self.add_path("metal1", [pin.rc()-correct, pin_last.rc()-correct])
#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()])
def route_supplies(self):
""" 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
pin=self.rbc_inst.get_pin("vdd")
# Don't rotate this via to vit in FreePDK45
self.add_power_pin("vdd", pin.center(), rotate=0)
# Don't rotate this via to vit in FreePDK45. In the custom cell, the pin cannot be placed
# 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"):
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]
pin = self.rbc_inst.get_pin(wl)
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)
self.add_path("metal1", [pin.lc()+correct, pin_last.lc()+correct])
#correct = vector(0.5*drc("minwidth_metal1"), 0)
#self.add_path("metal1", [pin.lc()+correct, pin_last.lc()+correct])
# DRAIN ROUTE
# Route the drain to the vdd rail

View File

@ -25,6 +25,7 @@ class sense_amp(design.design):
def input_load(self):
#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.
return spice["min_tx_drain_c"]*(bitline_pmos_size/parameter["min_tx_size"])#ff

View File

@ -218,7 +218,7 @@ class single_level_column_mux_array(design.design):
rotate=90)
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"])
#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

View File

@ -223,13 +223,13 @@ class sram_base(design):
from control_logic import control_logic
# Create the control logic module for each port type
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)
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)
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)
# Create the address and control flops (but not the clk)

View File

@ -24,6 +24,26 @@ class replica_bitline_test(openram_test):
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)
#debug.error("Exiting...", 1)
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 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
@ -31,7 +51,7 @@ class replica_bitline_test(openram_test):
a = replica_bitline.replica_bitline(stages,fanout,rows)
self.local_check(a)
# check replica bitline in multi-port
# check replica bitline in pbitcell multi-port
OPTS.bitcell = "pbitcell"
OPTS.replica_bitcell = "replica_pbitcell"
OPTS.num_rw_ports = 1
@ -61,7 +81,7 @@ class replica_bitline_test(openram_test):
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))

View File

@ -20,7 +20,7 @@ class control_logic_test(openram_test):
# check control logic for single port
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)
# check control logic for multi-port
@ -31,7 +31,7 @@ class control_logic_test(openram_test):
OPTS.num_r_ports = 0
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)
# Check port specific control logic
@ -40,15 +40,15 @@ class control_logic_test(openram_test):
OPTS.num_r_ports = 1
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)
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)
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)
globals.end_openram()

View File

@ -20,6 +20,9 @@ class psram_1bank_2mux_func_test(openram_test):
OPTS.netlist_only = True
OPTS.bitcell = "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
from importlib import reload

View File

@ -11,7 +11,7 @@ import globals
from globals import OPTS
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):
def runTest(self):
@ -20,6 +20,9 @@ class psram_1bank_4mux_func_test(openram_test):
OPTS.netlist_only = True
OPTS.bitcell = "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
from importlib import reload

View File

@ -11,7 +11,7 @@ import globals
from globals import OPTS
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):
def runTest(self):
@ -20,6 +20,9 @@ class psram_1bank_8mux_func_test(openram_test):
OPTS.netlist_only = True
OPTS.bitcell = "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
from importlib import reload
@ -29,7 +32,7 @@ class psram_1bank_8mux_func_test(openram_test):
from sram import sram
from sram_config import sram_config
c = sram_config(word_size=4,
num_words=512,
num_words=256,
num_banks=1)
c.words_per_row=8
debug.info(1, "Functional test for psram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,

View File

@ -20,6 +20,9 @@ class psram_1bank_nomux_func_test(openram_test):
OPTS.netlist_only = True
OPTS.bitcell = "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
from importlib import reload

View File

@ -11,7 +11,7 @@ import globals
from globals import OPTS
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):
def runTest(self):

View File

@ -11,7 +11,7 @@ import globals
from globals import OPTS
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):
def runTest(self):
@ -30,7 +30,7 @@ class sram_1bank_8mux_func_test(openram_test):
from sram import sram
from sram_config import sram_config
c = sram_config(word_size=4,
num_words=512,
num_words=256,
num_banks=1)
c.words_per_row=8
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
@ -38,6 +38,7 @@ class sram_1bank_8mux_func_test(openram_test):
c.words_per_row,
c.num_banks))
s = sram(c, name="sram")
tempspice = OPTS.openram_temp + "temp.sp"
tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice)

View File

@ -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.

View File

@ -1,10 +1,15 @@
.SUBCKT cell_6t bl br wl vdd gnd
* Inverter 1
MM0 Qbar Q gnd gnd NMOS_VTG W=205.00n L=50n
MM4 Qbar Q vdd vdd PMOS_VTG W=90n L=50n
* Inverer 2
MM1 Q Qbar gnd gnd NMOS_VTG W=205.00n L=50n
MM5 Q Qbar vdd vdd PMOS_VTG W=90n L=50n
* Access transistors
MM3 bl wl Q gnd NMOS_VTG W=135.00n L=50n
MM2 br wl Qb gnd NMOS_VTG W=135.00n L=50n
MM1 Q Qb gnd gnd NMOS_VTG W=205.00n L=50n
MM0 Qb Q gnd gnd NMOS_VTG W=205.00n L=50n
MM5 Q Qb vdd vdd PMOS_VTG W=90n L=50n
MM4 Qb Q vdd vdd PMOS_VTG W=90n L=50n
MM2 br wl Qbar gnd NMOS_VTG W=135.00n L=50n
.ENDS cell_6t

View File

@ -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

View File

@ -1,10 +1,15 @@
.SUBCKT replica_cell_6t bl br wl vdd gnd
MM3 bl wl gnd gnd NMOS_VTG W=135.00n L=50n
MM2 br wl net4 gnd NMOS_VTG W=135.00n L=50n
MM1 gnd net4 gnd gnd NMOS_VTG W=205.00n L=50n
MM0 net4 gnd gnd gnd NMOS_VTG W=205.00n L=50n
MM5 gnd net4 vdd vdd PMOS_VTG W=90n L=50n
MM4 net4 gnd vdd vdd PMOS_VTG W=90n L=50n
.ENDS replica_cell_6t
* Inverter 1
MM0 vdd Q gnd gnd NMOS_VTG W=205.00n L=50n
MM4 vdd Q vdd vdd PMOS_VTG W=90n L=50n
* Inverer 2
MM1 Q vdd gnd gnd NMOS_VTG W=205.00n L=50n
MM5 Q vdd vdd vdd PMOS_VTG W=90n L=50n
* Access transistors
MM3 bl wl Q gnd NMOS_VTG W=135.00n L=50n
MM2 br wl vdd gnd NMOS_VTG W=135.00n L=50n
.ENDS cell_6t

Binary file not shown.

View File

@ -1,6 +1,6 @@
magic
tech scmos
timestamp 1540504134
timestamp 1541193956
<< nwell >>
rect 0 50 54 79
<< pwell >>
@ -139,10 +139,10 @@ rect 0 0 54 74
<< labels >>
rlabel metal1 27 4 27 4 1 wl1
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 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 >>

View File

@ -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 >>

View File

@ -1,6 +1,6 @@
magic
tech scmos
timestamp 1536091380
timestamp 1541443051
<< nwell >>
rect -8 29 42 51
<< pwell >>
@ -76,15 +76,15 @@ rect 17 6 21 10
rect -2 44 15 48
rect 19 44 32 48
rect -2 40 2 44
rect 22 40 26 44
rect 32 40 36 44
rect 11 36 12 40
rect 26 36 27 40
rect -2 26 2 29
rect 11 22 15 36
rect -2 16 2 22
rect 11 18 15 36
rect 23 24 27 36
rect -2 18 15 22
rect 25 20 27 24
rect -2 16 2 18
rect 14 14 15 18
rect 23 18 27 20
rect 32 26 36 29

View File

@ -3,11 +3,16 @@
.SUBCKT cell_6t bl br wl vdd gnd
* SPICE3 file created from cell_6t.ext - technology: scmos
M1000 a_36_40# a_28_32# vdd vdd p w=0.6u l=0.8u
M1001 vdd a_36_40# a_28_32# vdd p w=0.6u l=0.8u
M1002 a_36_40# a_28_32# gnd gnd n w=1.6u l=0.4u
M1003 gnd a_36_40# a_28_32# gnd n w=1.6u l=0.4u
M1004 a_36_40# wl bl gnd n w=0.8u l=0.4u
M1005 a_28_32# wl br gnd n w=0.8u l=0.4u
* Inverter 1
M1000 Q Qbar vdd vdd p w=0.6u l=0.8u
M1002 Q Qbar gnd gnd n w=1.6u l=0.4u
* Inverter 2
M1001 vdd Q Qbar vdd p w=0.6u l=0.8u
M1003 gnd Q Qbar gnd n w=1.6u l=0.4u
* Access transistors
M1004 Q wl bl gnd n w=0.8u l=0.4u
M1005 Qbar wl br gnd n w=0.8u l=0.4u
.ENDS

View File

@ -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

View File

@ -1,14 +1,18 @@
*********************** "cell_6t" ******************************
.SUBCKT replica_cell_6t bl br wl vdd gnd
* SPICE3 file created from replica_cell_6t.ext - technology: scmos
* SPICE3 file created from cell_6t.ext - technology: scmos
M1000 gnd a_28_32# vdd vdd p w=0.6u l=0.8u
M1001 vdd gnd a_28_32# vdd p w=0.6u l=0.8u
** SOURCE/DRAIN TIED
M1002 gnd a_28_32# gnd gnd n w=1.6u l=0.4u
M1003 gnd gnd a_28_32# gnd n w=1.6u l=0.4u
M1004 gnd wl bl gnd n w=0.8u l=0.4u
M1005 a_28_32# wl br gnd n w=0.8u l=0.4u
* Inverter 1
M1000 Q vdd vdd vdd p w=0.6u l=0.8u
M1002 Q vdd gnd gnd n w=1.6u l=0.4u
* Inverter 2
M1001 vdd Q vdd vdd p w=0.6u l=0.8u
M1003 gnd Q vdd gnd n w=1.6u l=0.4u
* Access transistors
M1004 Q wl bl gnd n w=0.8u l=0.4u
M1005 vdd wl br gnd n w=0.8u l=0.4u
.ENDS

View File

@ -1,5 +1,5 @@
tech
format 29
format 31
scmos
end
@ -301,11 +301,6 @@ style lambda=0.20(p)
scalefactor 20 10
options calma-permissive-labels
# This is a custom section to add bounding boxes in OpenRAM
layer BB bb
labels bb
calma 63 0
layer CWN nwell,rnw,nwr,nwsd,nwsc
bloat-or pdiff,apres,rpd,pdc/a,pfet * 120
bloat-or nsd,nsc/a * 60
@ -1769,11 +1764,6 @@ cifinput
style lambda=0.20(p)
scalefactor 20
# This is a custom section to add bounding boxes in OpenRAM
layer bb BB
labels BB
calma 63 0
layer nwell CWN
and-not CWNR
and-not CTA
@ -6701,7 +6691,7 @@ drc
edge4way nfet,pfet,fet space/active,ndiff,anres,rnd,ndc/a,pdiff,apres,rpd,pdc/a 3 ndiff,anres,rnd,ndc/a,pdiff,apres,rpd,pdc/a,nfet,pfet,fet 0 0 \
"N-Diffusion,P-Diffusion overhang of Transistor < 3 (Mosis #3.4)" active
edge4way poly,fp,rp,pc/a ~(poly,fp,pres,rp,pc/a,nfet,pfet,fet,prp)/active 1 space space 1 \
edge4way poly,fp,rp,pc/a ~(poly,fp,pres,rp,pc/a,nfet,pfet,fet,prp)/active 1 space/a space/a 1 \
"Poly spacing to Diffusion < 1 (Mosis #3.5)"
edge4way nfet ~(nfet)/active 2 ~(pselect)/select ~(nfet)/active 2 \
@ -7212,13 +7202,15 @@ extract
planeorder via3 14
planeorder fill 15
substrate *psd,space/w,pwell well
resist (ndiff,anres,rnd,ndc,nsd,nwsd,nsc,nwsc)/active 3700
resist (pdiff,apres,rpd,pdc,psd,psc)/active 2800
resist (nwell)/well 1018000
resist (rnw,nwr)/active 1018000
resist (rnw,nwr)/active 1018000 0.5
resist (pwell)/well 1
resist (poly,fp,rp,pc,pc,nfet,pfet,fet)/active 6000
resist (pres)/active 6000
resist (pres)/active 6000 0.5
resist (m1,fm1,rm1,ndc,nsc,nwsc,pdc,psc,pc,m2c,m2c)/metal1 80
resist (m2,fm2,rm2,m2c,m3c,m3c)/metal2 70
resist (m3,fm3,rm3,m3c,m4c,m4c)/metal3 80
@ -7416,33 +7408,30 @@ extract
#metali
#fets
#devices
fet pfet pdiff,pdc 2 pfet Vdd! nwell 52 181
fet pfet pdiff,pdc 1 pfet Vdd! nwell 52 181
fet nfet ndiff,ndc 2 nfet Gnd! pwell 55 182
fet nfet ndiff,ndc 1 nfet Gnd! pwell 55 182
device mosfet pfet pfet pdiff,pdc nwell ERROR 52 181
device mosfet nfet nfet ndiff,ndc pwell,space/w ERROR 55 182
fetresis pfet linear 12182
fetresis pfet saturation 12182
fetresis nfet linear 3961
fetresis nfet saturation 3961
fet rnwell nsd,nsc 2 nwellResistor Gnd! nwell,pwell 0 0
fet rpoly poly,pc 2 polyResistor Gnd! nwell,pwell 0 0
fet nwr nwsd 2 nwellFig1bResistor Gnd! nwell,pwell 0 0
fet rndiff ndiff,ndc 2 ndiffResistor Gnd! nwell,pwell 0 0
fet rpdiff pdiff,pdc 2 pdiffResistor Gnd! nwell,pwell 0 0
device resistor nwellResistor rnwell *nsd
device resistor polyResistor rpoly *poly
device resistor nwellFig1bResistor nwr nwsd
device resistor ndiffResistor rndiff *ndiff
device resistor pdiffResistor rpdiff *pdiff
fet rmetal1 metal1 2 metal1Resistor Gnd! nwell,pwell 0 0
fet rmetal2 metal2 2 metal2Resistor Gnd! nwell,pwell 0 0
fet rmetal3 metal3 2 metal3Resistor Gnd! nwell,pwell 0 0
fet rmetal4 metal4 2 metal4Resistor Gnd! nwell,pwell 0 0
device resistor metal1Resistor rmetal1 *metal1
device resistor metal2Resistor rmetal2 *metal2
device resistor metal3Resistor rmetal3 *metal3
device resistor metal4Resistor rmetal4 *metal4
fet pres poly,pc 2 presResistor Gnd! nwell,pwell 0 0
fet anres ndiff,ndc 2 anresResistor Gnd! nwell,pwell 0 0
fet apres pdiff,pdc 2 apresResistor Gnd! nwell,pwell 0 0
device resistor presResistor pres *poly
device resistor anresResistor anres *ndiff
device resistor apresResistor apres *pdiff
end

View File

@ -240,7 +240,7 @@ spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"
#spice stimulus related variables
spice["feasible_period"] = 5 # estimated feasible period in ns
spice["feasible_period"] = 5 # estimated feasible period in ns
spice["supply_voltages"] = [4.5, 5.0, 5.5] # Supply voltage corners in [Volts]
spice["nom_supply_voltage"] = 5.0 # Nominal supply voltage in [Volts]
spice["rise_time"] = 0.05 # rise time in [Nano-seconds]