From 10085d85ab8965c4401ab1722a3a9f55e035cc49 Mon Sep 17 00:00:00 2001 From: Hunter Nichols Date: Wed, 21 Jul 2021 14:59:02 -0700 Subject: [PATCH] Changed CACTI drain cap function to be roughly equivalent but use less parameters. Added drain cap functions to relevant modules. Added drain cap parameters in tech files. --- compiler/base/hierarchy_spice.py | 55 +++++++----------------------- compiler/bitcells/bitcell_base.py | 22 +++++++++++- compiler/custom/nand2_dec.py | 14 +++++++- compiler/custom/nand3_dec.py | 14 +++++++- compiler/custom/nand4_dec.py | 14 +++++++- compiler/custom/sense_amp.py | 18 ++++++++++ compiler/pgates/pinv.py | 11 ++++++ compiler/pgates/pnand2.py | 13 ++++++- compiler/pgates/pnand3.py | 13 ++++++- compiler/pgates/pnand4.py | 13 ++++++- compiler/pgates/ptx.py | 8 ++++- technology/freepdk45/tech/tech.py | 5 +++ technology/scn4m_subm/tech/tech.py | 5 +++ 13 files changed, 154 insertions(+), 51 deletions(-) diff --git a/compiler/base/hierarchy_spice.py b/compiler/base/hierarchy_spice.py index 98b94351..2bea7e46 100644 --- a/compiler/base/hierarchy_spice.py +++ b/compiler/base/hierarchy_spice.py @@ -540,63 +540,32 @@ class spice(): def drain_c_(self, width, - nchannel, stack, - next_arg_thresh_folding_width_or_height_cell, - fold_dimension, - _is_cell): + folds): - if _is_cell: - dt = tech.sram_cell # SRAM cell access transistor - - else: - dt = tech.peri_global - - - c_junc_area = dt.C_junc - c_junc_sidewall = dt.C_junc_sidewall - c_fringe = 2*dt.C_fringe - c_overlap = 2*dt.C_overlap + c_junc_area = tech.spice["c_junc"] + c_junc_sidewall = tech.spice["c_junc_sw"] + c_fringe = 2*tech.spice["c_overlap"] + c_overlap = 2*tech.spice["c_fringe"] drain_C_metal_connecting_folded_tr = 0 - - # determine the width of the transistor after folding (if it is getting folded) - if next_arg_thresh_folding_width_or_height_cell == 0: - # interpret fold_dimension as the the folding width threshold - # i.e. the value of transistor width above which the transistor gets folded - w_folded_tr = fold_dimension - - else: - # interpret fold_dimension as the height of the cell that this transistor is part of. - h_tr_region = fold_dimension - 2 * tech.HPOWERRAIL - # TODO : w_folded_tr must come from Component::compute_gate_area() - ratio_p_to_n = 2.0 / (2.0 + 1.0) - if nchannel: - w_folded_tr = (1 - ratio_p_to_n) * (h_tr_region - tech.MIN_GAP_BET_P_AND_N_DIFFS) - - else: - w_folded_tr = ratio_p_to_n * (h_tr_region - tech.MIN_GAP_BET_P_AND_N_DIFFS) - - - num_folded_tr = int(ceil(width / w_folded_tr)) - - if num_folded_tr < 2: - w_folded_tr = width + w_folded_tr = width/folds + num_folded_tr = folds # only for drain - total_drain_w = (tech.w_poly_contact + 2 * tech.spacing_poly_to_contact) +\ - (stack - 1) * tech.spacing_poly_to_poly + total_drain_w = (tech.spice["w_poly_contact"] + 2 * tech.drc["active_contact_to_gate"]) +\ + (stack - 1) * tech.spice["spacing_poly_to_poly"] drain_h_for_sidewall = w_folded_tr total_drain_height_for_cap_wrt_gate = w_folded_tr + 2 * w_folded_tr * (stack - 1) if num_folded_tr > 1: - total_drain_w += (num_folded_tr - 2) * (tech.w_poly_contact + 2 * tech.spacing_poly_to_contact) +\ - (num_folded_tr - 1) * ((stack - 1) * tech.spacing_poly_to_poly) + total_drain_w += (num_folded_tr - 2) * (tech.spice["w_poly_contact"] + 2 * tech.drc["active_contact_to_gate"]) +\ + (num_folded_tr - 1) * ((stack - 1) * tech.spice["spacing_poly_to_poly"]) if num_folded_tr%2 == 0: drain_h_for_sidewall = 0 total_drain_height_for_cap_wrt_gate *= num_folded_tr - drain_C_metal_connecting_folded_tr = tech.wire_local.C_per_um * total_drain_w + drain_C_metal_connecting_folded_tr = tech.spice["wire_c_per_um"] * total_drain_w drain_C_area = c_junc_area * total_drain_w * w_folded_tr diff --git a/compiler/bitcells/bitcell_base.py b/compiler/bitcells/bitcell_base.py index 72cbc40b..e71a383b 100644 --- a/compiler/bitcells/bitcell_base.py +++ b/compiler/bitcells/bitcell_base.py @@ -212,4 +212,24 @@ class bitcell_base(design.design): def get_input_capacitance(self): """Input cap of input, passes width of gates to gate cap function""" # Input cap of both access TX connected to the wordline - return self.gate_c(2*parameter["6T_access_size"]) \ No newline at end of file + return self.gate_c(2*parameter["6T_access_size"]) + + def get_intrinsic_capacitance(self): + """Get the drain capacitances of the TXs in the gate.""" + stack = 1 + mult = 1 + # FIXME: Need to define TX sizes of bitcell storage node. Using + # min_width as a temp value + + # Add the inverter drain Cap and the bitline TX drain Cap + nmos_drain_c = self.drain_c_(drc["minwidth_tx"]*mult, + stack, + mult) + pmos_drain_c = self.drain_c_(drc["minwidth_tx"]*mult, + stack, + mult) + + bl_nmos_drain_c = self.drain_c_(parameter["6T_access_size"], + stack, + mult) + return nmos_drain_c + pmos_drain_c + bl_nmos_drain_c \ No newline at end of file diff --git a/compiler/custom/nand2_dec.py b/compiler/custom/nand2_dec.py index cafc7c34..33b7729b 100644 --- a/compiler/custom/nand2_dec.py +++ b/compiler/custom/nand2_dec.py @@ -84,4 +84,16 @@ class nand2_dec(design.design): def get_input_capacitance(self): """Input cap of input, passes width of gates to gate cap function""" - return self.gate_c(self.nmos_width+self.pmos_width) \ No newline at end of file + return self.gate_c(self.nmos_width+self.pmos_width) + + def get_intrinsic_capacitance(self): + """Get the drain capacitances of the TXs in the gate.""" + nmos_stack = 2 + mult = 1 + nmos_drain_c = self.drain_c_(self.nmos_width*mult, + nmos_stack, + mult) + pmos_drain_c = self.drain_c_(self.pmos_width*mult, + 1, + mult) + return nmos_drain_c + pmos_drain_c \ No newline at end of file diff --git a/compiler/custom/nand3_dec.py b/compiler/custom/nand3_dec.py index 4be8e8ca..af0d2f1f 100644 --- a/compiler/custom/nand3_dec.py +++ b/compiler/custom/nand3_dec.py @@ -84,4 +84,16 @@ class nand3_dec(design.design): def get_input_capacitance(self): """Input cap of input, passes width of gates to gate cap function""" - return self.gate_c(self.nmos_width+self.pmos_width) \ No newline at end of file + return self.gate_c(self.nmos_width+self.pmos_width) + + def get_intrinsic_capacitance(self): + """Get the drain capacitances of the TXs in the gate.""" + nmos_stack = 3 + mult = 1 + nmos_drain_c = self.drain_c_(self.nmos_width*mult, + nmos_stack, + mult) + pmos_drain_c = self.drain_c_(self.pmos_width*mult, + 1, + mult) + return nmos_drain_c + pmos_drain_c \ No newline at end of file diff --git a/compiler/custom/nand4_dec.py b/compiler/custom/nand4_dec.py index a0e2621c..a4afadbe 100644 --- a/compiler/custom/nand4_dec.py +++ b/compiler/custom/nand4_dec.py @@ -84,4 +84,16 @@ class nand4_dec(design.design): def get_input_capacitance(self): """Input cap of input, passes width of gates to gate cap function""" - return self.gate_c(self.nmos_width+self.pmos_width) \ No newline at end of file + return self.gate_c(self.nmos_width+self.pmos_width) + + def get_intrinsic_capacitance(self): + """Get the drain capacitances of the TXs in the gate.""" + nmos_stack = 4 + mult = 1 + nmos_drain_c = self.drain_c_(self.nmos_width*mult, + nmos_stack, + mult) + pmos_drain_c = self.drain_c_(self.pmos_width*mult, + 1, + mult) + return nmos_drain_c + pmos_drain_c \ No newline at end of file diff --git a/compiler/custom/sense_amp.py b/compiler/custom/sense_amp.py index d2a3ba49..4064cc89 100644 --- a/compiler/custom/sense_amp.py +++ b/compiler/custom/sense_amp.py @@ -90,3 +90,21 @@ class sense_amp(design.design): def get_input_capacitance(self): """Input cap of input, passes width of gates to gate cap function""" return self.gate_c(parameter["sa_inv_nmos_size"]) + + def get_intrinsic_capacitance(self): + """Get the drain capacitances of the TXs in the gate.""" + stack = 1 + mult = 1 + # Add the inverter drain Cap and the bitline TX drain Cap + nmos_drain_c = self.drain_c_(parameter["sa_inv_nmos_size"]*mult, + stack, + mult) + pmos_drain_c = self.drain_c_(parameter["sa_inv_pmos_size"]*mult, + stack, + mult) + + bitline_pmos_size = 8 + bl_pmos_drain_c = self.drain_c_(drc("minwidth_tx")*bitline_pmos_size, + stack, + mult) + return nmos_drain_c + pmos_drain_c + bl_pmos_drain_c diff --git a/compiler/pgates/pinv.py b/compiler/pgates/pinv.py index 01f9535f..a3e467b7 100644 --- a/compiler/pgates/pinv.py +++ b/compiler/pgates/pinv.py @@ -353,3 +353,14 @@ class pinv(pgate.pgate): def get_input_capacitance(self): """Input cap of input, passes width of gates to gate cap function""" return self.gate_c(self.nmos_width+self.pmos_width) + + def get_intrinsic_capacitance(self): + """Get the drain capacitances of the TXs in the gate.""" + nmos_stack = 1 + nmos_drain_c = self.drain_c_(self.nmos_width*self.tx_mults, + nmos_stack, + self.tx_mults) + pmos_drain_c = self.drain_c_(self.pmos_width*self.tx_mults, + 1, + self.tx_mults) + return nmos_drain_c + pmos_drain_c \ No newline at end of file diff --git a/compiler/pgates/pnand2.py b/compiler/pgates/pnand2.py index d06c37a4..1fafc210 100644 --- a/compiler/pgates/pnand2.py +++ b/compiler/pgates/pnand2.py @@ -329,5 +329,16 @@ class pnand2(pgate.pgate): def get_input_capacitance(self): """Input cap of input, passes width of gates to gate cap function""" - return self.gate_c(self.nmos_width+self.pmos_width) + return self.gate_c(self.nmos_width+self.pmos_width) + + def get_intrinsic_capacitance(self): + """Get the drain capacitances of the TXs in the gate.""" + nmos_stack = 2 + nmos_drain_c = self.drain_c_(self.nmos_width*self.tx_mults, + nmos_stack, + self.tx_mults) + pmos_drain_c = self.drain_c_(self.pmos_width*self.tx_mults, + 1, + self.tx_mults) + return nmos_drain_c + pmos_drain_c \ No newline at end of file diff --git a/compiler/pgates/pnand3.py b/compiler/pgates/pnand3.py index 798be423..b59d0064 100644 --- a/compiler/pgates/pnand3.py +++ b/compiler/pgates/pnand3.py @@ -362,4 +362,15 @@ class pnand3(pgate.pgate): def get_input_capacitance(self): """Input cap of input, passes width of gates to gate cap function""" - return self.gate_c(self.nmos_width+self.pmos_width) \ No newline at end of file + return self.gate_c(self.nmos_width+self.pmos_width) + + def get_intrinsic_capacitance(self): + """Get the drain capacitances of the TXs in the gate.""" + nmos_stack = 3 + nmos_drain_c = self.drain_c_(self.nmos_width*self.tx_mults, + nmos_stack, + self.tx_mults) + pmos_drain_c = self.drain_c_(self.pmos_width*self.tx_mults, + 1, + self.tx_mults) + return nmos_drain_c + pmos_drain_c \ No newline at end of file diff --git a/compiler/pgates/pnand4.py b/compiler/pgates/pnand4.py index b7c7a823..80607331 100644 --- a/compiler/pgates/pnand4.py +++ b/compiler/pgates/pnand4.py @@ -379,4 +379,15 @@ class pnand4(pgate.pgate): def get_input_capacitance(self): """Input cap of input, passes width of gates to gate cap function""" - return self.gate_c(self.nmos_width+self.pmos_width) \ No newline at end of file + return self.gate_c(self.nmos_width+self.pmos_width) + + def get_intrinsic_capacitance(self): + """Get the drain capacitances of the TXs in the gate.""" + nmos_stack = 4 + nmos_drain_c = self.drain_c_(self.nmos_width*self.tx_mults, + nmos_stack, + self.tx_mults) + pmos_drain_c = self.drain_c_(self.pmos_width*self.tx_mults, + 1, + self.tx_mults) + return nmos_drain_c + pmos_drain_c \ No newline at end of file diff --git a/compiler/pgates/ptx.py b/compiler/pgates/ptx.py index ffe82025..11b615bf 100644 --- a/compiler/pgates/ptx.py +++ b/compiler/pgates/ptx.py @@ -562,4 +562,10 @@ class ptx(design.design): def get_input_capacitance(self): """Input cap of input, passes width of gates to gate cap function""" - return self.gate_c(self.tx_width) \ No newline at end of file + return self.gate_c(self.tx_width) + + def get_intrinsic_capacitance(self): + """Get the drain capacitances of the TXs in the gate.""" + return self.drain_c_(self.tx_width*self.tx_mults, + 1, + self.mults) diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index 33d4bba2..6fb57a4e 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -466,6 +466,11 @@ spice["c_g_ideal"] = spice["cox"]*drc["minlength_channel"] # F/um spice["c_overlap"] = 0.2*spice["c_g_ideal"] # F/um spice["c_fringe"] = 0 # F/um, not defined in this technology spice["cpolywire"] = 0 # F/um, replicated from CACTI which is hardcoded to 0 +spice["c_junc"] = 5e-16 #F/um^2 +spice["c_junc_sw"] = 5e-16 #F/um +spice["w_poly_contact"] = 0.065 # um +spice["spacing_poly_to_poly"] = 0.14 # um +spice["wire_c_per_um"] = 0 # Temp value ################################################### # Technology Tool Preferences diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index 172dbb49..0c94dee8 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -413,6 +413,11 @@ spice["c_g_ideal"] = spice["cox"]*drc["minlength_channel"] # F/um spice["c_overlap"] = 0.2*spice["c_g_ideal"] # F/um spice["c_fringe"] = 0 # F/um, not defined in this technology spice["cpolywire"] = 0 # F/um, replicated from CACTI which is hardcoded to 0 +spice["c_junc"] = 9.276962e-16 #F/um^2 +spice["c_junc_sw"] = 3.181055e-16 #F/um +spice["w_poly_contact"] = 2*_lambda_ +spice["spacing_poly_to_poly"] = 3*_lambda_ +spice["wire_c_per_um"] = 0 # Temp value ################################################### # Technology Tool Preferences