PEP8 cleanup

This commit is contained in:
mrg 2020-04-15 14:29:43 -07:00
parent 1564d6e02b
commit e95c97d7a5
1 changed files with 180 additions and 173 deletions

View File

@ -5,18 +5,16 @@
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
from math import log
import design
from tech import drc, parameter
from tech import cell_properties as props
import debug
import contact
from sram_factory import factory
import math
from vector import vector
from globals import OPTS
import logical_effort
class control_logic(design.design):
"""
Dynamically generated Control logic for the total SRAM circuit.
@ -44,6 +42,7 @@ class control_logic(design.design):
self.inv_parasitic_delay = logical_effort.logical_effort.pinv
# Determines how much larger the sen delay should be. Accounts for possible error in model.
# FIXME: This should be made a parameter
self.wl_timing_tolerance = 1
self.wl_stage_efforts = None
self.sen_stage_efforts = None
@ -71,7 +70,6 @@ class control_logic(design.design):
self.add_boundary()
self.DRC_LVS()
def add_pins(self):
""" Add the pins to the control logic module. """
self.add_pin_list(self.input_list + ["clk"] + self.rbl_list, "INPUT")
@ -101,7 +99,6 @@ class control_logic(design.design):
height=dff_height)
self.add_mod(self.rbl_driver)
# clk_buf drives a flop for every address
addr_flops = math.log(self.num_words, 2) + math.log(self.words_per_row, 2)
# plus data flops and control flops
@ -151,7 +148,6 @@ class control_logic(design.design):
height=dff_height)
self.add_mod(self.p_en_bar_driver)
self.nand2 = factory.create(module_type="pnand2",
height=dff_height)
self.add_mod(self.nand2)
@ -195,7 +191,8 @@ class control_logic(design.design):
# self.sen_delay_rise,self.sen_delay_fall = self.get_delays_to_sen() #get the new timing
# self.delay_chain_resized = True
debug.check(OPTS.delay_chain_stages%2, "Must use odd number of delay chain stages for inverting delay chain.")
debug.check(OPTS.delay_chain_stages % 2,
"Must use odd number of delay chain stages for inverting delay chain.")
self.delay_chain=factory.create(module_type="delay_chain",
fanout_list = OPTS.delay_chain_stages * [ OPTS.delay_chain_fanout_per_stage ])
self.add_mod(self.delay_chain)
@ -251,13 +248,16 @@ class control_logic(design.design):
previous_delay_chain_delay = (previous_fanout + 1 + self.inv_parasitic_delay) * previous_stages
debug.info(2, "Previous delay chain produced {} delay units".format(previous_delay_chain_delay))
delay_fanout = 3 # This can be anything >=2
# This can be anything >=2
delay_fanout = 3
# 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_per_stage = delay_fanout + 1 + self.inv_parasitic_delay
delay_stages = ceil(required_delay / delay_per_stage)
# force an even number of stages.
if delay_stages % 2 == 1:
delay_stages += 1
# 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))
@ -266,24 +266,33 @@ class control_logic(design.design):
def get_dynamic_delay_fanout_list(self, previous_stages, previous_fanout):
"""Determine the size of the delay chain used for the Sense Amp Enable using path delays"""
previous_delay_chain_delay = (previous_fanout+1+self.inv_parasitic_delay)*previous_stages
previous_delay_per_stage = previous_fanout + 1 + self.inv_parasitic_delay
previous_delay_chain_delay = previous_delay_per_stage * previous_stages
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
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))
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.
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)
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)
debug.info(1,"Fall stages={}, rise stages={}".format(stages_fall,stages_rise))
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)
debug.info(1,
"Fall stages={}, rise stages={}".format(stages_fall,
stages_rise))
if abs(stages_fall - stages_rise) == 1 and not stages_close:
stages_close = True
safe_fanout_rise = fanout_rise
@ -313,13 +322,17 @@ class control_logic(design.design):
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
if required_delay <= 3+self.inv_parasitic_delay: #3 is the minimum delay per stage (with pinv=0).
# 3 is the minimum delay per stage (with pinv=0).
if required_delay <= 3 + self.inv_parasitic_delay:
return 1
delay_stages = ceil(required_delay/(fanout+1+self.inv_parasitic_delay))
delay_per_stage = fanout + 1 + self.inv_parasitic_delay
delay_stages = ceil(required_delay / delay_per_stage)
return delay_stages
def calculate_stage_list(self, total_stages, fanout_rise, fanout_fall):
"""Produces a list of fanouts which determine the size of the delay chain. List length is the number of stages.
"""
Produces a list of fanouts which determine the size of the delay chain.
List length is the number of stages.
Assumes the first stage is falling.
"""
stage_list = []
@ -366,7 +379,6 @@ class control_logic(design.design):
self.supply_list = ["vdd", "gnd"]
def route_rails(self):
""" Add the input signal inverted tracks """
height = self.control_logic_center.y - self.m2_pitch
@ -374,7 +386,6 @@ class control_logic(design.design):
self.rail_offsets = self.create_vertical_bus("m2", self.m2_pitch, offset, self.internal_bus_list, height)
def create_instances(self):
""" Create all the instances """
self.create_dffs()
@ -390,8 +401,6 @@ class control_logic(design.design):
self.create_delay()
self.create_pen_row()
def place_instances(self):
""" Place all the instances """
# Keep track of all right-most instances to determine row boundary
@ -459,7 +468,6 @@ class control_logic(design.design):
self.route_gated_clk_buf()
self.route_supply()
def create_delay(self):
""" Create the replica bitline """
self.delay_inst=self.add_inst(name="delay_chain",
@ -488,11 +496,9 @@ class control_logic(design.design):
self.add_via_center(layers=self.m1_stack,
offset=in_pos)
# Input from RBL goes to the delay line for futher delay
self.copy_layout_pin(self.delay_inst, "in", "rbl_bl")
def create_clk_buf_row(self):
""" Create the multistage and gated clock buffer """
self.clk_buf_inst = self.add_inst(name="clkbuf",
@ -516,13 +522,12 @@ class control_logic(design.design):
self.add_via_center(layers=self.m1_stack,
offset=clk_pos)
# Connect this at the bottom of the buffer
out_pos = self.clk_buf_inst.get_pin("Z").center()
mid1 = vector(out_pos.x, 2 * self.m2_pitch)
mid2 = vector(self.rail_offsets["clk_buf"].x, mid1.y)
bus_pos = self.rail_offsets["clk_buf"]
self.add_wire(("m3","via2","m2"),[out_pos, mid1, mid2, bus_pos])
self.add_wire(self.m2_stack[::-1], [out_pos, mid1, mid2, bus_pos])
# The pin is on M1, so we need another via as well
self.add_via_center(layers=self.m1_stack,
offset=self.clk_buf_inst.get_pin("Z").center())
@ -557,15 +562,20 @@ class control_logic(design.design):
# This is the second gate over, so it needs to be on M3
clkbuf_map = zip(["A"], ["cs"])
self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("m3", "via2", "m2"))
self.connect_vertical_bus(clkbuf_map,
self.gated_clk_bar_inst,
self.rail_offsets,
self.m2_stack[::-1])
# The pin is on M1, so we need another via as well
self.add_via_center(layers=self.m1_stack,
offset=self.gated_clk_bar_inst.get_pin("A").center())
# This is the second gate over, so it needs to be on M3
clkbuf_map = zip(["Z"], ["gated_clk_bar"])
self.connect_vertical_bus(clkbuf_map, self.gated_clk_bar_inst, self.rail_offsets, ("m3", "via2", "m2"))
self.connect_vertical_bus(clkbuf_map,
self.gated_clk_bar_inst,
self.rail_offsets,
self.m2_stack[::-1])
# The pin is on M1, so we need another via as well
self.add_via_center(layers=self.m1_stack,
offset=self.gated_clk_bar_inst.get_pin("Z").center())
@ -586,9 +596,11 @@ class control_logic(design.design):
clkbuf_map = zip(["A", "B"], ["clk_buf", "cs"])
self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, self.rail_offsets)
clkbuf_map = zip(["Z"], ["gated_clk_buf"])
self.connect_vertical_bus(clkbuf_map, self.gated_clk_buf_inst, self.rail_offsets, ("m3", "via2", "m2"))
self.connect_vertical_bus(clkbuf_map,
self.gated_clk_buf_inst,
self.rail_offsets,
self.m2_stack[::-1])
# The pin is on M1, so we need another via as well
self.add_via_center(layers=self.m1_stack,
offset=self.gated_clk_buf_inst.get_pin("Z").center())
@ -656,7 +668,6 @@ class control_logic(design.design):
# hence we use rbl_bl_delay as well.
self.connect_inst(["rbl_bl_delay", "gated_clk_bar", input_name, "s_en", "vdd", "gnd"])
def place_sen_row(self, row):
x_offset = self.control_x_offset
@ -664,7 +675,6 @@ class control_logic(design.design):
self.row_end_inst.append(self.s_en_gate_inst)
def route_sen(self):
if self.port_type=="rw":
@ -700,11 +710,9 @@ class control_logic(design.design):
self.add_via_center(layers=self.m1_stack,
offset=self.rbl_bl_delay_inv_inst.get_pin("Z").center())
rbl_map = zip(["A"], ["rbl_bl_delay"])
self.connect_vertical_bus(rbl_map, self.rbl_bl_delay_inv_inst, self.rail_offsets)
def create_wen_row(self):
# input: we (or cs) output: w_en
@ -720,7 +728,6 @@ class control_logic(design.design):
# 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"])
def place_wen_row(self, row):
x_offset = self.control_x_offset
@ -784,7 +791,6 @@ class control_logic(design.design):
return (y_off, mirror)
def connect_output(self, inst, pin_name, out_name):
""" Create an output pin on the right side from the pin of a given instance. """
@ -795,8 +801,6 @@ class control_logic(design.design):
start=out_pin.center(),
end=right_pos)
def route_supply(self):
""" Add vdd and gnd to the instance cells """
@ -824,8 +828,6 @@ class control_logic(design.design):
self.copy_layout_pin(self.ctrl_dff_inst, "gnd")
self.copy_layout_pin(self.ctrl_dff_inst, "vdd")
def add_lvs_correspondence_points(self):
""" This adds some points for easier debugging if LVS goes wrong.
These should probably be turned off by default though, since extraction
@ -852,17 +854,18 @@ class control_logic(design.design):
height=pin.height(),
width=pin.width())
def get_delays_to_wl(self):
"""Get the delay (in delay units) of the clk to a wordline in the bitcell array"""
debug.check(self.sram.all_mods_except_control_done, "Cannot calculate sense amp enable delay unless all module have been added.")
self.wl_stage_efforts = self.get_wordline_stage_efforts()
clk_to_wl_rise, clk_to_wl_fall = logical_effort.calculate_relative_rise_fall_delays(self.wl_stage_efforts)
total_delay = clk_to_wl_rise + clk_to_wl_fall
debug.info(1, "Clock to wl delay is rise={:.3f}, fall={:.3f}, total={:.3f} in delay units".format(clk_to_wl_rise, clk_to_wl_fall,total_delay))
debug.info(1,
"Clock to wl delay is rise={:.3f}, fall={:.3f}, total={:.3f} in delay units".format(clk_to_wl_rise,
clk_to_wl_fall,
total_delay))
return clk_to_wl_rise, clk_to_wl_fall
def get_wordline_stage_efforts(self):
"""Follows the gated_clk_bar -> wl_en -> wordline signal for the total path efforts"""
stage_effort_list = []
@ -882,14 +885,18 @@ class control_logic(design.design):
return stage_effort_list
def get_delays_to_sen(self):
"""Get the delay (in delay units) of the clk to a sense amp enable.
"""
Get the delay (in delay units) of the clk to a sense amp enable.
This does not incorporate the delay of the replica bitline.
"""
debug.check(self.sram.all_mods_except_control_done, "Cannot calculate sense amp enable delay unless all module have been added.")
self.sen_stage_efforts = self.get_sa_enable_stage_efforts()
clk_to_sen_rise, clk_to_sen_fall = logical_effort.calculate_relative_rise_fall_delays(self.sen_stage_efforts)
total_delay = clk_to_sen_rise + clk_to_sen_fall
debug.info(1, "Clock to s_en delay is rise={:.3f}, fall={:.3f}, total={:.3f} in delay units".format(clk_to_sen_rise, clk_to_sen_fall,total_delay))
debug.info(1,
"Clock to s_en delay is rise={:.3f}, fall={:.3f}, total={:.3f} in delay units".format(clk_to_sen_rise,
clk_to_sen_fall,
total_delay))
return clk_to_sen_rise, clk_to_sen_fall
def get_sa_enable_stage_efforts(self):
@ -931,7 +938,7 @@ class control_logic(design.design):
stage_effort_list = []
# Calculate the load on clk_buf_bar
ext_clk_buf_cout = self.sram.get_clk_bar_cin()
# ext_clk_buf_cout = self.sram.get_clk_bar_cin()
# Operations logic starts on negative edge
last_stage_rise = False