Skip to content
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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()
Copy link
Collaborator

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



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):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add more parameterization here, for the diffpair transistors' length, width,etc.
also add options for taprings, welltaps and such

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)
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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()
Loading