From a12ebeed9fbe0e8951434dc4bbb0a5d36bdd771d Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 12 Feb 2018 09:33:23 -0800 Subject: [PATCH] Add multiple process corners. Unit tests use nominal corner only. Add fake SCMOS nominal models, but they are broken. --- compiler/characterizer/stimuli.py | 21 +++++++++---------- compiler/globals.py | 6 +++--- compiler/tests/21_hspice_delay_test.py | 3 ++- compiler/tests/21_hspice_setuphold_test.py | 3 ++- compiler/tests/21_ngspice_delay_test.py | 3 ++- compiler/tests/21_ngspice_setuphold_test.py | 3 ++- compiler/tests/22_sram_func_test.py | 3 ++- compiler/tests/config_20_freepdk45.py | 3 +++ compiler/tests/config_20_scn3me_subm.py | 3 +++ technology/freepdk45/tech/tech.py | 13 ++++++++---- technology/scn3me_subm/models/nom/nmos.sp | 12 +++++++++++ technology/scn3me_subm/models/nom/pmos.sp | 11 ++++++++++ technology/scn3me_subm/tech/tech.py | 14 ++++++++++--- .../setup_scripts/setup_openram_freepdk45.py | 2 +- .../setup_openram_scn3me_subm.py | 8 +++---- 15 files changed, 77 insertions(+), 31 deletions(-) create mode 100644 technology/scn3me_subm/models/nom/nmos.sp create mode 100644 technology/scn3me_subm/models/nom/pmos.sp diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index c253f32b..297d9f37 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -26,8 +26,7 @@ class stimuli(): self.sf = stim_file - (self.process, self.vdd_voltage, self.temperature) = corner - self.gnd_voltage = 0 + (self.process, self.voltage, self.temperature) = corner self.device_models = tech.spice["fet_models"][self.process] @@ -158,7 +157,7 @@ class stimuli(): # shift signal times earlier for setup time times = np.array(clk_times) - setup*period - values = np.array(data_values) * self.vdd_voltage + values = np.array(data_values) * self.voltage half_slew = 0.5 * slew self.sf.write("* (time, data): {}\n".format(zip(clk_times, data_values))) self.sf.write("V{0} {0} 0 PWL (0n {1}v ".format(sig_name, values[0])) @@ -174,10 +173,10 @@ class stimuli(): self.sf.write("V{0} {0} 0 DC {1}\n".format(sig_name, v_val)) def get_inverse_voltage(self, value): - if value > 0.5*self.vdd_voltage: - return self.gnd_voltage - elif value <= 0.5*self.vdd_voltage: - return self.vdd_voltage + if value > 0.5*self.voltage: + return 0 + elif value <= 0.5*self.voltage: + return self.voltage else: debug.error("Invalid value to get an inverse of: {0}".format(value)) @@ -256,11 +255,11 @@ class stimuli(): def write_supply(self): """ Writes supply voltage statements """ - self.sf.write("V{0} {0} 0.0 {1}\n".format(self.vdd_name, self.vdd_voltage)) - self.sf.write("V{0} {0} 0.0 {1}\n".format(self.gnd_name, self.gnd_voltage)) + self.sf.write("V{0} {0} 0.0 {1}\n".format(self.vdd_name, self.voltage)) + self.sf.write("V{0} {0} 0.0 {1}\n".format(self.gnd_name, 0)) # This is for the test power supply - self.sf.write("V{0} {0} 0.0 {1}\n".format("test"+self.vdd_name, self.vdd_voltage)) - self.sf.write("V{0} {0} 0.0 {1}\n".format("test"+self.gnd_name, self.gnd_voltage)) + self.sf.write("V{0} {0} 0.0 {1}\n".format("test"+self.vdd_name, self.voltage)) + self.sf.write("V{0} {0} 0.0 {1}\n".format("test"+self.gnd_name, 0)) def run_sim(self): diff --git a/compiler/globals.py b/compiler/globals.py index 21c108df..5ce3e90e 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -291,11 +291,11 @@ def import_tech(): import tech # Set some default options now based on the technology... if (OPTS.process_corners == ""): - OPTS.process_corners = [tech.spice["nom_corner"][0]] + OPTS.process_corners = tech.spice["fet_models"].keys() if (OPTS.supply_voltages == ""): - OPTS.supply_voltages = [tech.spice["nom_corner"][1]] + OPTS.supply_voltages = tech.spice["supply_voltages"] if (OPTS.temperatures == ""): - OPTS.temperatures = [tech.spice["nom_corner"][2]] + OPTS.temperatures = tech.spice["temperatures"] def print_time(name, now_time, last_time=None): diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index 69eee383..10f50b14 100644 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -43,7 +43,8 @@ class timing_sram_test(openram_test): probe_data = s.word_size - 1 debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data)) - d = delay.delay(s,tempspice,tech.spice["nom_corner"]) + corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) + d = delay.delay(s,tempspice,corner) import tech loads = [tech.spice["msflop_in_cap"]*4] slews = [tech.spice["rise_time"]*2] diff --git a/compiler/tests/21_hspice_setuphold_test.py b/compiler/tests/21_hspice_setuphold_test.py index d68fa423..9649a7a4 100644 --- a/compiler/tests/21_hspice_setuphold_test.py +++ b/compiler/tests/21_hspice_setuphold_test.py @@ -31,7 +31,8 @@ class timing_setup_test(openram_test): import tech slews = [tech.spice["rise_time"]*2] - sh = setup_hold.setup_hold(tech.spice["nom_corner"]) + corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) + sh = setup_hold.setup_hold(corner) data = sh.analyze(slews,slews) if OPTS.tech_name == "freepdk45": diff --git a/compiler/tests/21_ngspice_delay_test.py b/compiler/tests/21_ngspice_delay_test.py index e857fca1..d0330830 100644 --- a/compiler/tests/21_ngspice_delay_test.py +++ b/compiler/tests/21_ngspice_delay_test.py @@ -41,7 +41,8 @@ class timing_sram_test(openram_test): probe_data = s.word_size - 1 debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data)) - d = delay.delay(s,tempspice,tech.spice["nom_corner"]) + corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) + d = delay.delay(s,tempspice,corner) import tech loads = [tech.spice["msflop_in_cap"]*4] slews = [tech.spice["rise_time"]*2] diff --git a/compiler/tests/21_ngspice_setuphold_test.py b/compiler/tests/21_ngspice_setuphold_test.py index e3c90914..4e28ce47 100644 --- a/compiler/tests/21_ngspice_setuphold_test.py +++ b/compiler/tests/21_ngspice_setuphold_test.py @@ -30,7 +30,8 @@ class timing_setup_test(openram_test): import tech slews = [tech.spice["rise_time"]*2] - sh = setup_hold.setup_hold(tech.spice["nom_corner"]) + corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) + sh = setup_hold.setup_hold(corner) data = sh.analyze(slews,slews) if OPTS.tech_name == "freepdk45": diff --git a/compiler/tests/22_sram_func_test.py b/compiler/tests/22_sram_func_test.py index bbbc334b..f8042880 100644 --- a/compiler/tests/22_sram_func_test.py +++ b/compiler/tests/22_sram_func_test.py @@ -43,7 +43,8 @@ class sram_func_test(openram_test): probe_data = s.word_size - 1 debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data)) - d = delay.delay(s,tempspice,tech.spice["nom_corner"]) + corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) + d = delay.delay(s,tempspice,corner) d.set_probe(probe_address,probe_data) # This will exit if it doesn't find a feasible period diff --git a/compiler/tests/config_20_freepdk45.py b/compiler/tests/config_20_freepdk45.py index 4eb4f091..d7e1880e 100644 --- a/compiler/tests/config_20_freepdk45.py +++ b/compiler/tests/config_20_freepdk45.py @@ -3,5 +3,8 @@ num_words = 16 num_banks = 1 tech_name = "freepdk45" +process_corners = ["TT"] +supply_voltages = [1.0] +temperatures = [25] diff --git a/compiler/tests/config_20_scn3me_subm.py b/compiler/tests/config_20_scn3me_subm.py index 178eb91e..40addd69 100644 --- a/compiler/tests/config_20_scn3me_subm.py +++ b/compiler/tests/config_20_scn3me_subm.py @@ -3,4 +3,7 @@ num_words = 16 num_banks = 1 tech_name = "scn3me_subm" +process_corners = ["TT"] +supply_voltages = [5.0] +temperatures = [25] diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index c58f0ef5..dacc3644 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -239,16 +239,21 @@ spice["nmos"] = "nmos_vtg" spice["pmos"] = "pmos_vtg" # This is a map of corners to model files SPICE_MODEL_DIR=os.environ.get("SPICE_MODEL_DIR") -spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/NMOS_VTG.inc",SPICE_MODEL_DIR+"/PMOS_VTG.inc"]} +spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/models_nom/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_nom/NMOS_VTG.inc"], + "FF" : [SPICE_MODEL_DIR+"/models_ff/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_ff/NMOS_VTG.inc"], + "SF" : [SPICE_MODEL_DIR+"/models_ss/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_ff/NMOS_VTG.inc"], + "FS" : [SPICE_MODEL_DIR+"/models_ff/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_ss/NMOS_VTG.inc"], + "SS" : [SPICE_MODEL_DIR+"/models_ss/PMOS_VTG.inc",SPICE_MODEL_DIR+"/models_ss/NMOS_VTG.inc"]} #spice stimulus related variables -spice["feasible_period"] = 5 # estimated feasible period in ns -spice["supply_voltage"] = 1.0 # ideal vdd in [Volts] +spice["feasible_period"] = 5 # estimated feasible period in ns +spice["supply_voltages"] = [0.9, 1.0, 1.1] # Supply voltage corners in [Volts] spice["rise_time"] = 0.005 # rise time in [Nano-seconds] spice["fall_time"] = 0.005 # fall time in [Nano-seconds] -spice["nom_corner"] = ("TT", 1.0, 25) # Nominal process corner +spice["temperatures"] = [0, 25, 100] # Temperature corners (celcius) #sram signal names +#FIXME: We don't use these everywhere... spice["vdd_name"] = "vdd" spice["gnd_name"] = "gnd" spice["control_signals"] = ["CSb", "WEb", "OEb"] diff --git a/technology/scn3me_subm/models/nom/nmos.sp b/technology/scn3me_subm/models/nom/nmos.sp new file mode 100644 index 00000000..359de4c9 --- /dev/null +++ b/technology/scn3me_subm/models/nom/nmos.sp @@ -0,0 +1,12 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL NFET NMOS (LEVEL=3 VTO=0.669845 KP=113.7771E-6 ++ NSUB=6E16 U0=458 VFB=-0.851 GAMMA=0.5705 TOX=13.9n ++ TNOM=27) + + diff --git a/technology/scn3me_subm/models/nom/pmos.sp b/technology/scn3me_subm/models/nom/pmos.sp new file mode 100644 index 00000000..18c9dc36 --- /dev/null +++ b/technology/scn3me_subm/models/nom/pmos.sp @@ -0,0 +1,11 @@ +********************************************* +* Transistor Models +* Note: These models are approximate +* and should be substituted with actual +* models from MOSIS or SCN3ME +********************************************* + +.MODEL PFET PMOS (LEVEL=3 VTO=-0.921340 KP=366.0244-6 ++ NSUB=6E16 U0=212 VFB=0.395 GAMMA=0.2370 TOX=13.9n ++ TNOM=27) + diff --git a/technology/scn3me_subm/tech/tech.py b/technology/scn3me_subm/tech/tech.py index c89f5613..ee6fb694 100755 --- a/technology/scn3me_subm/tech/tech.py +++ b/technology/scn3me_subm/tech/tech.py @@ -199,16 +199,24 @@ spice["nmos"]="n" spice["pmos"]="p" # This is a map of corners to model files SPICE_MODEL_DIR=os.environ.get("SPICE_MODEL_DIR") -spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/on_c5n.sp"] } +# FIXME: Uncomment when we have the new spice models +spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"] } +# spice["fet_models"] = { "TT" : [SPICE_MODEL_DIR+"/nom/pmos.sp",SPICE_MODEL_DIR+"/nom/nmos.sp"], +# "FF" : [SPICE_MODEL_DIR+"/ff/pmos.sp",SPICE_MODEL_DIR+"/ff/nmos.sp"], +# "FS" : [SPICE_MODEL_DIR+"/ff/pmos.sp",SPICE_MODEL_DIR+"/ss/nmos.sp"], +# "SF" : [SPICE_MODEL_DIR+"/ss/pmos.sp",SPICE_MODEL_DIR+"/ff/nmos.sp"], +# "SS" : [SPICE_MODEL_DIR+"/ss/pmos.sp",SPICE_MODEL_DIR+"/ss/nmos.sp"] } + #spice stimulus related variables spice["feasible_period"] = 5 # estimated feasible period in ns -spice["supply_voltage"] = 5.0 # ideal vdd in [Volts] +spice["supply_voltages"] = [4.5, 5.0, 5.5] # Supply voltage corners in [Volts] spice["rise_time"] = 0.05 # rise time in [Nano-seconds] spice["fall_time"] = 0.05 # fall time in [Nano-seconds] -spice["nom_corner"] = ("TT", 5.0, 25) # Nominal process corner +spice["temperatures"] = [0, 25, 100] # Temperature corners (celcius) #sram signal names +#FIXME: We don't use these everywhere... spice["vdd_name"] = "vdd" spice["gnd_name"] = "gnd" spice["control_signals"] = ["CSb", "WEb", "OEb"] diff --git a/technology/setup_scripts/setup_openram_freepdk45.py b/technology/setup_scripts/setup_openram_freepdk45.py index db145d72..35e819ee 100644 --- a/technology/setup_scripts/setup_openram_freepdk45.py +++ b/technology/setup_scripts/setup_openram_freepdk45.py @@ -32,7 +32,7 @@ os.environ["DRCLVS_HOME"] = DRCLVS_HOME # SPICE_MODEL_DIR = os.path.abspath(os.environ.get("SPICE_MODEL_DIR")) # except: # Always use the one in the PDK dir for FreePDK45 -os.environ["SPICE_MODEL_DIR"] = PDK_DIR+"/ncsu_basekit/models/hspice/tran_models/models_nom" +os.environ["SPICE_MODEL_DIR"] = PDK_DIR+"/ncsu_basekit/models/hspice/tran_models" ########################## #Paths required for OPENRAM to function diff --git a/technology/setup_scripts/setup_openram_scn3me_subm.py b/technology/setup_scripts/setup_openram_scn3me_subm.py index fcc69db8..410996ef 100644 --- a/technology/setup_scripts/setup_openram_scn3me_subm.py +++ b/technology/setup_scripts/setup_openram_scn3me_subm.py @@ -27,10 +27,10 @@ except: DRCLVS_HOME=OPENRAM_TECH+"/scn3me_subm/tech" os.environ["DRCLVS_HOME"] = DRCLVS_HOME -try: - SPICE_MODEL_DIR = os.path.abspath(os.environ.get("SPICE_MODEL_DIR")) -except: - os.environ["SPICE_MODEL_DIR"] = "/mada/software/techfiles/scn3me_subm" +# try: +# SPICE_MODEL_DIR = os.path.abspath(os.environ.get("SPICE_MODEL_DIR")) +# except: +os.environ["SPICE_MODEL_DIR"] = OPENRAM_TECH+"/models" ########################## # Paths required for OPENRAM to function