diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index 24237e4f..e4b966ca 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -56,8 +56,6 @@ class bank(design.design): self.add_modules() self.setup_layout_constraints() - self.add_power_ring(self.core_bbox) - # FIXME: Move this to the add modules function self.add_bank_select() @@ -451,6 +449,7 @@ class bank(design.design): temp = [] temp.extend(self.input_control_signals) + temp.append("bank_sel") temp.extend(self.control_signals) temp.extend(["vdd", "gnd"]) self.connect_inst(temp) @@ -488,39 +487,41 @@ class bank(design.design): #the column decoder (if there is one) or the tristate output #driver. # Leave room for the output below the tri gate. - tri_gate_min_point = self.tri_gate_array_inst.by() - 3*self.m2_pitch - row_decoder_min_point = self.row_decoder_inst.by() + tri_gate_min_y_offset = self.tri_gate_array_inst.by() - 3*self.m2_pitch + row_decoder_min_y_offset = self.row_decoder_inst.by() if self.col_addr_size > 0: - col_decoder_min_point = self.col_decoder_inst.by() + col_decoder_min_y_offset = self.col_decoder_inst.by() else: - col_decoder_min_point = row_decoder_min_point + col_decoder_min_y_offset = row_decoder_min_y_offset if self.num_banks>1: # The control gating logic is below the decoder # Min of the control gating logic and tri gate. - self.min_point = min(col_decoder_min_point - self.bank_select.height, tri_gate_min_point) + self.min_y_offset = min(col_decoder_min_y_offset - self.bank_select.height, tri_gate_min_y_offset) else: # Just the min of the decoder logic logic and tri gate. - self.min_point = min(col_decoder_min_point, tri_gate_min_point) + self.min_y_offset = min(col_decoder_min_y_offset, tri_gate_min_y_offset) # The max point is always the top of the precharge bitlines # Add a vdd and gnd power rail above the array - self.max_point = self.precharge_array_inst.uy() + 3*self.m1_width + self.max_y_offset = self.precharge_array_inst.uy() + 3*self.m1_width + self.max_x_offset = self.bitcell_array_inst.ur().x + 3*self.m1_width + self.min_x_offset = self.row_decoder_inst.lx() + # Create the core bbox for the power rings - ur = vector(self.bitcell_array_inst.ur().x + 3*self.m1_width, self.max_point) - ll = vector(self.row_decoder_inst.lx(), self.min_point) + ur = vector(self.max_x_offset, self.max_y_offset) + ll = vector(self.min_x_offset, self.min_y_offset) self.core_bbox = [ll, ur] - + self.add_power_ring(self.core_bbox) + # Compute the vertical rail positions for later use - self.right_gnd_x_offset = ur.x + self.right_gnd_x_offset = self.right_gnd_x_center - 0.5*self.supply_rail_pitch self.right_vdd_x_offset = self.right_gnd_x_offset + self.supply_rail_pitch - self.left_vdd_x_offset = ll.x - self.supply_rail_pitch + self.left_vdd_x_offset = self.left_gnd_x_center - 0.5*self.supply_rail_pitch self.left_gnd_x_offset = self.left_vdd_x_offset - self.supply_rail_pitch - - # Add a vdd and gnd power rail below the array - self.min_point -= 2*self.supply_rail_pitch - # Add a vdd and gnd power rail above the array - self.max_point += self.supply_rail_pitch + self.supply_rail_width + + # Have the pins go below the vdd and gnd power rail at the bottom + self.min_y_offset -= 2*self.supply_rail_pitch self.height = ur.y - ll.y + 4*self.supply_rail_pitch self.width = ur.x - ll.x + 4*self.supply_rail_pitch @@ -547,9 +548,9 @@ class bank(design.design): self.bus_xoffset[self.control_signals[i]]=x_offset + 0.5*self.m2_width # Pins are added later if this is a single bank, so just add rectangle now self.add_rect(layer="metal2", - offset=vector(x_offset, self.min_point), + offset=vector(x_offset, self.min_y_offset), width=self.m2_width, - height=self.height) + height=self.max_y_offset-self.min_y_offset) @@ -606,12 +607,12 @@ class bank(design.design): """ Metal 3 routing of tri_gate output data """ for i in range(self.word_size): tri_gate_out_position = self.tri_gate_array_inst.get_pin("out[{}]".format(i)).ul() - data_line_position = vector(tri_gate_out_position.x, self.min_point) + data_line_position = vector(tri_gate_out_position.x, self.min_y_offset) self.add_via(("metal2", "via2", "metal3"), data_line_position) self.add_rect(layer="metal3", offset=data_line_position, width=drc["minwidth_metal3"], - height=tri_gate_out_position.y - self.min_point) + height=tri_gate_out_position.y - self.min_y_offset) self.add_layout_pin(text="DATA[{}]".format(i), layer="metal2", offset=data_line_position, @@ -620,12 +621,12 @@ class bank(design.design): def route_row_decoder(self): """ Routes the row decoder inputs and supplies """ - # # Create inputs for the row address lines - # for i in range(self.row_addr_size): - # addr_idx = i + self.col_addr_size - # decoder_name = "A[{}]".format(i) - # addr_name = "A[{}]".format(addr_idx) - # self.copy_layout_pin(self.row_decoder_inst, decoder_name, addr_name) + # Create inputs for the row address lines + for i in range(self.row_addr_size): + addr_idx = i + self.col_addr_size + decoder_name = "A[{}]".format(i) + addr_name = "A[{}]".format(addr_idx) + self.copy_layout_pin(self.row_decoder_inst, decoder_name, addr_name) # Route the power and ground, but only BELOW the y=0 since the @@ -909,15 +910,15 @@ class bank(design.design): # it's not an input pin if we have multiple banks self.add_label_pin(text=ctrl, layer="metal2", - offset=vector(x_offset, self.min_point), + offset=vector(x_offset, self.min_y_offset), width=self.m2_width, - height=self.height) + height=self.max_y_offset-self.min_y_offset) else: self.add_layout_pin(text=ctrl, layer="metal2", - offset=vector(x_offset, self.min_point), + offset=vector(x_offset, self.min_y_offset), width=self.m2_width, - height=self.height) + height=self.max_y_offset-self.min_y_offset) def connect_rail_from_right(self,inst, pin, rail): diff --git a/compiler/modules/bank_select.py b/compiler/modules/bank_select.py index 31aa0a8a..45a9b0ec 100644 --- a/compiler/modules/bank_select.py +++ b/compiler/modules/bank_select.py @@ -26,6 +26,7 @@ class bank_select(design.design): self.control_signals = ["gated_"+str for str in self.input_control_signals] self.add_pin_list(self.input_control_signals, "INPUT") + self.add_pin("bank_sel") self.add_pin_list(self.control_signals, "OUTPUT") self.add_pin("vdd","POWER") self.add_pin("gnd","GROUND") diff --git a/compiler/modules/dff_inv.py b/compiler/modules/dff_inv.py new file mode 100644 index 00000000..44bdadf5 --- /dev/null +++ b/compiler/modules/dff_inv.py @@ -0,0 +1,128 @@ +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_inv(design.design): + """ + This is a simple DFF with an inverted output. Some DFFs + do not have Qbar, so this will create it. + """ + + def __init__(self, inv_size=1, name=""): + + if name=="": + name = "dff_inv_{0}".format(inv_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=inv_size,height=self.dff.height) + self.add_mod(self.inv1) + + self.width = self.dff.width + self.inv1.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_inv_dff", + mod=self.dff, + offset=vector(0,0)) + self.connect_inst(["D", "Q", "clk", "vdd", "gnd"]) + + # Add INV1 to the right + self.inv1_inst=self.add_inst(name="dff_inv_inv1", + mod=self.inv1, + offset=vector(self.dff_inst.rx(),0)) + self.connect_inst(["Q", "Qb", "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()) + + + 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.dff_inst.get_pin("Q") + self.add_layout_pin_center_rect(text="Q", + layer=dout_pin.layer, + offset=dout_pin.center()) + + dout_pin = self.inv1_inst.get_pin("Z") + self.add_layout_pin_center_rect(text="Qb", + layer="metal2", + offset=dout_pin.center()) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=dout_pin.center()) + + + + 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=load) + return dff_delay + inv1_delay + diff --git a/compiler/modules/dff_inv_array.py b/compiler/modules/dff_inv_array.py new file mode 100644 index 00000000..a4cdc92e --- /dev/null +++ b/compiler/modules/dff_inv_array.py @@ -0,0 +1,180 @@ +import debug +import design +from tech import drc +from math import log +from vector import vector +from globals import OPTS +import dff_inv + +class dff_inv_array(design.design): + """ + This is a simple row (or multiple rows) of flops. + Unlike the data flops, these are never spaced out. + """ + + def __init__(self, rows, columns, inv_size=2, name=""): + self.rows = rows + self.columns = columns + + if name=="": + name = "dff_array_{0}x{1}".format(rows, columns) + design.design.__init__(self, name) + debug.info(1, "Creating {}".format(self.name)) + + self.dff = dff_inv.dff_inv(inv_size) + self.add_mod(self.dff) + + self.width = self.columns * self.dff.width + self.height = self.rows * self.dff.height + + self.create_layout() + + def create_layout(self): + self.add_pins() + self.create_dff_array() + self.add_layout_pins() + self.DRC_LVS() + + def add_pins(self): + for y in range(self.rows): + for x in range(self.columns): + self.add_pin(self.get_din_name(y,x)) + for y in range(self.rows): + for x in range(self.columns): + self.add_pin(self.get_dout_name(y,x)) + self.add_pin(self.get_dout_bar_name(y,x)) + self.add_pin("clk") + self.add_pin("vdd") + self.add_pin("gnd") + + def create_dff_array(self): + self.dff_insts={} + for y in range(self.rows): + for x in range(self.columns): + name = "Xdff_r{0}_c{1}".format(y,x) + if (y % 2 == 0): + base = vector(x*self.dff.width,y*self.dff.height) + mirror = "R0" + else: + base = vector(x*self.dff.width,(y+1)*self.dff.height) + mirror = "MX" + self.dff_insts[x,y]=self.add_inst(name=name, + mod=self.dff, + offset=base, + mirror=mirror) + self.connect_inst([self.get_din_name(y,x), + self.get_dout_name(y,x), + self.get_dout_bar_name(y,x), + "clk", + "vdd", + "gnd"]) + + def get_din_name(self, row, col): + if self.columns == 1: + din_name = "din[{0}]".format(row) + elif self.rows == 1: + din_name = "din[{0}]".format(col) + else: + din_name = "din[{0}][{1}]".format(row,col) + + return din_name + + def get_dout_name(self, row, col): + if self.columns == 1: + dout_name = "dout[{0}]".format(row) + elif self.rows == 1: + dout_name = "dout[{0}]".format(col) + else: + dout_name = "dout[{0}][{1}]".format(row,col) + + return dout_name + + def get_dout_bar_name(self, row, col): + if self.columns == 1: + dout_bar_name = "dout_bar[{0}]".format(row) + elif self.rows == 1: + dout_bar_name = "dout_bar[{0}]".format(col) + else: + dout_bar_name = "dout_bar[{0}][{1}]".format(row,col) + + return dout_bar_name + + def add_layout_pins(self): + + for y in range(self.rows): + # Continous vdd rail along with label. + vdd_pin=self.dff_insts[0,y].get_pin("vdd") + self.add_layout_pin(text="vdd", + layer="metal1", + offset=vdd_pin.ll(), + width=self.width, + height=self.m1_width) + + # Continous gnd rail along with label. + gnd_pin=self.dff_insts[0,y].get_pin("gnd") + self.add_layout_pin(text="gnd", + layer="metal1", + offset=gnd_pin.ll(), + width=self.width, + height=self.m1_width) + + + for y in range(self.rows): + for x in range(self.columns): + din_pin = self.dff_insts[x,y].get_pin("D") + debug.check(din_pin.layer=="metal2","DFF D pin not on metal2") + self.add_layout_pin(text=self.get_din_name(y,x), + layer=din_pin.layer, + offset=din_pin.ll(), + width=din_pin.width(), + height=din_pin.height()) + + dout_pin = self.dff_insts[x,y].get_pin("Q") + debug.check(dout_pin.layer=="metal2","DFF Q pin not on metal2") + self.add_layout_pin(text=self.get_dout_name(y,x), + layer=dout_pin.layer, + offset=dout_pin.ll(), + width=dout_pin.width(), + height=dout_pin.height()) + + + dout_bar_pin = self.dff_insts[x,y].get_pin("Qb") + debug.check(dout_bar_pin.layer=="metal2","DFF Qb pin not on metal2") + self.add_layout_pin(text=self.get_dout_bar_name(y,x), + layer=dout_bar_pin.layer, + offset=dout_bar_pin.ll(), + width=dout_bar_pin.width(), + height=dout_bar_pin.height()) + + + # Create vertical spines to a single horizontal rail + clk_pin = self.dff_insts[0,0].get_pin("clk") + debug.check(clk_pin.layer=="metal2","DFF clk pin not on metal2") + if self.columns==1: + self.add_layout_pin(text="clk", + layer="metal2", + offset=clk_pin.ll().scale(1,0), + width=self.m2_width, + height=self.height) + else: + self.add_layout_pin(text="clk", + layer="metal3", + offset=vector(0,0), + width=self.width, + height=self.m3_width) + for x in range(self.columns): + clk_pin = self.dff_insts[x,0].get_pin("clk") + # Make a vertical strip for each column + self.add_layout_pin(text="clk", + layer="metal2", + offset=clk_pin.ll().scale(1,0), + width=self.m2_width, + height=self.height) + # Drop a via to the M3 pin + self.add_via_center(layers=("metal2","via2","metal3"), + offset=clk_pin.center().scale(1,0)) + + + + def analytical_delay(self, slew, load=0.0): + return self.dff.analytical_delay(slew=slew, load=load) diff --git a/compiler/options.py b/compiler/options.py index 946d76cc..7c419990 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -59,7 +59,8 @@ class options(optparse.Values): ms_flop = "ms_flop" ms_flop_array = "ms_flop_array" dff = "dff" - dff_array = "dff_buf_array" + dff_array = "dff_array" + dff_buf_array = "dff_buf_array" control_logic = "control_logic" bitcell_array = "bitcell_array" sense_amp = "sense_amp" diff --git a/compiler/pgates/pinvbuf.py b/compiler/pgates/pinvbuf.py index fcb137dc..dd7ff37f 100644 --- a/compiler/pgates/pinvbuf.py +++ b/compiler/pgates/pinvbuf.py @@ -11,21 +11,23 @@ class pinvbuf(design.design): This is a simple inverter/buffer used for driving loads. It is used in the column decoder for 1:2 decoding and as the clock buffer. """ + c = reload(__import__(OPTS.bitcell)) + bitcell = getattr(c, OPTS.bitcell) - def __init__(self, inv1_size=2, inv2_size=4, name=""): + def __init__(self, inv1_size=2, inv2_size=4, height=bitcell.height, name=""): if name=="": name = "pinvbuf_{0}_{1}".format(inv1_size, inv2_size) design.design.__init__(self, name) debug.info(1, "Creating {}".format(self.name)) - self.inv = pinv(size=1) + self.inv = pinv(size=1, height=height) self.add_mod(self.inv) - self.inv1 = pinv(size=inv1_size) + self.inv1 = pinv(size=inv1_size, height=height) self.add_mod(self.inv1) - self.inv2 = pinv(size=inv2_size) + self.inv2 = pinv(size=inv2_size, height=height) self.add_mod(self.inv2) self.width = 2*self.inv1.width + self.inv2.width diff --git a/compiler/sram.py b/compiler/sram.py index 5dd27885..e05cd3be 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -219,18 +219,17 @@ class sram(design.design): # 3/5/18 MRG: Cannot reference positions inside submodules because boundaries # are not recomputed using instance placement. So, place the control logic such that it aligns # with the top of the SRAM. - control_gap = 2*self.m3_width - control_pos = vector(-self.control_logic.width-control_gap, - self.bank.height-self.control_logic.height-3*self.supply_rail_width) + control_pos = vector(-self.control_logic.width - self.m3_pitch, + self.bank.height - self.control_logic.height - 3*self.supply_rail_width) self.add_control_logic(position=control_pos) # Leave room for the control routes to the left of the flops addr_pos = vector(self.control_logic_inst.lx() + 4*self.m2_pitch, 3*self.supply_rail_pitch) - self.add_control_addr_dff(addr_pos) + self.add_addr_dff(addr_pos) - self.width = self.bank.width + self.control_logic.height + control_gap - self.height = self.bank.height + self.width = self.bank.width + self.control_logic.width + 2*self.supply_rail_pitch + self.height = self.bank.height + 2*self.supply_rail_pitch def route_shared_banks(self): @@ -933,7 +932,7 @@ class sram(design.design): return line_positions - def add_control_addr_dff(self, position): + def add_addr_dff(self, position): """ Add and place address and control flops """ self.addr_dff_inst = self.add_inst(name="address", mod=self.addr_dff, @@ -945,7 +944,7 @@ class sram(design.design): inputs.append("ADDR[{}]".format(i)) outputs.append("A[{}]".format(i)) - self.connect_inst(inputs + outputs + ["clk", "vdd", "gnd"]) + self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"]) def add_control_logic(self, position): """ Add and place control logic """ @@ -989,9 +988,6 @@ class sram(design.design): for i in range(self.addr_size): self.copy_layout_pin(self.addr_dff_inst, "din[{}]".format(i),"ADDR[{}]".format(i)) - self.copy_layout_pin(self.addr_dff_inst, "clk") - - # Power ring contains the power pins def add_two_banks(self): # Placement of bank 0 (left) @@ -1083,10 +1079,8 @@ class sram(design.design): self.copy_layout_pin(self.control_logic_inst, n.lower(), n) # Connect the clock between the flops and control module - # FIXME: Buffered clock should drive the flops, but then - # it would change the setup time... flop_pin = self.addr_dff_inst.get_pin("clk") - ctrl_pin = self.control_logic_inst.get_pin("clk") + ctrl_pin = self.control_logic_inst.get_pin("clk_buf") flop_pos = flop_pin.uc() ctrl_pos = ctrl_pin.bc() mid_ypos = 0.5*(ctrl_pos.y+flop_pos.y) @@ -1109,7 +1103,7 @@ class sram(design.design): self.add_path("metal1", [left_rail_pos, vdd_pos]) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=left_rail_pos, - size = (1,3), + size = (1,self.supply_vias), rotate=90) # Route the vdd rails to the TOP @@ -1121,7 +1115,7 @@ class sram(design.design): self.add_path("metal2", [top_rail_pos, vdd_pos]) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=top_rail_pos, - size = (1,3)) + size = (1,self.supply_vias)) def route_single_bank_gnd(self): @@ -1138,7 +1132,7 @@ class sram(design.design): self.add_path("metal1", [left_rail_pos, gnd_pos]) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=left_rail_pos, - size = (1,3), + size = (1,self.supply_vias), rotate=90) # Route the vdd rails to the TOP @@ -1150,7 +1144,7 @@ class sram(design.design): self.add_path("metal2", [top_rail_pos, gnd_pos]) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=top_rail_pos, - size = (1,3)) + size = (1,self.supply_vias)) def sp_write(self, sp_name): diff --git a/compiler/tests/11_dff_inv_array_test.py b/compiler/tests/11_dff_inv_array_test.py new file mode 100644 index 00000000..48a37f9e --- /dev/null +++ b/compiler/tests/11_dff_inv_array_test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python2.7 +""" +Run a regresion test on a dff_array. +""" + +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_inv_array_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_inv_array + + debug.info(2, "Testing dff_inv_array for 3x3") + a = dff_inv_array.dff_inv_array(rows=3, columns=3) + self.local_check(a) + + debug.info(2, "Testing dff_inv_array for 1x3") + a = dff_inv_array.dff_inv_array(rows=1, columns=3) + self.local_check(a) + + debug.info(2, "Testing dff_inv_array for 3x1") + a = dff_inv_array.dff_inv_array(rows=3, columns=1) + 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/compiler/tests/11_dff_inv_test.py b/compiler/tests/11_dff_inv_test.py new file mode 100644 index 00000000..f50845b8 --- /dev/null +++ b/compiler/tests/11_dff_inv_test.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python2.7 +""" +Run a regresion test on a dff_inv. +""" + +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_inv_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_inv + + debug.info(2, "Testing dff_inv 4x") + a = dff_inv.dff_inv(4) + 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/compiler/verify/magic.py b/compiler/verify/magic.py index 37e5f1b0..8207d373 100644 --- a/compiler/verify/magic.py +++ b/compiler/verify/magic.py @@ -135,7 +135,6 @@ def write_netgen_script(cell_name, sp_name): # This circuit has symmetries and needs to be flattened to resolve them or the banks won't pass # Is there a more elegant way to add this when needed? f.write("flatten class {{{0}.spice precharge_array}}\n".format(cell_name)) - f.write("flatten class {{{0}.spice dff_array}}\n".format(cell_name)) f.write("property {{nfet {0}.spice}} remove as ad ps pd\n".format(cell_name)) f.write("property {{pfet {0}.spice}} remove as ad ps pd\n".format(cell_name)) f.write("property {{n {0}}} remove as ad ps pd\n".format(sp_name))