diff --git a/compiler/characterizer/delay.py b/compiler/characterizer/delay.py index 1bf01f45..2ffc2d6e 100644 --- a/compiler/characterizer/delay.py +++ b/compiler/characterizer/delay.py @@ -125,11 +125,14 @@ class delay(): # meas statement for delay and power measurements self.sf.write("* Measure statements for delay and power\n") + for comment in self.cycle_comments: + self.sf.write("* {}\n".format(comment)) + trig_name = "clk" targ_name = "{0}".format("d[{0}]".format(self.probe_data)) trig_val = targ_val = 0.5 * self.vdd # add measure statments for delay0 - # delay the target to measure after the negetive edge + # delay the target to measure after the negative edge stimuli.gen_meas_delay(stim_file=self.sf, meas_name="DELAY0", trig_name=trig_name, @@ -238,12 +241,14 @@ class delay(): # if it failed or the read was longer than a period if type(delay0)!=float or type(delay1)!=float or type(slew1)!=float or type(slew0)!=float: + debug.info(2,"Failed simulation: period {0} load {1} slew {2}, delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,load,slew,delay0,delay1,slew0,slew1)) return (False,0,0,0,0) delay0 *= 1e9 delay1 *= 1e9 slew0 *= 1e9 slew1 *= 1e9 if delay0>period or delay1>period or slew0>period or slew1>period: + debug.info(2,"UNsuccessful simulation: period {0} load {1} slew {2}, delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,load,slew,delay0,delay1,slew0,slew1)) return (False,0,0,0,0) else: debug.info(2,"Successful simulation: period {0} load {1} slew {2}, delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,load,slew,delay0,delay1,slew0,slew1)) @@ -394,46 +399,56 @@ class delay(): of the cycles to do a timing evaluation. The last time is the end of the simulation and does not need a rising edge.""" + self.cycle_comments = [] # idle cycle, no operation t_current = period self.cycle_times = [] - # cycle0: W data 1 address 1111 to initialize cell to a value self.cycle_times.append(t_current) + self.cycle_comments.append("Cycle0 {}ns: W data 1 address 111 to initialize cell".format(t_current)) t_current += period # cycle1: W data 0 address 1111 (to ensure a write of value works) self.cycle_times.append(t_current) self.write0_cycle=1 + self.cycle_comments.append("Cycle1 {}ns: W data 0 address 111 (to ensure a write of value works)".format(t_current)) t_current += period # cycle2: W data 1 address 0000 (to clear the data bus cap) self.cycle_times.append(t_current) + self.cycle_comments.append("Cycle2 {}ns: W data 1 address 0000 (to clear bus caps)".format(t_current)) t_current += period # cycle3: R data 0 address 1111 to check W0 works self.cycle_times.append(t_current) self.read0_cycle=3 + self.cycle_comments.append("Cycle3 {}ns: R data 0 address 1111 to check W0 worked".format(t_current)) t_current += period # cycle4: W data 1 address 1111 (to ensure a write of value works) self.cycle_times.append(t_current) self.write1_cycle=4 + self.cycle_comments.append("Cycle4 {}ns: W data 1 address 1111 (to ensure a write of value worked)".format(t_current)) t_current += period # cycle5: W data 0 address 0000 (to clear the data bus cap) self.cycle_times.append(t_current) + self.cycle_comments.append("Cycle5 {}ns: W data 0 address 0000 (to clear bus caps)".format(t_current)) t_current += period # cycle6: R data 1 address 1111 to check W1 works self.cycle_times.append(t_current) self.read1_cycle=6 + self.cycle_comments.append("Cycle6 {}ns: R data 1 address 1111 to check W1 worked".format(t_current)) t_current += period # cycle7: wait a clock period to end the simulation self.cycle_times.append(t_current) + self.cycle_comments.append("Cycle7 {}ns: Idle period to end simulation".format(t_current)) t_current += period + + def analytical_model(self,sram, slews, loads): """ Just return the analytical model results for the SRAM. diff --git a/compiler/characterizer/stimuli.py b/compiler/characterizer/stimuli.py index 6cba2015..7ffd9e85 100644 --- a/compiler/characterizer/stimuli.py +++ b/compiler/characterizer/stimuli.py @@ -290,7 +290,7 @@ def run_sim(): 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(OPTS.spice_exe, + cmd = "{0} {1} -c {2}xa.cfg -o {2}xa -mt 2".format(OPTS.spice_exe, temp_stim, OPTS.openram_temp) valid_retcode=0 diff --git a/compiler/characterizer/trim_spice.py b/compiler/characterizer/trim_spice.py index a5025d60..30f041a4 100644 --- a/compiler/characterizer/trim_spice.py +++ b/compiler/characterizer/trim_spice.py @@ -45,23 +45,30 @@ class trim_spice(): # Always start fresh if we do multiple reductions self.sp_buffer = self.spice - - # Find the row and column indices for the removals - # Convert address froms tring to int - address = int(address,2) - array_row = address >> self.col_addr_size - # Which word in the array (0 if only one word) - if self.col_addr_size>0: - lower_mask = int(self.col_addr_size-1) - lower_address = address & lower_mask - else: - lower_address=0 - # Which bit in the array - array_bit = lower_address*self.word_size + data_bit + # Split up the address and convert to an int + wl_address = int(address[self.col_addr_size:],2) + col_address = int(address[0:self.col_addr_size],2) # 1. Keep cells in the bitcell array based on WL and BL - wl_name = "wl[{}]".format(array_row) - bl_name = "bl[{}]".format(array_bit) + wl_name = "wl[{}]".format(wl_address) + bl_name = "bl[{}]".format(self.words_per_row*data_bit + col_address) + + # Prepend info about the trimming + addr_msg = "Keeping {} address".format(address) + self.sp_buffer.insert(0, "* "+addr_msg) + debug.info(1,addr_msg) + data_msg = "Keeping {} data bit".format(data_bit) + self.sp_buffer.insert(0, "* "+data_msg) + debug.info(1,data_msg) + bl_msg = "Keeping {} (trimming other BLs)".format(bl_name) + wl_msg = "Keeping {} (trimming other WLs)".format(wl_name) + self.sp_buffer.insert(0, "* "+bl_msg) + debug.info(1,bl_msg) + self.sp_buffer.insert(0, "* "+wl_msg) + debug.info(1,wl_msg) + self.sp_buffer.insert(0, "* It should NOT be used for LVS!!") + self.sp_buffer.insert(0, "* WARNING: This is a TRIMMED NETLIST.") + self.remove_insts("bitcell_array",[wl_name,bl_name]) # 2. Keep sense amps basd on BL diff --git a/compiler/example_config_freepdk45.py b/compiler/example_config_freepdk45.py index cd8a17b8..16545b2d 100644 --- a/compiler/example_config_freepdk45.py +++ b/compiler/example_config_freepdk45.py @@ -1,5 +1,5 @@ word_size = 2 -num_words = 16 +num_words = 128 num_banks = 1 tech_name = "freepdk45" diff --git a/compiler/globals.py b/compiler/globals.py index e579e949..1c4605aa 100644 --- a/compiler/globals.py +++ b/compiler/globals.py @@ -12,7 +12,7 @@ import re import importlib # Current version of OpenRAM. -VERSION = "1.01" +VERSION = "Beta" USAGE = "Usage: openram.py [options] \nUse -h for help.\n" diff --git a/compiler/sram.py b/compiler/sram.py index 70e6f80a..d0ced623 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -989,7 +989,13 @@ class sram(design.design): ############################################################ sp = open(sp_name, 'w') + sp.write("**************************************************\n") sp.write("* OpenRAM generated memory.\n") + sp.write("* Words: {}\n".format(self.num_words)) + sp.write("* Data bits: {}\n".format(self.word_size)) + sp.write("* Banks: {}\n".format(self.num_banks)) + sp.write("* Column mux: {}:1\n".format(self.words_per_row)) + sp.write("**************************************************\n") # This causes unit test mismatch # sp.write("* Created: {0}\n".format(datetime.datetime.now())) # sp.write("* User: {0}\n".format(getpass.getuser()))