Remove sense enable during writes

This commit is contained in:
Matt Guthaus 2019-09-07 20:04:48 -07:00
parent e5db02f7d8
commit 322af0ec09
1 changed files with 32 additions and 23 deletions

View File

@ -66,7 +66,7 @@ class control_logic(design.design):
""" Create layout and route between modules """
self.place_instances()
self.route_all()
# self.add_lvs_correspondence_points()
#self.add_lvs_correspondence_points()
self.add_boundary()
self.DRC_LVS()
@ -201,7 +201,7 @@ class control_logic(design.design):
def get_heuristic_delay_chain_size(self):
"""Use a basic heuristic to determine the size of the delay chain used for the Sense Amp Enable """
#FIXME: The minimum was 2 fanout, now it will not pass DRC unless it is 3. Why?
# FIXME: The minimum was 2 fanout, now it will not pass DRC unless it is 3. Why?
delay_fanout = 3 # This can be anything >=3
# Model poorly captures delay of the column mux. Be pessismistic for column mux
if self.words_per_row >= 2:
@ -209,8 +209,8 @@ class control_logic(design.design):
else:
delay_stages = 2
#Read ports have a shorter s_en delay. The model is not accurate enough to catch this difference
#on certain sram configs.
# Read ports have a shorter s_en delay. The model is not accurate enough to catch this difference
# on certain sram configs.
if self.port_type == "r":
delay_stages+=2
@ -226,7 +226,7 @@ class control_logic(design.design):
def does_sen_rise_fall_timing_match(self):
"""Compare the relative rise/fall delays of the sense amp enable and wordline"""
self.set_sen_wl_delays()
#This is not necessarily more reliable than total delay in some cases.
# This is not necessarily more reliable than total delay in some cases.
if (self.wl_delay_rise*self.wl_timing_tolerance >= self.sen_delay_rise or
self.wl_delay_fall*self.wl_timing_tolerance >= self.sen_delay_fall):
return False
@ -236,8 +236,9 @@ class control_logic(design.design):
def does_sen_total_timing_match(self):
"""Compare the total delays of the sense amp enable and wordline"""
self.set_sen_wl_delays()
#The sen delay must always be bigger than than the wl delay. This decides how much larger the sen delay must be before
#a re-size is warranted.
# The sen delay must always be bigger than than the wl
# delay. This decides how much larger the sen delay must be
# before a re-size is warranted.
if self.wl_delay*self.wl_timing_tolerance >= self.sen_delay:
return False
else:
@ -250,14 +251,14 @@ class control_logic(design.design):
debug.info(2, "Previous delay chain produced {} delay units".format(previous_delay_chain_delay))
delay_fanout = 3 # This can be anything >=2
#The delay chain uses minimum sized inverters. There are (fanout+1)*stages inverters and each
#inverter adds 1 unit of delay (due to minimum size). This also depends on the pinv value
# The delay chain uses minimum sized inverters. There are (fanout+1)*stages inverters and each
# inverter adds 1 unit of delay (due to minimum size). This also depends on the pinv value
required_delay = self.wl_delay*self.wl_timing_tolerance - (self.sen_delay-previous_delay_chain_delay)
debug.check(required_delay > 0, "Cannot size delay chain to have negative delay")
delay_stages = ceil(required_delay/(delay_fanout+1+self.inv_parasitic_delay))
if delay_stages%2 == 1: #force an even number of stages.
delay_stages+=1
#Fanout can be varied as well but is a little more complicated but potentially optimal.
# Fanout can be varied as well but is a little more complicated but potentially optimal.
debug.info(1, "Setting delay chain to {} stages with {} fanout to match {} delay".format(delay_stages, delay_fanout, required_delay))
return (delay_stages, delay_fanout)
@ -268,16 +269,16 @@ class control_logic(design.design):
debug.info(2, "Previous delay chain produced {} delay units".format(previous_delay_chain_delay))
fanout_rise = fanout_fall = 2 # This can be anything >=2
#The delay chain uses minimum sized inverters. There are (fanout+1)*stages inverters and each
#inverter adds 1 unit of delay (due to minimum size). This also depends on the pinv value
# The delay chain uses minimum sized inverters. There are (fanout+1)*stages inverters and each
# inverter adds 1 unit of delay (due to minimum size). This also depends on the pinv value
required_delay_fall = self.wl_delay_fall*self.wl_timing_tolerance - (self.sen_delay_fall-previous_delay_chain_delay/2)
required_delay_rise = self.wl_delay_rise*self.wl_timing_tolerance - (self.sen_delay_rise-previous_delay_chain_delay/2)
debug.info(2,"Required delays from chain: fall={}, rise={}".format(required_delay_fall,required_delay_rise))
#If the fanout is different between rise/fall by this amount. Stage algorithm is made more pessimistic.
# If the fanout is different between rise/fall by this amount. Stage algorithm is made more pessimistic.
WARNING_FANOUT_DIFF = 5
stages_close = False
#The stages need to be equal (or at least a even number of stages with matching rise/fall delays)
# The stages need to be equal (or at least a even number of stages with matching rise/fall delays)
while True:
stages_fall = self.calculate_stages_with_fixed_fanout(required_delay_fall,fanout_fall)
stages_rise = self.calculate_stages_with_fixed_fanout(required_delay_rise,fanout_rise)
@ -294,8 +295,8 @@ class control_logic(design.design):
fanout_rise = safe_fanout_rise
fanout_fall = safe_fanout_fall
break
#There should also be a condition to make sure the fanout does not get too large.
#Otherwise, increase the fanout of delay with the most stages, calculate new stages
# There should also be a condition to make sure the fanout does not get too large.
# Otherwise, increase the fanout of delay with the most stages, calculate new stages
elif stages_fall>stages_rise:
fanout_fall+=1
else:
@ -304,13 +305,13 @@ class control_logic(design.design):
total_stages = max(stages_fall,stages_rise)*2
debug.info(1, "New Delay chain: stages={}, fanout_rise={}, fanout_fall={}".format(total_stages, fanout_rise, fanout_fall))
#Creates interleaved fanout list of rise/fall delays. Assumes fall is the first stage.
# Creates interleaved fanout list of rise/fall delays. Assumes fall is the first stage.
stage_list = [fanout_fall if i%2==0 else fanout_rise for i in range(total_stages)]
return stage_list
def calculate_stages_with_fixed_fanout(self, required_delay, fanout):
from math import ceil
#Delay being negative is not an error. It implies that any amount of stages would have a negative effect on the overall delay
# Delay being negative is not an error. It implies that any amount of stages would have a negative effect on the overall delay
if required_delay <= 3+self.inv_parasitic_delay: #3 is the minimum delay per stage (with pinv=0).
return 1
delay_stages = ceil(required_delay/(fanout+1+self.inv_parasitic_delay))
@ -343,7 +344,7 @@ class control_logic(design.design):
# list of output control signals (for making a vertical bus)
if self.port_type == "rw":
self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "we", "clk_buf", "cs_bar", "cs"]
self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "we", "clk_buf", "we_bar", "cs"]
elif self.port_type == "r":
self.internal_bus_list = ["rbl_bl_delay_bar", "rbl_bl_delay", "gated_clk_bar", "gated_clk_buf", "clk_buf", "cs_bar", "cs"]
else:
@ -639,11 +640,14 @@ class control_logic(design.design):
def create_sen_row(self):
""" Create the sense enable buffer. """
if self.port_type=="rw":
input_name = "we_bar"
else:
input_name = "cs_bar"
# GATE FOR S_EN
# Uses cs_bar (not we_bar) for feed-thru reads
self.s_en_gate_inst = self.add_inst(name="buf_s_en_and",
mod=self.sen_and3)
self.connect_inst(["rbl_bl_delay", "gated_clk_bar", "cs_bar", "s_en", "vdd", "gnd"])
self.connect_inst(["rbl_bl_delay", "gated_clk_bar", input_name, "s_en", "vdd", "gnd"])
def place_sen_row(self,row):
@ -656,7 +660,12 @@ class control_logic(design.design):
def route_sen(self):
sen_map = zip(["A", "B", "C"], ["rbl_bl_delay", "gated_clk_bar", "cs_bar"])
if self.port_type=="rw":
input_name = "we_bar"
else:
input_name = "cs_bar"
sen_map = zip(["A", "B", "C"], ["rbl_bl_delay", "gated_clk_bar", input_name])
self.connect_vertical_bus(sen_map, self.s_en_gate_inst, self.rail_offsets)
self.connect_output(self.s_en_gate_inst, "Z", "s_en")
@ -733,7 +742,7 @@ class control_logic(design.design):
def route_dffs(self):
if self.port_type == "rw":
dff_out_map = zip(["dout_bar_0", "dout_bar_1", "dout_0"], ["cs", "we", "cs_bar"])
dff_out_map = zip(["dout_bar_0", "dout_bar_1", "dout_1"], ["cs", "we", "we_bar"])
elif self.port_type == "r":
dff_out_map = zip(["dout_bar_0", "dout_0"], ["cs", "cs_bar"])
else: