From 6ac474d642372df526c67b5e41bb439bd90b25b5 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Wed, 12 Dec 2018 00:43:08 -0800 Subject: [PATCH] Added bitline measures with hardcoded names. --- compiler/characterizer/bitline_delay.py | 70 ++++++++++++++++++++++--- compiler/characterizer/stimuli.py | 10 ++++ compiler/characterizer/trim_spice.py | 2 +- compiler/tests/21_hspice_delay_test.py | 5 +- 4 files changed, 78 insertions(+), 9 deletions(-) diff --git a/compiler/characterizer/bitline_delay.py b/compiler/characterizer/bitline_delay.py index ab28cdc9..8123695c 100644 --- a/compiler/characterizer/bitline_delay.py +++ b/compiler/characterizer/bitline_delay.py @@ -19,7 +19,7 @@ class bitline_delay(delay): def __init__(self, sram, spfile, corner): delay.__init__(self,sram,spfile,corner) - self.period = 1 + self.period = tech.spice["feasible_period"] self.is_bitline_measure = True def create_measurement_names(self): @@ -38,17 +38,75 @@ class bitline_delay(delay): self.sf.write("* {}\n".format(comment)) for read_port in self.targ_read_ports: - self.write_bitline_measures_read_port(read_port) - + self.write_bitline_measures_read_port(read_port) + def write_bitline_measures_read_port(self, port): """ Write the measure statements to quantify the delay and power results for a read port. """ # add measure statements for delays/slews - for dname in self.delay_meas_names: - meas_values = self.get_delay_meas_values(dname, port) - self.stim.gen_meas_delay(*meas_values) + measure_bit = 0 + self.stim.gen_meas_find_voltage("bl_volt", "Xsram.s_en0", "Xsram.Xbank0.bl_{}".format(measure_bit), .5, "RISE", 3*self.period) + self.stim.gen_meas_find_voltage("br_volt", "Xsram.s_en0", "Xsram.Xbank0.br_{}".format(measure_bit), .5, "RISE", 3*self.period) + def gen_test_cycles_one_port(self, read_port, write_port): + """Sets a list of key time-points [ns] of the waveform (each rising edge) + of the cycles to do a timing evaluation of a single port """ + + # Create the inverse address for a scratch address + inverse_address = self.calculate_inverse_address() + + # For now, ignore data patterns and write ones or zeros + data_ones = "1"*self.word_size + data_zeros = "0"*self.word_size + + if self.t_current == 0: + self.add_noop_all_ports("Idle cycle (no positive clock edge)", + inverse_address, data_zeros) + + self.add_write("W data 1 address {}".format(inverse_address), + inverse_address,data_ones,write_port) + + self.add_write("W data 0 address {} to write value".format(self.probe_address), + self.probe_address,data_zeros,write_port) + self.measure_cycles[write_port]["write0"] = len(self.cycle_times)-1 + + # This also ensures we will have a H->L transition on the next read + self.add_read("R data 1 address {} to set DOUT caps".format(inverse_address), + inverse_address,data_zeros,read_port) + + self.add_read("R data 0 address {} to check W0 worked".format(self.probe_address), + self.probe_address,data_zeros,read_port) + + def run_delay_simulation(self): + """ + This tries to simulate a period and checks if the result works. If + so, it returns True and the delays, slews, and powers. It + works on the trimmed netlist by default, so powers do not + include leakage of all cells. + """ + #Sanity Check + debug.check(self.period > 0, "Target simulation period non-positive") + + result = [{} for i in self.all_ports] + # Checking from not data_value to data_value + self.write_delay_stimulus() + + self.stim.run_sim() #running sim prodoces spice output file. + + for port in self.targ_read_ports: + bitlines_meas_vals = {} + for mname in self.bitline_meas_names: + bitlines_meas_vals[mname] = parse_spice_list("timing", mname) + #Check that power parsing worked. + for name, val in bitlines_meas_vals.items(): + if type(val)!=float: + debug.error("Failed to Parse Bitline Values:\n\t\t{0}".format(bitlines_meas_vals),1) #Printing the entire dict looks bad. + result[port].update(bitlines_meas_vals) + + + # The delay is from the negative edge for our SRAM + return (True,result) def analyze(self, probe_address, probe_data, slews, loads): """Measures the bitline swing of the differential bitlines (bl/br) at 50% s_en """ diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index e5b24387..8c6b059f 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -216,6 +216,16 @@ class stimuli(): targ_dir, targ_td)) + def gen_meas_find_voltage(self, meas_name, trig_name, targ_name, trig_val, trig_dir, trig_td): + """ Creates the .meas statement for the measurement of delay """ + measure_string=".meas tran {0} FIND v({1}) WHEN v({2})={3}v {4}=1 TD={5}n \n\n" + self.sf.write(measure_string.format(meas_name, + targ_name, + trig_name, + trig_val, + trig_dir, + trig_td)) + def gen_meas_power(self, meas_name, t_initial, t_final): """ Creates the .meas statement for the measurement of avg power """ # power mea cmd is different in different spice: diff --git a/compiler/characterizer/trim_spice.py b/compiler/characterizer/trim_spice.py index a33df26c..88195fee 100644 --- a/compiler/characterizer/trim_spice.py +++ b/compiler/characterizer/trim_spice.py @@ -50,7 +50,7 @@ class trim_spice(): # Split up the address and convert to an int wl_address = int(address[self.col_addr_size:],2) - if self.col_addr_size>1: + if self.col_addr_size>0: col_address = int(address[0:self.col_addr_size],2) else: col_address = 0 diff --git a/compiler/tests/21_hspice_delay_test.py b/compiler/tests/21_hspice_delay_test.py index 6eca93f5..53b089f9 100755 --- a/compiler/tests/21_hspice_delay_test.py +++ b/compiler/tests/21_hspice_delay_test.py @@ -23,13 +23,12 @@ class timing_sram_test(openram_test): from importlib import reload import characterizer reload(characterizer) - from characterizer import delay + from characterizer import delay, bitline_delay from sram import sram from sram_config import sram_config c = sram_config(word_size=1, num_words=16, num_banks=1) - c.words_per_row=1 debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") s = sram(c, name="sram1") @@ -42,10 +41,12 @@ class timing_sram_test(openram_test): corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) d = delay(s.s, tempspice, corner) + bl = bitline_delay(s.s, tempspice, corner) import tech loads = [tech.spice["msflop_in_cap"]*4] slews = [tech.spice["rise_time"]*2] data, port_data = d.analyze(probe_address, probe_data, slews, loads) + #bitline_swing = bl.analyze(probe_address, probe_data, slews, loads) #Combine info about port into all data data.update(port_data[0])