From 7d7ffe76e0301fd288ed5273baf7092ad355ea84 Mon Sep 17 00:00:00 2001 From: mrg Date: Wed, 22 Sep 2021 16:54:52 -0700 Subject: [PATCH] Debugging klayout for SCMOS and FreePDK45. --- compiler/verify/klayout.py | 35 +++- technology/freepdk45/tech/freepdk45.lylvs | 11 +- technology/freepdk45/tech/tech.py | 3 + technology/scn4m_subm/tech/scn4m_subm.lylvs | 214 ++++++++++++++++++++ technology/scn4m_subm/tech/tech.py | 3 + 5 files changed, 258 insertions(+), 8 deletions(-) create mode 100644 technology/scn4m_subm/tech/scn4m_subm.lylvs diff --git a/compiler/verify/klayout.py b/compiler/verify/klayout.py index b5e1fb82..ca19e79b 100644 --- a/compiler/verify/klayout.py +++ b/compiler/verify/klayout.py @@ -41,6 +41,16 @@ def write_drc_script(cell_name, gds_name, extract, final_verification, output_pa else: debug.warning("Could not locate file: {}".format(full_drc_file)) + # Copy .gds file into the output directory + if os.path.isabs(gds_name): + shutil.copy(gds_name, output_path) + gds_name = os.path.basename(gds_name) + + # Copy .sp file into the output directory + if sp_name and os.path.isabs(sp_name): + shutil.copy(sp_name, output_path) + sp_name = os.path.basename(sp_name) + # Create an auxiliary script to run calibre with the runset run_file = output_path + "run_drc.sh" f = open(run_file, "w") @@ -111,14 +121,29 @@ def write_lvs_script(cell_name, gds_name, sp_name, final_verification=False, out else: debug.warning("Could not locate file: {}".format(full_lvs_file)) + # Copy .gds file into the output directory + if os.path.isabs(gds_name): + shutil.copy(gds_name, output_path) + gds_name = os.path.basename(gds_name) + + # Copy .sp file into the output directory + if os.path.isabs(sp_name): + shutil.copy(sp_name, output_path) + sp_name = os.path.basename(sp_name) + run_file = output_path + "/run_lvs.sh" f = open(run_file, "w") f.write("#!/bin/sh\n") - cmd = "{0} -b -r {1} -rd input={2} -rd report={4}.lvs.report -rd schematic={3} -rd target_netlist={4}.spice".format(OPTS.lvs_exe[1], - lvs_file, - gds_name, - sp_name, - cell_name) + if final_verification: + connect_supplies = "" + else: + connect_supplies = "-rd connect_supplies=1" + cmd = "{0} -b -r {1} -rd input={2} -rd report={4}.lvs.report -rd schematic={3} -rd target_netlist={4}.spice {5}".format(OPTS.lvs_exe[1], + lvs_file, + gds_name, + sp_name, + cell_name, + connect_supplies) f.write(cmd) f.write("\n") f.close() diff --git a/technology/freepdk45/tech/freepdk45.lylvs b/technology/freepdk45/tech/freepdk45.lylvs index 5d8e50b3..64fde014 100644 --- a/technology/freepdk45/tech/freepdk45.lylvs +++ b/technology/freepdk45/tech/freepdk45.lylvs @@ -205,9 +205,14 @@ connect(metal10, metal10_pin) # Global schematic.simplify -connect_global(pwell, "PWELL") -connect_global(nwell, "NWELL") -connect_global(bulk, "BULK") +if $connect_supplies + connect_implicit("vdd") + connect_implicit("gnd") +end + +#connect_global(pwell, "PWELL") +#connect_global(nwell, "NWELL") +#connect_global(bulk, "BULK") #for pat in %w(pnand*_0 and2_dec_0 port_address* replica_bitcell_array) # connect_explicit(pat, [ "NWELL", "vdd" ]) diff --git a/technology/freepdk45/tech/tech.py b/technology/freepdk45/tech/tech.py index fd477077..2ae9c06c 100644 --- a/technology/freepdk45/tech/tech.py +++ b/technology/freepdk45/tech/tech.py @@ -480,5 +480,8 @@ spice["sa_transconductance"] = (spice["mobility_n"])*spice["cox"]*(parameter["sa drc_name = "calibre" lvs_name = "calibre" pex_name = "calibre" +drc_name = "klayout" +lvs_name = "klayout" +pex_name = "klayout" blackbox_bitcell = False diff --git a/technology/scn4m_subm/tech/scn4m_subm.lylvs b/technology/scn4m_subm/tech/scn4m_subm.lylvs new file mode 100644 index 00000000..16dd5c6e --- /dev/null +++ b/technology/scn4m_subm/tech/scn4m_subm.lylvs @@ -0,0 +1,214 @@ + + + + + lvs + + + + false + false + + true + lvs_scripts + tools_menu.lvs.end + dsl + lvs-dsl-xml + # +# Extraction for freePDK45 +# +############################ +tstart = Time.now + +# optionnal for a batch launch : klayout -b -rd input=my_layout.gds -rd report=my_report.lyrdb -rd schematic=reference_netlist.cir -rd target_netlist=extracted_netlist.cir -r lvs_freepdk45.lvs +if $input + source($input) +end + +if $report + report_lvs($report) +else + report_lvs("lvs_report.lvsdb") +end + +if $schematic +#reference netlist + schematic($schematic) +else + schematic(RBA::CellView::active.filename.sub(/\.(oas|gds|oas.gz|gds.gz)$/, ".sp")) +end + +# true: use net names instead of numbers +# false: use numbers for nets +spice_with_net_names = true + +# true: put in comments with details +# false: no comments +spice_with_comments = true + +if $target_netlist + target_netlist($target_netlist) +else + # target_netlist("netlist.cir", write_spice(spice_with_net_names, spice_with_comments), "The netlist comment goes here.") + target_netlist(File.join(File.dirname(RBA::CellView::active.filename), source.cell_name+"_extracted.cir"), write_spice(spice_with_net_names, spice_with_comments), "Extracted by KLayout on : #{Time.now.strftime("%d/%m/%Y %H:%M")}") +end + +# Hierarchical mode +deep +# Use 4 CPU cores +threads(4) +# Print details +verbose(true) + + +# layers definitions +######################## +info("Layers definitions") + + DNW = input(38,0) + nwell = input(42,0) + pwell = input(41,0) + CW = input(59,0) + active = input(43,0) + TA = input(60,0) + PBase = input(58,0) + poly = input(46,0) + SB = input(29,0) + nplus = input(45,0) + pplus = input(44,0) + PO2 = input(56,0) + HR = input(34,0) + Contact = input(25,0) + ContactPoly = input(47,0) + ContactActive = input(48,0) + ContactPoly2 = input(55, 0) + CT = Contact + ContactPoly + ContactActive + ContactPoly2 + M1 = input(49,0) + V1 = input(50,0) + M2 = input(51,0) + V2 = input(61,0) + M3 = input(62,0) + V3 = input(30,0) + M4 = input(31,0) + CTM = input(35,0) + V4 = input(32,0) + M5 = input(33,0) + V5 = input(36,0) + M6 = input(37,0) + Glass = input(52,0) + Pads = input(26,0) + +# layers processing +######################## +info("Layers processing") + +# Bulk layer for terminal provisioning +bulk = polygon_layer + +active_in_nwell = active & nwell +pactive = active_in_nwell & pplus +ntie = active_in_nwell & nplus +pgate = pactive & poly +psd = pactive - pgate + +active_in_pwell = active & pwell +nactive = active_in_pwell & nplus +ptie = active_in_pwell & pplus +ngate = nactive & poly +nsd = nactive - ngate + + +cheat("cell_6t", "dummy_cell_6t", "cell_1rw", "dummy_cell_1rw", "cell_2rw", "dummy_cell_2rw", "dff","wordline_driver_0") { + +# PMOS transistor device extraction +extract_devices(mos4("p"), { "SD" => psd, "G" => pgate, "tS" => psd, "tD" => psd, "tG" => poly, "W" => nwell }) + +# NMOS transistor device extraction +extract_devices(mos4("n"), { "SD" => nsd, "G" => ngate, "tS" => nsd, "tD" => nsd, "tG" => poly, "W" => pwell }) + +} + +# Define connectivity for netlist extraction + +# Inter-layer +connect(nwell, ntie) +connect(pwell, ptie) +connect(CT, ntie) +connect(CT, ptie) +connect(psd, CT) +connect(nsd, CT) +connect(poly, CT) +connect(CT, M1) +connect(CT, M1) +connect(M1, V1) +connect(V1, M2) +connect(M2, V2) +connect(V2, M3) +connect(M3, V3) +connect(V3, M4) +connect(M4, V4) +connect(V4, M5) +connect(M5, V5) +connect(V5, M6) + + +# Global +schematic.simplify + +if $connect_supplies + connect_implicit("vdd") + connect_implicit("gnd") +end + +connect_global(pwell, "PWELL") +connect_global(nwell, "NWELL") +#connect_global(bulk, "BULK") + +#for pat in %w(pnand*_0 and2_dec_0 port_address* replica_bitcell_array) +# connect_explicit(pat, [ "NWELL", "vdd" ]) +# connect_explicit(pat, [ "BULK", "PWELL", "gnd" ]) +#end + +#for pat in %w(XOR* XNOR* TLAT* TINV* TBUF* SDFF* OR* OAI* NOR* NAND* MUX* LOGIC* INV* HA* FILLCELL* +# FA* DLL* DLH* DFF* DFFS* DFFR* DFFRS* CLKGATE* CLKBUF* BUF* AOI* ANTENNA* AND*) +# connect_explicit(pat, [ "NWELL", "VDD" ]) +# connect_explicit(pat, [ "BULK", "VSS" ]) +#end + +# Actually performs the extraction +netlist # ... not really required + +# Flatten cells which are present in one netlist only +align +# SIMPLIFICATION of the netlist +#netlist.make_top_level_pins +#netlist.combine_devices +#netlist.purge +#netlist.purge_nets +netlist.simplify + +# Tolerances for the devices extracted parameters +# tolerance(device_class_name, parameter_name [, :absolute => absolute_tolerance] [, :relative => relative_tolerance]) +tolerance("P", "W", :absolute => 1.nm, :relative => 0.001) +tolerance("N", "W", :absolute => 1.nm, :relative => 0.001) + +#max_res(1000000) +#min_caps(1e-15) + +max_branch_complexity(65536) +max_depth(16) + +if ! compare + #raise "ERROR : Netlists don't match" + puts "ERROR : Netlists don't match" +else + puts "CONGRATULATIONS! Netlists match." +end + +# time spent for the LVS +time = Time.now +hours = ((time - tstart)/3600).to_i +minutes = ((time - tstart)/60 - hours * 60).to_i +seconds = ((time - tstart) - (minutes * 60 + hours * 3600)).to_i +$stdout.write "LVS finished at : #{time.hour}:#{time.min}:#{time.sec} - LVS duration = #{hours} hrs. #{minutes} min. #{seconds} sec.\n" + diff --git a/technology/scn4m_subm/tech/tech.py b/technology/scn4m_subm/tech/tech.py index a8c44996..374ba4c8 100644 --- a/technology/scn4m_subm/tech/tech.py +++ b/technology/scn4m_subm/tech/tech.py @@ -428,5 +428,8 @@ spice["sa_transconductance"] = (spice["mobility_n"])*spice["cox"]*(parameter["sa drc_name = "magic" lvs_name = "netgen" pex_name = "magic" +drc_name = "klayout" +lvs_name = "klayout" +pex_name = "klayout" blackbox_bitcell = False