From a2f81aeae486c0af1a0e6e67b12790d25e287eef Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 6 Aug 2019 16:29:07 -0700 Subject: [PATCH 1/4] Combine rbl_wl and wl_en. Size p_en_bar slower than wl_en. --- compiler/modules/bank.py | 18 ++++---- compiler/modules/control_logic.py | 74 +++++++++++-------------------- compiler/sram/sram_base.py | 10 ++--- 3 files changed, 39 insertions(+), 63 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 613a3381..f3491b79 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -84,8 +84,6 @@ class bank(design.design): self.add_pin("dout{0}_{1}".format(port,bit),"OUTPUT") for port in self.read_ports: self.add_pin(self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]),"OUTPUT") - for port in self.read_ports: - self.add_pin(self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]),"INPUT") for port in self.write_ports: for bit in range(self.word_size): self.add_pin("din{0}_{1}".format(port,bit),"INPUT") @@ -306,13 +304,13 @@ class bank(design.design): self.input_control_signals = [] port_num = 0 for port in range(OPTS.num_rw_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "rbl_wl{}".format(port_num)]) + self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_w_ports): self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "p_en_bar{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_r_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "rbl_wl{}".format(port_num)]) + self.input_control_signals.append(["wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)]) port_num += 1 # Number of control lines in the bus for each port @@ -422,9 +420,9 @@ class bank(design.design): for row in range(self.num_rows): for wordline in self.wl_names: temp.append("{0}_{1}".format(wordline,row)) - for rbl in range(self.num_rbl): - rbl_wl_name=self.bitcell_array.get_rbl_wl_name(rbl) - temp.append(rbl_wl_name) + for port in self.all_ports: + if self.port_data[port].has_rbl(): + temp.append("wl_en{0}".format(port)) temp.append("vdd") temp.append("gnd") self.connect_inst(temp) @@ -947,7 +945,7 @@ class bank(design.design): if port in self.read_ports: rbl_wl_name = self.bitcell_array.get_rbl_wl_name(self.port_rbl_map[port]) - connection.append((self.prefix+"rbl_wl{}".format(port), self.bitcell_array_inst.get_pin(rbl_wl_name).lc())) + connection.append((self.prefix+"wl_en{}".format(port), self.bitcell_array_inst.get_pin(rbl_wl_name).lc())) if port in self.write_ports: connection.append((self.prefix+"w_en{}".format(port), self.port_data_inst[port].get_pin("w_en").lc())) @@ -967,10 +965,10 @@ class bank(design.design): control_signal = self.prefix+"wl_en{}".format(port) if port%2: pin_pos = self.port_address_inst[port].get_pin("wl_en").uc() - mid_pos = pin_pos + vector(0,self.m2_gap) # to route down to the top of the bus + mid_pos = pin_pos + vector(0,2*self.m2_gap) # to route down to the top of the bus else: pin_pos = self.port_address_inst[port].get_pin("wl_en").bc() - mid_pos = pin_pos - vector(0,self.m2_gap) # to route down to the top of the bus + mid_pos = pin_pos - vector(0,2*self.m2_gap) # to route down to the top of the bus control_x_offset = self.bus_xoffset[port][control_signal].x control_pos = vector(control_x_offset, mid_pos.y) self.add_wire(("metal1","via1","metal2"),[pin_pos, mid_pos, control_pos]) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 1d2226b1..f5531d6f 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -101,20 +101,26 @@ class control_logic(design.design): self.add_mod(self.rbl_driver) - # clk_buf drives a flop for every address and control bit + # 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 + num_flops = addr_flops + self.word_size + self.num_control_signals + # each flop internally has a FO 5 approximately # plus about 5 fanouts for the control logic - # each flop internally has a FO 4 approximately - clock_fanout = 4*(math.log(self.num_words,2) + math.log(self.words_per_row,2) \ - + self.num_control_signals) + 5 + clock_fanout = 5*num_flops + 5 self.clk_buf_driver = factory.create(module_type="pdriver", fanout=clock_fanout, height=dff_height) self.add_mod(self.clk_buf_driver) + # We will use the maximum since this same value is used to size the wl_en + # and the p_en_bar drivers + max_fanout = max(self.num_rows,self.num_cols) + # wl_en drives every row in the bank self.wl_en_driver = factory.create(module_type="pdriver", - fanout=self.num_rows, + fanout=max_fanout, height=dff_height) self.add_mod(self.wl_en_driver) @@ -132,14 +138,16 @@ class control_logic(design.design): # used to generate inverted signals with low fanout self.inv = factory.create(module_type="pinv", - size=1, - height=dff_height) + size=1, + height=dff_height) self.add_mod(self.inv) # p_en_bar drives every column in the bitcell array + # but it is sized the same as the wl_en driver with + # prepended 3 inverter stages to guarantee it is slower and odd polarity + driver_size_list = [1,1,1,*self.wl_en_driver.get_sizes()] self.p_en_bar_driver = factory.create(module_type="pdriver", - neg_polarity=True, - fanout=self.num_cols, + size_list=driver_size_list, height=dff_height) self.add_mod(self.p_en_bar_driver) @@ -346,9 +354,9 @@ class control_logic(design.design): # Outputs to the bank if self.port_type == "rw": - self.output_list = ["rbl_wl", "s_en", "w_en"] + self.output_list = ["s_en", "w_en"] elif self.port_type == "r": - self.output_list = ["rbl_wl", "s_en"] + self.output_list = ["s_en"] else: self.output_list = ["w_en"] self.output_list.append("p_en_bar") @@ -376,7 +384,6 @@ class control_logic(design.design): if (self.port_type == "rw") or (self.port_type == "w"): self.create_wen_row() if (self.port_type == "rw") or (self.port_type == "r"): - self.create_rbl_row() self.create_sen_row() self.create_delay() self.create_pen_row() @@ -410,9 +417,6 @@ class control_logic(design.design): height = self.w_en_gate_inst.uy() control_center_y = self.w_en_gate_inst.uy() row += 1 - if (self.port_type == "rw") or (self.port_type == "r"): - self.place_rbl_row(row) - row += 1 self.place_pen_row(row) row += 1 if (self.port_type == "rw") or (self.port_type == "r"): @@ -441,7 +445,6 @@ class control_logic(design.design): if (self.port_type == "rw") or (self.port_type == "w"): self.route_wen() if (self.port_type == "rw") or (self.port_type == "r"): - self.route_rbl() self.route_sen() self.route_pen() self.route_clk_buf() @@ -596,42 +599,15 @@ class control_logic(design.design): def route_wlen(self): wlen_map = zip(["A"], ["gated_clk_bar"]) - self.connect_vertical_bus(wlen_map, self.wl_en_inst, self.rail_offsets) + self.connect_vertical_bus(wlen_map, self.wl_en_inst, self.rail_offsets) + self.connect_output(self.wl_en_inst, "Z", "wl_en") - def create_rbl_row(self): - - self.rbl_inst=self.add_inst(name="rbl_driver", - mod=self.rbl_driver) - # input: gated_clk_bar, output: rbl_wl - self.connect_inst(["gated_clk_bar", "rbl_wl", "vdd", "gnd"]) - - def place_rbl_row(self,row): - x_off = self.control_x_offset - (y_off,mirror)=self.get_offset(row) - - offset = vector(x_off, y_off) - self.rbl_inst.place(offset, mirror) - - self.row_end_inst.append(self.rbl_inst) - - def route_rbl(self): - """ Connect the logic for the rbl_in generation """ - - rbl_in_map = zip(["A"], ["gated_clk_bar"]) - self.connect_vertical_bus(rbl_in_map, self.rbl_inst, self.rail_offsets) - self.connect_output(self.rbl_inst, "Z", "rbl_wl") - - # Input from RBL goes to the delay line for futher delay - self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") - def create_pen_row(self): - input_name = "gated_clk_buf" - - # input: pre_p_en, output: p_en_bar + # input: gated_clk_bar, output: p_en_bar self.p_en_bar_inst=self.add_inst(name="inv_p_en_bar", mod=self.p_en_bar_driver) - self.connect_inst([input_name, "p_en_bar", "vdd", "gnd"]) + self.connect_inst(["gated_clk_buf", "p_en_bar", "vdd", "gnd"]) def place_pen_row(self,row): @@ -690,6 +666,10 @@ class control_logic(design.design): self.add_wire(("metal1","via1","metal2"),[out_pos, mid1,in_pos]) self.connect_output(self.s_en_gate_inst, "Z", "s_en") + + # Input from RBL goes to the delay line for futher delay + self.copy_layout_pin(self.delay_inst, "in", "rbl_bl") + def create_wen_row(self): diff --git a/compiler/sram/sram_base.py b/compiler/sram/sram_base.py index 45befe16..f34d058e 100644 --- a/compiler/sram/sram_base.py +++ b/compiler/sram/sram_base.py @@ -341,8 +341,6 @@ class sram_base(design, verilog, lef): temp.append("DOUT{0}[{1}]".format(port,bit)) for port in self.read_ports: temp.append("rbl_bl{0}".format(port)) - for port in self.read_ports: - temp.append("rbl_wl{0}".format(port)) for port in self.write_ports: for bit in range(self.word_size): temp.append("BANK_DIN{0}[{1}]".format(port,bit)) @@ -506,9 +504,6 @@ class sram_base(design, verilog, lef): temp.append("rbl_bl{}".format(port)) # Ouputs - if port in self.read_ports: - temp.append("rbl_wl{}".format(port)) - if port in self.read_ports: temp.append("s_en{}".format(port)) if port in self.write_ports: @@ -530,7 +525,10 @@ class sram_base(design, verilog, lef): in_pos = src_pin.rc() else: in_pos = src_pin.lc() - out_pos = dest_pin.center() + if src_pin.cy() < dest_pin.cy(): + out_pos = dest_pin.bc() + else: + out_pos = dest_pin.uc() # move horizontal first self.add_wire(("metal3","via2","metal2"),[in_pos, vector(out_pos.x,in_pos.y),out_pos]) From ae46a464b99468e7e11c7c3eabc2969ba128604d Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Tue, 6 Aug 2019 17:17:59 -0700 Subject: [PATCH 2/4] Undo delay changes. Fix bus order for DRC. --- compiler/modules/bank.py | 6 +++--- compiler/modules/control_logic.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index f3491b79..4fa95c44 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -304,13 +304,13 @@ class bank(design.design): self.input_control_signals = [] port_num = 0 for port in range(OPTS.num_rw_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)]) + self.input_control_signals.append(["w_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_en{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_w_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "w_en{}".format(port_num), "p_en_bar{}".format(port_num)]) + self.input_control_signals.append(["w_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_en{}".format(port_num)]) port_num += 1 for port in range(OPTS.num_r_ports): - self.input_control_signals.append(["wl_en{}".format(port_num), "s_en{}".format(port_num), "p_en_bar{}".format(port_num)]) + self.input_control_signals.append(["s_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_en{}".format(port_num)]) port_num += 1 # Number of control lines in the bus for each port diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index f5531d6f..a5c5dc12 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -120,7 +120,7 @@ class control_logic(design.design): # wl_en drives every row in the bank self.wl_en_driver = factory.create(module_type="pdriver", - fanout=max_fanout, + fanout=self.num_rows, height=dff_height) self.add_mod(self.wl_en_driver) @@ -145,9 +145,9 @@ class control_logic(design.design): # p_en_bar drives every column in the bitcell array # but it is sized the same as the wl_en driver with # prepended 3 inverter stages to guarantee it is slower and odd polarity - driver_size_list = [1,1,1,*self.wl_en_driver.get_sizes()] self.p_en_bar_driver = factory.create(module_type="pdriver", - size_list=driver_size_list, + fanout=self.num_cols, + neg_polarity=True, height=dff_height) self.add_mod(self.p_en_bar_driver) From c2655fcaa9a3429cda129df6da9d798ce68e0b44 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 7 Aug 2019 16:01:05 -0700 Subject: [PATCH 3/4] Update pnor2 to new placement logic --- compiler/pgates/pnor2.py | 76 ++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index fa52c528..15bdba9c 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -5,12 +5,13 @@ # (acting for and on behalf of Oklahoma State University) # All rights reserved. # +import contact import pgate import debug from tech import drc, parameter, spice from vector import vector from globals import OPTS -import contact +import logical_effort from sram_factory import factory class pnor2(pgate.pgate): @@ -38,28 +39,30 @@ class pnor2(pgate.pgate): pgate.pgate.__init__(self, name, height) - def add_pins(self): - """ Adds pins for spice netlist """ - pin_list = ["A", "B", "Z", "vdd", "gnd"] - dir_list = ["INPUT", "INPUT", "OUTPUT", "INOUT", "INOUT"] - self.add_pin_list(pin_list, dir_list) - def create_netlist(self): self.add_pins() + self.add_ptx() self.create_ptx() - self.setup_layout_constants() def create_layout(self): """ Calls all functions related to the generation of the layout """ - self.add_supply_rails() - self.add_ptx() + + self.setup_layout_constants() + self.route_supply_rails() + self.place_ptx() self.connect_rails() self.add_well_contacts() self.extend_wells(self.well_pos) self.route_inputs() self.route_output() - def create_ptx(self): + def add_pins(self): + """ Adds pins for spice netlist """ + pin_list = ["A", "B", "Z", "vdd", "gnd"] + dir_list = ["INPUT", "INPUT", "OUTPUT", "INOUT", "INOUT"] + self.add_pin_list(pin_list, dir_list) + + def add_ptx(self): """ Create the PMOS and NMOS transistors. """ self.nmos = factory.create(module_type="ptx", width=self.nmos_width, @@ -104,7 +107,7 @@ class pnor2(pgate.pgate): self.top_bottom_space = max(0.5*self.m1_width + self.m1_space + extra_contact_space, drc("poly_extend_active"), self.poly_space) - def add_supply_rails(self): + def route_supply_rails(self): """ Add vdd/gnd rails to the top and bottom. """ self.add_layout_pin_rect_center(text="gnd", layer="metal1", @@ -116,7 +119,31 @@ class pnor2(pgate.pgate): offset=vector(0.5*self.width,self.height), width=self.width) - def add_ptx(self): + def create_ptx(self): + """ + Add PMOS and NMOS to the layout at the upper-most and lowest position + to provide maximum routing in channel + """ + + self.pmos1_inst=self.add_inst(name="pnor2_pmos1", + mod=self.pmos) + self.connect_inst(["vdd", "A", "net1", "vdd"]) + + self.pmos2_inst = self.add_inst(name="pnor2_pmos2", + mod=self.pmos) + self.connect_inst(["net1", "B", "Z", "vdd"]) + + + self.nmos1_inst=self.add_inst(name="pnor2_nmos1", + mod=self.nmos) + self.connect_inst(["Z", "A", "gnd", "gnd"]) + + self.nmos2_inst=self.add_inst(name="pnor2_nmos2", + mod=self.nmos) + self.connect_inst(["Z", "B", "gnd", "gnd"]) + + + def place_ptx(self): """ Add PMOS and NMOS to the layout at the upper-most and lowest position to provide maximum routing in channel @@ -124,29 +151,16 @@ class pnor2(pgate.pgate): pmos1_pos = vector(self.pmos.active_offset.x, self.height - self.pmos.active_height - self.top_bottom_space) - self.pmos1_inst=self.add_inst(name="pnor2_pmos1", - mod=self.pmos, - offset=pmos1_pos) - self.connect_inst(["vdd", "A", "net1", "vdd"]) + self.pmos1_inst.place(pmos1_pos) self.pmos2_pos = pmos1_pos + self.overlap_offset - self.pmos2_inst = self.add_inst(name="pnor2_pmos2", - mod=self.pmos, - offset=self.pmos2_pos) - self.connect_inst(["net1", "B", "Z", "vdd"]) - + self.pmos2_inst.place(self.pmos2_pos) nmos1_pos = vector(self.pmos.active_offset.x, self.top_bottom_space) - self.nmos1_inst=self.add_inst(name="pnor2_nmos1", - mod=self.nmos, - offset=nmos1_pos) - self.connect_inst(["Z", "A", "gnd", "gnd"]) - + self.nmos1_inst.place(nmos1_pos) + self.nmos2_pos = nmos1_pos + self.overlap_offset - self.nmos2_inst=self.add_inst(name="pnor2_nmos2", - mod=self.nmos, - offset=self.nmos2_pos) - self.connect_inst(["Z", "B", "gnd", "gnd"]) + self.nmos2_inst.place(self.nmos2_pos) # Output position will be in between the PMOS and NMOS self.output_pos = vector(0,0.5*(pmos1_pos.y+nmos1_pos.y+self.nmos.active_height)) From 275891084b744b8d8b34b40ab2b350945c48c236 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 7 Aug 2019 16:33:29 -0700 Subject: [PATCH 4/4] Add pand3 --- compiler/pgates/pand3.py | 138 ++++++++++++++++++++++++++++++++ compiler/tests/04_pand3_test.py | 38 +++++++++ 2 files changed, 176 insertions(+) create mode 100644 compiler/pgates/pand3.py create mode 100755 compiler/tests/04_pand3_test.py diff --git a/compiler/pgates/pand3.py b/compiler/pgates/pand3.py new file mode 100644 index 00000000..b221ad84 --- /dev/null +++ b/compiler/pgates/pand3.py @@ -0,0 +1,138 @@ +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import debug +from tech import drc +from math import log +from vector import vector +from globals import OPTS +import pgate +from sram_factory import factory + +class pand3(pgate.pgate): + """ + This is a simple buffer used for driving loads. + """ + def __init__(self, name, size=1, height=None): + debug.info(1, "Creating pand3 {}".format(name)) + self.add_comment("size: {}".format(size)) + + self.size = size + + # Creates the netlist and layout + pgate.pgate.__init__(self, name, height) + + def create_netlist(self): + self.add_pins() + self.create_modules() + self.create_insts() + + def create_modules(self): + # Shield the cap, but have at least a stage effort of 4 + self.nand = factory.create(module_type="pnand3",height=self.height) + self.add_mod(self.nand) + + self.inv = factory.create(module_type="pinv", size=self.size, height=self.height) + self.add_mod(self.inv) + + def create_layout(self): + self.width = self.nand.width + self.inv.width + self.place_insts() + self.add_wires() + self.add_layout_pins() + self.DRC_LVS() + + def add_pins(self): + self.add_pin("A", "INPUT") + self.add_pin("B", "INPUT") + self.add_pin("C", "INPUT") + self.add_pin("Z", "OUTPUT") + self.add_pin("vdd", "POWER") + self.add_pin("gnd", "GROUND") + + def create_insts(self): + self.nand_inst=self.add_inst(name="pand3_nand", + mod=self.nand) + self.connect_inst(["A", "B", "C", "zb_int", "vdd", "gnd"]) + + self.inv_inst=self.add_inst(name="pand3_inv", + mod=self.inv) + self.connect_inst(["zb_int", "Z", "vdd", "gnd"]) + + def place_insts(self): + # Add NAND to the right + self.nand_inst.place(offset=vector(0,0)) + + # Add INV to the right + self.inv_inst.place(offset=vector(self.nand_inst.rx(),0)) + + def add_wires(self): + # nand Z to inv A + z1_pin = self.nand_inst.get_pin("Z") + a2_pin = self.inv_inst.get_pin("A") + mid1_point = vector(0.5*(z1_pin.cx()+a2_pin.cx()), z1_pin.cy()) + mid2_point = vector(mid1_point, a2_pin.cy()) + self.add_path("metal1", [z1_pin.center(), mid1_point, mid2_point, a2_pin.center()]) + + + def add_layout_pins(self): + # Continous vdd rail along with label. + vdd_pin=self.inv_inst.get_pin("vdd") + self.add_layout_pin(text="vdd", + layer="metal1", + offset=vdd_pin.ll().scale(0,1), + width=self.width, + height=vdd_pin.height()) + + # Continous gnd rail along with label. + gnd_pin=self.inv_inst.get_pin("gnd") + self.add_layout_pin(text="gnd", + layer="metal1", + offset=gnd_pin.ll().scale(0,1), + width=self.width, + height=vdd_pin.height()) + + pin = self.inv_inst.get_pin("Z") + self.add_layout_pin_rect_center(text="Z", + layer=pin.layer, + offset=pin.center(), + width=pin.width(), + height=pin.height()) + + for pin_name in ["A","B", "C"]: + pin = self.nand_inst.get_pin(pin_name) + self.add_layout_pin_rect_center(text=pin_name, + layer=pin.layer, + offset=pin.center(), + width=pin.width(), + height=pin.height()) + + + + def analytical_delay(self, corner, slew, load=0.0): + """ Calculate the analytical delay of DFF-> INV -> INV """ + nand_delay = self.nand.analytical_delay(corner, slew=slew, load=self.inv.input_load()) + inv_delay = self.inv.analytical_delay(corner, slew=nand_delay.slew, load=load) + return nand_delay + inv_delay + + def get_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_stage_effort(stage1_cout, inp_is_rise) + stage_effort_list.append(stage1) + last_stage_is_rise = stage1.is_rise + + stage2 = self.inv.get_stage_effort(external_cout, last_stage_is_rise) + stage_effort_list.append(stage2) + + return stage_effort_list + + def get_cin(self): + """Return the relative input capacitance of a single input""" + return self.nand.get_cin() + diff --git a/compiler/tests/04_pand3_test.py b/compiler/tests/04_pand3_test.py new file mode 100755 index 00000000..4408f6e8 --- /dev/null +++ b/compiler/tests/04_pand3_test.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 +# See LICENSE for licensing information. +# +# Copyright (c) 2016-2019 Regents of the University of California and The Board +# of Regents for the Oklahoma Agricultural and Mechanical College +# (acting for and on behalf of Oklahoma State University) +# All rights reserved. +# +import unittest +from testutils import * +import sys,os +sys.path.append(os.getenv("OPENRAM_HOME")) +import globals +from globals import OPTS +from sram_factory import factory +import debug + +class pand3_test(openram_test): + + def runTest(self): + globals.init_openram("config_{0}".format(OPTS.tech_name)) + global verify + import verify + + import pand3 + + debug.info(2, "Testing pand3 gate 4x") + a = pand3.pand3(name="pand3x4", size=4) + self.local_check(a) + + 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(testRunner=debugTestRunner())