-
Notifications
You must be signed in to change notification settings - Fork 104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added draft PR of generator for strongARM comparator #338
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
from gdsfactory.components import rectangle | ||
from gdsfactory import Component | ||
from glayout.flow.pdk.mappedpdk import MappedPDK | ||
from glayout.flow.primitives.fet import nmos | ||
from glayout.flow.placement.two_transistor_interdigitized import two_pfet_interdigitized | ||
from glayout.flow.placement.four_transistor_interdigitized import generic_4T_interdigitzed | ||
from glayout.flow.placement.two_transistor_interdigitized import two_nfet_interdigitized | ||
from glayout.flow.pdk.util.comp_utils import prec_ref_center, movey, evaluate_bbox, movex, align_comp_to_port | ||
from glayout.flow.routing.smart_route import smart_route, c_route, straight_route, L_route | ||
from glayout.flow.pdk.sky130_mapped import sky130_mapped_pdk | ||
from glayout.flow.spice import Netlist | ||
|
||
def diffPair_netlist(fetL: Component, fetR: Component): | ||
diffPair_netlist = Netlist(circuit_name ='diffPair', nodes=['VIP', 'VIM', 'VD1', 'VD2', 'VTAIL', 'VBULK']) | ||
diffPair_netlist.connect_netlist( | ||
fetL.info['netlist'], | ||
[('G','VIP'), ('D','VD1'), ('S','VTAIL'), ('B','VBULK')] | ||
) | ||
diffPair_netlist.connect_netlist( | ||
fetR.info['netlist'], | ||
[('G','VIM'), ('D','VD2'), ('S','VTAIL'), ('B','VBULK')] | ||
) | ||
return diffPair_netlist | ||
|
||
def diffPair(pdk: MappedPDK, width, length): | ||
diffPair=Component(name="diffPair") | ||
diffp = two_nfet_interdigitized(pdk, numcols=2, dummy=True, with_substrate_tap=False, with_tie=True, width=width, length=length, rmult=1) | ||
diffp_ref = prec_ref_center(diffp) | ||
diffPair.add(diffp_ref) | ||
diffPair.add_ports(diffp_ref.get_ports_list(), prefix="diffp_") | ||
diffPair << smart_route(pdk,diffPair.ports["diffp_A_source_E"],diffPair.ports["diffp_B_source_E"],diffp_ref,diffPair) | ||
#add labels | ||
met1_label = (68, 5) | ||
met1_pin = (68, 16) | ||
move_info = list() | ||
diffPair.unlock() | ||
#inp label | ||
vinplabel = rectangle(layer=met1_pin, size=(0.5,0.5), centered=True).copy() | ||
vinplabel.add_label(text="VIP",layer=met1_label) | ||
move_info.append((vinplabel,diffPair.ports["diffp_A_gate_N"],None)) | ||
#inm label | ||
vinmlabel = rectangle(layer=met1_pin, size=(0.05,0.05), centered=True).copy() | ||
vinmlabel.add_label(text="Vim",layer=met1_label) | ||
move_info.append((vinmlabel,diffPair.ports["diffp_B_gate_N"],None)) | ||
#vtail label | ||
vtaillabel = rectangle(layer=met1_pin, size=(0.05,0.05), centered=True).copy() | ||
vtaillabel.add_label(text="Vtail",layer=met1_label) | ||
move_info.append((vtaillabel,diffPair.ports["diffp_A_source_N"],None)) | ||
#vd1 label | ||
vd1label = rectangle(layer=met1_pin, size=(0.05,0.05), centered=True).copy() | ||
vd1label.add_label(text="Vd1",layer=met1_label) | ||
move_info.append((vd1label,diffPair.ports["diffp_A_drain_N"],None)) | ||
#vd2 label | ||
vd2label = rectangle(layer=met1_pin, size=(0.05,0.05), centered=True).copy() | ||
vd2label.add_label(text="Vd2",layer=met1_label) | ||
move_info.append((vd2label,diffPair.ports["diffp_B_drain_N"],None)) | ||
#vbulk label | ||
vbulklabel = rectangle(layer=met1_pin, size=(0.05,0.05), centered=True).copy() | ||
vbulklabel.add_label(text="Vbulk",layer=met1_label) | ||
move_info.append((vbulklabel,diffPair.ports["diffp_welltie_N_bottom_lay_S"],None)) | ||
#move everything to position | ||
for comp, prt, alignment in move_info: | ||
alignment = ('c','b') if alignment is None else alignment | ||
compref = align_comp_to_port(comp, prt, alignment=alignment) | ||
diffPair.add(compref) | ||
|
||
diffPair.flatten() | ||
diffPair.write_gds("./strong.gds") | ||
#spice netlist | ||
fetL = nmos(pdk, width=2*width, length=length, with_dummy=(True, False)) | ||
fetR = nmos(pdk, width=2*width, length=length, with_dummy=(False, True)) | ||
diffPair.info['netlist'] = diffPair_netlist(fetL, fetR) | ||
#print(diffPair.info['netlist'].generate_netlist()) | ||
#print(diffPair.get_ports_list()) | ||
lvs_result = sky130_mapped_pdk.lvs_netgen(diffPair,'diffPair') | ||
return diffPair | ||
|
||
diffPair(sky130_mapped_pdk,2,0.4).show() | ||
|
||
|
||
def cross_coupled_load(pdk: MappedPDK, ccinv_col): | ||
cross_coupled_load=Component(name="cross_coupled_load") | ||
cross_couple = generic_4T_interdigitzed(pdk, numcols=ccinv_col, top_row_device="pfet", bottom_row_device="nfet", length=0.4) | ||
cross_couple_ref = prec_ref_center(cross_couple) | ||
cross_coupled_load.add(cross_couple_ref) | ||
cross_coupled_load.add_ports(cross_couple_ref.get_ports_list(), prefix="cross_couple_") | ||
cross_coupled_load << smart_route(pdk,cross_coupled_load.ports["cross_couple_top_A_source_E"],cross_coupled_load.ports["cross_couple_top_B_source_E"],cross_couple_ref,cross_coupled_load) | ||
cross_coupled_load << smart_route(pdk,cross_coupled_load.ports["cross_couple_bottom_A_source_E"],cross_coupled_load.ports["cross_couple_bottom_B_source_E"],cross_couple_ref,cross_coupled_load) | ||
cross_coupled_load << smart_route(pdk,cross_coupled_load.ports["cross_couple_top_A_drain_E"],cross_coupled_load.ports["cross_couple_top_B_gate_E"],cross_couple_ref,cross_coupled_load) | ||
cross_coupled_load << smart_route(pdk,cross_coupled_load.ports["cross_couple_bottom_A_drain_E"],cross_coupled_load.ports["cross_couple_bottom_B_gate_E"],cross_couple_ref,cross_coupled_load) | ||
cross_coupled_load << smart_route(pdk,cross_coupled_load.ports["cross_couple_top_B_drain_E"],cross_coupled_load.ports["cross_couple_top_A_gate_E"],cross_couple_ref,cross_coupled_load) | ||
cross_coupled_load << smart_route(pdk,cross_coupled_load.ports["cross_couple_bottom_B_drain_E"],cross_coupled_load.ports["cross_couple_bottom_A_gate_E"],cross_couple_ref,cross_coupled_load) | ||
cross_coupled_load << smart_route(pdk,cross_coupled_load.ports["cross_couple_top_B_gate_E"],cross_coupled_load.ports["cross_couple_bottom_B_gate_E"],cross_couple_ref,cross_coupled_load) | ||
cross_coupled_load << smart_route(pdk,cross_coupled_load.ports["cross_couple_top_A_gate_W"],cross_coupled_load.ports["cross_couple_bottom_A_gate_W"],cross_couple_ref,cross_coupled_load) | ||
return cross_coupled_load | ||
|
||
#cross_coupled_load(gf180_mapped_pdk,2,0.5).show() | ||
|
||
def mystrongARM(pdk: MappedPDK, diffp_w, diffp_l, ccinv_col, clk_fing, reset_w, reset_l): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add more parameterization here, for the diffpair transistors' length, width,etc. |
||
mystrongARM=Component(name="mystrongARM") | ||
diffp = diffPair(pdk, diffp_w, diffp_l) | ||
diffp_ref = prec_ref_center(diffp) | ||
mystrongARM.add(diffp_ref) | ||
|
||
|
||
cross_couple = cross_coupled_load(pdk, ccinv_col) | ||
cross_couple_ref = prec_ref_center(cross_couple) | ||
mystrongARM.add(cross_couple_ref) | ||
|
||
|
||
clk_nmos = nmos(pdk, width=4, fingers=clk_fing, rmult=1, with_substrate_tap=False, with_dnwell=False) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why did you decide default width to be 4 micron? |
||
clk_nmos_ref = prec_ref_center(clk_nmos) | ||
mystrongARM.add(clk_nmos_ref) | ||
|
||
reset_pmos_right = two_pfet_interdigitized(pdk, numcols=2, dummy=False, with_substrate_tap=False, with_tie=True, width=reset_w, length=reset_l, rmult=1) | ||
reset_pmos_ref1 = prec_ref_center(reset_pmos_right) | ||
mystrongARM.add(reset_pmos_ref1) | ||
offsety_reset_pmos=evaluate_bbox(cross_couple)[1]/4 | ||
|
||
reset_pmos_left = two_pfet_interdigitized(pdk, numcols=2, dummy=False, with_substrate_tap=False, with_tie=True, width=reset_w, length=reset_l, rmult=1) | ||
reset_pmos_ref2 = prec_ref_center(reset_pmos_left) | ||
mystrongARM.add(reset_pmos_ref2) | ||
offsetx_cross = (evaluate_bbox(cross_couple)[0]-evaluate_bbox(reset_pmos_left)[0])/2 | ||
|
||
offsety_diffp = (evaluate_bbox(diffp)[1]-evaluate_bbox(clk_nmos)[1])/2 | ||
offsety_cross = (evaluate_bbox(cross_couple)[1]-evaluate_bbox(diffp)[1])/2 | ||
|
||
movey(reset_pmos_ref2, evaluate_bbox(clk_nmos_ref)[1]+pdk.util_max_metal_seperation() + offsety_diffp + evaluate_bbox(diffp)[1]+pdk.util_max_metal_seperation() + offsety_cross+offsety_reset_pmos) | ||
movex(cross_couple_ref, evaluate_bbox(reset_pmos_left)[0]+pdk.util_max_metal_seperation()+offsetx_cross) | ||
movex(diffp_ref, evaluate_bbox(reset_pmos_left)[0]+pdk.util_max_metal_seperation()+offsetx_cross) | ||
movex(clk_nmos_ref, evaluate_bbox(reset_pmos_left)[0]+pdk.util_max_metal_seperation()+offsetx_cross) | ||
movey(cross_couple_ref, evaluate_bbox(clk_nmos_ref)[1]+pdk.util_max_metal_seperation() + offsety_diffp + evaluate_bbox(diffp)[1]+pdk.util_max_metal_seperation() + offsety_cross) | ||
movey(diffp_ref, evaluate_bbox(clk_nmos_ref)[1]+pdk.util_max_metal_seperation()+offsety_diffp) | ||
movey(reset_pmos_ref1, evaluate_bbox(clk_nmos_ref)[1]+pdk.util_max_metal_seperation() + offsety_diffp + evaluate_bbox(diffp)[1]+pdk.util_max_metal_seperation() + offsety_cross + offsety_reset_pmos) | ||
movex(reset_pmos_ref1, evaluate_bbox(reset_pmos_left)[0]+pdk.util_max_metal_seperation() + evaluate_bbox(cross_couple)[0]+pdk.util_max_metal_seperation()) | ||
#print("bbox",evaluate_bbox(clk_nmos_ref)[1]) | ||
mystrongARM.add_ports(diffp_ref.get_ports_list(), prefix="strongARM_") | ||
mystrongARM.add_ports(cross_couple_ref.get_ports_list(), prefix="strongARM_") | ||
mystrongARM.add_ports(clk_nmos_ref.get_ports_list(), prefix="strongARM_clk_nmos_") | ||
mystrongARM.add_ports(reset_pmos_ref1.get_ports_list(), prefix="strongARM_clk_reset_pmos_r_") | ||
mystrongARM.add_ports(reset_pmos_ref2.get_ports_list(), prefix="strongARM_clk_reset_pmos_l_") | ||
Comment on lines
+137
to
+141
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add ports after all the routing has been done, it is beneficial to include the routes' ports as well |
||
|
||
mystrongARM << c_route(pdk, mystrongARM.ports["strongARM_diffp_A_drain_W"], mystrongARM.ports["strongARM_cross_couple_bottom_A_source_W"], extension = 1.25) | ||
mystrongARM << c_route(pdk, mystrongARM.ports["strongARM_diffp_B_drain_E"], mystrongARM.ports["strongARM_cross_couple_bottom_B_source_E"], extension = 1.25) | ||
mystrongARM << smart_route(pdk, mystrongARM.ports["strongARM_diffp_A_source_W"], mystrongARM.ports["strongARM_clk_nmos_drain_W"], clk_nmos_ref, mystrongARM) | ||
mystrongARM << smart_route(pdk, mystrongARM.ports["strongARM_diffp_A_source_E"], mystrongARM.ports["strongARM_clk_nmos_drain_E"], clk_nmos_ref, mystrongARM) | ||
mystrongARM << smart_route(pdk, mystrongARM.ports["strongARM_clk_reset_pmos_r_A_source_E"], mystrongARM.ports["strongARM_clk_reset_pmos_r_B_source_E"],reset_pmos_ref1,mystrongARM) | ||
mystrongARM << smart_route(pdk, mystrongARM.ports["strongARM_clk_reset_pmos_l_A_source_E"], mystrongARM.ports["strongARM_clk_reset_pmos_l_B_source_E"],reset_pmos_ref2,mystrongARM) | ||
mystrongARM << smart_route(pdk, mystrongARM.ports["strongARM_clk_reset_pmos_r_A_drain_E"], mystrongARM.ports["strongARM_cross_couple_bottom_B_drain_E"]) | ||
mystrongARM << smart_route(pdk, mystrongARM.ports["strongARM_clk_reset_pmos_r_B_drain_E"], mystrongARM.ports["strongARM_cross_couple_bottom_B_source_E"], extension = 1.25) | ||
mystrongARM << smart_route(pdk, mystrongARM.ports["strongARM_clk_reset_pmos_l_A_drain_W"], mystrongARM.ports["strongARM_cross_couple_bottom_A_drain_W"]) | ||
mystrongARM << smart_route(pdk, mystrongARM.ports["strongARM_clk_reset_pmos_l_B_drain_W"], mystrongARM.ports["strongARM_cross_couple_bottom_A_source_W"], extension = 1.25) | ||
mystrongARM << smart_route(pdk, mystrongARM.ports["strongARM_clk_reset_pmos_r_A_gate_W"], mystrongARM.ports["strongARM_clk_reset_pmos_r_B_gate_W"],reset_pmos_ref1,mystrongARM) | ||
mystrongARM << smart_route(pdk, mystrongARM.ports["strongARM_clk_reset_pmos_l_A_gate_E"], mystrongARM.ports["strongARM_clk_reset_pmos_l_B_gate_E"],reset_pmos_ref2,mystrongARM) | ||
|
||
mystrongARM << c_route(pdk, mystrongARM.ports["strongARM_clk_reset_pmos_r_A_gate_E"], mystrongARM.ports["strongARM_clk_nmos_gate_E"], extension = 3) | ||
mystrongARM << c_route(pdk, mystrongARM.ports["strongARM_clk_reset_pmos_l_A_gate_W"], mystrongARM.ports["strongARM_clk_nmos_gate_W"], extension = 3) | ||
return mystrongARM | ||
|
||
#mystrongARM(gf180_mapped_pdk, 8, 0.4, 2, 4, 3, 0.4).show() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove this line once the PR is ready