From 8d9b79dfd806bea4a73dc5fb1a8ecff138d0ff43 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Fri, 16 Feb 2018 15:25:27 -0800 Subject: [PATCH] Add dff_buf for buffered flop arrays. --- compiler/modules/dff.py | 2 +- compiler/modules/dff_buf.py | 146 +++++++ compiler/tests/11_dff_buf_test.py | 36 ++ technology/freepdk45/gds_lib/dff.gds | Bin 22528 -> 22528 bytes technology/freepdk45/sp_lib/dff.sp | 18 +- technology/scn3me_subm/gds_lib/dff.gds | Bin 18414 -> 16622 bytes technology/scn3me_subm/mag_lib/dff.mag | 538 ++++++++++++------------- technology/scn3me_subm/sp_lib/dff.sp | 14 +- 8 files changed, 458 insertions(+), 296 deletions(-) create mode 100644 compiler/modules/dff_buf.py create mode 100644 compiler/tests/11_dff_buf_test.py diff --git a/compiler/modules/dff.py b/compiler/modules/dff.py index 2db12281..62e424cb 100644 --- a/compiler/modules/dff.py +++ b/compiler/modules/dff.py @@ -10,7 +10,7 @@ class dff(design.design): Memory address flip-flop """ - pin_names = ["d", "q", "clk", "vdd", "gnd"] + pin_names = ["D", "Q", "clk", "vdd", "gnd"] (width,height) = utils.get_libcell_size("dff", GDS["unit"], layer["boundary"]) pin_map = utils.get_libcell_pins(pin_names, "dff", GDS["unit"], layer["boundary"]) diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py new file mode 100644 index 00000000..bcd03f16 --- /dev/null +++ b/compiler/modules/dff_buf.py @@ -0,0 +1,146 @@ +import debug +import design +from tech import drc +from math import log +from vector import vector +from globals import OPTS +from pinv import pinv + +class dff_buf(design.design): + """ + This is a simple buffered DFF. The output is buffered + with two inverters, of variable size, to provide q + and qbar. This is to enable driving large fanout loads. + """ + + def __init__(self, inv1_size, inv2_size, name=""): + + if name=="": + name = "dff_buf_{0}_{1}".format(inv1_size, inv2_size) + design.design.__init__(self, name) + debug.info(1, "Creating {}".format(self.name)) + + c = reload(__import__(OPTS.dff)) + self.mod_dff = getattr(c, OPTS.dff) + self.dff = self.mod_dff("dff") + self.add_mod(self.dff) + + self.inv1 = pinv(size=inv1_size,height=self.dff.height) + self.add_mod(self.inv1) + + self.inv2 = pinv(size=inv2_size,height=self.dff.height) + self.add_mod(self.inv2) + + self.width = self.dff.width + self.inv1.width + self.inv2.width + self.height = self.dff.height + + self.create_layout() + + def create_layout(self): + self.add_pins() + self.add_insts() + self.add_wires() + self.add_layout_pins() + self.DRC_LVS() + + def add_pins(self): + self.add_pin("D") + self.add_pin("Q") + self.add_pin("Qb") + self.add_pin("clk") + self.add_pin("vdd") + self.add_pin("gnd") + + def add_insts(self): + # Add the DFF + self.dff_inst=self.add_inst(name="dff_buf_dff", + mod=self.dff, + offset=vector(0,0)) + self.connect_inst(["D", "qint", "clk", "vdd", "gnd"]) + + # Add INV1 to the right + self.inv1_inst=self.add_inst(name="dff_buf_inv1", + mod=self.inv1, + offset=vector(self.dff_inst.rx(),0)) + self.connect_inst(["qint", "Qb", "vdd", "gnd"]) + + # Add INV2 to the right + self.inv2_inst=self.add_inst(name="dff_buf_inv2", + mod=self.inv2, + offset=vector(self.inv1_inst.rx(),0)) + self.connect_inst(["Qb", "Q", "vdd", "gnd"]) + + def add_wires(self): + # Route dff q to inv1 a + q_pin = self.dff_inst.get_pin("Q") + a1_pin = self.inv1_inst.get_pin("A") + mid_point = vector(a1_pin.cx(), q_pin.cy()) + self.add_wire(("metal3","via2","metal2"), + [q_pin.center(), mid_point, a1_pin.center()]) + self.add_via_center(("metal2","via2","metal3"), + q_pin.center()) + self.add_via_center(("metal1","via1","metal2"), + a1_pin.center()) + + # Route inv1 z to inv2 a + z1_pin = self.inv1_inst.get_pin("Z") + a2_pin = self.inv2_inst.get_pin("A") + mid_point = vector(z1_pin.cx(), a2_pin.cy()) + self.add_wire(("metal1","via1","metal2"), + [z1_pin.center(), mid_point, a2_pin.center()]) + + def add_layout_pins(self): + + # Continous vdd rail along with label. + vdd_pin=self.dff_inst.get_pin("vdd") + self.add_layout_pin(text="vdd", + layer="metal1", + offset=vdd_pin.ll(), + width=self.width, + height=vdd_pin.height()) + + # Continous gnd rail along with label. + gnd_pin=self.dff_inst.get_pin("gnd") + self.add_layout_pin(text="gnd", + layer="metal1", + offset=gnd_pin.ll(), + width=self.width, + height=vdd_pin.height()) + + clk_pin = self.dff_inst.get_pin("clk") + self.add_layout_pin(text="clk", + layer=clk_pin.layer, + offset=clk_pin.ll(), + width=clk_pin.width(), + height=clk_pin.height()) + + din_pin = self.dff_inst.get_pin("D") + self.add_layout_pin(text="D", + layer=din_pin.layer, + offset=din_pin.ll(), + width=din_pin.width(), + height=din_pin.height()) + + dout_pin = self.inv2_inst.get_pin("Z") + self.add_layout_pin(text="Q", + layer=dout_pin.layer, + offset=dout_pin.ll(), + width=dout_pin.width(), + height=dout_pin.height()) + + dout_pin = self.inv1_inst.get_pin("Z") + self.add_layout_pin(text="Qb", + layer=dout_pin.layer, + offset=dout_pin.ll(), + width=dout_pin.width(), + height=dout_pin.height()) + + + + def analytical_delay(self, slew, load=0.0): + """ Calculate the analytical delay of DFF-> INV -> INV """ + dff_delay=self.dff.analytical_delay(slew=slew, load=self.inv1.input_load()) + inv1_delay = self.inv1.analytical_delay(slew=dff_delay.slew, load=self.inv2.input_load()) + inv2_delay = self.inv2.analytical_delay(slew=inv1_delay.slew, load=load) + return dff_delay + inv1_delay + inv2_delay + diff --git a/compiler/tests/11_dff_buf_test.py b/compiler/tests/11_dff_buf_test.py new file mode 100644 index 00000000..3827647e --- /dev/null +++ b/compiler/tests/11_dff_buf_test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python2.7 +""" +Run a regresion test on a dff_buf. +""" + +import unittest +from testutils import header,openram_test +import sys,os +sys.path.append(os.path.join(sys.path[0],"..")) +import globals +from globals import OPTS +import debug + +class dff_buf_test(openram_test): + + def runTest(self): + globals.init_openram("config_20_{0}".format(OPTS.tech_name)) + global verify + import verify + OPTS.check_lvsdrc = False + + import dff_buf + + debug.info(2, "Testing dff_buf 4x 8x") + a = dff_buf.dff_buf(4, 8) + self.local_check(a) + + OPTS.check_lvsdrc = True + globals.end_openram() + +# instantiate a copdsay of the class to actually run the test +if __name__ == "__main__": + (OPTS, args) = globals.parse_args() + del sys.argv[1:] + header(__file__, OPTS.tech_name) + unittest.main() diff --git a/technology/freepdk45/gds_lib/dff.gds b/technology/freepdk45/gds_lib/dff.gds index 572020266bfa851afb05d797d738e6316c4e751e..db7d3af31b9b86b49b4bf1bb369048f353431d67 100644 GIT binary patch delta 109 zcmZqJz}T>Xae}NPAA=Nw00R#bTS{tLVrfnZ1A_=NtDVA;*-IY>f3sAI5x?NO<_Cie zD-#0;10w?yP%R6C6@w6%1=c$;?f|39#D&tEtr#ycG6rtuWxnUSd9}|@&dpCe4lr*{ I37f+R0OxBRXae}NP7lR6eC<6}@TS{tLVrfnZ1A_=NtDVA;*-IY>f3sAI5x?NOmWe@z zm5G6afsuiUL4bjU!HPi$%mVA37>9ZUcK diff --git a/technology/freepdk45/sp_lib/dff.sp b/technology/freepdk45/sp_lib/dff.sp index 8cc62891..51d99ad1 100644 --- a/technology/freepdk45/sp_lib/dff.sp +++ b/technology/freepdk45/sp_lib/dff.sp @@ -3,11 +3,11 @@ * Program "Calibre xRC" * Version "v2007.2_34.24" * -.subckt dff d q clk vdd gnd +.subckt dff D Q clk vdd gnd * -MM21 q a_66_6# gnd gnd NMOS_VTG L=5e-08 W=5e-07 +MM21 Q a_66_6# gnd gnd NMOS_VTG L=5e-08 W=5e-07 MM19 a_76_6# a_2_6# a_66_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 -MM20 gnd q a_76_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 +MM20 gnd Q a_76_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 MM18 a_66_6# clk a_61_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 MM17 a_61_6# a_34_4# gnd gnd NMOS_VTG L=5e-08 W=2.5e-07 MM10 gnd clk a_2_6# gnd NMOS_VTG L=5e-08 W=5e-07 @@ -15,9 +15,9 @@ MM16 a_34_4# a_22_6# gnd gnd NMOS_VTG L=5e-08 W=2.5e-07 MM15 gnd a_34_4# a_31_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 MM14 a_31_6# clk a_22_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 MM13 a_22_6# a_2_6# a_17_6# gnd NMOS_VTG L=5e-08 W=2.5e-07 -MM12 a_17_6# d gnd gnd NMOS_VTG L=5e-08 W=2.5e-07 -MM11 q a_66_6# vdd vdd PMOS_VTG L=5e-08 W=1e-06 -MM9 vdd q a_76_84# vdd PMOS_VTG L=5e-08 W=2.5e-07 +MM12 a_17_6# D gnd gnd NMOS_VTG L=5e-08 W=2.5e-07 +MM11 Q a_66_6# vdd vdd PMOS_VTG L=5e-08 W=1e-06 +MM9 vdd Q a_76_84# vdd PMOS_VTG L=5e-08 W=2.5e-07 MM8 a_76_84# clk a_66_6# vdd PMOS_VTG L=5e-08 W=2.5e-07 MM7 a_66_6# a_2_6# a_61_74# vdd PMOS_VTG L=5e-08 W=5e-07 MM6 a_61_74# a_34_4# vdd vdd PMOS_VTG L=5e-08 W=5e-07 @@ -26,16 +26,16 @@ MM5 a_34_4# a_22_6# vdd vdd PMOS_VTG L=5e-08 W=5e-07 MM4 vdd a_34_4# a_31_74# vdd PMOS_VTG L=5e-08 W=5e-07 MM3 a_31_74# a_2_6# a_22_6# vdd PMOS_VTG L=5e-08 W=5e-07 MM2 a_22_6# clk a_17_74# vdd PMOS_VTG L=5e-08 W=5e-07 -MM1 a_17_74# d vdd vdd PMOS_VTG L=5e-08 W=5e-07 +MM1 a_17_74# D vdd vdd PMOS_VTG L=5e-08 W=5e-07 * c_9 a_66_6# 0 0.271997f * c_20 clk 0 0.350944f -* c_27 q 0 0.202617f +* c_27 Q 0 0.202617f * c_32 a_76_84# 0 0.0210573f * c_38 a_76_6# 0 0.0204911f * c_45 a_34_4# 0 0.172306f * c_55 a_2_6# 0 0.283119f * c_59 a_22_6# 0 0.157312f -* c_64 d 0 0.0816386f +* c_64 D 0 0.0816386f * c_73 gnd 0 0.254131f * c_81 vdd 0 0.23624f * diff --git a/technology/scn3me_subm/gds_lib/dff.gds b/technology/scn3me_subm/gds_lib/dff.gds index 679792f4c0996808545cbe0dcc2d0a0070d5ac80..b96235c7500aba5314ed95369b44d5000c60b5ff 100644 GIT binary patch literal 16622 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