diff --git a/compiler/characterizer/__init__.py b/compiler/characterizer/__init__.py index 3bf4829a..08d443a9 100644 --- a/compiler/characterizer/__init__.py +++ b/compiler/characterizer/__init__.py @@ -8,22 +8,22 @@ import setup_hold debug.info(2,"Initializing characterizer...") -spice_exe = "" +OPTS.spice_exe = "" if not OPTS.analytical_delay: if OPTS.spice_name != "": - spice_exe=find_exe(OPTS.spice_name) - if spice_exe=="": + OPTS.spice_exe=find_exe(OPTS.spice_name) + if OPTS.spice_exe=="": debug.error("{0} not found. Unable to perform characterization.".format(OPTS.spice_name),1) else: - (choice,spice_exe) = get_tool("spice",["xa", "hspice", "ngspice", "ngspice.exe"]) - OPTS.spice_name = choice + (OPTS.spice_name,OPTS.spice_exe) = get_tool("spice",["xa", "hspice", "ngspice", "ngspice.exe"]) # set the input dir for spice files if using ngspice if OPTS.spice_name == "ngspice": os.environ["NGSPICE_INPUT_DIR"] = "{0}".format(OPTS.openram_temp) - if spice_exe == "": + if OPTS.spice_exe == "": debug.error("No recognizable spice version found. Unable to perform characterization.",1) + diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index d367b518..69a0bb32 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -283,25 +283,24 @@ def run_sim(): import datetime start_time = datetime.datetime.now() - from characterizer import spice_exe if OPTS.spice_name == "xa": # Output the xa configurations here. FIXME: Move this to write it once. xa_cfg = open("{}xa.cfg".format(OPTS.openram_temp), "w") xa_cfg.write("set_sim_level -level 7\n") xa_cfg.write("set_powernet_level 7 -node vdd\n") xa_cfg.close() - cmd = "{0} {1} -c {2}xa.cfg -o {2}xa -mt 20".format(spice_exe, + cmd = "{0} {1} -c {2}xa.cfg -o {2}xa -mt 20".format(OPTS.spice_exe, temp_stim, OPTS.openram_temp) valid_retcode=0 elif OPTS.spice_name == "hspice": # TODO: Should make multithreading parameter a configuration option - cmd = "{0} -mt 2 -i {1} -o {2}timing".format(spice_exe, + cmd = "{0} -mt 2 -i {1} -o {2}timing".format(OPTS.spice_exe, temp_stim, OPTS.openram_temp) valid_retcode=0 else: - cmd = "{0} -b -o {2}timing.lis {1}".format(spice_exe, + cmd = "{0} -b -o {2}timing.lis {1}".format(OPTS.spice_exe, temp_stim, OPTS.openram_temp) # for some reason, ngspice-25 returns 1 when it only has acceptable warnings diff --git a/compiler/tests/#03_ptx_4finger_pmos_test.py# b/compiler/tests/#03_ptx_4finger_pmos_test.py# new file mode 100644 index 00000000..43931cc3 --- /dev/null +++ b/compiler/tests/#03_ptx_4finger_pmos_test.py# @@ -0,0 +1,154 @@ +#!/usr/bin/env python2.7 +"Run a regresion test on a basic parameterized transistors" + +import unittest +from testutils import header +import sys,os +sys.path.append(os.path.join(sys.path[0],"..")) +import globals +from globals import OPTS +import debug + +class ptx_test(unittest.TestCase): + + def runTest(self): + globals.init_openram("config_20_{0}".format(OPTS.tech_name)) + global verify + import verify + OPTS.check_lvsdrc = False + + import ptx + import tech + + debug.info(2, "Checking three fingers PMOS") + fet = ptx.ptx(width=tech.drc["minwidth_tx"], + mults=4, + tx_type="pmos", + connect_active=True, + connect_poly=True) + self.local_check(fet) + + OPTS.check_lvsdrc = True + globals.end_openram() + + def add_mods(self, fet): + self.create_contacts() + self.add_well_extension(fet) + self.add_wire_extension(fet) + self.add_well_tiedown(fet) + self.add_poly_tiedown(fet) + + def create_contacts(self): + layer_stack = ("active", "contact", "metal1") + self.well_contact = contact.contact(layer_stack) + + layer_stack = ("poly", "contact", "metal1") + self.poly_contact = contact.contact(layer_stack) + + def add_well_tiedown(self, fet): + offset = [fet.active_contact_positions[0][0], + fet.active_contact_positions[0][1] + fet.well_height] + fet.add_inst(name="well_tap", + mod=self.well_contact, + offset=offset, + mirror="R0", + rotate=0) + fet.well_contact = self.well_contact + fet.well_tiedown_location = offset + + def add_well_extension(self, fet): + well_define = {"pmos": "nwell", + "nmos": "pwell"} + well_type = well_define[fet.tx_type] + offset = getattr(fet,"{}_position".format(well_type)) + if tech.info["has_{0}".format(well_type)]: + fet.add_rect(layerNumber=tech.layer[well_type], + offset=offset, + width=fet.well_width, + height=2 * fet.well_height) + fet.add_rect(layerNumber=tech.layer["{0}implant".format(fet.tx_type[0])], + offset=offset, + width=fet.well_width, + height=2 * fet.well_height) + fet.add_rect(layerNumber=tech.layer["vtg"], + offset=offset, + width=fet.well_width, + height=2 * fet.well_height) + + well_type = "{0}well".format(fet.tx_type[0]) + offset[1] = offset[1] - 3 * fet.well_height + if tech.info["has_{0}".format(well_type)]: + fet.add_rect(layerNumber=tech.layer[well_type], + offset=offset, + width=fet.well_width, + height=3 * fet.well_height) + fet.add_rect(layerNumber=tech.layer["{0}implant".format(well_define[fet.tx_type][ + 0])], + offset=offset, + width=fet.well_width, + height=3 * fet.well_height) + fet.add_rect(layerNumber=tech.layer["vtg"], + offset=offset, + width=fet.well_width, + height=3 * fet.well_height) + + def add_wire_extension(self, fet): + xcorrect = (fet.active_contact.width / 2) - (tech.drc["minwidth_metal1"] / 2) + offset = [fet.active_contact_positions[0][0] + xcorrect, + fet.active_contact_positions[0][1]] + fet.add_rect(layerNumber=tech.layer["metal1"], + offset=offset, + width=tech.drc["minwidth_metal1"], + height=fet.well_height) + + offset = [fet.active_contact_positions[-1][0] + xcorrect, + fet.active_contact_positions[-1][1] - 2 * fet.well_height] + fet.add_rect(layerNumber=tech.layer["metal1"], + offset=offset, + width=tech.drc["minwidth_metal1"], + height=2 * fet.well_height) + + offset = [fet.poly_positions[-1][0], + fet.poly_positions[-1][1] - (fet.well_height)] + fet.add_rect(layerNumber=tech.layer["poly"], + offset=offset, + width=tech.drc["minwidth_poly"], + height=fet.well_height) + + def add_poly_tiedown(self, fet): + xcorrect = abs(self.poly_contact.upper_layer_vertical_enclosure - + self.poly_contact.lower_layer_vertical_enclosure) + offset = [fet.poly_positions[-1][0] - xcorrect, + fet.poly_positions[-1][1] - (fet.well_height)] + fet.add_inst(name="poly_contact", + mod=self.poly_contact, + offset=offset, + mirror="R270") + + + offset = [fet.active_contact_positions[-1][0], fet.active_contact_positions + [-1][1] - 2 * fet.well_height - self.well_contact.height] + fet.poly_tiedown_location = offset + fet.add_inst(name="n_tiedown", + mod=self.well_contact, + offset=offset) + tech.ptx_port.add_custom_layer(fet) + + def local_check(self, fet): + tempspice = OPTS.openram_temp + "temp.sp" + tempgds = OPTS.openram_temp + "temp.gds" + + fet.sp_write(tempspice) + fet.gds_write(tempgds) + + self.assertFalse(verify.run_drc(fet.name, tempgds)) + + os.remove(tempspice) + os.remove(tempgds) + +# 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/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index 5dcd6ff5..87b6576e 100644 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -18,12 +18,12 @@ class timing_sram_test(unittest.TestCase): OPTS.check_lvsdrc = False OPTS.spice_name="hspice" OPTS.analytical_delay = False - self.assertTrue(OPTS.spice_exe) # This is a hack to reload the characterizer __init__ with the spice version import characterizer reload(characterizer) from characterizer import delay + self.assertTrue(OPTS.spice_exe) import sram diff --git a/compiler/tests/21_hspice_setuphold_test.py b/compiler/tests/21_hspice_setuphold_test.py index 4a10c92e..a0d9df02 100644 --- a/compiler/tests/21_hspice_setuphold_test.py +++ b/compiler/tests/21_hspice_setuphold_test.py @@ -18,12 +18,12 @@ class timing_setup_test(unittest.TestCase): OPTS.check_lvsdrc = False OPTS.spice_name="hspice" OPTS.analytical_delay = False - self.assertTrue(OPTS.spice_exe) # This is a hack to reload the characterizer __init__ with the spice version import characterizer reload(characterizer) from characterizer import setup_hold + self.assertTrue(OPTS.spice_exe) import sram import tech diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index defa2130..45249cd6 100644 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -18,12 +18,12 @@ class timing_sram_test(unittest.TestCase): OPTS.check_lvsdrc = False OPTS.spice_name="ngspice" OPTS.analytical_delay = False - self.assertTrue(OPTS.spice_exe) # This is a hack to reload the characterizer __init__ with the spice version import characterizer reload(characterizer) from characterizer import delay + self.assertTrue(OPTS.spice_exe) import sram diff --git a/compiler/tests/21_ngspice_setuphold_test.py b/compiler/tests/21_ngspice_setuphold_test.py index 4c417190..185c877c 100644 --- a/compiler/tests/21_ngspice_setuphold_test.py +++ b/compiler/tests/21_ngspice_setuphold_test.py @@ -18,12 +18,12 @@ class timing_setup_test(unittest.TestCase): OPTS.check_lvsdrc = False OPTS.spice_name="ngspice" OPTS.analytical_delay = False - self.assertTrue(OPTS.spice_exe) # This is a hack to reload the characterizer __init__ with the spice version import characterizer reload(characterizer) from characterizer import setup_hold + self.assertTrue(OPTS.spice_exe) import sram import tech diff --git a/compiler/tests/bsim4v4.out b/compiler/tests/bsim4v4.out new file mode 100644 index 00000000..672a874c --- /dev/null +++ b/compiler/tests/bsim4v4.out @@ -0,0 +1,6 @@ +BSIM4: Berkeley Short Channel IGFET Model-4 +Developed by Xuemei (Jane) Xi, Jin He, Mohan Dunga, Prof. Ali Niknejad and Prof. Chenming Hu in 2003. + +++++++++++ BSIM4v4 PARAMETER CHECKING BELOW ++++++++++ +Warning: This model supports BSIM4.2.1, 4.3.0 and 4.4.0; you specified a wrong version number. +Model = nmos_vtg diff --git a/compiler/tests/catfile b/compiler/tests/catfile new file mode 100644 index 00000000..daa2cc23 --- /dev/null +++ b/compiler/tests/catfile @@ -0,0 +1,15 @@ +05_bitcell_array_test.py +06_hierarchical_decoder_test.py +06_hierarchical_predecode2x4_test.py +06_hierarchical_predecode3x8_test.py +07_single_level_column_mux_array_test.py +08_precharge_array_test.py +09_sense_amp_array_test.py +10_write_driver_array_test.py +11_ms_flop_array_test.py +12_tri_gate_array_test.py +13_delay_chain_test.py +14_replica_bitline_test.py +16_control_logic_test.py +19_multi_bank_test.py +19_single_bank_test.py