diff --git a/compiler/bitcells/replica_bitcell_1rw_1r.py b/compiler/bitcells/replica_bitcell_1rw_1r.py new file mode 100644 index 00000000..790a6251 --- /dev/null +++ b/compiler/bitcells/replica_bitcell_1rw_1r.py @@ -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 diff --git a/compiler/characterizer/functional.py b/compiler/characterizer/functional.py index a777437d..b69ab2e8 100644 --- a/compiler/characterizer/functional.py +++ b/compiler/characterizer/functional.py @@ -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() diff --git a/compiler/characterizer/simulation.py b/compiler/characterizer/simulation.py index d4fb210e..e624250a 100644 --- a/compiler/characterizer/simulation.py +++ b/compiler/characterizer/simulation.py @@ -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), diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index e6662617..4ac32967 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -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 """ diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index 8095d049..84aaa63d 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -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 diff --git a/compiler/modules/sense_amp.py b/compiler/modules/sense_amp.py index 6187b37a..3a857efd 100644 --- a/compiler/modules/sense_amp.py +++ b/compiler/modules/sense_amp.py @@ -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 diff --git a/compiler/modules/single_level_column_mux_array.py b/compiler/modules/single_level_column_mux_array.py index a74f8514..d78e0fdc 100644 --- a/compiler/modules/single_level_column_mux_array.py +++ b/compiler/modules/single_level_column_mux_array.py @@ -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 diff --git a/compiler/sram_base.py b/compiler/sram_base.py index cc8247ed..a1be1f30 100644 --- a/compiler/sram_base.py +++ b/compiler/sram_base.py @@ -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) diff --git a/compiler/tests/14_replica_bitline_test.py b/compiler/tests/14_replica_bitline_test.py index 9853b581..08d9be5f 100755 --- a/compiler/tests/14_replica_bitline_test.py +++ b/compiler/tests/14_replica_bitline_test.py @@ -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)) diff --git a/compiler/tests/16_control_logic_test.py b/compiler/tests/16_control_logic_test.py index ef435c4c..818c2eaf 100755 --- a/compiler/tests/16_control_logic_test.py +++ b/compiler/tests/16_control_logic_test.py @@ -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() diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index 1e1367ed..f2679c03 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -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 diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index de2e01d4..a8d6dab2 100755 --- a/compiler/tests/22_psram_1bank_4mux_func_test.py +++ b/compiler/tests/22_psram_1bank_4mux_func_test.py @@ -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 diff --git a/compiler/tests/22_psram_1bank_8mux_func_test.py b/compiler/tests/22_psram_1bank_8mux_func_test.py index 02ea2f3b..1a0a1ec5 100755 --- a/compiler/tests/22_psram_1bank_8mux_func_test.py +++ b/compiler/tests/22_psram_1bank_8mux_func_test.py @@ -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, diff --git a/compiler/tests/22_psram_1bank_nomux_func_test.py b/compiler/tests/22_psram_1bank_nomux_func_test.py index ce852dff..7817b055 100755 --- a/compiler/tests/22_psram_1bank_nomux_func_test.py +++ b/compiler/tests/22_psram_1bank_nomux_func_test.py @@ -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 diff --git a/compiler/tests/22_sram_1bank_4mux_func_test.py b/compiler/tests/22_sram_1bank_4mux_func_test.py index cf972843..0df3ff0e 100755 --- a/compiler/tests/22_sram_1bank_4mux_func_test.py +++ b/compiler/tests/22_sram_1bank_4mux_func_test.py @@ -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): diff --git a/compiler/tests/22_sram_1bank_8mux_func_test.py b/compiler/tests/22_sram_1bank_8mux_func_test.py index 61c0efb7..16122a49 100755 --- a/compiler/tests/22_sram_1bank_8mux_func_test.py +++ b/compiler/tests/22_sram_1bank_8mux_func_test.py @@ -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) diff --git a/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py new file mode 100755 index 00000000..aa80656d --- /dev/null +++ b/compiler/tests/22_sram_1rw_1r_1bank_nomux_func_test.py @@ -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() diff --git a/technology/freepdk45/gds_lib/replica_cell_1rw_1r.gds b/technology/freepdk45/gds_lib/replica_cell_1rw_1r.gds new file mode 100644 index 00000000..8bc45cbb Binary files /dev/null and b/technology/freepdk45/gds_lib/replica_cell_1rw_1r.gds differ diff --git a/technology/freepdk45/sp_lib/replica_cell_1rw_1r.sp b/technology/freepdk45/sp_lib/replica_cell_1rw_1r.sp new file mode 100644 index 00000000..72a014ec --- /dev/null +++ b/technology/freepdk45/sp_lib/replica_cell_1rw_1r.sp @@ -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 + diff --git a/technology/scn4m_subm/gds_lib/cell_1rw_1r.gds b/technology/scn4m_subm/gds_lib/cell_1rw_1r.gds index 0b13d628..4254ba26 100644 Binary files a/technology/scn4m_subm/gds_lib/cell_1rw_1r.gds and b/technology/scn4m_subm/gds_lib/cell_1rw_1r.gds differ diff --git a/technology/scn4m_subm/gds_lib/replica_cell_1rw_1r.gds b/technology/scn4m_subm/gds_lib/replica_cell_1rw_1r.gds new file mode 100644 index 00000000..836708c3 Binary files /dev/null and b/technology/scn4m_subm/gds_lib/replica_cell_1rw_1r.gds differ diff --git a/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag index e6420e89..85323b17 100644 --- a/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag +++ b/technology/scn4m_subm/mag_lib/cell_1rw_1r.mag @@ -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 >> diff --git a/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag b/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag new file mode 100644 index 00000000..38edce07 --- /dev/null +++ b/technology/scn4m_subm/mag_lib/replica_cell_1rw_1r.mag @@ -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 >> diff --git a/technology/scn4m_subm/sp_lib/replica_cell_1rw_1r.sp b/technology/scn4m_subm/sp_lib/replica_cell_1rw_1r.sp new file mode 100644 index 00000000..0a235af8 --- /dev/null +++ b/technology/scn4m_subm/sp_lib/replica_cell_1rw_1r.sp @@ -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 + diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 0e81953a..25afd844 100755 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -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]