From 97c08bce959733e76218e4758e785e4d8fa49807 Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Wed, 21 Mar 2018 13:20:48 -0700 Subject: [PATCH] Add dffs to control logic. Rename layout pin segment/rect functions for consistency. Redo gnd/vdd pins in control. Shift s_en buffers even with other cells. --- compiler/base/geometry.py | 8 ++ compiler/base/hierarchy_layout.py | 4 +- compiler/modules/bank.py | 2 +- compiler/modules/bank_select.py | 8 +- compiler/modules/control_logic.py | 177 ++++++++++------------------ compiler/modules/delay_chain.py | 2 +- compiler/modules/dff_buf.py | 22 ++-- compiler/modules/dff_inv.py | 22 ++-- compiler/modules/precharge.py | 2 +- compiler/modules/replica_bitline.py | 125 ++++++++++++-------- compiler/modules/wordline_driver.py | 4 +- compiler/options.py | 2 - compiler/pgates/pgate.py | 4 +- compiler/pgates/pinv.py | 10 +- compiler/pgates/pinvbuf.py | 6 +- compiler/pgates/pnand2.py | 6 +- compiler/pgates/pnand3.py | 6 +- compiler/pgates/pnor2.py | 8 +- compiler/pgates/ptx.py | 10 +- compiler/sram.py | 19 +-- 20 files changed, 215 insertions(+), 232 deletions(-) diff --git a/compiler/base/geometry.py b/compiler/base/geometry.py index 22915e3c..7860e83c 100644 --- a/compiler/base/geometry.py +++ b/compiler/base/geometry.py @@ -110,6 +110,14 @@ class geometry: """ Return the right edge """ return self.boundary[1].x + def cx(self): + """ Return the center x """ + return 0.5*(self.boundary[0].x + self.boundary[1].x) + + def cy(self): + """ Return the center y """ + return 0.5*(self.boundary[0].y + self.boundary[1].y) + class instance(geometry): """ diff --git a/compiler/base/hierarchy_layout.py b/compiler/base/hierarchy_layout.py index fb5f4225..010680d6 100644 --- a/compiler/base/hierarchy_layout.py +++ b/compiler/base/hierarchy_layout.py @@ -204,7 +204,7 @@ class layout(lef.lef): new_name = pin.name self.add_layout_pin(new_name, pin.layer, pin.ll(), pin.width(), pin.height()) - def add_layout_pin_center_segment(self, text, layer, start, end): + def add_layout_pin_segment_center(self, text, layer, start, end): """ Creates a path like pin with center-line convention """ debug.check(start.x==end.x or start.y==end.y,"Cannot have a non-manhatten layout pin.") @@ -228,7 +228,7 @@ class layout(lef.lef): return self.add_layout_pin(text, layer, ll_offset, width, height) - def add_layout_pin_center_rect(self, text, layer, offset, width=None, height=None): + def add_layout_pin_rect_center(self, text, layer, offset, width=None, height=None): """ Creates a path like pin with center-line convention """ if width==None: width=drc["minwidth_{0}".format(layer)] diff --git a/compiler/modules/bank.py b/compiler/modules/bank.py index e4b966ca..32c596aa 100644 --- a/compiler/modules/bank.py +++ b/compiler/modules/bank.py @@ -458,7 +458,7 @@ class bank(design.design): """ Route the bank select logic. """ for input_name in self.input_control_signals+["bank_sel"]: in_pos = self.bank_select_inst.get_pin(input_name).lc() - self.add_layout_pin_center_segment(text=input_name, + self.add_layout_pin_segment_center(text=input_name, layer="metal3", start=vector(self.left_gnd_x_offset,in_pos.y), end=in_pos) diff --git a/compiler/modules/bank_select.py b/compiler/modules/bank_select.py index 45a9b0ec..2eae7610 100644 --- a/compiler/modules/bank_select.py +++ b/compiler/modules/bank_select.py @@ -151,7 +151,7 @@ class bank_select(design.design): # Route the pin to the left edge as well bank_sel_pin_pos=vector(0, 0) bank_sel_pin_end=vector(bank_sel_line_pos.x, bank_sel_pin_pos.y) - self.add_layout_pin_center_segment(text="bank_sel", + self.add_layout_pin_segment_center(text="bank_sel", layer="metal3", start=bank_sel_pin_pos, end=bank_sel_pin_end) @@ -208,7 +208,7 @@ class bank_select(design.design): self.add_via_center(layers=("metal2", "via2", "metal3"), offset=logic_pos, rotate=90) - self.add_layout_pin_center_segment(text=input_name, + self.add_layout_pin_segment_center(text=input_name, layer="metal3", start=input_pos, end=logic_pos) @@ -224,14 +224,14 @@ class bank_select(design.design): # Add vdd/gnd supply rails gnd_pin = inv_inst.get_pin("gnd") left_gnd_pos = vector(0, gnd_pin.cy()) - self.add_layout_pin_center_segment(text="gnd", + self.add_layout_pin_segment_center(text="gnd", layer="metal1", start=left_gnd_pos, end=gnd_pin.rc()) vdd_pin = inv_inst.get_pin("vdd") left_vdd_pos = vector(0, vdd_pin.cy()) - self.add_layout_pin_center_segment(text="vdd", + self.add_layout_pin_segment_center(text="vdd", layer="metal1", start=left_vdd_pos, end=vdd_pin.rc()) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index 4d6703e4..d168f636 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -7,6 +7,8 @@ from pinv import pinv from pnand2 import pnand2 from pnand3 import pnand3 from pinvbuf import pinvbuf +from dff_inv import dff_inv +from dff_inv_array import dff_inv_array import math from vector import vector from globals import OPTS @@ -28,15 +30,15 @@ class control_logic(design.design): def create_layout(self): """ Create layout and route between modules """ self.setup_layout_offsets() + self.add_pins() self.create_modules() self.add_rails() self.add_modules() self.add_routing() - - def create_modules(self): - """ add all the required modules """ + def add_pins(self): + """ Add the pins to the control logic module. """ for pin in self.input_list + ["clk"]: self.add_pin(pin,"INPUT") for pin in self.output_list: @@ -44,19 +46,28 @@ class control_logic(design.design): self.add_pin("vdd","POWER") self.add_pin("gnd","GROUND") - self.nand2 = pnand2() + def create_modules(self): + """ add all the required modules """ + + dff = dff_inv() + dff_height = dff.height + + self.ctrl_dff_array = dff_inv_array(rows=3,columns=1) + self.add_mod(self.ctrl_dff_array) + + self.nand2 = pnand2(height=dff_height) self.add_mod(self.nand2) - self.nand3 = pnand3() + self.nand3 = pnand3(height=dff_height) self.add_mod(self.nand3) # Special gates: inverters for buffering - self.clkbuf = pinvbuf(4,16) + self.clkbuf = pinvbuf(4,16,height=dff_height) self.add_mod(self.clkbuf) - self.inv = self.inv1 = pinv(1) + self.inv = self.inv1 = pinv(size=1, height=dff_height) self.add_mod(self.inv1) - self.inv2 = pinv(2) + self.inv2 = pinv(size=4, height=dff_height) self.add_mod(self.inv2) - self.inv8 = pinv(8) + self.inv8 = pinv(size=16, height=dff_height) self.add_mod(self.inv8) c = reload(__import__(OPTS.replica_bitline)) @@ -82,10 +93,13 @@ class control_logic(design.design): # Some cells may have pwell/nwell spacing problems too when the wells are different heights. #self.cell_gap = max(self.m2_pitch,drc["pwell_to_nwell"]) + # List of input control signals self.input_list =["csb","web","oeb"] - self.input_width = len(self.input_list)*self.m2_pitch - self.input_bar_list = ["clk_buf_bar", "we", "cs", "oe"] - self.input_bar_width = len(self.input_bar_list)*self.m2_pitch + self.dff_output_list =["cs_bar", "cs", "we_bar", "we", "oe_bar", "oe"] + # list of output control signals (for making a vertical bus) + self.internal_list = ["clk_buf", "clk_buf_bar", "we", "cs", "oe"] + self.internal_width = len(self.internal_list)*self.m2_pitch + # Ooutputs to the bank self.output_list = ["s_en", "w_en", "tri_en", "tri_en_bar", "clk_buf_bar", "clk_buf"] self.supply_list = ["vdd", "gnd"] self.rail_width = len(self.input_list)*len(self.output_list)*self.m2_pitch @@ -95,22 +109,11 @@ class control_logic(design.design): #self.replica_bitline_gap = 2*self.m2_pitch def add_rails(self): - """ Add the input signal tracks and their inverted tracks """ - height = 4*self.inv1.height - self.m2_pitch - for i in range(len(self.input_list)): - name = self.input_list[i] - offset = vector(i*self.m2_pitch,0) - self.add_layout_pin(text=name, - layer="metal2", - offset=offset, - width=drc["minwidth_metal2"], - height=height) - self.rail_x_offsets[name]=offset.x + 0.5*drc["minwidth_metal2"] # center offset - + """ Add the input signal inverted tracks """ height = 6*self.inv1.height - self.m2_pitch - for i in range(len(self.input_bar_list)): - name = self.input_bar_list[i] - offset = vector(i*self.m2_pitch + self.input_width + self.inv1.width, 0) + for i in range(len(self.internal_list)): + name = self.internal_list[i] + offset = vector(i*self.m2_pitch + self.ctrl_dff_array.width, 0) # just for LVS correspondence... self.add_label_pin(text=name, layer="metal2", @@ -122,8 +125,7 @@ class control_logic(design.design): def add_modules(self): """ Place all the modules """ - self.add_input_inv() - + self.add_dffs() self.add_clk_buffer(row=0) self.add_we_row(row=2) self.add_trien_row(row=3) @@ -146,7 +148,7 @@ class control_logic(design.design): def add_routing(self): """ Routing between modules """ - self.route_input_inv() + self.route_dffs() self.route_trien() self.route_trien_bar() self.route_rblk() @@ -171,7 +173,7 @@ class control_logic(design.design): def add_clk_buffer(self,row): """ Add the multistage clock buffer below the control flops """ - x_off = self.input_width + self.inv1.width + self.input_bar_width + x_off = self.ctrl_dff_array.width + self.internal_width y_off = row*self.inv1.height if row % 2: y_off += self.clkbuf.height @@ -189,7 +191,7 @@ class control_logic(design.design): def add_rblk_row(self,row): - x_off = self.input_width + self.inv1.width + self.input_bar_width + x_off = self.ctrl_dff_array.width + self.internal_width y_off = row*self.inv1.height if row % 2: y_off += self.inv1.height @@ -221,7 +223,7 @@ class control_logic(design.design): def add_sen_row(self,row): """ The sense enable buffer gets placed to the far right of the row. """ - x_off = self.replica_bitline.width - self.inv8.width + x_off = self.ctrl_dff_array.width + self.internal_width y_off = row*self.inv1.height if row % 2: y_off += self.inv1.height @@ -249,7 +251,7 @@ class control_logic(design.design): self.row_sen_end_x = self.replica_bitline.width def add_trien_row(self, row): - x_off = self.input_width + self.inv1.width + self.input_bar_width + x_off = self.ctrl_dff_array.width + self.internal_width y_off = row*self.inv1.height if row % 2: y_off += self.inv1.height @@ -293,7 +295,7 @@ class control_logic(design.design): def add_trien_bar_row(self, row): - x_off = self.input_width + self.inv1.width + self.input_bar_width + x_off = self.ctrl_dff_array.width + self.internal_width y_off = row*self.inv1.height if row % 2: y_off += self.inv1.height @@ -334,55 +336,34 @@ class control_logic(design.design): self.row_trien_bar_end_x = x_off - def route_input_inv(self): + def route_dffs(self): """ Route the input inverters """ - self.connect_rail_from_left(self.cs_inv,"A","csb") - self.connect_rail_from_left(self.we_inv,"A","web") - self.connect_rail_from_left(self.oe_inv,"A","oeb") + self.connect_rail_from_right(self.ctrl_dff_inst,"dout_bar[0]","cs") + self.connect_rail_from_right(self.ctrl_dff_inst,"dout_bar[1]","we") + self.connect_rail_from_right(self.ctrl_dff_inst,"dout_bar[2]","oe") - self.connect_rail_from_right(self.cs_inv,"Z","cs") - self.connect_rail_from_right(self.we_inv,"Z","we") - self.connect_rail_from_right(self.oe_inv,"Z","oe") + # Connect the clock rail to the other clock rail + in_pos = self.ctrl_dff_inst.get_pin("clk").uc() + mid_pos = in_pos + vector(0,self.m2_pitch) + rail_pos = vector(self.rail_x_offsets["clk_buf"], mid_pos.y) + self.add_wire(("metal1","via1","metal2"),[in_pos, mid_pos, rail_pos]) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=rail_pos, + rotate=90) - def add_input_inv(self): - """ Add the three input inverters """ - y_off = 0 - mirror = "R0" - # input: csb output: cs - self.cs_inv_offset = vector(self.input_width, y_off) - self.cs_inv=self.add_inst(name="cs_inv", - mod=self.inv1, - offset=self.cs_inv_offset, - mirror=mirror) - self.connect_inst(["csb", "cs", "vdd", "gnd"]) - y_off += 2*self.inv1.height - mirror = "MX" - - # input: oeb output: oe - self.oe_inv_offset = vector(self.input_width, y_off) - self.oe_inv=self.add_inst(name="oe_inv", - mod=self.inv1, - offset=self.oe_inv_offset, - mirror=mirror) - self.connect_inst(["oeb", "oe", "vdd", "gnd"]) + def add_dffs(self): + """ Add the three input DFFs (with inverters) """ + self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs", + mod=self.ctrl_dff_array, + offset=vector(0,0)) - # Skip a row to prevent via conflict - y_off += 2*self.inv1.height - mirror = "MX" - - # input: web output: we - self.we_inv_offset = vector(self.input_width, y_off) - self.we_inv=self.add_inst(name="we_inv", - mod=self.inv1, - offset=self.we_inv_offset, - mirror=mirror) - self.connect_inst(["web", "we", "vdd", "gnd"]) + self.connect_inst(self.input_list + self.dff_output_list + ["clk_buf"] + self.supply_list) def add_we_row(self,row): - x_off = self.input_width + self.inv1.width + self.input_bar_width + x_off = self.ctrl_dff_inst.width + self.internal_width y_off = row*self.inv1.height if row % 2: y_off += self.inv1.height @@ -575,11 +556,12 @@ class control_logic(design.design): """ Route the clk and clk_buf_bar signal internally """ clk_pin = self.clkbuf.get_pin("A") - self.add_layout_pin_center_segment(text="clk", + self.add_layout_pin_segment_center(text="clk", layer="metal2", start=clk_pin.bc(), end=clk_pin.bc().scale(1,0)) + self.connect_rail_from_right_m2m3(self.clkbuf, "Z", "clk_buf") self.connect_rail_from_right_m2m3(self.clkbuf, "Zb", "clk_buf_bar") self.connect_output(self.clkbuf, "Z", "clk_buf") self.connect_output(self.clkbuf, "Zb", "clk_buf_bar") @@ -588,7 +570,7 @@ class control_logic(design.design): """ Create an output pin on the right side from the pin of a given instance. """ out_pin = inst.get_pin(pin_name) right_pos=out_pin.center() + vector(self.width-out_pin.cx(),0) - self.add_layout_pin_center_segment(text=out_name, + self.add_layout_pin_segment_center(text=out_name, layer="metal1", start=out_pin.center(), end=right_pos) @@ -612,7 +594,7 @@ class control_logic(design.design): yoffset = i*self.inv1.height - self.add_layout_pin_center_segment(text=name, + self.add_layout_pin_segment_center(text=name, layer="metal1", start=vector(rows_start,yoffset), end=vector(rows_end,yoffset)) @@ -628,43 +610,10 @@ class control_logic(design.design): # width=rows_end-rows_start, # height=well_width) - for vdd_pin in self.rbl_inst.get_pins("vdd"): - if vdd_pin.layer != "metal1": - continue - left = vdd_pin.lc().scale(0,1) - right = left + vector(rows_end,0) - self.add_layout_pin_center_segment(text="vdd", - layer="metal1", - start=left, - end=right) - for gnd_pin in self.rbl_inst.get_pins("gnd"): - if gnd_pin.layer != "metal1": - continue - left = gnd_pin.lc().scale(0,1) - right = left + vector(rows_end,0) - self.add_layout_pin_center_segment(text="gnd", - layer="metal1", - start=left, - end=right) - - for vdd_pin in self.rbl_inst.get_pins("vdd"): - if vdd_pin.layer != "metal2": - continue - self.add_layout_pin(text="vdd", - layer="metal2", - offset=vdd_pin.ll(), - height=vdd_pin.height(), - width=vdd_pin.width()) - - for gnd_pin in self.rbl_inst.get_pins("gnd"): - if gnd_pin.layer != "metal2": - continue - self.add_layout_pin(text="gnd", - layer="metal2", - offset=gnd_pin.ll(), - height=gnd_pin.height(), - width=gnd_pin.width()) + self.copy_layout_pin(self.rbl_inst,"gnd") + self.copy_layout_pin(self.rbl_inst,"vdd") + def add_lvs_correspondence_points(self): diff --git a/compiler/modules/delay_chain.py b/compiler/modules/delay_chain.py index de0386b1..1b8ae4b8 100644 --- a/compiler/modules/delay_chain.py +++ b/compiler/modules/delay_chain.py @@ -194,7 +194,7 @@ class delay_chain(design.design): offset=a_pin.center()) mid_point = vector(a_pin.cx()+3*self.m2_width,a_pin.cy()) self.add_path("metal2",[a_pin.center(), mid_point, mid_point.scale(1,0)]) - self.add_layout_pin_center_segment(text="out", + self.add_layout_pin_segment_center(text="out", layer="metal2", start=mid_point, end=mid_point.scale(1,0)) diff --git a/compiler/modules/dff_buf.py b/compiler/modules/dff_buf.py index 29ad3802..4a696827 100644 --- a/compiler/modules/dff_buf.py +++ b/compiler/modules/dff_buf.py @@ -74,13 +74,17 @@ class dff_buf(design.design): # 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()) + mid_x_offset = 0.5*(a1_pin.cx() + q_pin.cx()) + mid1 = vector(mid_x_offset, q_pin.cy()) + mid2 = vector(mid_x_offset, a1_pin.cy()) + self.add_path("metal3", + [q_pin.center(), mid1, mid2, a1_pin.center()]) + self.add_via_center(layers=("metal2","via2","metal3"), + offset=q_pin.center()) + self.add_via_center(layers=("metal2","via2","metal3"), + offset=a1_pin.center()) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=a1_pin.center()) # Route inv1 z to inv2 a z1_pin = self.inv1_inst.get_pin("Z") @@ -121,14 +125,14 @@ class dff_buf(design.design): height=din_pin.height()) dout_pin = self.inv2_inst.get_pin("Z") - self.add_layout_pin_center_rect(text="Q", + self.add_layout_pin_rect_center(text="Q", layer="metal2", offset=dout_pin.center()) self.add_via_center(layers=("metal1","via1","metal2"), offset=dout_pin.center()) dout_pin = self.inv2_inst.get_pin("A") - self.add_layout_pin_center_rect(text="Qb", + self.add_layout_pin_rect_center(text="Qb", layer="metal2", offset=dout_pin.center()) self.add_via_center(layers=("metal1","via1","metal2"), diff --git a/compiler/modules/dff_inv.py b/compiler/modules/dff_inv.py index 44bdadf5..f7cd8e65 100644 --- a/compiler/modules/dff_inv.py +++ b/compiler/modules/dff_inv.py @@ -65,13 +65,17 @@ class dff_inv(design.design): # 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()) + mid_x_offset = 0.5*(a1_pin.cx() + q_pin.cx()) + mid1 = vector(mid_x_offset, q_pin.cy()) + mid2 = vector(mid_x_offset, a1_pin.cy()) + self.add_path("metal3", + [q_pin.center(), mid1, mid2, a1_pin.center()]) + self.add_via_center(layers=("metal2","via2","metal3"), + offset=q_pin.center()) + self.add_via_center(layers=("metal2","via2","metal3"), + offset=a1_pin.center()) + self.add_via_center(layers=("metal1","via1","metal2"), + offset=a1_pin.center()) def add_layout_pins(self): @@ -107,12 +111,12 @@ class dff_inv(design.design): height=din_pin.height()) dout_pin = self.dff_inst.get_pin("Q") - self.add_layout_pin_center_rect(text="Q", + self.add_layout_pin_rect_center(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", + self.add_layout_pin_rect_center(text="Qb", layer="metal2", offset=dout_pin.center()) self.add_via_center(layers=("metal1","via1","metal2"), diff --git a/compiler/modules/precharge.py b/compiler/modules/precharge.py index 26e3b5f1..a0c45599 100644 --- a/compiler/modules/precharge.py +++ b/compiler/modules/precharge.py @@ -118,7 +118,7 @@ class precharge(pgate.pgate): rotate=90) # adds the en rail on metal1 - self.add_layout_pin_center_segment(text="en", + self.add_layout_pin_segment_center(text="en", layer="metal1", start=offset.scale(0,1), end=offset.scale(0,1)+vector(self.width,0)) diff --git a/compiler/modules/replica_bitline.py b/compiler/modules/replica_bitline.py index e86de04f..63762d43 100644 --- a/compiler/modules/replica_bitline.py +++ b/compiler/modules/replica_bitline.py @@ -133,8 +133,8 @@ class replica_bitline(design.design): def route(self): """ Connect all the signals together """ - self.route_gnd() self.route_vdd() + self.route_gnd() self.route_access_tx() @@ -210,28 +210,25 @@ class replica_bitline(design.design): # Route the vdd lines from left to right # Add via for the delay chain - left_vdd_start = self.dc_inst.ll().scale(1,0) + left_vdd_start = self.dc_inst.ll().scale(1,0) - vector(self.m2_pitch,0) left_vdd_end = vector(left_vdd_start.x, self.rbl_inst.uy()) - self.left_vdd_pin=self.add_layout_pin_center_segment(text="vdd", - layer="metal2", - start=left_vdd_start, - end=left_vdd_end) + self.left_vdd_pin=self.add_segment_center(layer="metal2", + start=left_vdd_start, + end=left_vdd_end) # Vdd line to the left of the replica bitline center_vdd_start = self.rbc_inst.ll() - vector(3*self.m2_pitch,0) center_vdd_end = vector(center_vdd_start.x, self.rbl_inst.uy()) - self.center_vdd_pin=self.add_layout_pin_center_segment(text="vdd", - layer="metal2", - start=center_vdd_start, - end=center_vdd_end) + self.center_vdd_pin=self.add_segment_center(layer="metal2", + start=center_vdd_start, + end=center_vdd_end) # Vdd line to the right of the replica bitline right_vdd_start = self.rbc_inst.lr() + vector(2*self.m2_pitch,0) right_vdd_end = vector(right_vdd_start.x, self.rbl_inst.uy()) - self.right_vdd_pin=self.add_layout_pin_center_segment(text="vdd", - layer="metal2", - start=right_vdd_start, - end=right_vdd_end) + self.right_vdd_pin=self.add_segment_center(layer="metal2", + start=right_vdd_start, + end=right_vdd_end) @@ -243,9 +240,10 @@ class replica_bitline(design.design): continue start = vector(self.center_vdd_pin.cx(),pin.cy()) end = vector(self.right_vdd_pin.cx(),pin.cy()) - self.add_segment_center(layer="metal1", - start=start, - end=end) + self.add_layout_pin_segment_center(text="vdd", + layer="metal1", + start=start, + end=end) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=start, rotate=90) @@ -265,9 +263,10 @@ class replica_bitline(design.design): # with the RBL pins #end = vector(center_vdd_pin.cx(),pin.cy()) end = pin.rc() - self.add_segment_center(layer="metal1", - start=start, - end=end) + self.add_layout_pin_segment_center(text="vdd", + layer="metal1", + start=start, + end=end) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=start, rotate=90) @@ -303,14 +302,24 @@ class replica_bitline(design.design): # Create the RBL rails too rbl_pins = self.rbl_inst.get_pins("vdd") for pin in rbl_pins: - if pin.layer != "metal2": + if pin.layer != "metal1": continue - start = vector(pin.cx(),self.right_vdd_pin.by()) - end = vector(pin.cx(),self.right_vdd_pin.uy()) - self.add_layout_pin_center_segment(text="vdd", - layer="metal2", + # If above the delay line, route the full width + left = vector(self.left_vdd_pin.cx(),pin.cy()) + center = vector(self.center_vdd_pin.cx(),pin.cy()) + if pin.cy() > self.dc_inst.uy() + self.m1_pitch: + start = left + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=left, + rotate=90) + else: + start = center + end = vector(self.right_vdd_pin.cx()+0.5*self.m1_width,pin.cy()) + self.add_layout_pin_segment_center(text="vdd", + layer="metal1", start=start, end=end) + @@ -322,28 +331,25 @@ class replica_bitline(design.design): # Route the gnd lines from left to right # Add via for the delay chain - left_gnd_start = self.dc_inst.ll().scale(1,0) - vector(self.m2_pitch,0) + left_gnd_start = self.dc_inst.ll().scale(1,0) - vector(2*self.m2_pitch,0) left_gnd_end = vector(left_gnd_start.x, self.rbl_inst.uy()+self.m2_pitch) - self.left_gnd_pin=self.add_layout_pin_center_segment(text="gnd", - layer="metal2", - start=left_gnd_start, - end=left_gnd_end) + self.left_gnd_pin=self.add_segment_center(layer="metal2", + start=left_gnd_start, + end=left_gnd_end) # Gnd line to the left of the replica bitline center_gnd_start = self.rbc_inst.ll().scale(1,0) - vector(2*self.m2_pitch,0) center_gnd_end = vector(center_gnd_start.x, self.rbl_inst.uy()+self.m2_pitch) - self.center_gnd_pin=self.add_layout_pin_center_segment(text="gnd", - layer="metal2", - start=center_gnd_start, - end=center_gnd_end) + self.center_gnd_pin=self.add_segment_center(layer="metal2", + start=center_gnd_start, + end=center_gnd_end) # Gnd line to the right of the replica bitline right_gnd_start = self.rbc_inst.lr().scale(1,0) + vector(self.m2_pitch,0) right_gnd_end = vector(right_gnd_start.x, self.rbl_inst.uy()+self.m2_pitch) - self.right_gnd_pin=self.add_layout_pin_center_segment(text="gnd", - layer="metal2", - start=right_gnd_start, - end=right_gnd_end) + self.right_gnd_pin=self.add_segment_center(layer="metal2", + start=right_gnd_start, + end=right_gnd_end) @@ -353,13 +359,24 @@ class replica_bitline(design.design): pin = self.rbl_inst.get_pin(wl) if pin.layer != "metal1": continue - start = vector(self.center_gnd_pin.cx(),pin.cy()) - end = vector(self.right_gnd_pin.cx(),pin.cy()) - self.add_segment_center(layer="metal1", - start=start, - end=end) + # If above the delay line, route the full width + left = vector(self.left_gnd_pin.cx(),pin.cy()) + center = vector(self.center_gnd_pin.cx(),pin.cy()) + if pin.cy() > self.dc_inst.uy() + self.m1_pitch: + start = left + else: + start = center + end = vector(self.right_gnd_pin.cx(),pin.cy()) + self.add_layout_pin_segment_center(text="gnd", + layer="metal1", + start=start, + end=end) + if start == left: + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=left, + rotate=90) self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=start, + offset=center, rotate=90) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=end, @@ -371,13 +388,23 @@ class replica_bitline(design.design): for pin in rbl_gnd_pins: if pin.layer != "metal1": continue - start = vector(self.center_gnd_pin.cx(),pin.cy()) + # If above the delay line, route the full width + left = vector(self.left_gnd_pin.cx(),pin.cy()) + center = vector(self.center_gnd_pin.cx(),pin.cy()) + if pin.cy() > self.dc_inst.uy() + self.m1_pitch: + start = left + else: + start = center end = vector(self.right_gnd_pin.cx(),pin.cy()) self.add_segment_center(layer="metal1", start=start, end=end) + if start == left: + self.add_via_center(layers=("metal1", "via1", "metal2"), + offset=left, + rotate=90) self.add_via_center(layers=("metal1", "via1", "metal2"), - offset=start, + offset=center, rotate=90) self.add_via_center(layers=("metal1", "via1", "metal2"), offset=end, @@ -430,7 +457,7 @@ class replica_bitline(design.design): continue start = vector(pin.cx(),self.right_gnd_pin.by()) end = vector(pin.cx(),self.right_gnd_pin.uy()) - self.add_layout_pin_center_segment(text="gnd", + self.add_layout_pin_segment_center(text="gnd", layer="metal2", start=start, end=end) @@ -440,13 +467,13 @@ class replica_bitline(design.design): def add_layout_pins(self): """ Route the input and output signal """ en_offset = self.dc_inst.get_pin("in").bc() - self.add_layout_pin_center_segment(text="en", + self.add_layout_pin_segment_center(text="en", layer="metal2", start=en_offset, end=en_offset.scale(1,0)) out_offset = self.rbl_inv_inst.get_pin("Z").center() - self.add_layout_pin_center_segment(text="out", + self.add_layout_pin_segment_center(text="out", layer="metal2", start=out_offset, end=out_offset.scale(1,0)) diff --git a/compiler/modules/wordline_driver.py b/compiler/modules/wordline_driver.py index aa7eba01..1d1d181b 100644 --- a/compiler/modules/wordline_driver.py +++ b/compiler/modules/wordline_driver.py @@ -176,7 +176,7 @@ class wordline_driver(design.design): input_offset = vector(0,b_pos.y + up_or_down) mid_via_offset = vector(clk_offset.x,input_offset.y) + vector(0.5*self.m2_width+self.m2_space+0.5*contact.m1m2.width,0) # must under the clk line in M1 - self.add_layout_pin_center_segment(text="in[{0}]".format(row), + self.add_layout_pin_segment_center(text="in[{0}]".format(row), layer="metal1", start=input_offset, end=mid_via_offset) @@ -192,7 +192,7 @@ class wordline_driver(design.design): # output each WL on the right wl_offset = inv2_inst.get_pin("Z").rc() - self.add_layout_pin_center_segment(text="wl[{0}]".format(row), + self.add_layout_pin_segment_center(text="wl[{0}]".format(row), layer="metal1", start=wl_offset, end=wl_offset-vector(self.m1_width,0)) diff --git a/compiler/options.py b/compiler/options.py index 7c419990..ce9217c0 100644 --- a/compiler/options.py +++ b/compiler/options.py @@ -59,8 +59,6 @@ class options(optparse.Values): ms_flop = "ms_flop" ms_flop_array = "ms_flop_array" dff = "dff" - 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/pgate.py b/compiler/pgates/pgate.py index 0a258048..4e47934d 100644 --- a/compiler/pgates/pgate.py +++ b/compiler/pgates/pgate.py @@ -76,11 +76,11 @@ class pgate(design.design): self.add_contact_center(layers=("poly", "contact", "metal1"), offset=contact_offset, rotate=rotate) - # self.add_layout_pin_center_segment(text=name, + # self.add_layout_pin_segment_center(text=name, # layer="metal1", # start=left_gate_offset.scale(0,1), # end=left_gate_offset) - self.add_layout_pin_center_rect(text=name, + self.add_layout_pin_rect_center(text=name, layer="metal1", offset=contact_offset, width=contact_m1_width, diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 7bf71e5d..ab5528a3 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -148,12 +148,12 @@ class pinv(pgate.pgate): def add_supply_rails(self): """ Add vdd/gnd rails to the top and bottom. """ - self.add_layout_pin_center_rect(text="gnd", + self.add_layout_pin_rect_center(text="gnd", layer="metal1", offset=vector(0.5*self.width,0), width=self.width) - self.add_layout_pin_center_rect(text="vdd", + self.add_layout_pin_rect_center(text="vdd", layer="metal1", offset=vector(0.5*self.width,self.height), width=self.width) @@ -208,13 +208,13 @@ class pinv(pgate.pgate): if self.route_output == True: # This extends the output to the edge of the cell output_offset = mid_drain_offset.scale(0,1) + vector(self.width,0) - self.add_layout_pin_center_segment(text="Z", + self.add_layout_pin_segment_center(text="Z", layer="metal1", start=mid_drain_offset, end=output_offset) else: # This leaves the output as an internal pin (min sized) - self.add_layout_pin_center_rect(text="Z", + self.add_layout_pin_rect_center(text="Z", layer="metal1", offset=mid_drain_offset + vector(0.5*self.m1_width,0)) @@ -257,4 +257,4 @@ class pinv(pgate.pgate): c_load = load c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff transistion_prob = spice["inv_transisition_prob"] - return transistion_prob*(c_load + c_para) \ No newline at end of file + return transistion_prob*(c_load + c_para) diff --git a/compiler/pgates/pinvbuf.py b/compiler/pgates/pinvbuf.py index dd7ff37f..bb604923 100644 --- a/compiler/pgates/pinvbuf.py +++ b/compiler/pgates/pinvbuf.py @@ -130,14 +130,14 @@ class pinvbuf(design.design): height=vdd_pin.height()) z_pin = self.inv4_inst.get_pin("Z") - self.add_layout_pin_center_rect(text="Z", + self.add_layout_pin_rect_center(text="Z", layer="metal2", offset=z_pin.center()) self.add_via_center(layers=("metal1","via1","metal2"), offset=z_pin.center()) zb_pin = self.inv3_inst.get_pin("Z") - self.add_layout_pin_center_rect(text="Zb", + self.add_layout_pin_rect_center(text="Zb", layer="metal2", offset=zb_pin.center()) self.add_via_center(layers=("metal1","via1","metal2"), @@ -145,7 +145,7 @@ class pinvbuf(design.design): a_pin = self.inv1_inst.get_pin("A") - self.add_layout_pin_center_rect(text="A", + self.add_layout_pin_rect_center(text="A", layer="metal2", offset=a_pin.center()) self.add_via_center(layers=("metal1","via1","metal2"), diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index fa576850..4ced0390 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -102,12 +102,12 @@ class pnand2(pgate.pgate): def add_supply_rails(self): """ Add vdd/gnd rails to the top and bottom. """ - self.add_layout_pin_center_rect(text="gnd", + self.add_layout_pin_rect_center(text="gnd", layer="metal1", offset=vector(0.5*self.width,0), width=self.width) - self.add_layout_pin_center_rect(text="vdd", + self.add_layout_pin_rect_center(text="vdd", layer="metal1", offset=vector(0.5*self.width,self.height), width=self.width) @@ -197,7 +197,7 @@ class pnand2(pgate.pgate): self.add_path("metal2",[pmos_pin.bc(), mid_offset, nmos_pin.uc()]) # This extends the output to the edge of the cell - self.add_layout_pin_center_rect(text="Z", + self.add_layout_pin_rect_center(text="Z", layer="metal1", offset=mid_offset, width=contact.m1m2.first_layer_height, diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 02262b39..67b35954 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -100,12 +100,12 @@ class pnand3(pgate.pgate): def add_supply_rails(self): """ Add vdd/gnd rails to the top and bottom. """ - self.add_layout_pin_center_rect(text="gnd", + self.add_layout_pin_rect_center(text="gnd", layer="metal1", offset=vector(0.5*self.width,0), width=self.width) - self.add_layout_pin_center_rect(text="vdd", + self.add_layout_pin_rect_center(text="vdd", layer="metal1", offset=vector(0.5*self.width,self.height), width=self.width) @@ -218,7 +218,7 @@ class pnand3(pgate.pgate): # This extends the output to the edge of the cell self.add_contact_center(layers=("metal1", "via1", "metal2"), offset=mid_offset) - self.add_layout_pin_center_rect(text="Z", + self.add_layout_pin_rect_center(text="Z", layer="metal1", offset=mid_offset, width=contact.m1m2.first_layer_width, diff --git a/compiler/pgates/pnor2.py b/compiler/pgates/pnor2.py index 4ee1583e..3b571916 100644 --- a/compiler/pgates/pnor2.py +++ b/compiler/pgates/pnor2.py @@ -106,12 +106,12 @@ class pnor2(pgate.pgate): def add_supply_rails(self): """ Add vdd/gnd rails to the top and bottom. """ - self.add_layout_pin_center_rect(text="gnd", + self.add_layout_pin_rect_center(text="gnd", layer="metal1", offset=vector(0.5*self.width,0), width=self.width) - self.add_layout_pin_center_rect(text="vdd", + self.add_layout_pin_rect_center(text="vdd", layer="metal1", offset=vector(0.5*self.width,self.height), width=self.width) @@ -208,7 +208,7 @@ class pnor2(pgate.pgate): self.add_contact_center(layers=("metal1", "via1", "metal2"), offset=mid3_offset, rotate=90) - self.add_layout_pin_center_rect(text="Z", + self.add_layout_pin_rect_center(text="Z", layer="metal1", offset=mid3_offset, width=contact.m1m2.first_layer_height, @@ -240,4 +240,4 @@ class pnor2(pgate.pgate): c_para = spice["min_tx_drain_c"]*(self.nmos_size/parameter["min_tx_size"])#ff transistion_prob = spice["nor2_transisition_prob"] return transistion_prob*(c_load + c_para) - \ No newline at end of file + diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index ed9c8e74..34c1e511 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -210,7 +210,7 @@ class ptx(design.design): for a in source_positions: self.add_path(("metal1"), [a,a+pin_offset.scale(source_dir,source_dir)]) # Add a single horizontal pin - self.add_layout_pin_center_segment(text="S", + self.add_layout_pin_segment_center(text="S", layer="metal1", start=source_positions[0]+source_offset-end_offset, end=source_positions[-1]+source_offset+end_offset) @@ -222,7 +222,7 @@ class ptx(design.design): for a in drain_positions: self.add_path(("metal1"), [a,a+drain_offset]) # Add a single horizontal pin - self.add_layout_pin_center_segment(text="D", + self.add_layout_pin_segment_center(text="D", layer="metal1", start=drain_positions[0]+drain_offset-end_offset, end=drain_positions[-1]+drain_offset+end_offset) @@ -246,7 +246,7 @@ class ptx(design.design): offset=poly_offset, height=self.poly_height, width=self.poly_width) - self.add_layout_pin_center_rect(text="G", + self.add_layout_pin_rect_center(text="G", layer="poly", offset=poly_offset, height=self.poly_height, @@ -329,7 +329,7 @@ class ptx(design.design): size=(1, self.num_contacts), implant_type=self.implant_type, well_type=self.well_type) - self.add_layout_pin_center_rect(text="S", + self.add_layout_pin_rect_center(text="S", layer="metal1", offset=pos, width=contact.mod.second_layer_width, @@ -342,7 +342,7 @@ class ptx(design.design): size=(1, self.num_contacts), implant_type=self.implant_type, well_type=self.well_type) - self.add_layout_pin_center_rect(text="D", + self.add_layout_pin_rect_center(text="D", layer="metal1", offset=pos, width=contact.mod.second_layer_width, diff --git a/compiler/sram.py b/compiler/sram.py index e05cd3be..6bde0078 100644 --- a/compiler/sram.py +++ b/compiler/sram.py @@ -5,6 +5,8 @@ import design from math import log,sqrt,ceil import contact from bank import bank +from dff_buf_array import dff_buf_array +from dff_array import dff_array import datetime import getpass from vector import vector @@ -21,15 +23,6 @@ class sram(design.design): c = reload(__import__(OPTS.control_logic)) self.mod_control_logic = getattr(c, OPTS.control_logic) - if num_banks>1: - # Use a buffered array for big arrays - # Also ensures we have Qbar when FF doesn't - c = reload(__import__(OPTS.dff_buf_array)) - self.mod_dff_array = getattr(c, OPTS.dff_buf_array) - else: - c = reload(__import__(OPTS.dff_array)) - self.mod_dff_array = getattr(c, OPTS.dff_array) - c = reload(__import__(OPTS.bitcell)) self.mod_bitcell = getattr(c, OPTS.bitcell) self.bitcell = self.mod_bitcell() @@ -809,9 +802,9 @@ class sram(design.design): def create_multi_bank_modules(self): """ Create the multibank address flops and bank decoder """ - self.msb_address = self.mod_dff_array(name="msb_address", - rows=1, - columns=self.num_banks/2) + self.msb_address = dff_buf_array(name="msb_address", + rows=1, + columns=self.num_banks/2) self.add_mod(self.msb_address) if self.num_banks>2: @@ -827,7 +820,7 @@ class sram(design.design): # Create the address and control flops (but not the clk) dff_size = self.addr_size - self.addr_dff = self.mod_dff_array(name="dff_array", rows=dff_size, columns=1) + self.addr_dff = self.dff_array(name="dff_array", rows=dff_size, columns=1) self.add_mod(self.addr_dff) # Create the bank module (up to four are instantiated)