From ea55bda493e121c4a90dd46ccc0ef44cb08ccb01 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Wed, 5 Dec 2018 17:10:11 -0800 Subject: [PATCH] Changed s_en delay calculation based recent control logic changes. --- compiler/characterizer/logical_effort.py | 4 +- compiler/modules/bank.py | 6 +- compiler/modules/control_logic.py | 75 +++++++------------ compiler/modules/replica_bitline.py | 4 +- compiler/modules/wordline_driver.py | 20 ++--- compiler/pgates/pand2.py | 13 +++- compiler/pgates/pbuf.py | 7 +- compiler/sram_base.py | 12 +-- .../tests/22_psram_1bank_2mux_func_test.py | 2 +- .../tests/22_psram_1bank_4mux_func_test.py | 2 +- 10 files changed, 66 insertions(+), 79 deletions(-) diff --git a/compiler/characterizer/logical_effort.py b/compiler/characterizer/logical_effort.py index b54124d5..bf8c1585 100644 --- a/compiler/characterizer/logical_effort.py +++ b/compiler/characterizer/logical_effort.py @@ -19,7 +19,7 @@ class logical_effort(): self.is_rise = out_is_rise def __str__(self): - return "g = " + str(self.logical_effort) + ", h = " + str(self.eletrical_effort) + ", p = " + str(self.parasitic_scale)+"*pinv" + return "g=" + str(self.logical_effort) + ", h=" + str(self.eletrical_effort) + ", p=" + str(self.parasitic_scale)+"*pinv, rise_delay="+str(self.is_rise) def get_stage_effort(self): return self.logical_effort*self.eletrical_effort @@ -37,8 +37,10 @@ def calculate_relative_delay(stage_effort_list, pinv=parameter["min_inv_para_del def calculate_relative_rise_fall_delays(stage_effort_list, pinv=parameter["min_inv_para_delay"]): """Calculates the rise/fall delays of a given delay path made of a list of logical effort objects.""" + debug.info(2, "Calculating rise/fall relative delays") total_rise_delay, total_fall_delay = 0,0 for stage in stage_effort_list: + debug.info(3, stage) if stage.is_rise: total_rise_delay += stage.get_stage_delay(pinv) else: diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 1644025c..a0508b51 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -1254,10 +1254,10 @@ class bank(design.design): return stage_effort_list - def get_clk_cin(self): + def get_wl_en_cin(self): """Get the relative capacitance of all the clk connections in the bank""" - #Current bank only uses clock (clk_buf) as an enable for the wordline driver. - total_clk_cin = self.wordline_driver.get_clk_cin() + #wl_en only used in the wordline driver. + total_clk_cin = self.wordline_driver.get_wl_en_cin() return total_clk_cin def get_clk_bar_cin(self): diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index c9bd7bef..c1ad33cd 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -30,9 +30,11 @@ class control_logic(design.design): self.words_per_row = words_per_row self.port_type = port_type + self.enable_delay_chain_resizing = False + #This is needed to resize the delay chain. Likely to be changed at some point. - #self.sram=sram - self.sram=None #disable re-sizing for debugging, FIXME: resizing is not working, needs to be adjusted for new control logic. + self.sram=sram + #self.sram=None #disable re-sizing for debugging, FIXME: resizing is not working, needs to be adjusted for new control logic. self.wl_timing_tolerance = 1 #Determines how much larger the sen delay should be. Accounts for possible error in model. self.parasitic_inv_delay = parameter["min_inv_para_delay"] #Keeping 0 for now until further testing. @@ -112,7 +114,9 @@ class control_logic(design.design): bitcell_loads = int(math.ceil(self.num_rows / 2.0)) self.replica_bitline = replica_bitline([delay_fanout_heuristic]*delay_stages_heuristic, bitcell_loads, name="replica_bitline_"+self.port_type) - if self.sram != None and not self.does_sen_total_timing_match(): #check condition based on resizing method + self.set_sen_wl_delays() + + if self.sram != None and self.enable_delay_chain_resizing and not self.does_sen_total_timing_match(): #check condition based on resizing method #This resizes to match fall and rise delays, can make the delay chain weird sizes. # stage_list = self.get_dynamic_delay_fanout_list(delay_stages_heuristic, delay_fanout_heuristic) # self.replica_bitline = replica_bitline(stage_list, bitcell_loads, name="replica_bitline_resized_"+self.port_type) @@ -794,17 +798,16 @@ class control_logic(design.design): def determine_wordline_stage_efforts(self): - """Follows the clock signal to the clk_buf signal to the wordline signal for the total path efforts""" + """Follows the gated_clk_bar -> wl_en -> wordline signal for the total path efforts""" stage_effort_list = [] - #Initial direction of clock signal for this path - is_clk_rise = False + #Initial direction of gated_clk_bar signal for this path + is_clk_bar_rise = True - #Calculate the load on clk_buf within the module and add it to external load - internal_cout = self.ctrl_dff_array.get_clk_cin() - external_cout = self.sram.get_clk_cin() + #Calculate the load on wl_en within the module and add it to external load + external_cout = self.sram.get_wl_en_cin() #First stage is the clock buffer - stage_effort_list += self.clkbuf.determine_z_stage_efforts(internal_cout+external_cout, is_clk_rise) + stage_effort_list += self.clkbuf.get_output_stage_efforts(external_cout, is_clk_bar_rise) last_stage_is_rise = stage_effort_list[-1].is_rise #Then ask the sram for the other path delays (from the bank) @@ -824,56 +827,28 @@ class control_logic(design.design): return clk_to_sen_rise, clk_to_sen_fall def determine_sa_enable_stage_efforts(self): - """Follows the clock signal to the sense amp enable signal adding each stages stage effort to a list""" + """Follows the gated_clk_bar signal to the sense amp enable signal adding each stages stage effort to a list""" stage_effort_list = [] #Calculate the load on clk_buf_bar - int_clk_buf_cout = self.get_clk_buf_bar_cin() ext_clk_buf_cout = self.sram.get_clk_bar_cin() #Initial direction of clock signal for this path - is_clk_rise = False + is_clk_bar_rise = True - #First stage is the clock buffer - stage1 = self.clkbuf.determine_clk_buf_bar_stage_efforts(int_clk_buf_cout+ext_clk_buf_cout, is_clk_rise) - stage_effort_list += stage1 + #First stage, gated_clk_bar -(and2)-> rbl_in + stage1_cout = self.replica_bitline.get_en_cin() + stage_effort_list += self.and2.get_output_stage_efforts(stage1_cout, is_clk_bar_rise) last_stage_rise = stage_effort_list[-1].is_rise - #nand2 stage - stage2_cout = self.inv1.get_cin() - stage2 = self.nand2.get_effort_stage(stage2_cout, last_stage_rise) - stage_effort_list.append(stage2) + #Replica bitline stage, rbl_in -(rbl)-> pre_s_en + stage2_cout = self.buf8.get_cin() + stage_effort_list += self.replica_bitline.determine_sen_stage_efforts(stage2_cout, last_stage_rise) last_stage_rise = stage_effort_list[-1].is_rise - #inverter stage - stage3_cout = self.replica_bitline.get_en_cin() - stage3 = self.inv1.get_effort_stage(stage3_cout, last_stage_rise) - stage_effort_list.append(stage3) + #buffer stage, pre_s_en -(buffer)-> s_en + stage3_cout = self.sram.get_sen_cin() + stage_effort_list += self.buf8.get_output_stage_efforts(stage3_cout, last_stage_rise) last_stage_rise = stage_effort_list[-1].is_rise - #Replica bitline stage - stage4_cout = self.inv2.get_cin() - stage4 = self.replica_bitline.determine_sen_stage_efforts(stage4_cout, last_stage_rise) - stage_effort_list += stage4 - last_stage_rise = stage_effort_list[-1].is_rise - - #inverter (inv2) stage - stage5_cout = self.inv8.get_cin() - stage5 = self.inv2.get_effort_stage(stage5_cout, last_stage_rise) - stage_effort_list.append(stage5) - last_stage_rise = stage_effort_list[-1].is_rise - - #inverter (inv8) stage, s_en output - clk_sen_cout = self.sram.get_sen_cin() - stage6 = self.inv8.get_effort_stage(clk_sen_cout, last_stage_rise) - stage_effort_list.append(stage6) return stage_effort_list - - def get_clk_buf_bar_cin(self): - """Get the relative capacitance off the clk_buf_bar signal internal to the control logic""" - we_nand_cin = self.nand2.get_cin() - if self.port_type == "rw": - nand_mod = self.nand3 - else: - nand_mod = self.nand2 - sen_nand_cin = nand_mod.get_cin() - return we_nand_cin + sen_nand_cin \ No newline at end of file + \ No newline at end of file diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index d7e344e2..8538fbee 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -627,6 +627,8 @@ class replica_bitline(design.design): return stage_effort_list def get_delayed_en_cin(self): + """Get the fanout capacitance (relative) of the delayed enable from the delay chain.""" access_tx_cin = self.access_tx.get_cin() rbc_cin = self.replica_bitcell.get_wl_cin() - return access_tx_cin + rbc_cin \ No newline at end of file + return access_tx_cin + rbc_cin + \ No newline at end of file diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index 99d06ad1..af82fbc5 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -222,23 +222,19 @@ class wordline_driver(design.design): def determine_wordline_stage_efforts(self, external_cout, inp_is_rise=True): """Follows the clk_buf to a wordline signal adding each stages stage effort to a list""" stage_effort_list = [] - stage1_cout = self.nand2.get_cin() - stage1 = self.inv_no_output.get_effort_stage(stage1_cout, inp_is_rise) + + stage1_cout = self.inv.get_cin() + stage1 = self.nand2.get_effort_stage(stage1_cout, inp_is_rise) stage_effort_list.append(stage1) last_stage_is_rise = stage1.is_rise - stage2_cout = self.inv.get_cin() - stage2 = self.nand2.get_effort_stage(stage2_cout, last_stage_is_rise) + stage2 = self.inv.get_effort_stage(external_cout, last_stage_is_rise) stage_effort_list.append(stage2) - last_stage_is_rise = stage2.is_rise - - stage3 = self.inv.get_effort_stage(external_cout, last_stage_is_rise) - stage_effort_list.append(stage3) return stage_effort_list - def get_clk_cin(self): - """Get the relative capacitance of all the clk connections in the bank""" - #Clock is connected as an input to 1 inverter per row - total_cin = self.inv_no_output.get_cin() * self.rows + def get_wl_en_cin(self): + """Get the relative capacitance of all the enable connections in the bank""" + #The enable is connected to a nand2 for every row. + total_cin = self.nand2.get_cin() * self.rows return total_cin \ No newline at end of file diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index 00b6731c..5eb1ceb9 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -125,4 +125,15 @@ class pand2(pgate.pgate): inv_delay = self.inv.analytical_delay(slew=nand_delay.slew, load=load) return nand_delay + inv_delay - + def get_output_stage_efforts(self, external_cout, inp_is_rise=False): + """Get the stage efforts of the A or B -> Z path""" + stage_effort_list = [] + stage1_cout = self.inv.get_cin() + stage1 = self.nand.get_effort_stage(stage1_cout, inp_is_rise) + stage_effort_list.append(stage1) + last_stage_is_rise = stage1.is_rise + + stage2 = self.inv.get_effort_stage(external_cout, last_stage_is_rise) + stage_effort_list.append(stage2) + + return stage_effort_list diff --git a/compiler/pgates/pbuf.py b/compiler/pgates/pbuf.py index f293edc2..9b6c59ff 100644 --- a/compiler/pgates/pbuf.py +++ b/compiler/pgates/pbuf.py @@ -125,7 +125,7 @@ class pbuf(pgate.pgate): inv2_delay = self.inv2.analytical_delay(slew=inv1_delay.slew, load=load) return inv1_delay + inv2_delay - def determine_z_stage_efforts(self, external_cout, inp_is_rise=False): + def get_output_stage_efforts(self, external_cout, inp_is_rise=False): """Get the stage efforts of the A -> Z path""" stage_effort_list = [] stage1_cout = self.inv2.get_cin() @@ -137,3 +137,8 @@ class pbuf(pgate.pgate): stage_effort_list.append(stage2) return stage_effort_list + + def get_cin(self): + """Returns the relative capacitance of the input""" + input_cin = self.inv1.get_cin() + return input_cin \ No newline at end of file diff --git a/compiler/sram_base.py b/compiler/sram_base.py index d5b64f0b..bbd8e3e5 100644 --- a/compiler/sram_base.py +++ b/compiler/sram_base.py @@ -491,17 +491,13 @@ class sram_base(design): return stage_effort_list - def get_clk_cin(self): + def get_wl_en_cin(self): """Gets the capacitive load the of clock (clk_buf) for the sram""" #As clk_buf is an output of the control logic. The cap for that module is not determined here. - row_addr_clk_cin = self.row_addr_dff.get_clk_cin() - data_clk_cin = self.data_dff.get_clk_cin() - col_addr_clk_cin = 0 - if self.col_addr_size > 0: - col_addr_clk_cin = self.col_addr_dff.get_clk_cin() - bank_clk_cin = self.bank.get_clk_cin() + #Only the wordline drivers within the bank use this signal + bank_clk_cin = self.bank.get_wl_en_cin() - return row_addr_clk_cin + data_clk_cin + col_addr_clk_cin + bank_clk_cin + return bank_clk_cin def get_clk_bar_cin(self): """Gets the capacitive load the of clock (clk_buf_bar) for the sram""" diff --git a/compiler/tests/22_psram_1bank_2mux_func_test.py b/compiler/tests/22_psram_1bank_2mux_func_test.py index 19d4ab58..545b300b 100755 --- a/compiler/tests/22_psram_1bank_2mux_func_test.py +++ b/compiler/tests/22_psram_1bank_2mux_func_test.py @@ -11,7 +11,7 @@ import globals from globals import OPTS import debug -@unittest.skip("SKIPPING 22_psram_1bank_2mux_1rw_1r_1w_func_test, third port reads are broken?") +#@unittest.skip("SKIPPING 22_psram_1bank_2mux_1rw_1r_1w_func_test, third port reads are broken?") class psram_1bank_2mux_1rw_1r_1w_func_test(openram_test): def runTest(self): diff --git a/compiler/tests/22_psram_1bank_4mux_func_test.py b/compiler/tests/22_psram_1bank_4mux_func_test.py index dc6fffff..65ac76e3 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, third port reads are broken?") +#@unittest.skip("SKIPPING 22_psram_1bank_4mux_func_test, third port reads are broken?") class psram_1bank_4mux_func_test(openram_test): def runTest(self):