From b440031855155b0e9be6d5863aab14a7461742db Mon Sep 17 00:00:00 2001 From: Matt Guthaus Date: Mon, 26 Nov 2018 15:29:42 -0800 Subject: [PATCH] Add netlist only mode to new pgates --- compiler/modules/control_logic.py | 172 +++++++++++++----------------- compiler/pgates/pand2.py | 57 +++++----- compiler/pgates/pbuf.py | 62 ++++++----- compiler/pgates/pnand2.py | 1 - 4 files changed, 141 insertions(+), 151 deletions(-) diff --git a/compiler/modules/control_logic.py b/compiler/modules/control_logic.py index d227dfce..16c2dbe9 100644 --- a/compiler/modules/control_logic.py +++ b/compiler/modules/control_logic.py @@ -4,8 +4,9 @@ from tech import drc, parameter import debug import contact from pinv import pinv +from pbuf import pbuf +from pand2 import pand2 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 @@ -71,22 +72,30 @@ class control_logic(design.design): self.ctrl_dff_array = dff_inv_array(rows=self.num_control_signals,columns=1) self.add_mod(self.ctrl_dff_array) + self.and2 = pand2(height=dff_height) + self.add_mod(self.and2) + self.nand2 = pnand2(height=dff_height) self.add_mod(self.nand2) - self.nand3 = pnand3(height=dff_height) - self.add_mod(self.nand3) # Special gates: inverters for buffering # Size the clock for the number of rows (fanout) clock_driver_size = max(1,int(self.num_rows/4)) - self.clkbuf = pinvbuf(clock_driver_size,height=dff_height) + self.clkbuf = pbuf(size=clock_driver_size, height=dff_height) self.add_mod(self.clkbuf) - self.inv = self.inv1 = pinv(size=1, height=dff_height) - self.add_mod(self.inv1) - self.inv2 = pinv(size=4, height=dff_height) - self.add_mod(self.inv2) - self.inv8 = pinv(size=16, height=dff_height) - self.add_mod(self.inv8) + + self.pbuf8 = pbuf(size=8, height=dff_height) + self.add_mod(self.pbuf8) + + self.pbuf1 = pbuf(size=1, height=dff_height) + self.add_mod(self.pbuf1) + + # self.inv = self.inv1 = pinv(size=1, height=dff_height) + # self.add_mod(self.inv1) + # self.inv2 = pinv(size=4, height=dff_height) + # self.add_mod(self.inv2) + # self.inv8 = pinv(size=16, height=dff_height) + # self.add_mod(self.inv8) if (self.port_type == "rw") or (self.port_type == "r"): from importlib import reload @@ -157,7 +166,7 @@ class control_logic(design.design): def create_instances(self): """ Create all the instances """ self.create_dffs() - self.create_clk_row() + self.create_clk_rows() if (self.port_type == "rw") or (self.port_type == "w"): self.create_we_row() if (self.port_type == "rw") or (self.port_type == "r"): @@ -177,8 +186,10 @@ class control_logic(design.design): row = 0 # Add the logic on the right of the bus - self.place_clk_row(row=row) # clk is a double-high cell - row += 2 + self.place_clkbuf_row(row=row) + row += 1 + self.place_gated_clk_row(row=row) + row += 1 if (self.port_type == "rw") or (self.port_type == "w"): self.place_we_row(row=row) height = self.w_en_inst.uy() @@ -219,11 +230,11 @@ class control_logic(design.design): """ Create the replica bitline """ self.rbl_inst=self.add_inst(name="replica_bitline", mod=self.replica_bitline) - self.connect_inst(["rbl_in", "pre_s_en", "vdd", "gnd"]) + self.connect_inst(["pre_p_en", "pre_s_en", "vdd", "gnd"]) def place_rbl(self,row): """ Place the replica bitline """ - y_off = row * self.inv1.height + 2*self.m1_pitch + y_off = row * self.nand2.height + 2*self.m1_pitch # Add the RBL above the rows # Add to the right of the control rows and routing channel @@ -231,30 +242,38 @@ class control_logic(design.design): self.rbl_inst.place(self.replica_bitline_offset) - def create_clk_row(self): - """ Create the multistage clock buffer """ + def create_clk_rows(self): + """ Create the multistage and gated clock buffer """ self.clkbuf_inst = self.add_inst(name="clkbuf", mod=self.clkbuf) - self.connect_inst(["clk","clk_buf_bar","clk_buf","vdd","gnd"]) + self.connect_inst(["clk","clk_buf","vdd","gnd"]) - def place_clk_row(self,row): + self.gated_clk_inst = self.add_inst(name="gated_clkbuf", + mod=self.pbuf1) + self.connect_inst(["cs","clk_buf","gated_clk","vdd","gnd"]) + + def place_clkbuf_row(self,row): """ Place the multistage clock buffer below the control flops """ x_off = self.ctrl_dff_array.width + self.internal_bus_width (y_off,mirror)=self.get_offset(row) - clkbuf_offset = vector(x_off,y_off) - self.clkbuf_inst.place(clkbuf_offset) + offset = vector(x_off,y_off) + self.clkbuf_inst.place(offset) self.row_end_inst.append(self.clkbuf_inst) + + def place_gatedclk_row(self,row): + """ Place the gated clk logic below the control flops """ + x_off = self.ctrl_dff_array.width + self.internal_bus_width + (y_off,mirror)=self.get_offset(row) + offset = vector(x_off,y_off) + self.gated_clk_inst.place(offset) + self.row_end_inst.append(self.gated_clk_inst) def create_rbl_in_row(self): - self.rbl_in_bar_inst=self.add_inst(name="nand2_rbl_in_bar", - mod=self.nand2) - self.connect_inst(["clk_buf_bar", "cs", "rbl_in_bar", "vdd", "gnd"]) - - # input: rbl_in_bar, output: rbl_in - self.rbl_in_inst=self.add_inst(name="inv_rbl_in", - mod=self.inv1) - self.connect_inst(["rbl_in_bar", "rbl_in", "vdd", "gnd"]) + # input: gated_clk, we_bar, output: pre_p_en + self.pre_p_en_inst=self.add_inst(name="and2_pre_p_en", + mod=self.and2) + self.connect_inst(["gated_clk", "we_bar", "pre_p_en", "vdd", "gnd"]) def place_rbl_in_row(self,row): @@ -262,28 +281,20 @@ class control_logic(design.design): (y_off,mirror)=self.get_offset(row) - self.rbl_in_bar_offset = vector(x_off, y_off) - self.rbl_in_bar_inst.place(offset=self.rbl_in_bar_offset, - mirror=mirror) - x_off += self.nand2.width + self.pre_p_en_offset = vector(x_off, y_off) + self.pre_p_en_inst.place(offset=self.pre_p_en_offset, + mirror=mirror) + x_off += self.and2.width - self.rbl_in_offset = vector(x_off, y_off) - self.rbl_in_inst.place(offset=self.rbl_in_offset, - mirror=mirror) - self.row_end_inst.append(self.rbl_in_inst) + self.row_end_inst.append(self.pre_p_en_inst) def create_sen_row(self): """ Create the sense enable buffer. """ - # input: pre_s_en, output: pre_s_en_bar - self.pre_s_en_bar_inst=self.add_inst(name="inv_pre_s_en_bar", - mod=self.inv2) - self.connect_inst(["pre_s_en", "pre_s_en_bar", "vdd", "gnd"]) - - # BUFFER INVERTERS FOR S_EN - # input: input: pre_s_en_bar, output: s_en - self.s_en_inst=self.add_inst(name="inv_s_en", - mod=self.inv8) - self.connect_inst(["pre_s_en_bar", "s_en", "vdd", "gnd"]) + # BUFFER FOR S_EN + # input: pre_s_en, output: s_en + self.s_en_inst=self.add_inst(name="buf_s_en", + mod=self.pbuf8) + self.connect_inst(["pre_s_en", "s_en", "vdd", "gnd"]) def place_sen_row(self,row): """ @@ -293,11 +304,6 @@ class control_logic(design.design): x_off = self.ctrl_dff_array.width + self.internal_bus_width (y_off,mirror)=self.get_offset(row) - self.pre_s_en_bar_offset = vector(x_off, y_off) - self.pre_s_en_bar_inst.place(offset=self.pre_s_en_bar_offset, - mirror=mirror) - x_off += self.inv2.width - self.s_en_offset = vector(x_off, y_off) self.s_en_inst.place(offset=self.s_en_offset, mirror=mirror) @@ -341,9 +347,9 @@ class control_logic(design.design): def get_offset(self,row): """ Compute the y-offset and mirroring """ - y_off = row*self.inv1.height + y_off = row*self.nand2.height if row % 2: - y_off += self.inv1.height + y_off += self.nand2.height mirror="MX" else: mirror="R0" @@ -351,60 +357,36 @@ class control_logic(design.design): return (y_off,mirror) def create_we_row(self): - # input: WE, CS output: w_en_bar + # input: we, gated_clk output: pre_w_en if self.port_type == "rw": - nand_mod = self.nand3 - temp = ["clk_buf_bar", "cs", "we", "w_en_bar", "vdd", "gnd"] + self.pre_w_en_inst = self.add_inst(name="and_pre_w_en", + mod=self.pand2) + self.connect_inst(["we", "gated_clk", "pre_w_en", "vdd", "gnd"]) + input_name = "pre_w_en" else: - nand_mod = self.nand2 - temp = ["clk_buf_bar", "cs", "w_en_bar", "vdd", "gnd"] - - self.w_en_bar_inst = self.add_inst(name="nand3_w_en_bar", - mod=nand_mod) - self.connect_inst(temp) - - # input: w_en_bar, output: pre_w_en - self.pre_w_en_inst = self.add_inst(name="inv_pre_w_en", - mod=self.inv1) - self.connect_inst(["w_en_bar", "pre_w_en", "vdd", "gnd"]) - - # BUFFER INVERTERS FOR W_EN - self.pre_w_en_bar_inst = self.add_inst(name="inv_pre_w_en_bar", - mod=self.inv2) - self.connect_inst(["pre_w_en", "pre_w_en_bar", "vdd", "gnd"]) - - self.w_en_inst = self.add_inst(name="inv_w_en2", - mod=self.inv8) - self.connect_inst(["pre_w_en_bar", "w_en", "vdd", "gnd"]) + # No we signal is needed for write-only ports + input_name = "gated_clk" + + # BUFFER FOR W_EN + self.w_en_inst = self.add_inst(name="w_en_buf", + mod=self.pbuf8) + self.connect_inst([input_name, "w_en", "vdd", "gnd"]) def place_we_row(self,row): x_off = self.ctrl_dff_inst.width + self.internal_bus_width (y_off,mirror)=self.get_offset(row) - w_en_bar_offset = vector(x_off, y_off) - self.w_en_bar_inst.place(offset=w_en_bar_offset, - mirror=mirror) if self.port_type == "rw": - x_off += self.nand3.width - else: + pre_w_en_offset = vector(x_off, y_off) + self.pre_w_en_inst.place(offset=pre_w_en_offset, + mirror=mirror) x_off += self.nand2.width - pre_w_en_offset = vector(x_off, y_off) - self.pre_w_en_inst.place(offset=pre_w_en_offset, - mirror=mirror) - x_off += self.inv1.width - - pre_w_en_bar_offset = vector(x_off, y_off) - self.pre_w_en_bar_inst.place(offset=pre_w_en_bar_offset, - mirror=mirror) - x_off += self.inv2.width - - w_en_offset = vector(x_off, y_off) + w_en_offset = vector(x_off, y_off) self.w_en_inst.place(offset=w_en_offset, mirror=mirror) - x_off += self.inv8.width - + self.row_end_inst.append(self.w_en_inst) diff --git a/compiler/pgates/pand2.py b/compiler/pgates/pand2.py index caeff11b..40183113 100644 --- a/compiler/pgates/pand2.py +++ b/compiler/pgates/pand2.py @@ -17,38 +17,40 @@ class pand2(design.design): unique_id = 1 - def __init__(self, driver_size=4, height=bitcell.height, name=""): - - stage_effort = 4 - # FIXME: Change the number of stages to support high drives. + def __init__(self, size=1, height=bitcell.height, name=""): + self.size = size + self.height = height + if name=="": - name = "pand2_{0}_{1}".format(driver_size, pand2.unique_id) + name = "pand2_{0}_{1}".format(size, pand2.unique_id) pand2.unique_id += 1 design.design.__init__(self, name) debug.info(1, "Creating {}".format(self.name)) + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() + + + 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 = pnand2(height=height) + self.nand = pnand2(height=self.height) self.add_mod(self.nand) - self.inv = pinv(size=driver_size, height=height) + self.inv = pinv(size=self.size, height=self.height) self.add_mod(self.inv) - self.width = self.nand.width + self.inv.width - self.height = self.inv.height - - self.create_layout() - - #self.offset_all_coordinates() - - self.DRC_LVS() - def create_layout(self): - self.add_pins() - self.add_insts() + self.width = self.nand.width + self.inv.width + self.place_insts() self.add_wires() self.add_layout_pins() @@ -59,20 +61,21 @@ class pand2(design.design): self.add_pin("vdd") self.add_pin("gnd") - def add_insts(self): - # Add NAND to the right + def create_insts(self): self.nand_inst=self.add_inst(name="pand2_nand", - mod=self.nand, - offset=vector(0,0)) + mod=self.nand) self.connect_inst(["A", "B", "zb_int", "vdd", "gnd"]) + self.inv_inst=self.add_inst(name="pand2_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=self.add_inst(name="pand2_inv", - mod=self.inv, - offset=vector(self.nand_inst.rx(),0)) - self.connect_inst(["zb_int", "Z", "vdd", "gnd"]) - + self.inv_inst.place(offset=vector(self.nand_inst.rx(),0)) def add_wires(self): # nand Z to inv A diff --git a/compiler/pgates/pbuf.py b/compiler/pgates/pbuf.py index 0d30a89b..3cad8c17 100644 --- a/compiler/pgates/pbuf.py +++ b/compiler/pgates/pbuf.py @@ -16,39 +16,33 @@ class pbuf(design.design): unique_id = 1 - def __init__(self, driver_size=4, height=bitcell.height, name=""): + def __init__(self, size=4, height=bitcell.height, name=""): - stage_effort = 4 + self.stage_effort = 4 + self.size = size + self.width = 0 + self.height = height # FIXME: Change the number of stages to support high drives. if name=="": - name = "pbuf_{0}_{1}".format(driver_size, pbuf.unique_id) + name = "pbuf_{0}_{1}".format(self.size, pbuf.unique_id) pbuf.unique_id += 1 design.design.__init__(self, name) debug.info(1, "Creating {}".format(self.name)) - - # Shield the cap, but have at least a stage effort of 4 - input_size = max(1,int(driver_size/stage_effort)) - self.inv1 = pinv(size=input_size, height=height) # 1 - self.add_mod(self.inv1) - - self.inv2 = pinv(size=driver_size, height=height) # 2 - self.add_mod(self.inv2) + self.create_netlist() + if not OPTS.netlist_only: + self.create_layout() - self.width = self.inv1.width + self.inv2.width - self.height = self.inv1.height - - self.create_layout() - - #self.offset_all_coordinates() - - self.DRC_LVS() + def create_netlist(self): + self.add_pins() + self.create_modules() + self.create_insts() def create_layout(self): - self.add_pins() - self.add_insts() + self.width = self.inv1.width + self.inv2.width + self.place_insts() self.add_wires() self.add_layout_pins() @@ -58,19 +52,31 @@ class pbuf(design.design): self.add_pin("vdd") self.add_pin("gnd") - def add_insts(self): - # Add INV1 to the right + def create_modules(self): + # Shield the cap, but have at least a stage effort of 4 + input_size = max(1,int(self.size/self.stage_effort)) + self.inv1 = pinv(size=input_size, height=self.height) + self.add_mod(self.inv1) + + self.inv2 = pinv(size=self.size, height=self.height) + self.add_mod(self.inv2) + + def create_insts(self): self.inv1_inst=self.add_inst(name="buf_inv1", - mod=self.inv1, - offset=vector(0,0)) + mod=self.inv1) self.connect_inst(["A", "zb_int", "vdd", "gnd"]) - # Add INV2 to the right self.inv2_inst=self.add_inst(name="buf_inv2", - mod=self.inv2, - offset=vector(self.inv1_inst.rx(),0)) + mod=self.inv2) self.connect_inst(["zb_int", "Z", "vdd", "gnd"]) + + def place_insts(self): + # Add INV1 to the right + self.inv1_inst.place(vector(0,0)) + + # Add INV2 to the right + self.inv2_inst.place(vector(self.inv1_inst.rx(),0)) def add_wires(self): diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index 27cf021f..440c31d0 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -33,7 +33,6 @@ class pnand2(pgate.pgate): self.create_netlist() if not OPTS.netlist_only: self.create_layout() - #self.DRC_LVS() def create_netlist(self):