all remaining spice for delay control

This commit is contained in:
samuelkcrow 2022-04-27 12:13:36 -07:00
parent 66502fc5dc
commit 62a65f8053
3 changed files with 51 additions and 42 deletions

View File

@ -13930,17 +13930,17 @@ Xnand2_glitch3 out6 g3_end glitch3_bar vdd gnd pnand2
Xinv_glitch3_buf glitch3_bar glitch3_buf vdd gnd pinv_11 Xinv_glitch3_buf glitch3_bar glitch3_buf vdd gnd pinv_11
* is cs_buf needed on larger memories? I don't remember why I needed this for small mems. Some timing bs surely * is cs_buf needed on larger memories? I don't remember why I needed this for small mems. Some timing bs surely
* I have a feeling this was another misguided workaround to proper gate sizing smh my head bruh * I have a feeling this was another misguided workaround to proper gate sizing smh my head bruh
Xbuf_cs cs cs_buf vdd gnd pdriver_0 *Xbuf_cs cs cs_buf vdd gnd pdriver_0
Xclkbuf clk clk_buf vdd gnd pdriver_0 Xclkbuf clk clk_buf vdd gnd pdriver_0
Xinv_clk_bar clk_buf clk_bar vdd gnd pinv_17 Xinv_clk_bar clk_buf clk_bar vdd gnd pinv_17
Xand2_gated_clk_bar clk_bar cs gated_clk_bar vdd gnd pand2 Xand2_gated_clk_bar clk_bar cs gated_clk_bar vdd gnd pand2
Xand2_gated_clk_buf clk_buf cs gated_clk_buf vdd gnd pand2 Xand2_gated_clk_buf clk_buf cs gated_clk_buf vdd gnd pand2
* uhhhh do I really need this?? can't I just roll this into one gate with the next? * uhhhh do I really need this?? can't I just roll this into one gate with the next?
Xinv_pre_s glitch3_buf pre_s vdd gnd pinv_11 Xinv_pre_sen glitch3_buf pre_sen vdd gnd pinv_11
* I'm an idiot and the following two and3 gates are not supposed to be the same size smh * I'm an idiot and the following two and3 gates are not supposed to be the same size smh
Xand_s_en we_bar gated_clk_bar pre_s s_en vdd gnd pand3 Xand_s_en we_bar gated_clk_bar pre_sen s_en vdd gnd pand3
Xand_w_en we glitch2_bar glitch3_buf w_en vdd gnd pand3 Xand_w_en we glitch2_bar glitch3_buf w_en vdd gnd pand3
Xand_wl_en_unbuf cs_buf glitch2_bar wl_en_unbuf vdd gnd pand2 Xand_wl_en_unbuf cs glitch2_bar wl_en_unbuf vdd gnd pand2
* Xbuf_wl_en is an untested addition, probably too slow but honestly hard to say because the * Xbuf_wl_en is an untested addition, probably too slow but honestly hard to say because the
* fanout was so horrible on wl_en without it that maybe it's actually better now ¯\_()_/¯ * fanout was so horrible on wl_en without it that maybe it's actually better now ¯\_()_/¯
Xbuf_wl_en wl_en_unbuf wl_en vdd gnd pdriver_1 Xbuf_wl_en wl_en_unbuf wl_en vdd gnd pdriver_1

View File

@ -14,7 +14,7 @@ from globals import OPTS
import logical_effort import logical_effort
class control_logic(design.design): class control_logic_delay(design.design):
""" """
Dynamically generated Control logic for the total SRAM circuit. Dynamically generated Control logic for the total SRAM circuit.
Variant: delay-based Variant: delay-based
@ -96,10 +96,6 @@ class control_logic(design.design):
size=12, size=12,
height=dff_height) height=dff_height)
self.rbl_driver = factory.create(module_type="pbuf",
size=self.num_cols,
height=dff_height)
# clk_buf drives a flop for every address # clk_buf drives a flop for every address
addr_flops = math.log(self.num_words, 2) + math.log(self.words_per_row, 2) addr_flops = math.log(self.num_words, 2) + math.log(self.words_per_row, 2)
# plus data flops and control flops # plus data flops and control flops
@ -154,8 +150,9 @@ class control_logic(design.design):
debug.check(OPTS.delay_chain_stages % 2, debug.check(OPTS.delay_chain_stages % 2,
"Must use odd number of delay chain stages for inverting delay chain.") "Must use odd number of delay chain stages for inverting delay chain.")
self.delay_chain=factory.create(module_type="delay_chain", self.multi_delay_chain=factory.create(module_type = "multi_delay_chain",
fanout_list = OPTS.delay_chain_stages * [ OPTS.delay_chain_fanout_per_stage ]) fanout_list = OPTS.delay_chain_stages * [ OPTS.delay_chain_fanout_per_stage ],
pinout_list = [1, 6, 7, 14]) # TODO: generate this list programatically
# not being used # not being used
def get_dynamic_delay_chain_size(self, previous_stages, previous_fanout): def get_dynamic_delay_chain_size(self, previous_stages, previous_fanout):
@ -302,13 +299,14 @@ class control_logic(design.design):
self.create_clk_buf_row() self.create_clk_buf_row()
self.create_gated_clk_bar_row() self.create_gated_clk_bar_row()
self.create_gated_clk_buf_row() self.create_gated_clk_buf_row()
self.create_delay()
self.create_glitches()
self.create_glitch3_additional_invs()
self.create_wlen_row() self.create_wlen_row()
if (self.port_type == "rw") or (self.port_type == "w"): if (self.port_type == "rw") or (self.port_type == "w"):
self.create_rbl_delay_row()
self.create_wen_row() self.create_wen_row()
if (self.port_type == "rw") or (self.port_type == "r"): if (self.port_type == "rw") or (self.port_type == "r"):
self.create_sen_row() self.create_sen_row()
self.create_delay()
self.create_pen_row() self.create_pen_row()
def place_instances(self): def place_instances(self):
@ -380,11 +378,10 @@ class control_logic(design.design):
self.route_supply() self.route_supply()
def create_delay(self): def create_delay(self):
""" Create the replica bitline """ """ Create the delay chain """
self.delay_inst=self.add_inst(name="delay_chain", self.delay_inst=self.add_inst(name="multi_delay_chain",
mod=self.delay_chain) mod=self.multi_delay_chain)
# rbl_bl_delay is asserted (1) when the bitline has been discharged self.connect_inst(["gated_clk_buf", "out1", "out6", "out7", "out14", "vdd", "gnd"])
self.connect_inst(["rbl_bl", "rbl_bl_delay", "vdd", "gnd"])
def place_delay(self, row): def place_delay(self, row):
""" Place the replica bitline """ """ Place the replica bitline """
@ -416,28 +413,28 @@ class control_logic(design.design):
# glitch{1-3} are internal timing signals based on different in/out # glitch{1-3} are internal timing signals based on different in/out
# points on the delay chain for adjustable start time and duration # points on the delay chain for adjustable start time and duration
def create_glitches(self): def create_glitches(self):
self.glitch1_inv = self.add_inst(name="inv_glitch1", self.glitch1_inv_inst = self.add_inst(name="inv_glitch1",
mod=self.inv) mod=self.inv)
self.connect_inst(["out6", "g1_end", "vdd", "gnd"]) self.connect_inst(["out6", "g1_end", "vdd", "gnd"])
self.glitch2_inv = self.add_inst(name="inv_glitch2", self.glitch2_inv_inst = self.add_inst(name="inv_glitch2",
mod=self.inv) mod=self.inv)
self.connect_inst(["out7", "g2_end", "vdd", "gnd"]) self.connect_inst(["out7", "g2_end", "vdd", "gnd"])
self.glitch3_inv = self.add_inst(name="inv_glitch3", self.glitch3_inv_inst = self.add_inst(name="inv_glitch3",
mod=self.inv) mod=self.inv)
self.connect_inst(["out14", "g3_end", "vdd", "gnd"]) self.connect_inst(["out14", "g3_end", "vdd", "gnd"])
self.glitch1_nand = self.add_inst(name="nand2_glitch1", self.glitch1_nand_inst = self.add_inst(name="nand2_glitch1",
mod=self.nand2) mod=self.nand2)
self.connect_inst(["out1", "g1_end", "glitch1_bar", "vdd", "gnd"]) self.connect_inst(["out1", "g1_end", "glitch1_bar", "vdd", "gnd"])
self.glitch2_nand = self.add_inst(name="nand2_glitch2", self.glitch2_nand_inst = self.add_inst(name="nand2_glitch2",
mod=self.nand2) mod=self.nand2)
self.connect_inst(["gated_clk_buf", "g2_end", "glitch2_bar", "vdd", "gnd"]) self.connect_inst(["gated_clk_buf", "g2_end", "glitch2_bar", "vdd", "gnd"])
self.glitch3_nand = self.add_inst(name="nand2_glitch3", self.glitch3_nand_inst = self.add_inst(name="nand2_glitch3",
mod=self.nand2) mod=self.nand2)
self.connect_inst(["out6", "g3_end", "glitch3_bar", "vdd", "gnd"]) self.connect_inst(["out6", "g3_end", "glitch3_bar", "vdd", "gnd"])
def create_clk_buf_row(self): def create_clk_buf_row(self):
@ -544,10 +541,13 @@ class control_logic(design.design):
offset=z_pin.center()) offset=z_pin.center())
def create_wlen_row(self): def create_wlen_row(self):
# input pre_p_en, output: wl_en self.wl_en_unbuf_and_inst = self.add_inst(name="and_wl_en_unbuf",
mod=self.wl_en_and)
self.connect_inst(["cs", "glitch2_bar", "wl_en_unbuf", "vdd", "gnd"])
self.wl_en_inst=self.add_inst(name="buf_wl_en", self.wl_en_inst=self.add_inst(name="buf_wl_en",
mod=self.wl_en_driver) mod=self.wl_en_driver)
self.connect_inst(["gated_clk_bar", "wl_en", "vdd", "gnd"]) self.connect_inst(["wl_en_unbuf", "wl_en", "vdd", "gnd"])
def place_wlen_row(self, row): def place_wlen_row(self, row):
x_offset = self.control_x_offset x_offset = self.control_x_offset
@ -563,15 +563,13 @@ class control_logic(design.design):
self.connect_output(self.wl_en_inst, "Z", "wl_en") self.connect_output(self.wl_en_inst, "Z", "wl_en")
def create_pen_row(self): def create_pen_row(self):
self.p_en_bar_nand_inst=self.add_inst(name="nand_p_en_bar", # FIXME: comment below
mod=self.nand2)
# We use the rbl_bl_delay here to ensure that the p_en is only asserted when the # We use the rbl_bl_delay here to ensure that the p_en is only asserted when the
# bitlines have already been discharged. Otherwise, it is a combination loop. # bitlines have already been discharged. Otherwise, it is a combination loop.
self.connect_inst(["gated_clk_buf", "rbl_bl_delay", "p_en_bar_unbuf", "vdd", "gnd"])
self.p_en_bar_driver_inst=self.add_inst(name="buf_p_en_bar", self.p_en_bar_driver_inst=self.add_inst(name="buf_p_en_bar",
mod=self.p_en_bar_driver) mod=self.p_en_bar_driver)
self.connect_inst(["p_en_bar_unbuf", "p_en_bar", "vdd", "gnd"]) self.connect_inst(["glitch1_bar", "p_en_bar", "vdd", "gnd"])
def place_pen_row(self, row): def place_pen_row(self, row):
x_offset = self.control_x_offset x_offset = self.control_x_offset
@ -597,6 +595,16 @@ class control_logic(design.design):
self.connect_output(self.p_en_bar_driver_inst, "Z", "p_en_bar") self.connect_output(self.p_en_bar_driver_inst, "Z", "p_en_bar")
def create_glitch3_additional_invs(self):
""" A pair of inverters to create additional signals from and buffer glitch 3"""
self.glitch3_buf_inv_inst = self.add_inst(name="inv_glitch3_buf",
mod=self.inv)
self.connect_inst(["glitch3_bar", "glitch3_buf", "vdd", "gnd"])
self.pre_sen_inv = self.add_inst(name="inv_pre_sen",
mod=self.inv)
self.connect_inst(["gltich3_buf", "pre_sen", "vdd", "gnd"])
def create_sen_row(self): def create_sen_row(self):
""" Create the sense enable buffer. """ """ Create the sense enable buffer. """
if self.port_type=="rw": if self.port_type=="rw":
@ -604,12 +612,13 @@ class control_logic(design.design):
else: else:
input_name = "cs" input_name = "cs"
# GATE FOR S_EN # GATE FOR S_EN
self.s_en_gate_inst = self.add_inst(name="buf_s_en_and", self.s_en_gate_inst = self.add_inst(name="and_s_en",
mod=self.sen_and3) mod=self.sen_and3)
# FIXME: comment below
# s_en is asserted in the second half of the cycle during a read. # s_en is asserted in the second half of the cycle during a read.
# we also must wait until the bitline has been discharged enough for proper sensing # we also must wait until the bitline has been discharged enough for proper sensing
# hence we use rbl_bl_delay as well. # hence we use rbl_bl_delay as well.
self.connect_inst(["rbl_bl_delay", "gated_clk_bar", input_name, "s_en", "vdd", "gnd"]) self.connect_inst(["pre_sen", "gated_clk_bar", input_name, "s_en", "vdd", "gnd"])
def place_sen_row(self, row): def place_sen_row(self, row):
x_offset = self.control_x_offset x_offset = self.control_x_offset
@ -640,10 +649,10 @@ class control_logic(design.design):
input_name = "cs" input_name = "cs"
# GATE THE W_EN # GATE THE W_EN
self.w_en_gate_inst = self.add_inst(name="w_en_and", self.w_en_gate_inst = self.add_inst(name="and_w_en",
mod=self.wen_and) mod=self.wen_and)
# Only drive the writes in the second half of the clock cycle during a write operation. # Only drive the writes in the second half of the clock cycle during a write operation.
self.connect_inst([input_name, "rbl_bl_delay_bar", "gated_clk_bar", "w_en", "vdd", "gnd"]) self.connect_inst([input_name, "glitch2_bar", "glitch3_buf", "w_en", "vdd", "gnd"])
def place_wen_row(self, row): def place_wen_row(self, row):
x_offset = self.control_x_offset x_offset = self.control_x_offset

View File

@ -12,7 +12,7 @@ from globals import OPTS
from sram_factory import factory from sram_factory import factory
class delay_chain(design.design): class multi_delay_chain(design.design):
""" """
Generate a delay chain with the given number of stages, fanout, and output pins. Generate a delay chain with the given number of stages, fanout, and output pins.
Fanout list contains the electrical effort (fanout) of each stage. Fanout list contains the electrical effort (fanout) of each stage.
@ -36,7 +36,7 @@ class delay_chain(design.design):
self.rows = len(self.fanout_list) self.rows = len(self.fanout_list)
# defaults to signle output at end of delay chain # defaults to signle output at end of delay chain
if len(self.pinout_list) == 0: if len(pinout_list) == 0:
self.pinout_list = [self.rows] # TODO: check for off-by-one here self.pinout_list = [self.rows] # TODO: check for off-by-one here
else: else:
self.pinout_list = pinout_list self.pinout_list = pinout_list