blob: 506ce78f5a0b2820e7f3a309ad6877f505a17ff6 [file] [log] [blame]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001###
2### Source file sky130.tcl
3### Process this file with the preprocessor script
4###
5#-----------------------------------------------------
6# Magic/TCL design kit for SKYWATER TECHNAME
7#-----------------------------------------------------
8# Tim Edwards
Tim Edwardsd7289eb2020-09-10 21:48:31 -04009# Revision 1 ALPHA 9/10/2020
Tim Edwards55f4d0e2020-07-05 15:41:02 -040010#-----------------------------------------------------
11
12set TECHPATH STAGING_PATH
13if [catch {set PDKPATH}] {set PDKPATH ${TECHPATH}/TECHNAME}
14set PDKNAME TECHNAME
15# "sky130" is the namespace used for all devices
16set PDKNAMESPACE sky130
17puts stdout "Loading TECHNAME Device Generator Menu ..."
18
19# Initialize toolkit menus to the wrapper window
20
21global Opts
22namespace eval sky130 {}
23
24# Set the window callback
25if [catch {set Opts(callback)}] {set Opts(callback) ""}
26set Opts(callback) [subst {sky130::addtechmenu \$framename; $Opts(callback)}]
27
28# if {![info exists Opts(cmdentry)]} {set Opts(cmdentry) 1}
29
30# Set options specific to this PDK
31set Opts(hidelocked) 1
32set Opts(hidespecial) 1
33
34# Create new "tool" proc that doesn't have the netlist tool.
35proc magic::nexttool {} {
36 global Opts
37
38 # Don't attempt to switch tools while a selection drag is active
39 if {$Opts(motion) == {}} {
40 switch $Opts(tool) {
41 box { magic::tool wiring }
42 wiring { magic::tool pick }
43 default { magic::tool box }
44 }
45 }
46}
47
48# This shoule be part of sitedef. . .
49macro space magic::nexttool
50
51# Wrap the closewrapper procedure so that closing the last
52# window is equivalent to quitting.
53if {[info commands closewrapper] == "closewrapper"} {
54 rename closewrapper closewrapperonly
55 proc closewrapper { framename } {
56 if {[llength [windownames all]] <= 1} {
57 magic::quit
58 } else {
59 closewrapperonly $framename
60 }
61 }
62}
63
64# Remove maze router layers from the toolbar by locking them
65tech lock fence,magnet,rotate
66
67namespace eval sky130 {
68 namespace path {::tcl::mathop ::tcl::mathfunc}
69
70 set ruleset [dict create]
71
72 # Process DRC rules (magic style)
73
74 dict set ruleset poly_surround 0.08 ;# Poly surrounds contact
75 dict set ruleset diff_surround 0.06 ;# Diffusion surrounds contact
76 dict set ruleset gate_to_diffcont 0.145 ;# Gate to diffusion contact center
77 dict set ruleset gate_to_polycont 0.275 ;# Gate to poly contact center
78 dict set ruleset gate_extension 0.13 ;# Poly extension beyond gate
79 dict set ruleset diff_extension 0.29 ;# Diffusion extension beyond gate
80 dict set ruleset contact_size 0.17 ;# Minimum contact size
81 dict set ruleset via_size 0.17 ;# Minimum via size
82 dict set ruleset metal_surround 0.08 ;# Local interconnect overlaps contact
83 dict set ruleset sub_surround 0.18 ;# Sub/well surrounds diffusion
84 dict set ruleset diff_spacing 0.28 ;# Diffusion spacing rule
85 dict set ruleset poly_spacing 0.21 ;# Poly spacing rule
86 dict set ruleset diff_poly_space 0.075 ;# Diffusion to poly spacing rule
87 dict set ruleset diff_gate_space 0.20 ;# Diffusion to gate poly spacing rule
88 dict set ruleset metal_spacing 0.23 ;# Local interconnect spacing rule
89 dict set ruleset mmetal_spacing 0.14 ;# Metal spacing rule (above local interconnect)
90 dict set ruleset res_to_cont 0.20 ;# resistor to contact center
91 dict set ruleset res_diff_space 0.20 ;# resistor to guard ring
92}
93
94#-----------------------------------------------------
95# magic::addtechmenu
96#-----------------------------------------------------
97
98proc sky130::addtechmenu {framename} {
99 global Winopts Opts
100
101 # Check for difference between magic 8.1.125 and earlier, and 8.1.126 and later
102 if {[catch {${framename}.titlebar cget -height}]} {
103 set layoutframe ${framename}.pane.top
104 } else {
105 set layoutframe ${framename}
106 }
107
108 # List of devices is long. Divide into two sections for active and passive deivces
109 magic::add_toolkit_menu $layoutframe "Devices 1" pdk1
110
111 magic::add_toolkit_command $layoutframe "nmos (MOSFET)" \
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400112 "magic::gencell sky130::sky130_fd_pr__nfet_01v8" pdk1
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400113 magic::add_toolkit_command $layoutframe "pmos (MOSFET)" \
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400114 "magic::gencell sky130::sky130_fd_pr__pfet_01v8" pdk1
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400115
116 magic::add_toolkit_separator $layoutframe pdk1
117 magic::add_toolkit_command $layoutframe "n-diode" \
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400118 "magic::gencell sky130::sky130_fd_pr__diode_pw2nd_05v5" pdk1
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400119 magic::add_toolkit_command $layoutframe "p-diode" \
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400120 "magic::gencell sky130::sky130_fd_pr__diode_pd2nw_05v5" pdk1
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400121
122 magic::add_toolkit_separator $layoutframe pdk1
123 magic::add_toolkit_command $layoutframe "MOS varactor" \
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400124 "magic::gencell sky130::sky130_fd_pr__cap_var_lvt" pdk1
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400125 magic::add_toolkit_separator $layoutframe pdk1
126
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400127 magic::add_toolkit_command $layoutframe "NPN 1.0 x 1.0" \
Tim Edwardsc6202ef2020-09-20 17:16:33 -0400128 "magic::gencell sky130::sky130_fd_pr__rf_npn_05v5_W1p00L1p00" pdk1
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400129 magic::add_toolkit_command $layoutframe "NPN 1.0 x 2.0" \
Tim Edwardsc6202ef2020-09-20 17:16:33 -0400130 "magic::gencell sky130::sky130_fd_pr__rf_npn_05v5_W1p00L2p00" pdk1
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400131 magic::add_toolkit_command $layoutframe "PNP 3.4 x 3.4" \
132 "magic::gencell sky130::sky130_fd_pr__pnp_05v5_W3p40L3p40" pdk1
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400133
134 magic::add_toolkit_separator $layoutframe pdk1
135
Tim Edwardsc6202ef2020-09-20 17:16:33 -0400136 magic::add_toolkit_command $layoutframe "inductor 1" \
137 "magic::gencell sky130::sky130_fd_pr__rf_test_coil1" pdk1
138 magic::add_toolkit_command $layoutframe "inductor 2" \
139 "magic::gencell sky130::sky130_fd_pr__rf_test_coil2" pdk1
140 magic::add_toolkit_command $layoutframe "inductor 3" \
141 "magic::gencell sky130::sky130_fd_pr__rf_test_coil3" pdk1
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400142
143 magic::add_toolkit_separator $layoutframe pdk1
144
145 magic::add_toolkit_command $layoutframe "substrate contact (1.8V)" \
146 "sky130::subconn_draw" pdk1
147 magic::add_toolkit_command $layoutframe "substrate contact (5.0V)" \
148 "sky130::mvsubconn_draw" pdk1
149 magic::add_toolkit_command $layoutframe "deep n-well region" \
150 "sky130::deep_nwell_draw" pdk1
151 magic::add_toolkit_command $layoutframe "mcon" \
152 "sky130::mcon_draw" pdk1
153 magic::add_toolkit_command $layoutframe "via1" \
154 "sky130::via1_draw" pdk1
155 magic::add_toolkit_command $layoutframe "via2" \
156 "sky130::via2_draw" pdk1
157#ifdef METAL5
158 magic::add_toolkit_command $layoutframe "via3" \
159 "sky130::via3_draw" pdk1
160 magic::add_toolkit_command $layoutframe "via4" \
161 "sky130::via4_draw" pdk1
162#endif (METAL5)
163
164
165 magic::add_toolkit_menu $layoutframe "Devices 2" pdk2
166
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400167 magic::add_toolkit_command $layoutframe "n-diff resistor (1.8V) - 120 Ohm/sq" \
168 "magic::gencell sky130::sky130_fd_pr__res_generic_nd" pdk2
169 magic::add_toolkit_command $layoutframe "p-diff resistor (1.8V) - 197 Ohm/sq" \
170 "magic::gencell sky130::sky130_fd_pr__res_generic_pd" pdk2
171 magic::add_toolkit_command $layoutframe "n-diff resistor (5.0V) - 114 Ohm/sq" \
Tim Edwards0ee0f182020-11-21 16:15:07 -0500172 "magic::gencell sky130::sky130_fd_pr__res_generic_nd__hv" pdk2
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400173 magic::add_toolkit_command $layoutframe "p-diff resistor (5.0V) - 191 Ohm/sq" \
Tim Edwards0ee0f182020-11-21 16:15:07 -0500174 "magic::gencell sky130::sky130_fd_pr__res_generic_pd__hv" pdk2
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400175
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400176 magic::add_toolkit_command $layoutframe "poly resistor - 48.2 Ohm/sq" \
177 "magic::gencell sky130::sky130_fd_pr__res_generic_po" pdk2
178 magic::add_toolkit_command $layoutframe "poly resistor - 319.8 Ohm/sq" \
179 "magic::gencell sky130::sky130_fd_pr__res_high_po_0p35" pdk2
180 magic::add_toolkit_command $layoutframe "poly resistor - 2000 Ohm/sq" \
181 "magic::gencell sky130::sky130_fd_pr__res_xhigh_po_0p35" pdk2
182 magic::add_toolkit_command $layoutframe "p-well resistor - 3050 Ohm/sq" \
183 "magic::gencell sky130::sky130_fd_pr__res_iso_pw" pdk2
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400184 magic::add_toolkit_separator $layoutframe pdk2
185
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400186 magic::add_toolkit_command $layoutframe "l1 metal resistor - 12.2 Ohm/sq" \
187 "magic::gencell sky130::sky130_fd_pr__res_generic_l1" pdk2
188 magic::add_toolkit_command $layoutframe "m1 metal resistor - 125 mOhm/sq" \
189 "magic::gencell sky130::sky130_fd_pr__res_generic_m1" pdk2
190 magic::add_toolkit_command $layoutframe "m2 metal resistor - 125 mOhm/sq" \
191 "magic::gencell sky130::sky130_fd_pr__res_generic_m2" pdk2
192 magic::add_toolkit_command $layoutframe "m3 metal resistor - 47 mOhm/sq" \
193 "magic::gencell sky130::sky130_fd_pr__res_generic_m3" pdk2
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400194#ifdef METAL5
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400195 magic::add_toolkit_command $layoutframe "m4 metal resistor - 47 mOhm/sq" \
196 "magic::gencell sky130::sky130_fd_pr__res_generic_m4" pdk2
197 magic::add_toolkit_command $layoutframe "m5 metal resistor - 29 mOhm/sq" \
198 "magic::gencell sky130::sky130_fd_pr__res_generic_m5" pdk2
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400199#endif (METAL5)
200
201#ifdef MIM
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400202 magic::add_toolkit_command $layoutframe "MiM cap - 1fF/um^2 (metal3)" \
203 "magic::gencell sky130::sky130_fd_pr__cap_mim_m3_1" pdk2
204 magic::add_toolkit_command $layoutframe "MiM cap - 1fF/um^2 (metal4)" \
205 "magic::gencell sky130::sky130_fd_pr__cap_mim_m3_2" pdk2
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400206#endif (MIM)
207 magic::add_toolkit_separator $layoutframe pdk2
208
Tim Edwardsc6202ef2020-09-20 17:16:33 -0400209 magic::add_toolkit_command $layoutframe "vpp 11.5x11.7 m1-m4, li/m5 shield" \
210 "magic::gencell sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldl1m5" pdk2
211 magic::add_toolkit_command $layoutframe "vpp 11.5x11.7 m1-m2" \
212 "magic::gencell sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_noshield" pdk2
213 magic::add_toolkit_command $layoutframe "vpp 8.6x7.8 m1-m2 l1 shield" \
214 "magic::gencell sky130::sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_l1shield" pdk2
215 magic::add_toolkit_command $layoutframe "vpp 4.4x4.6 m1-m2 l1 shield" \
216 "magic::gencell sky130::sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_l1shield" pdk2
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400217
218 ${layoutframe}.titlebar.mbuttons.drc.toolmenu add command -label "DRC Routing" -command {drc style drc(routing)}
219
220 # Add command entry window by default if enabled
221 if {[info exists Opts(cmdentry)]} {
222 set Winopts(${framename},cmdentry) $Opts(cmdentry)
223 } else {
224 set Winopts(${framename},cmdentry) 0
225 }
226 if {$Winopts(${framename},cmdentry) == 1} {
227 addcommandentry $framename
228 }
229}
230
231#----------------------------------------------------------------
232
Tim Edwards0ee0f182020-11-21 16:15:07 -0500233proc sky130::mcon_draw {{dir default}} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400234 set w [magic::i2u [box width]]
235 set h [magic::i2u [box height]]
236 if {$w < 0.17} {
237 puts stderr "Mcon width must be at least 0.17um"
238 return
239 }
240 if {$h < 0.17} {
241 puts stderr "Mcon height must be at least 0.17um"
242 return
243 }
Tim Edwards8ebc7742020-11-22 11:41:28 -0500244 suspendall
Tim Edwards0b1a8732020-12-30 15:15:08 -0500245 paint mcon
Tim Edwards0ee0f182020-11-21 16:15:07 -0500246 pushbox
247 if {($w < $h) || ($dir == "vert")} {
248 box grow e 0.03um
249 box grow w 0.03um
250 box grow n 0.06um
251 box grow s 0.06um
252 paint m1
253 } else {
254 box grow n 0.03um
255 box grow s 0.03um
256 box grow e 0.06um
257 box grow w 0.06um
258 paint m1
259 }
260 popbox
261 resumeall
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400262}
263
264proc sky130::via1_draw {} {
265 set w [magic::i2u [box width]]
266 set h [magic::i2u [box height]]
267 if {$w < 0.26} {
268 puts stderr "Via1 width must be at least 0.26um"
269 return
270 }
271 if {$h < 0.26} {
272 puts stderr "Via1 height must be at least 0.26um"
273 return
274 }
Tim Edwards8ebc7742020-11-22 11:41:28 -0500275 suspendall
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400276 paint via1
277 box grow n 0.05um
278 box grow s 0.05um
279 paint m2
280 box grow n -0.05um
281 box grow s -0.05um
282 box grow e 0.05um
283 box grow w 0.05um
284 paint m1
285 box grow e -0.05um
286 box grow w -0.05um
Tim Edwards0ee0f182020-11-21 16:15:07 -0500287 resumeall
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400288}
289
290proc sky130::via2_draw {} {
291 set w [magic::i2u [box width]]
292 set h [magic::i2u [box height]]
293 if {$w < 0.28} {
294 puts stderr "Via2 width must be at least 0.28um"
295 return
296 }
297 if {$h < 0.28} {
298 puts stderr "Via2 height must be at least 0.28um"
299 return
300 }
Tim Edwards8ebc7742020-11-22 11:41:28 -0500301 suspendall
Tim Edwardsb427e3b2020-11-22 15:28:54 -0500302 pushbox
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400303 paint via2
304 box grow n 0.05um
305 box grow s 0.05um
306 paint m2
Tim Edwardsb427e3b2020-11-22 15:28:54 -0500307 popbox
308 pushbox
309 box grow n 0.025um
310 box grow s 0.025um
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400311 box grow e 0.05um
312 box grow w 0.05um
313 paint m3
Tim Edwardsb427e3b2020-11-22 15:28:54 -0500314 popbox
Tim Edwards0ee0f182020-11-21 16:15:07 -0500315 resumeall
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400316}
317
318#ifdef METAL5
319proc sky130::via3_draw {} {
320 set w [magic::i2u [box width]]
321 set h [magic::i2u [box height]]
322 if {$w < 0.32} {
323 puts stderr "Via3 width must be at least 0.32um"
324 return
325 }
326 if {$h < 0.32} {
327 puts stderr "Via3 height must be at least 0.32um"
328 return
329 }
Tim Edwards8ebc7742020-11-22 11:41:28 -0500330 suspendall
Tim Edwardsb427e3b2020-11-22 15:28:54 -0500331 pushbox
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400332 paint via3
Tim Edwardsb427e3b2020-11-22 15:28:54 -0500333 box grow n 0.005um
334 box grow s 0.005um
335 box grow e 0.005um
336 box grow w 0.005um
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400337 paint m4
Tim Edwardsb427e3b2020-11-22 15:28:54 -0500338 popbox
339 pushbox
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400340 box grow e 0.05um
341 box grow w 0.05um
342 paint m3
Tim Edwardsb427e3b2020-11-22 15:28:54 -0500343 popbox
Tim Edwards0ee0f182020-11-21 16:15:07 -0500344 resumeall
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400345}
346
347proc sky130::via4_draw {} {
348 set w [magic::i2u [box width]]
349 set h [magic::i2u [box height]]
350 if {$w < 1.18} {
351 puts stderr "Via3 width must be at least 1.18um"
352 return
353 }
354 if {$h < 1.18} {
355 puts stderr "Via3 height must be at least 1.18um"
356 return
357 }
Tim Edwards8ebc7742020-11-22 11:41:28 -0500358 suspendall
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400359 paint via4
Tim Edwardsb427e3b2020-11-22 15:28:54 -0500360 pushbox
361 box grow n 0.12um
362 box grow s 0.12um
363 box grow e 0.12um
364 box grow w 0.12um
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400365 paint m5
Tim Edwardsb427e3b2020-11-22 15:28:54 -0500366 popbox
Tim Edwards0ee0f182020-11-21 16:15:07 -0500367 resumeall
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400368}
369#endif (METAL5)
370
371proc sky130::subconn_draw {} {
372 set w [magic::i2u [box width]]
373 set h [magic::i2u [box height]]
374 if {$w < 0.17} {
375 puts stderr "Substrate tap width must be at least 0.17um"
376 return
377 }
378 if {$h < 0.17} {
379 puts stderr "Substrate tap height must be at least 0.17um"
380 return
381 }
Tim Edwards8ebc7742020-11-22 11:41:28 -0500382 suspendall
Tim Edwardsb427e3b2020-11-22 15:28:54 -0500383 paint psc
384 pushbox
385 if {$w > $h} {
386 box grow e 0.08um
387 box grow w 0.08um
388 paint li
389 box grow e 0.04um
390 box grow w 0.04um
391 } else {
392 box grow n 0.08um
393 box grow s 0.08um
394 paint li
395 box grow n 0.04um
396 box grow s 0.04um
397 }
398 paint psd
399 popbox
Tim Edwards0ee0f182020-11-21 16:15:07 -0500400 resumeall
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400401}
402
403#----------------------------------------------------------------
404
405proc sky130::mvsubconn_draw {} {
406 set w [magic::i2u [box width]]
407 set h [magic::i2u [box height]]
408 if {$w < 0.17} {
409 puts stderr "Substrate tap width must be at least 0.17um"
410 return
411 }
412 if {$h < 0.17} {
413 puts stderr "Substrate tap height must be at least 0.17um"
414 return
415 }
Tim Edwards8ebc7742020-11-22 11:41:28 -0500416 suspendall
Tim Edwardsb427e3b2020-11-22 15:28:54 -0500417 paint mvpsc
418 pushbox
419 if {$w > $h} {
420 box grow e 0.08um
421 box grow w 0.08um
422 paint li
423 box grow e 0.04um
424 box grow w 0.04um
425 } else {
426 box grow n 0.08um
427 box grow s 0.08um
428 paint li
429 box grow n 0.04um
430 box grow s 0.04um
431 }
432 paint mvpsd
433 popbox
Tim Edwards0ee0f182020-11-21 16:15:07 -0500434 resumeall
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400435}
436
437#----------------------------------------------------------------
438
439proc sky130::deep_nwell_draw {} {
440 set w [magic::i2u [box width]]
441 set h [magic::i2u [box height]]
442 if {$w < 3.0} {
443 puts stderr "Deep-nwell region width must be at least 3.0um"
444 return
445 }
446 if {$h < 3.0} {
447 puts stderr "Deep-nwell region height must be at least 3.0um"
448 return
449 }
450 suspendall
451 tech unlock *
452 paint dnwell
453 pushbox
454 pushbox
455 box grow c 0.4um
456 paint nwell
457 box grow c -1.43um
458 erase nwell
459 popbox
460 box grow c 0.03um
461
462 pushbox
463 box width 0
464 box grow c 0.085um
465 paint li
466 pushbox
467 box grow n -0.3um
468 box grow s -0.3um
469 paint nsc
470 popbox
471 box grow c 0.1um
472 paint nsd
473 popbox
474
475 pushbox
476 box height 0
477 box grow c 0.085um
478 paint li
479 pushbox
480 box grow e -0.3um
481 box grow w -0.3um
482 paint nsc
483 popbox
484 box grow c 0.1um
485 paint nsd
486 popbox
487
488 pushbox
489 box move n [box height]i
490 box height 0
491 box grow c 0.085um
492 paint li
493 pushbox
494 box grow e -0.3um
495 box grow w -0.3um
496 paint nsc
497 popbox
498 box grow c 0.1um
499 paint nsd
500 popbox
501
502 pushbox
503 box move e [box width]i
504 box width 0
505 box grow c 0.085um
506 paint li
507 pushbox
508 box grow n -0.3um
509 box grow s -0.3um
510 paint nsc
511 box grow c 0.1um
512 paint nsd
513 popbox
514
515 popbox
516 tech revert
517 resumeall
518}
519
520#----------------------------------------------------------------
521
522proc sky130::res_recalc {field parameters} {
523 set snake 0
524 set sterm 0.0
525 set caplen 0
526 # Set a local variable for each parameter (e.g., $l, $w, etc.)
527 foreach key [dict keys $parameters] {
528 set $key [dict get $parameters $key]
529 }
530 set val [magic::spice2float $val]
531 set l [magic::spice2float $l]
532 set w [magic::spice2float $w]
533
534 if {$snake == 0} {
535 # Straight resistor calculation
536 switch $field {
537 val { set l [expr ($val * ($w - $dw) - (2 * $term)) / $rho]
538 set w [expr ((2 * $term + $l * $rho) / $val) + $dw]
539 }
540 w { set val [expr (2 * $term + $l * $rho) / ($w - $dw)]
541 set l [expr ($val * ($w - $dw) - (2 * $term)) / $rho]
542 }
543 l { set val [expr (2 * $term + $l * $rho) / ($w - $dw)]
544 set w [expr ((2 * $term + $l * $rho) / $val) + $dw]
545 }
546 }
547 } else {
548 set term [expr $term + $sterm]
549 # Snake resistor calculation
550 switch $field {
551 val { set l [expr (($val - $rho * ($nx - 1)) * ($w - $dw) \
552 - (2 * $term) - ($rho * $caplen * ($nx - 1))) \
553 / ($rho * $nx)]
554
555 set w [expr ((2 * $term + $l * $rho * $nx \
556 + $caplen * $rho * ($nx - 1)) \
557 / ($val - $rho * ($nx - 1))) + $dw]
558 }
559 w { set val [expr $rho * ($nx - 1) + ((2 * $term) \
560 + ($rho * $l * $nx) + ($rho * $caplen * ($nx - 1))) \
561 / ($w - $dw)]
562
563 set l [expr (($val - $rho * ($nx - 1)) * ($w - $dw) \
564 - (2 * $term) - ($rho * $caplen * ($nx - 1))) \
565 / ($rho * $nx)]
566 }
567 l { set val [expr $rho * ($nx - 1) + ((2 * $term) \
568 + ($rho * $l * $nx) + ($rho * $caplen * ($nx - 1))) \
569 / ($w - $dw)]
570
571 set w [expr ((2 * $term + $l * $rho * $nx \
572 + $caplen * $rho * ($nx - 1)) \
573 / ($val - $rho * ($nx - 1))) + $dw]
574 }
575 }
576 }
577
578 set val [magic::3digitpastdecimal $val]
579 set w [magic::3digitpastdecimal $w]
580 set l [magic::3digitpastdecimal $l]
581
582 dict set parameters val $val
583 dict set parameters w $w
584 dict set parameters l $l
585
586 return $parameters
587}
588
589#----------------------------------------------------------------
590# Drawn diode routines
591#----------------------------------------------------------------
592
593proc sky130::diode_recalc {field parameters} {
594 # Set a local variable for each parameter (e.g., $l, $w, etc.)
595 foreach key [dict keys $parameters] {
596 set $key [dict get $parameters $key]
597 }
598 switch $field {
599 area { puts stdout "area changed" }
600 peri { puts stdout "perimeter changed" }
601 w { puts stdout "width changed" }
602 l { puts stdout "length changed" }
603 }
604 dict set parameters area $area
605 dict set parameters peri $peri
606 dict set parameters w $w
607 dict set parameters l $l
608}
609
610#----------------------------------------------------------------
611# diode: Conversion from SPICE netlist parameters to toolkit
612#----------------------------------------------------------------
613
614proc sky130::diode_convert {parameters} {
615 set pdkparams [dict create]
616 dict for {key value} $parameters {
617 switch -nocase $key {
618 l -
619 w -
620 peri {
621 # Length, width, and perimeter are converted to units of microns
622 set value [magic::spice2float $value]
623 # set value [expr $value * 1e6]
624 set value [magic::3digitpastdecimal $value]
625 dict set pdkparams [string tolower $key] $value
626 }
627 area {
628 # area also converted to units of microns
629 set value [magic::spice2float $value]
630 # set value [expr $value * 1e12]
631 set value [magic::3digitpastdecimal $value]
632 dict set pdkparams [string tolower $key] $value
633 }
634 m {
635 # Convert m to ny
636 dict set pdkparams ny $value
637 }
638 }
639 }
640 return $pdkparams
641}
642
643#----------------------------------------------------------------
644# diode: Interactively specifies the fixed layout parameters
645#----------------------------------------------------------------
646
647proc sky130::diode_dialog {device parameters} {
648 # Editable fields: w, l, area, perim, nx, ny
649
650 magic::add_entry area "Area (um^2)" $parameters
651 magic::add_entry peri "Perimeter (um)" $parameters
652 sky130::compute_aptot $parameters
653 magic::add_message atot "Total area (um^2)" $parameters
654 magic::add_message ptot "Total perimeter (um)" $parameters
655 magic::add_entry l "Length (um)" $parameters
656 magic::add_entry w "Width (um)" $parameters
657 magic::add_entry nx "X Repeat" $parameters
658 magic::add_entry ny "Y Repeat" $parameters
659
660 if {[dict exists $parameters compatible]} {
661 set sellist [dict get $parameters compatible]
662 magic::add_selectlist gencell "Device type" $sellist $parameters $device
663 }
664
665 if {[dict exists $parameters doverlap]} {
666 magic::add_checkbox doverlap "Overlap at end contact" $parameters
667 }
668 if {[dict exists $parameters elc]} {
669 magic::add_checkbox elc "Add left end contact" $parameters
670 }
671 if {[dict exists $parameters erc]} {
672 magic::add_checkbox erc "Add right end contact" $parameters
673 }
674 if {[dict exists $parameters etc]} {
675 magic::add_checkbox etc "Add top end contact" $parameters
676 }
677 if {[dict exists $parameters ebc]} {
678 magic::add_checkbox ebc "Add bottom end contact" $parameters
679 }
680
681 if {[dict exists $parameters guard]} {
682 magic::add_checkbox full_metal "Full metal guard ring" $parameters
683 }
684 if {[dict exists $parameters glc]} {
685 magic::add_checkbox glc "Add left guard ring contact" $parameters
686 }
687 if {[dict exists $parameters grc]} {
688 magic::add_checkbox grc "Add right guard ring contact" $parameters
689 }
690 if {[dict exists $parameters gtc]} {
691 magic::add_checkbox gtc "Add top guard ring contact" $parameters
692 }
693 if {[dict exists $parameters gbc]} {
694 magic::add_checkbox gbc "Add bottom guard ring contact" $parameters
695 }
Tim Edwards0ee0f182020-11-21 16:15:07 -0500696 if {[dict exists $parameters viagb]} {
697 magic::add_entry viagb "Bottom guard ring via coverage \[+/-\](%)" $parameters
698 }
699 if {[dict exists $parameters viagt]} {
700 magic::add_entry viagt "Top guard ring via coverage \[+/-\](%)" $parameters
701 }
702 if {[dict exists $parameters viagr]} {
703 magic::add_entry viagr "Right guard ring via coverage \[+/-\](%)" $parameters
704 }
705 if {[dict exists $parameters viagl]} {
706 magic::add_entry viagl "Left guard ring via coverage \[+/-\](%)" $parameters
707 }
708
709 if {[dict exists $parameters vias]} {
710 magic::add_checkbox vias "Add vias over contacts" $parameters
711 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400712
713 magic::add_dependency sky130::diode_recalc $device sky130 l w area peri
714
715 # magic::add_checkbox dummy "Add dummy" $parameters
716}
717
718#----------------------------------------------------------------
719# Diode total area and perimeter computation
720#----------------------------------------------------------------
721
722proc sky130::compute_aptot {parameters} {
723 foreach key [dict keys $parameters] {
724 set $key [dict get $parameters $key]
725 }
726 set area [magic::spice2float $area]
727 set area [magic::3digitpastdecimal $area]
728 set peri [magic::spice2float $peri]
729 set peri [magic::3digitpastdecimal $peri]
730
731 # Compute total area
732 catch {set magic::atot_val [expr ($area * $nx * $ny)]}
733 # Compute total perimeter
734 catch {set magic::ptot_val [expr ($peri * $nx * $ny)]}
735}
736
737#----------------------------------------------------------------
738# diode: Check device parameters for out-of-bounds values
739#----------------------------------------------------------------
740
741proc sky130::diode_check {parameters} {
742
743 # Set a local variable for each parameter (e.g., $l, $w, etc.)
744 foreach key [dict keys $parameters] {
745 set $key [dict get $parameters $key]
746 }
747
748 # Normalize distance units to microns
749 set l [magic::spice2float $l]
750 set l [magic::3digitpastdecimal $l]
751 set w [magic::spice2float $w]
752 set w [magic::3digitpastdecimal $w]
753
754 set area [magic::spice2float $area]
755 set area [magic::3digitpastdecimal $area]
756 set peri [magic::spice2float $peri]
757 set peri [magic::3digitpastdecimal $peri]
758
759 if {$l == 0} {
760 # Calculate L from W and area
761 set l [expr ($area / $w)]
762 dict set parameters l [magic::float2spice $l]
763 } elseif {$w == 0} {
764 # Calculate W from L and area
765 set w [expr ($area / $l)]
766 dict set parameters w [magic::float2spice $w]
767 }
768 if {$w < $wmin} {
769 puts stderr "Diode width must be >= $wmin"
770 dict set parameters w $wmin
771 }
772 if {$l < $lmin} {
773 puts stderr "Diode length must be >= $lmin"
774 dict set parameters l $lmin
775 }
Tim Edwards0ee0f182020-11-21 16:15:07 -0500776
777 # Check via coverage for syntax
778 if {$guard == 1} {
779 if {[catch {expr abs($viagb)}]} {
780 puts stderr "Guard ring bottom via coverage must be numeric!"
781 dict set parameters viagb 0
782 } elseif {[expr abs($viagb)] > 100} {
783 puts stderr "Guard ring bottom via coverage can't be more than 100%"
784 dict set parameters viagb 100
785 }
786 if {[catch {expr abs($viagt)}]} {
787 puts stderr "Guard ring top via coverage must be numeric!"
788 dict set parameters viagt 0
789 } elseif {[expr abs($viagt)] > 100} {
790 puts stderr "Guard ring top via coverage can't be more than 100%"
791 dict set parameters viagt 100
792 }
793 if {[catch {expr abs($viagr)}]} {
794 puts stderr "Guard ring right via coverage must be numeric!"
795 dict set parameters viagr 0
796 } elseif {[expr abs($viagr)] > 100} {
797 puts stderr "Guard ring right via coverage can't be more than 100%"
798 dict set parameters viagr 100
799 }
800 if {[catch {expr abs($viagl)}]} {
801 puts stderr "Guard ring left via coverage must be numeric!"
802 dict set parameters viagl 0
803 } elseif {[expr abs($viagl)] > 100} {
804 puts stderr "Guard ring left via coverage can't be more than 100%"
805 dict set parameters viagl 100
806 }
807 }
808
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400809 # Calculate area and perimeter from L and W
810 set area [expr ($l * $w)]
811 dict set parameters area [magic::float2spice $area]
812 set peri [expr (2 * ($l + $w))]
813 dict set parameters peri [magic::float2spice $peri]
814 sky130::compute_aptot $parameters
815
816 return $parameters
817}
818
819#------------------------------------------------------------------
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400820# NOTE: sky130_fd_pr__diode_pw2nd_05v5_lvt,
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400821# sky130_fd_pr__diode_pw2nd_05v5_nvt, sky130_fd_pr__diode_pd2nw_05v5_lvt,
822# and sky130_fd_pr__diode_pd2nw_11v0 are all considered parasitic diodes.
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400823# They may be generated by invoking the build procedure on the
824# command line. To enable them in the PDK, add them to the
825# appropriate compatible {} list.
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400826#------------------------------------------------------------------
827
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400828proc sky130::sky130_fd_pr__diode_pw2nd_05v5_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400829 return {w 0.45 l 0.45 area 0.2025 peri 1.8 \
830 nx 1 ny 1 dummy 0 lmin 0.45 wmin 0.45 \
831 elc 1 erc 1 etc 1 ebc 1 doverlap 0 \
Tim Edwards27348db2020-10-28 22:49:29 -0400832 compatible {sky130_fd_pr__diode_pw2nd_05v5 sky130_fd_pr__diode_pw2nd_05v5_lvt \
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400833 sky130_fd_pr__diode_pw2nd_05v5_nvt sky130_fd_pr__diode_pw2nd_11v0} \
Tim Edwards0ee0f182020-11-21 16:15:07 -0500834 full_metal 1 vias 1 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400835}
836
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400837proc sky130::sky130_fd_pr__diode_pw2nd_05v5_lvt_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400838 return {w 0.45 l 0.45 area 0.2025 peri 1.8 \
839 nx 1 ny 1 dummy 0 lmin 0.45 wmin 0.45 \
840 elc 1 erc 1 etc 1 ebc 1 doverlap 0 \
Tim Edwards27348db2020-10-28 22:49:29 -0400841 compatible {sky130_fd_pr__diode_pw2nd_05v5 sky130_fd_pr__diode_pw2nd_05v5_lvt \
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400842 sky130_fd_pr__diode_pw2nd_05v5_nvt sky130_fd_pr__diode_pw2nd_11v0} \
Tim Edwards0ee0f182020-11-21 16:15:07 -0500843 full_metal 1 vias 1 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400844}
845
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400846proc sky130::sky130_fd_pr__diode_pw2nd_05v5_nvt_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400847 return {w 0.45 l 0.45 area 0.2024 peri 1.8 \
848 nx 1 ny 1 dummy 0 lmin 0.45 wmin 0.45 \
849 elc 1 erc 1 etc 1 ebc 1 doverlap 0 \
Tim Edwards27348db2020-10-28 22:49:29 -0400850 compatible {sky130_fd_pr__diode_pw2nd_05v5 sky130_fd_pr__diode_pw2nd_05v5_lvt \
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400851 sky130_fd_pr__diode_pw2nd_05v5_nvt sky130_fd_pr__diode_pw2nd_11v0} \
Tim Edwards0ee0f182020-11-21 16:15:07 -0500852 full_metal 1 vias 1 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400853}
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400854
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400855proc sky130::sky130_fd_pr__diode_pw2nd_11v0_defaults {} {
856 return {w 0.45 l 0.45 area 0.2024 peri 1.8 \
857 nx 1 ny 1 dummy 0 lmin 0.45 wmin 0.45 \
858 elc 1 erc 1 etc 1 ebc 1 doverlap 0 \
859 compatible {sky130_fd_pr__diode_pw2nd_05v5 sky130_fd_pr__diode_pw2nd_05v5_lvt \
860 sky130_fd_pr__diode_pw2nd_05v5_nvt sky130_fd_pr__diode_pw2nd_11v0} \
Tim Edwards0ee0f182020-11-21 16:15:07 -0500861 full_metal 1 vias 1 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400862}
863
864proc sky130::sky130_fd_pr__diode_pd2nw_05v5_defaults {} {
865 return {w 0.45 l 0.45 area 0.2025 peri 1.8 \
866 nx 1 ny 1 dummy 0 lmin 0.45 wmin 0.45 \
867 elc 1 erc 1 etc 1 ebc 1 \
868 glc 1 grc 1 gtc 1 gbc 1 doverlap 0 \
869 compatible {sky130_fd_pr__diode_pd2nw_05v5 sky130_fd_pr__diode_pd2nw_05v5_lvt \
Tim Edwards0ee0f182020-11-21 16:15:07 -0500870 sky130_fd_pr__diode_pd2nw_05v5_hvt sky130_fd_pr__diode_pd2nw_11v0} \
871 full_metal 1 vias 1 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400872}
873
874proc sky130::sky130_fd_pr__diode_pd2nw_05v5_lvt_defaults {} {
875 return {w 0.45 l 0.45 area 0.2025 peri 1.8 \
876 nx 1 ny 1 dummy 0 lmin 0.45 wmin 0.45 \
877 elc 1 erc 1 etc 1 ebc 1 \
878 glc 1 grc 1 gtc 1 gbc 1 doverlap 0 \
879 compatible {sky130_fd_pr__diode_pd2nw_05v5 sky130_fd_pr__diode_pd2nw_05v5_lvt \
880 sky130_fd_pr__diode_pd2nw_05v5_hvt sky130_fd_pr__diode_pd2nw_11v0} \
Tim Edwards0ee0f182020-11-21 16:15:07 -0500881 full_metal 1 vias 1 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400882}
883
884proc sky130::sky130_fd_pr__diode_pd2nw_05v5_hvt_defaults {} {
885 return {w 0.45 l 0.45 area 0.2025 peri 1.8 \
886 nx 1 ny 1 dummy 0 lmin 0.45 wmin 0.45 \
887 elc 1 erc 1 etc 1 ebc 1 \
888 glc 1 grc 1 gtc 1 gbc 1 doverlap 0 \
889 compatible {sky130_fd_pr__diode_pd2nw_05v5 sky130_fd_pr__diode_pd2nw_05v5_lvt \
890 sky130_fd_pr__diode_pd2nw_05v5_hvt sky130_fd_pr__diode_pd2nw_11v0} \
Tim Edwards0ee0f182020-11-21 16:15:07 -0500891 full_metal 1 vias 1 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400892}
893
894
895proc sky130::sky130_fd_pr__diode_pd2nw_11v0_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400896 return {w 0.45 l 0.45 area 0.2024 peri 1.8 \
897 nx 1 ny 1 dummy 0 lmin 0.45 wmin 0.45 \
898 elc 1 erc 1 etc 1 ebc 1 \
899 glc 1 grc 1 gtc 1 gbc 1 doverlap 0 \
Tim Edwards27348db2020-10-28 22:49:29 -0400900 compatible {sky130_fd_pr__diode_pd2nw_05v5 sky130_fd_pr__diode_pd2nw_05v5_lvt \
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400901 sky130_fd_pr__diode_pd2nw_05v5_hvt sky130_fd_pr__diode_pd2nw_11v0} \
Tim Edwards0ee0f182020-11-21 16:15:07 -0500902 full_metal 1 vias 1 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400903}
904
905#----------------------------------------------------------------
906
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400907proc sky130::sky130_fd_pr__diode_pw2nd_05v5_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400908 return [sky130::diode_convert $parameters]
909}
910
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400911proc sky130::sky130_fd_pr__diode_pw2nd_05v5_lvt_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400912 return [sky130::diode_convert $parameters]
913}
914
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400915proc sky130::sky130_fd_pr__diode_pw2nd_05v5_nvt_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400916 return [sky130::diode_convert $parameters]
917}
918
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400919proc sky130::sky130_fd_pr__diode_pw2nd_11v0_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400920 return [sky130::diode_convert $parameters]
921}
922
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400923proc sky130::sky130_fd_pr__diode_pd2nw_05v5_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400924 return [sky130::diode_convert $parameters]
925}
926
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400927proc sky130::sky130_fd_pr__diode_pd2nw_05v5_lvt_convert {parameters} {
928 return [sky130::diode_convert $parameters]
929}
930
931proc sky130::sky130_fd_pr__diode_pd2nw_05v5_hvt_convert {parameters} {
932 return [sky130::diode_convert $parameters]
933}
934
935proc sky130::sky130_fd_pr__diode_pd2nw_11v0_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400936 return [sky130::diode_convert $parameters]
937}
938
939#----------------------------------------------------------------
940
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400941proc sky130::sky130_fd_pr__diode_pw2nd_05v5_dialog {parameters} {
Tim Edwards27348db2020-10-28 22:49:29 -0400942 sky130::diode_dialog sky130_fd_pr__diode_pw2nd_05v5 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400943}
944
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400945proc sky130::sky130_fd_pr__diode_pw2nd_05v5_lvt_dialog {parameters} {
946 sky130::diode_dialog sky130_fd_pr__diode_pw2nd_05v5_lvt $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400947}
948
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400949proc sky130::sky130_fd_pr__diode_pw2nd_05v5_nvt_dialog {parameters} {
950 sky130::diode_dialog sky130_fd_pr__diode_pw2nd_05v5_nvt $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400951}
952
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400953proc sky130::sky130_fd_pr__diode_pw2nd_11v0_dialog {parameters} {
954 sky130::diode_dialog sky130_fd_pr__diode_pw2nd_11v0 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400955}
956
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400957proc sky130::sky130_fd_pr__diode_pd2nw_05v5_dialog {parameters} {
958 sky130::diode_dialog sky130_fd_pr__diode_pd2nw_05v5 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400959}
960
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400961proc sky130::sky130_fd_pr__diode_pd2nw_05v5_lvt_dialog {parameters} {
962 sky130::diode_dialog sky130_fd_pr__diode_pd2nw_05v5_lvt $parameters
963}
964
965proc sky130::sky130_fd_pr__diode_pd2nw_05v5_hvt_dialog {parameters} {
966 sky130::diode_dialog sky130_fd_pr__diode_pd2nw_05v5_hvt $parameters
967}
968
969proc sky130::sky130_fd_pr__diode_pd2nw_11v0_dialog {parameters} {
970 sky130::diode_dialog sky130_fd_pr__diode_pd2nw_11v0 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400971}
972
973#----------------------------------------------------------------
974
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400975proc sky130::sky130_fd_pr__diode_pw2nd_05v5_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400976 sky130::diode_check $parameters
977}
978
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400979proc sky130::sky130_fd_pr__diode_pw2nd_05v5_lvt_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400980 sky130::diode_check $parameters
981}
982
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400983proc sky130::sky130_fd_pr__diode_pw2nd_05v5_nvt_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400984 sky130::diode_check $parameters
985}
986
Tim Edwardsd7289eb2020-09-10 21:48:31 -0400987proc sky130::sky130_fd_pr__diode_pw2nd_11v0_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400988 sky130::diode_check $parameters
989}
990
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400991proc sky130::sky130_fd_pr__diode_pd2nw_05v5_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -0400992 sky130::diode_check $parameters
993}
994
Tim Edwardsbe6f1202020-10-29 10:37:46 -0400995proc sky130::sky130_fd_pr__diode_pd2nw_05v5_lvt_check {parameters} {
996 sky130::diode_check $parameters
997}
998
999proc sky130::sky130_fd_pr__diode_pd2nw_05v5_hvt_check {parameters} {
1000 sky130::diode_check $parameters
1001}
1002
1003proc sky130::sky130_fd_pr__diode_pd2nw_11v0_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001004 sky130::diode_check $parameters
1005}
1006
1007#----------------------------------------------------------------
1008# Diode: Draw a single device
1009#----------------------------------------------------------------
1010
1011proc sky130::diode_device {parameters} {
1012 # Epsilon for avoiding round-off errors
1013 set eps 0.0005
1014
1015 # Set local default values if they are not in parameters
1016 set dev_surround 0
1017 set dev_sub_type ""
1018
1019 # Set a local variable for each parameter (e.g., $l, $w, etc.)
1020 foreach key [dict keys $parameters] {
1021 set $key [dict get $parameters $key]
1022 }
1023
1024 # If there is no end_sub_surround, set it to sub_surround
1025 if {![dict exists $parameters end_sub_surround]} {
1026 set end_sub_surround $sub_surround
1027 }
1028
1029 # Draw the device
1030 pushbox
1031 box size 0 0
1032
1033 set hw [/ $w 2.0]
1034 set hl [/ $l 2.0]
1035
1036 # Calculate ring size (measured to contact center)
1037 set gx [+ $w [* 2.0 [+ $dev_spacing $dev_surround]] $contact_size]
1038 set gy [+ $l [* 2.0 [+ $dev_spacing $dev_surround]] $contact_size]
1039
1040 # Draw the ring first, because diode may occupy well/substrate plane
1041 set guardparams $parameters
1042 dict set guardparams plus_diff_type $end_type
1043 dict set guardparams plus_contact_type $end_contact_type
1044 dict set guardparams diff_surround $end_surround
1045 dict set guardparams sub_type $end_sub_type
1046 dict set guardparams sub_surround $sub_surround
1047 dict set guardparams guard_sub_surround $end_sub_surround
1048 dict set guardparams glc $elc
1049 dict set guardparams grc $erc
1050 dict set guardparams gtc $etc
1051 dict set guardparams gbc $ebc
1052 set cext [sky130::guard_ring $gx $gy $guardparams]
1053
1054 pushbox
1055 box grow n ${hl}um
1056 box grow s ${hl}um
1057 box grow e ${hw}um
1058 box grow w ${hw}um
1059 paint ${dev_type}
1060 set cext [sky130::unionbox $cext [sky130::getbox]]
1061
1062 if {$dev_sub_type != ""} {
1063 box grow n ${sub_surround}um
1064 box grow s ${sub_surround}um
1065 box grow e ${sub_surround}um
1066 box grow w ${sub_surround}um
1067 paint ${dev_sub_type}
1068 }
1069 popbox
1070
1071 if {${w} < ${l}} {
1072 set orient vert
1073 } else {
1074 set orient horz
1075 }
1076
1077 # Reduce width by surround amount
1078 set w [- $w [* ${dev_surround} 2.0]]
1079 set l [- $l [* ${dev_surround} 2.0]]
1080
Tim Edwards0ee0f182020-11-21 16:15:07 -05001081 # Draw via over contact first
1082 if {$vias != 0} {
1083 pushbox
1084 set ch $l
1085 if {$ch < $via_size} {set ch $via_size}
1086 set cw $w
1087 if {$cw < $via_size} {set cw $via_size}
1088 box grow n [/ $ch 2]um
1089 box grow s [/ $ch 2]um
1090 box grow w [/ $cw 2]um
1091 box grow e [/ $cw 2]um
1092 sky130::mcon_draw
1093 popbox
1094 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001095 set cext [sky130::unionbox $cext [sky130::draw_contact ${w} ${l} \
1096 ${dev_surround} ${metal_surround} ${contact_size} \
1097 ${dev_type} ${dev_contact_type} li ${orient}]]
1098
1099 popbox
1100 return $cext
1101}
1102
1103#----------------------------------------------------------------
1104# Diode: Draw the tiled device
1105#----------------------------------------------------------------
1106
1107proc sky130::diode_draw {parameters} {
1108 tech unlock *
1109
1110 # Set defaults if they are not in parameters
1111 set doverlap 0 ;# overlap diodes at contacts
1112 set guard 0 ;# draw a guard ring
1113 set prohibit_overlap false ;# don't prohibit overlaps
1114
1115 # Set a local variable for each parameter (e.g., $l, $w, etc.)
1116 foreach key [dict keys $parameters] {
1117 set $key [dict get $parameters $key]
1118 }
1119
1120 # Normalize distance units to microns
1121 set w [magic::spice2float $w]
1122 set l [magic::spice2float $l]
1123
1124 pushbox
1125 box values 0 0 0 0
1126
1127 # Determine the base device dimensions by drawing one device
1128 # while all layers are locked (nothing drawn). This allows the
1129 # base drawing routine to do complicated geometry without having
1130 # to duplicate it here with calculations.
1131
1132 tech lock *
1133 set bbox [sky130::diode_device $parameters]
1134 # puts stdout "Diagnostic: Device bounding box e $bbox (um)"
1135 tech unlock *
1136
1137 set fw [- [lindex $bbox 2] [lindex $bbox 0]]
1138 set fh [- [lindex $bbox 3] [lindex $bbox 1]]
1139 set lw [+ [lindex $bbox 2] [lindex $bbox 0]]
1140 set lh [+ [lindex $bbox 3] [lindex $bbox 1]]
1141
1142 # If prohibit_overlap is true, then end overlapping is prohibited when
1143 # nx or ny is > 1 to prevent DRC errors (typically from well spacing rule)
1144 if {$prohibit_overlap == true} {
1145 if {($nx > 1) || ($ny > 1)} {
1146 set doverlap 0
1147 }
1148 }
1149
1150 # Determine tile width and height (depends on overlap)
1151
1152 if {$doverlap == 0} {
1153 set dx [+ $fw $end_spacing]
1154 set dy [+ $fh $end_spacing]
1155 } else {
1156 # overlap contact
1157 set dx [- $fw [+ [* 2.0 $sub_surround] [* 2.0 $end_surround] $contact_size]]
1158 set dy [- $fh [+ [* 2.0 $sub_surround] [* 2.0 $end_surround] $contact_size]]
1159 }
1160
1161 # Determine core width and height
1162 set corex [+ [* [- $nx 1] $dx] $fw]
1163 set corey [+ [* [- $ny 1] $dy] $fh]
1164 set corellx [/ [+ [- $corex $fw] $lw] 2.0]
1165 set corelly [/ [+ [- $corey $fh] $lh] 2.0]
1166
1167 if {$guard != 0} {
1168 # Calculate guard ring size (measured to contact center)
1169 set gx [+ $corex [* 2.0 [+ $diff_spacing $diff_surround]] $contact_size]
1170 set gy [+ $corey [* 2.0 [+ $diff_spacing $diff_surround]] $contact_size]
1171
1172 # Draw the guard ring first, because diode may occupy well/substrate plane
1173 sky130::guard_ring $gx $gy $parameters
1174 }
1175
1176 pushbox
1177 box move w ${corellx}um
1178 box move s ${corelly}um
1179 if {($nx > 1) || ($ny > 1)} {
1180 pushbox
1181 set hfw [/ $fw 2.0]
1182 set hfh [/ $fh 2.0]
1183 box move w ${hfw}um
1184 box move s ${hfh}um
1185 box size ${corex}um ${corey}um
1186 paint $end_sub_type
1187 popbox
1188 }
1189 for {set xp 0} {$xp < $nx} {incr xp} {
1190 pushbox
1191 for {set yp 0} {$yp < $ny} {incr yp} {
1192 sky130::diode_device $parameters
1193 box move n ${dy}um
1194 }
1195 popbox
1196 box move e ${dx}um
1197 }
1198 popbox
1199 popbox
1200
1201 tech revert
1202}
1203
1204#----------------------------------------------------------------
1205
Tim Edwardsd7289eb2020-09-10 21:48:31 -04001206proc sky130::sky130_fd_pr__diode_pw2nd_05v5_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001207
1208 # Set a local variable for each rule in ruleset
1209 foreach key [dict keys $sky130::ruleset] {
1210 set $key [dict get $sky130::ruleset $key]
1211 }
1212
1213 set newdict [dict create \
1214 dev_type ndiode \
1215 dev_contact_type ndic \
1216 end_type psd \
1217 end_contact_type psc \
1218 end_sub_type psub \
1219 dev_spacing ${diff_spacing} \
1220 dev_surround ${diff_surround} \
1221 end_spacing ${diff_spacing} \
1222 end_surround 0 \
1223 ]
1224 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
1225 return [sky130::diode_draw $drawdict]
1226}
1227
1228#----------------------------------------------------------------
1229# NOTE: Use ppd instead of psd so that there is additional
1230# diffusion around the contact, allowing more space for the
Tim Edwardsbe6f1202020-10-29 10:37:46 -04001231# implant (likewise sky130_fd_pr__diode_pd2nw_05v5_lvt and
1232# sky130_fd_pr__diode_pd2nw_11v0).
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001233
Tim Edwardsd7289eb2020-09-10 21:48:31 -04001234proc sky130::sky130_fd_pr__diode_pw2nd_05v5_lvt_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001235
1236 # Set a local variable for each rule in ruleset
1237 foreach key [dict keys $sky130::ruleset] {
1238 set $key [dict get $sky130::ruleset $key]
1239 }
1240
1241 set newdict [dict create \
1242 dev_type ndiodelvt \
1243 dev_contact_type ndilvtc \
1244 end_type ppd \
1245 end_contact_type psc \
1246 end_sub_type psub \
1247 dev_spacing ${diff_spacing} \
1248 dev_surround ${diff_surround} \
1249 end_spacing ${diff_spacing} \
1250 end_surround ${diff_surround} \
1251 ]
1252 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
1253 return [sky130::diode_draw $drawdict]
1254}
1255
Tim Edwardsbe6f1202020-10-29 10:37:46 -04001256proc sky130::sky130_fd_pr__diode_pw2nd_05v5_nvt_draw {parameters} {
1257
1258 # Set a local variable for each rule in ruleset
1259 foreach key [dict keys $sky130::ruleset] {
1260 set $key [dict get $sky130::ruleset $key]
1261 }
1262
1263 set newdict [dict create \
1264 dev_type nndiode \
1265 dev_contact_type nndic \
1266 end_type mvpsd \
1267 end_contact_type mvpsc \
1268 end_sub_type psub \
1269 dev_spacing 0.37 \
1270 dev_surround ${diff_surround} \
1271 end_spacing 0.30 \
1272 end_surround ${diff_surround} \
1273 ]
1274 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
1275 return [sky130::diode_draw $drawdict]
1276}
1277
1278proc sky130::sky130_fd_pr__diode_pw2nd_11v0_draw {parameters} {
1279
1280 # Set a local variable for each rule in ruleset
1281 foreach key [dict keys $sky130::ruleset] {
1282 set $key [dict get $sky130::ruleset $key]
1283 }
1284
1285 set newdict [dict create \
1286 dev_type mvndiode \
1287 dev_contact_type mvndic \
1288 end_type mvpsd \
1289 end_contact_type mvpsc \
1290 end_sub_type psub \
1291 diff_spacing 0.37 \
1292 dev_spacing 0.39 \
1293 dev_surround ${diff_surround} \
1294 end_spacing 0.36 \
1295 end_surround ${diff_surround} \
1296 ]
1297 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
1298 return [sky130::diode_draw $drawdict]
1299}
1300
1301
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001302#----------------------------------------------------------------
1303
Tim Edwardsbe6f1202020-10-29 10:37:46 -04001304proc sky130::sky130_fd_pr__diode_pd2nw_05v5_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001305
1306 # Set a local variable for each rule in ruleset
1307 foreach key [dict keys $sky130::ruleset] {
1308 set $key [dict get $sky130::ruleset $key]
1309 }
1310
1311 set newdict [dict create \
1312 dev_type pdiode \
1313 guard 1 \
1314 dev_contact_type pdic \
1315 end_type nsd \
1316 end_contact_type nsc \
1317 end_sub_type nwell \
1318 plus_diff_type psd \
1319 plus_contact_type psc \
1320 sub_type psub \
1321 dev_spacing ${diff_spacing} \
1322 dev_surround ${diff_surround} \
1323 end_spacing ${diff_spacing} \
1324 end_surround 0 \
1325 ]
1326 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
1327 return [sky130::diode_draw $drawdict]
1328}
1329
1330#----------------------------------------------------------------
1331
Tim Edwardsbe6f1202020-10-29 10:37:46 -04001332proc sky130::sky130_fd_pr__diode_pd2nw_05v5_lvt_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001333
1334 # Set a local variable for each rule in ruleset
1335 foreach key [dict keys $sky130::ruleset] {
1336 set $key [dict get $sky130::ruleset $key]
1337 }
1338
1339 set newdict [dict create \
1340 dev_type pdiodelvt \
1341 guard 1 \
1342 dev_contact_type pdilvtc \
1343 end_type nnd \
1344 end_contact_type nsc \
1345 end_sub_type nwell \
1346 plus_diff_type psd \
1347 plus_contact_type psc \
1348 sub_type psub \
1349 dev_spacing ${diff_spacing} \
1350 dev_surround ${diff_surround} \
1351 end_spacing ${diff_spacing} \
1352 end_surround ${diff_surround} \
1353 ]
1354 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
1355 return [sky130::diode_draw $drawdict]
1356}
1357
1358#----------------------------------------------------------------
1359
Tim Edwardsbe6f1202020-10-29 10:37:46 -04001360proc sky130::sky130_fd_pr__diode_pd2nw_05v5_hvt_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001361
1362 # Set a local variable for each rule in ruleset
1363 foreach key [dict keys $sky130::ruleset] {
1364 set $key [dict get $sky130::ruleset $key]
1365 }
1366
1367 set newdict [dict create \
1368 dev_type pdiodehvt \
1369 guard 1 \
1370 dev_contact_type pdihvtc \
1371 end_type nnd \
1372 end_contact_type nsc \
1373 end_sub_type nwell \
1374 plus_diff_type psd \
1375 plus_contact_type psc \
1376 sub_type psub \
1377 dev_spacing ${diff_spacing} \
1378 dev_surround ${diff_surround} \
1379 end_spacing ${diff_spacing} \
1380 end_surround ${diff_surround} \
1381 ]
1382 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
1383 return [sky130::diode_draw $drawdict]
1384}
1385
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001386
1387#----------------------------------------------------------------
1388
Tim Edwardsbe6f1202020-10-29 10:37:46 -04001389proc sky130::sky130_fd_pr__diode_pd2nw_11v0_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001390
1391 # Set a local variable for each rule in ruleset
1392 foreach key [dict keys $sky130::ruleset] {
1393 set $key [dict get $sky130::ruleset $key]
1394 }
1395
1396 set newdict [dict create \
1397 guard 1 \
1398 dev_type mvpdiode \
1399 dev_contact_type mvpdic \
1400 end_type mvnsd \
1401 end_contact_type mvnsc \
1402 end_sub_type nwell \
1403 plus_diff_type mvpsd \
1404 plus_contact_type mvpsc \
1405 sub_type psub \
1406 diff_spacing 0.58 \
1407 dev_spacing 0.37 \
1408 dev_surround ${diff_surround} \
1409 end_spacing 0.30 \
1410 end_sub_surround 0.33 \
1411 end_surround ${diff_surround} \
1412 ]
1413 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
1414 return [sky130::diode_draw $drawdict]
1415}
1416
1417#----------------------------------------------------------------
Tim Edwards27348db2020-10-28 22:49:29 -04001418# Drawn capacitor routines
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001419# NOTE: Work in progress. These values need to be corrected.
1420#----------------------------------------------------------------
1421
1422#ifdef MIM
Tim Edwardsd7289eb2020-09-10 21:48:31 -04001423proc sky130::sky130_fd_pr__cap_mim_m3_1_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001424 return {w 2.00 l 2.00 val 4.0 carea 1.00 cperi 0.17 \
1425 nx 1 ny 1 dummy 0 square 0 lmin 2.00 wmin 2.00 \
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05001426 lmax 30.0 wmax 30.0 dc 0 bconnect 1 tconnect 1 \
1427 ccov 100}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001428}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04001429proc sky130::sky130_fd_pr__cap_mim_m3_2_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001430 return {w 2.00 l 2.00 val 4.0 carea 1.00 cperi 0.17 \
1431 nx 1 ny 1 dummy 0 square 0 lmin 2.00 wmin 2.00 \
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05001432 lmax 30.0 wmax 30.0 dc 0 bconnect 1 tconnect 1 \
1433 ccov 100}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001434}
1435#endif (MIM)
1436
1437
1438#----------------------------------------------------------------
1439# Recalculate capacitor values from GUI entries.
1440# Recomputes W/L and Value as long as 2 of them are present
1441# (To be completed)
1442#----------------------------------------------------------------
1443
1444proc sky130::cap_recalc {field parameters} {
1445 # Set a local variable for each parameter (e.g., $l, $w, etc.)
1446 foreach key [dict keys $parameters] {
1447 set $key [dict get $parameters $key]
1448 }
1449 switch $field {
1450 val { puts stdout "value changed" }
1451 w { puts stdout "width changed" }
1452 l { puts stdout "length changed" }
1453 }
1454 dict set parameters val $val
1455 dict set parameters w $w
1456 dict set parameters l $l
1457}
1458
1459#----------------------------------------------------------------
1460# Capacitor defaults:
1461#----------------------------------------------------------------
1462# w Width of drawn cap
1463# l Length of drawn cap
1464# nx Number of devices in X
1465# ny Number of devices in Y
1466# val Default cap value
1467# carea Area
1468# cperi Perimeter
1469# dummy Add dummy cap
1470# square Make square capacitor
1471#
1472# (not user-editable)
1473#
1474# wmin Minimum allowed width
1475# lmin Minimum allowed length
1476# dc Area to remove to calculated area
1477#----------------------------------------------------------------
1478
1479#----------------------------------------------------------------
1480# capacitor: Conversion from SPICE netlist parameters to toolkit
1481#----------------------------------------------------------------
1482
1483proc sky130::cap_convert {parameters} {
1484 set pdkparams [dict create]
1485 dict for {key value} $parameters {
1486 switch -nocase $key {
1487 l -
1488 w {
1489 # Length and width are converted to units of microns
1490 set value [magic::spice2float $value]
1491 # set value [expr $value * 1e6]
1492 set value [magic::3digitpastdecimal $value]
1493 dict set pdkparams [string tolower $key] $value
1494 }
1495 m {
1496 # Convert m to ny
1497 dict set pdkparams ny $value
1498 }
1499 }
1500 }
1501 return $pdkparams
1502}
1503
1504#ifdef MIM
Tim Edwardsd7289eb2020-09-10 21:48:31 -04001505proc sky130::sky130_fd_pr__cap_mim_m3_1_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001506 return [cap_convert $parameters]
1507}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04001508proc sky130::sky130_fd_pr__cap_mim_m3_2_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001509 return [cap_convert $parameters]
1510}
1511#endif (MIM)
1512
1513#----------------------------------------------------------------
1514# capacitor: Interactively specifies the fixed layout parameters
1515#----------------------------------------------------------------
1516
1517proc sky130::cap_dialog {device parameters} {
1518 # Editable fields: w, l, nx, ny, val
1519 # Checked fields: square, dummy
1520
1521 magic::add_entry val "Value (fF)" $parameters
1522 sky130::compute_ctot $parameters
1523 magic::add_message ctot "Total capacitance (pF)" $parameters
1524 magic::add_entry l "Length (um)" $parameters
1525 magic::add_entry w "Width (um)" $parameters
1526 magic::add_entry nx "X Repeat" $parameters
1527 magic::add_entry ny "Y Repeat" $parameters
1528
1529 if {[dict exists $parameters square]} {
1530 magic::add_checkbox square "Square capacitor" $parameters
1531 }
1532 if {[dict exists $parameters bconnect]} {
1533 magic::add_checkbox bconnect "Connect bottom plates in array" $parameters
1534 }
1535 if {[dict exists $parameters tconnect]} {
1536 magic::add_checkbox tconnect "Connect top plates in array" $parameters
1537 }
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05001538 if {[dict exists $parameters ccov]} {
1539 magic::add_entry ccov "Capacitor contact coverage \[+/-\](%)" $parameters
1540 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001541 if {[dict exists $parameters guard]} {
1542 magic::add_checkbox guard "Add guard ring" $parameters
1543 }
1544
1545 magic::add_dependency sky130::cap_recalc $device sky130 l w val
1546
1547 # magic::add_checkbox dummy "Add dummy" $parameters
1548}
1549
1550#ifdef MIM
Tim Edwardsd7289eb2020-09-10 21:48:31 -04001551proc sky130::sky130_fd_pr__cap_mim_m3_1_dialog {parameters} {
1552 sky130::cap_dialog sky130_fd_pr__cap_mim_m3_1 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001553}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04001554proc sky130::sky130_fd_pr__cap_mim_m3_2_dialog {parameters} {
1555 sky130::cap_dialog sky130_fd_pr__cap_mim_m3_2 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001556}
1557#endif (MIM)
1558
1559#----------------------------------------------------------------
1560# Capacitor total capacitance computation
1561#----------------------------------------------------------------
1562
1563proc sky130::compute_ctot {parameters} {
1564 foreach key [dict keys $parameters] {
1565 set $key [dict get $parameters $key]
1566 }
1567 set val [magic::spice2float $val]
1568 set val [magic::3digitpastdecimal $val]
1569
1570 # Compute total capacitance (and convert fF to pF)
1571 catch {set magic::ctot_val [expr (0.001 * $val * $nx * $ny)]}
1572}
1573
1574#----------------------------------------------------------------
1575# Capacitor: Draw a single device
1576#----------------------------------------------------------------
1577
1578proc sky130::cap_device {parameters} {
1579 # Epsilon for avoiding round-off errors
1580 set eps 0.0005
1581
1582 # Set local default values if they are not in parameters
1583 set cap_surround 0
1584 set bot_surround 0
1585 set top_surround 0
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05001586 set end_spacing 0
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001587 set bconnect 0 ;# bottom plates are connected in array
1588 set cap_spacing 0 ;# cap spacing in array
1589 set top_metal_space 0 ;# top metal spacing (if larger than cap spacing)
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05001590 set top_metal_width 0 ;# top metal minimum width
1591 set contact_size 0 ;# cap contact minimum size
1592 set ccov 100 ;# amount of contact coverage
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001593
1594 # Set a local variable for each parameter (e.g., $l, $w, etc.)
1595 foreach key [dict keys $parameters] {
1596 set $key [dict get $parameters $key]
1597 }
1598
1599 if {![dict exists $parameters top_metal_space]} {
1600 set top_metal_space $metal_spacing
1601 }
1602
1603 # Draw the device
1604 pushbox
1605 box size 0 0
1606
1607 pushbox
1608 set hw [/ $w 2.0]
1609 set hl [/ $l 2.0]
1610 box grow e ${hw}um
1611 box grow w ${hw}um
1612 box grow n ${hl}um
1613 box grow s ${hl}um
1614 paint ${cap_type}
1615 pushbox
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05001616
1617 # Find contact width if ccov is other than 100
1618 set cmaxw [- $w [* $cap_surround 2]]
1619 set cw [* $cmaxw [/ [expr abs($ccov)] 100.0]]
1620 # Contact width must meet minimum
1621 if {$cw < $contact_size} {set cw $contact_size}
1622 if {$cw < $top_metal_width} {set cw $top_metal_width}
1623 # Difference between maximum contact width and actual contact width
1624 set cdif [- $cmaxw $cw]
1625
1626 # Reduce the box to the maximum contact area
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001627 box grow n -${cap_surround}um
1628 box grow s -${cap_surround}um
1629 box grow e -${cap_surround}um
1630 box grow w -${cap_surround}um
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05001631
1632 set anchor [string index $ccov 0]
1633 if {$anchor == "+"} {
1634 box grow e -${cdif}um
1635 } elseif {$anchor == "-"} {
1636 box grow w -${cdif}um
1637 } else {
1638 set cdif [/ ${cdif} 2]
1639 box grow w -${cdif}um
1640 box grow e -${cdif}um
1641 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001642 paint ${cap_contact_type}
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05001643
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001644 pushbox
1645 box grow n ${top_surround}um
1646 box grow s ${top_surround}um
1647 box grow e ${top_surround}um
1648 box grow w ${top_surround}um
1649 paint ${top_type}
1650 set cext [sky130::getbox]
1651 popbox
1652 popbox
1653 pushbox
1654 box grow n ${bot_surround}um
1655 box grow s ${bot_surround}um
1656 box grow e ${bot_surround}um
1657 box grow w ${bot_surround}um
1658
1659 paint ${bot_type}
1660 # Create boundary using properties
1661 property FIXED_BBOX [box values]
1662 set cext [sky130::unionbox $cext [sky130::getbox]]
1663
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05001664 # Calculate the distance from the top metal on the cap contact
1665 # to the top metal on the end contact.
1666 set top_met_sep [+ $end_spacing [- $cdif $top_surround]]
1667
1668 # Diagnostic!
1669 puts stdout "cdif = $cdif"
1670 puts stdout "top_met_sep = $top_met_sep"
1671
1672 # Increase end spacing if top metal spacing rule is not met
1673 set loc_end_spacing $end_spacing
1674 if {$top_met_sep < $top_metal_space} {
1675 set loc_end_spacing [+ $loc_end_spacing [- $top_metal_space $top_met_sep]]
1676 }
1677 # Diagnostic!
1678 puts stdout "loc_end_spacing = $loc_end_spacing"
1679
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001680 # Extend bottom metal under contact to right
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05001681 box grow e ${loc_end_spacing}um
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001682 set chw [/ ${contact_size} 2.0]
1683 box grow e ${chw}um
1684 box grow e ${end_surround}um
1685 paint ${bot_type}
1686
1687 popbox
1688 popbox
1689
1690 # Draw contact to right. Reduce contact extent if devices are not
1691 # wired together and the top metal spacing rule limits the distance
1692 set lcont $l
1693 if {($bconnect == 0) && ($ny > 1)} {
1694 if {$cap_spacing < $top_metal_space} {
1695 set cspace [- $top_metal_space $cap_spacing]
1696 set lcont [- $l $cspace]
1697 }
1698 }
1699
1700 pushbox
1701 box move e ${hw}um
1702 box move e ${bot_surround}um
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05001703 box move e ${loc_end_spacing}um
Tim Edwards55f4d0e2020-07-05 15:41:02 -04001704 set cl [- [+ ${lcont} [* ${bot_surround} 2.0]] [* ${end_surround} 2.0]]
1705 set cl [- ${cl} ${metal_surround}] ;# see below
1706 set cext [sky130::unionbox $cext [sky130::draw_contact 0 ${cl} \
1707 ${end_surround} ${metal_surround} ${contact_size} \
1708 ${bot_type} ${top_contact_type} ${top_type} full]]
1709 popbox
1710 popbox
1711
1712 return $cext
1713
1714 # cl shrinks top and bottom to accomodate larger bottom metal
1715 # surround rule for contacts near a MiM cap. This should be its
1716 # own variable, but metal_surround is sufficient.
1717}
1718
1719#----------------------------------------------------------------
1720# Metal plate sandwich capacitor: Draw a single device
1721#----------------------------------------------------------------
1722
1723proc sky130::sandwich_cap_device {parameters} {
1724
1725 # Set a local variable for each parameter (e.g., $l, $w, etc.)
1726 foreach key [dict keys $parameters] {
1727 set $key [dict get $parameters $key]
1728 }
1729
1730 pushbox
1731 box size 0 0
1732
1733 set hw [/ $w 2.0]
1734 set hl [/ $l 2.0]
1735
1736 set cw [- [* $hw [/ 2.0 3]] [* $cont_surround 2.0]]
1737 set cl [- [* $hl [/ 2.0 3]] [* $cont_surround 2.0]]
1738
1739 # plate capacitor defines layers p0, p1, etc.
1740 for {set i 0} {$i < 20} {incr i} {
1741 if {[catch {set layer [subst \$p${i}_type]}]} {break} ;# no more layers defined
1742 pushbox
1743 box grow e ${hw}um
1744 box grow w ${hw}um
1745 box grow n ${hl}um
1746 box grow s ${hl}um
1747 if {![catch {set shrink [subst \$p${i}_shrink]}]} {
1748 box grow e -${shrink}um
1749 box grow w -${shrink}um
1750 box grow n -${shrink}um
1751 box grow s -${shrink}um
1752 set cutout_spacing [+ [* ${shrink} 2.0] [/ $via_size 2.0] $cont_surround]
1753 } else {
1754 set cutout_spacing 0
1755 }
1756
1757 paint ${layer}
1758
1759 if {$i == 1} {
1760 # Note that cap_type geometry is coincident with p1_type.
1761 # Typically, this will define a layer that outputs as both
1762 # poly and a capacitor definition layer.
1763 if {[dict exists $parameters cap_type]} {
1764 paint $cap_type
1765 }
1766 }
1767 popbox
1768
1769 # Even layers connect at corners, odd layers connect at sides.
1770 # Even layers cut out the sides, odd layers cut out the corners.
1771 # Layer zero has no side contacts or cutout.
1772
1773 if {[% $i 2] == 0} {
1774 set cornercmd paint
1775 set cornersize $cutout_spacing
1776 set sidecmd erase
1777 set nssidelong [+ $cutout_spacing [/ $hw 3.0]]
1778 set ewsidelong [+ $cutout_spacing [/ $hl 3.0]]
1779 set sideshort $cutout_spacing
1780 } else {
1781 set cornercmd erase
1782 set cornersize $cutout_spacing
1783 set sidecmd paint
1784 set nssidelong [/ $hw 3.0]
1785 set ewsidelong [/ $hl 3.0]
1786 set sideshort $cutout_spacing
1787 }
1788
1789 if {$i > 0} {
1790 pushbox
1791 box move e ${hw}um
1792 box grow n ${ewsidelong}um
1793 box grow s ${ewsidelong}um
1794 box grow w ${sideshort}um
1795 ${sidecmd} ${layer}
1796 popbox
1797 pushbox
1798 box move n ${hl}um
1799 box grow e ${nssidelong}um
1800 box grow w ${nssidelong}um
1801 box grow s ${sideshort}um
1802 ${sidecmd} ${layer}
1803 popbox
1804 pushbox
1805 box move w ${hw}um
1806 box grow n ${ewsidelong}um
1807 box grow s ${ewsidelong}um
1808 box grow e ${sideshort}um
1809 ${sidecmd} ${layer}
1810 popbox
1811 pushbox
1812 box move s ${hl}um
1813 box grow e ${nssidelong}um
1814 box grow w ${nssidelong}um
1815 box grow n ${sideshort}um
1816 ${sidecmd} ${layer}
1817 popbox
1818
1819 pushbox
1820 box move n ${hl}um
1821 box move e ${hw}um
1822 box grow s ${cornersize}um
1823 box grow w ${cornersize}um
1824 ${cornercmd} ${layer}
1825 popbox
1826 pushbox
1827 box move n ${hl}um
1828 box move w ${hw}um
1829 box grow s ${cornersize}um
1830 box grow e ${cornersize}um
1831 ${cornercmd} ${layer}
1832 popbox
1833 pushbox
1834 box move s ${hl}um
1835 box move e ${hw}um
1836 box grow n ${cornersize}um
1837 box grow w ${cornersize}um
1838 ${cornercmd} ${layer}
1839 popbox
1840 pushbox
1841 box move s ${hl}um
1842 box move w ${hw}um
1843 box grow n ${cornersize}um
1844 box grow e ${cornersize}um
1845 ${cornercmd} ${layer}
1846 popbox
1847 }
1848 }
1849
1850 # Draw contacts after all layers have been drawn, so that erasing
1851 # layers does not affect the contacts.
1852
1853 for {set i 0} {$i < 20} {incr i} {
1854 if {![catch {set contact [subst \$p${i}_contact_type]}]} {
1855 set layer [subst \$p${i}_type]
1856 set j [+ $i 1]
1857 set toplayer [subst \$p${j}_type]
1858
1859 # Draw corner contacts
1860 pushbox
1861 box move e ${hw}um
1862 box move n ${hl}um
1863 sky130::draw_contact 0 0 \
1864 ${cont_surround} ${cont_surround} ${via_size} \
1865 ${layer} ${contact} ${toplayer} full
1866 popbox
1867 pushbox
1868 box move w ${hw}um
1869 box move n ${hl}um
1870 sky130::draw_contact 0 0 \
1871 ${cont_surround} ${cont_surround} ${via_size} \
1872 ${layer} ${contact} ${toplayer} full
1873 popbox
1874 pushbox
1875 box move e ${hw}um
1876 box move s ${hl}um
1877 sky130::draw_contact 0 0 \
1878 ${cont_surround} ${cont_surround} ${via_size} \
1879 ${layer} ${contact} ${toplayer} full
1880 popbox
1881 pushbox
1882 box move w ${hw}um
1883 box move s ${hl}um
1884 sky130::draw_contact 0 0 \
1885 ${cont_surround} ${cont_surround} ${via_size} \
1886 ${layer} ${contact} ${toplayer} full
1887 popbox
1888
1889 # Draw side contacts (except on poly)
1890 if {$i > 0} {
1891 pushbox
1892 box move w ${hw}um
1893 sky130::draw_contact 0 ${cl} \
1894 ${cont_surround} ${cont_surround} ${via_size} \
1895 ${layer} ${contact} ${toplayer} full
1896 popbox
1897 pushbox
1898 box move e ${hw}um
1899 sky130::draw_contact 0 ${cl} \
1900 ${cont_surround} ${cont_surround} ${via_size} \
1901 ${layer} ${contact} ${toplayer} full
1902 popbox
1903 pushbox
1904 box move n ${hl}um
1905 sky130::draw_contact ${cw} 0 \
1906 ${cont_surround} ${cont_surround} ${via_size} \
1907 ${layer} ${contact} ${toplayer} full
1908 popbox
1909 pushbox
1910 box move s ${hl}um
1911 sky130::draw_contact ${cw} 0 \
1912 ${cont_surround} ${cont_surround} ${via_size} \
1913 ${layer} ${contact} ${toplayer} full
1914 popbox
1915 }
1916 } else {
1917 break
1918 }
1919 }
1920
1921 popbox
1922 # Bounding box is the same as the device length and width
1923 set cext [list -$hw -$hl $hw $hl]
1924 return $cext
1925}
1926
1927#----------------------------------------------------------------
1928# Capacitor: Draw the tiled device
1929#----------------------------------------------------------------
1930
1931proc sky130::cap_draw {parameters} {
1932 tech unlock *
1933 set savesnap [snap]
1934 snap internal
1935
1936 # Set defaults if they are not in parameters
1937 set coverlap 0 ;# overlap capacitors at contacts
1938 set guard 0 ;# draw a guard ring
1939 set sandwich 0 ;# this is not a plate sandwich capacitor
1940 set cap_spacing 0 ;# abutted caps if spacing is zero
1941 set cap_diff_spacing 0
1942 set wide_cap_spacing 0 ;# additional spacing for wide metal rule
1943 set wide_cap_width 0
1944 set end_spacing 0
1945 set end_surround 0
1946 set bot_surround 0
1947 set top_metal_width 0
1948 set bconnect 0 ;# connect bottom plates in array
1949 set tconnect 0 ;# connect top plates in array
1950 set top_type ""
1951
1952 # Set a local variable for each parameter (e.g., $l, $w, etc.)
1953 foreach key [dict keys $parameters] {
1954 set $key [dict get $parameters $key]
1955 }
1956
1957 # Normalize distance units to microns
1958 set w [magic::spice2float $w]
1959 set l [magic::spice2float $l]
1960
1961 pushbox
1962 box values 0 0 0 0
1963
1964 # Determine the base device dimensions by drawing one device
1965 # while all layers are locked (nothing drawn). This allows the
1966 # base drawing routine to do complicated geometry without having
1967 # to duplicate it here with calculations.
1968
1969 tech lock *
1970 if {$sandwich == 1} {
1971 set bbox [sky130::sandwich_cap_device $parameters]
1972 } else {
1973 set bbox [sky130::cap_device $parameters]
1974 }
1975 # puts stdout "Diagnostic: Device bounding box e $bbox (um)"
1976 tech unlock *
1977
1978 set fw [- [lindex $bbox 2] [lindex $bbox 0]]
1979 set fh [- [lindex $bbox 3] [lindex $bbox 1]]
1980 set lw [+ [lindex $bbox 2] [lindex $bbox 0]]
1981 set lh [+ [lindex $bbox 3] [lindex $bbox 1]]
1982
1983 set dwide 0
1984 if {($fw >= $wide_cap_width) && ($fh >= $wide_cap_width)} {
1985 set dwide $wide_cap_spacing
1986 }
1987
1988 # Determine tile width and height (depends on overlap)
1989 if {$coverlap == 0} {
1990 set dy [+ $fh $cap_spacing $dwide]
1991 } else {
1992 # overlap at end contact
1993 set dy [- $fh [+ $end_surround $end_surround $contact_size]]
1994 }
1995 # Contact is placed on right so spacing is determined by end_spacing.
1996 set dx [+ $fw $end_spacing $dwide]
1997
1998 # Determine core width and height
1999 set corex [+ [* [- $nx 1] $dx] $fw]
2000 set corey [+ [* [- $ny 1] $dy] $fh]
2001 set corellx [/ [+ [- $corex $fw] $lw] 2.0]
2002 set corelly [/ [+ [- $corey $fh] $lh] 2.0]
2003
2004 if {$guard != 0} {
2005 # Calculate guard ring size (measured to contact center)
2006 set gx [+ $corex [* 2.0 [+ $cap_diff_spacing $diff_surround]] $contact_size]
2007 set gy [+ $corey [* 2.0 [+ $end_spacing $diff_surround]] $contact_size]
2008
2009 # Draw the guard ring first.
2010 sky130::guard_ring $gx $gy $parameters
2011 }
2012
2013 set twidth [+ ${contact_size} ${end_surround} ${end_surround}]
2014 if {${twidth} < ${top_metal_width}} {
2015 set twidth ${top_metal_width}
2016 }
2017 set hmw [/ $twidth 2.0]
2018 set hdy [/ $dy 2.0]
2019 set cdx [+ [/ ${w} 2.0] ${bot_surround} ${end_spacing}]
2020
2021 pushbox
2022 box move w ${corellx}um
2023 box move s ${corelly}um
2024 for {set xp 0} {$xp < $nx} {incr xp} {
2025 pushbox
2026 for {set yp 0} {$yp < $ny} {incr yp} {
2027 if {$sandwich == 1} {
2028 sky130::sandwich_cap_device $parameters
2029 } else {
2030 sky130::cap_device $parameters
2031 }
2032 if {$ny > 1} {
2033 pushbox
2034 box grow e ${hmw}um
2035 box grow w ${hmw}um
2036 box grow n ${hdy}um
2037 box grow s ${hdy}um
2038 if {($top_type != "") && ($tconnect == 1)} {
2039 paint ${top_type}
2040 }
2041 if {($top_type != "") && ($bconnect == 1)} {
2042 box move e ${cdx}um
2043 paint ${top_type}
2044 }
2045 popbox
2046 }
2047 box move n ${dy}um
2048 }
2049 popbox
2050 box move e ${dx}um
2051 }
2052 popbox
2053 popbox
2054
2055 snap $savesnap
2056 tech revert
2057}
2058
2059#----------------------------------------------------------------
2060
2061#ifdef MIM
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002062proc sky130::sky130_fd_pr__cap_mim_m3_1_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002063 set newdict [dict create \
2064 top_type m4 \
2065 top_contact_type via3 \
2066 cap_type mimcap \
2067 cap_contact_type mimcc \
2068 bot_type m3 \
2069 bot_surround 0.5 \
2070 cap_spacing 0.5 \
2071 cap_surround 0.2 \
2072 top_surround 0.005 \
2073 end_surround 0.1 \
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05002074 end_spacing 0.1 \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002075 contact_size 0.32 \
2076 metal_surround 0.08 \
2077 ]
2078 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
2079 return [sky130::cap_draw $drawdict]
2080}
2081
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002082proc sky130::sky130_fd_pr__cap_mim_m3_2_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002083 set newdict [dict create \
2084 top_type m5 \
2085 top_contact_type via4 \
2086 cap_type mimcap2 \
2087 cap_contact_type mim2cc \
2088 bot_type m4 \
2089 bot_surround 0.5 \
2090 cap_spacing 0.5 \
2091 cap_surround 0.2 \
2092 top_surround 0.12 \
2093 end_surround 0.1 \
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05002094 end_spacing 0.1 \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002095 contact_size 1.18 \
2096 metal_surround 0.21 \
2097 top_metal_width 1.6 \
2098 top_metal_space 1.7 \
2099 ]
2100 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
2101 return [sky130::cap_draw $drawdict]
2102}
2103
2104#endif (MIM)
2105
2106#----------------------------------------------------------------
2107# capacitor: Check device parameters for out-of-bounds values
2108#----------------------------------------------------------------
2109
2110proc sky130::cap_check {parameters} {
2111 # In case wmax and/or lmax are undefined
2112 set lmax 0
2113 set wmax 0
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05002114 set ccov 100
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002115
2116 # Set a local variable for each parameter (e.g., $l, $w, etc.)
2117 foreach key [dict keys $parameters] {
2118 set $key [dict get $parameters $key]
2119 }
2120
2121 # Normalize distance units to microns
2122 set l [magic::spice2float $l]
2123 set l [magic::3digitpastdecimal $l]
2124 set w [magic::spice2float $w]
2125 set w [magic::3digitpastdecimal $w]
2126
2127 set val [magic::spice2float $val]
2128 set carea [magic::spice2float $carea]
2129 set cperi [magic::spice2float $cperi]
2130 set dc [magic::spice2float $dc]
2131
2132 if {$square == 1} {
2133 # Calculate L and W from value
2134 set a $carea
2135 set b [expr $cperi * 4]
2136 set c [expr -4 * $dc - $val]
2137 set l [expr ((-$b + sqrt($b * $b - (4 * $a * $c))) / (2 * $a))]
2138 dict set parameters l [magic::float2spice $l]
2139 set w $l
2140 dict set parameters w [magic::float2spice $w]
2141 } elseif {$l == 0} {
2142 # Calculate L from W and value
2143 set l [expr (($val + 4 * $dc - 2 * $w * $cperi) / ($w * $carea + 2 * $cperi))]
2144 dict set parameters l [magic::float2spice $l]
2145 } elseif {$w == 0} {
2146 # Calculate W from L and value
2147 set w [expr (($val + 4 * $dc - 2 * $l * $cperi) / ($l * $carea + 2 * $cperi))]
2148 dict set parameters w [magic::float2spice $w]
2149 }
2150 if {$w < $wmin} {
2151 puts stderr "Capacitor width must be >= $wmin"
2152 dict set parameters w $wmin
2153 set w $wmin
2154 }
2155 if {$l < $lmin} {
2156 puts stderr "Capacitor length must be >= $lmin"
2157 dict set parameters l $lmin
2158 set l $lmin
2159 }
2160 if {($wmax > 0) && ($w > $wmax)} {
2161 puts stderr "Capacitor width must be <= $wmax"
2162 dict set parameters w $wmax
2163 set w $wmax
2164 }
2165 if {($lmax > 0) && ($l > $lmax)} {
2166 puts stderr "Capacitor length must be <= $lmax"
2167 dict set parameters l $lmax
2168 set l $lmax
2169 }
Tim Edwards3c1dd9a2020-11-27 13:49:58 -05002170 if {[catch {expr abs($ccov)}]} {
2171 puts stderr "Capacitor contact coverage must be numeric!"
2172 dict set parameters ccov 100
2173 } elseif {[expr abs($ccov)] > 100} {
2174 puts stderr "Capaitor contact coverage can't be more than 100%"
2175 dict set parameters ccov 100
2176 }
2177
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002178 # Calculate value from L and W
2179 set cval [expr ($l * $w * $carea + 2 * ($l + $w) * $cperi - 4 * $dc)]
2180 dict set parameters val [magic::float2spice $cval]
2181 sky130::compute_ctot $parameters
2182
2183 return $parameters
2184}
2185
2186#ifdef MIM
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002187proc sky130::sky130_fd_pr__cap_mim_m3_1_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002188 return [sky130::cap_check $parameters]
2189}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002190proc sky130::sky130_fd_pr__cap_mim_m3_2_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002191 return [sky130::cap_check $parameters]
2192}
2193#endif (MIM)
2194
2195#----------------------------------------------------------------
2196# Drawn resistors
2197#----------------------------------------------------------------
2198
2199#----------------------------------------------------------------
2200# Resistor defaults:
2201#----------------------------------------------------------------
2202# User editable values:
2203#
2204# val Resistor value in ohms
2205# w Width
2206# l Length
2207# t Number of turns
2208# m Number devices in Y
2209# nx Number devices in X
2210# snake Use snake geometry (if not present, snake geometry not allowed)
2211# dummy Flag to mark addition of dummy resistor
2212#
2213# Non-user editable values:
2214#
2215# wmin Minimum allowed width
2216# lmin Minimum allowed length
2217# rho Resistance in ohms per square
2218# dw Delta width
2219# term Resistance per terminal
2220# sterm Additional resistance per terminal for snake geometry
2221#----------------------------------------------------------------
2222
2223#----------------------------------------------------------------
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002224# sky130_fd_pr__res_iso_pw: Specify all user-editable default values and those
2225# needed by sky130_fd_pr__res_iso_pw_check
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002226# NOTE: Work in progress. These values need to be corrected.
2227#----------------------------------------------------------------
2228
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002229proc sky130::sky130_fd_pr__res_iso_pw_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002230 return {w 2.650 l 26.50 m 1 nx 1 wmin 2.650 lmin 26.50 \
2231 rho 975 val 4875 dummy 0 dw 0.25 term 1.0 \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002232 guard 1 endcov 100 full_metal 1 vias 1 \
2233 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002234}
2235
2236#----------------------------------------------------------------
2237# rpp1: Specify all user-editable default values and those
2238# needed by rp1_check
2239#----------------------------------------------------------------
2240
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002241proc sky130::sky130_fd_pr__res_generic_po_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002242 return {w 0.330 l 1.650 m 1 nx 1 wmin 0.330 lmin 1.650 \
2243 rho 48.2 val 241 dummy 0 dw 0.0 term 0.0 \
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002244 sterm 0.0 caplen 0.4 snake 0 guard 1 \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002245 glc 1 grc 1 gtc 1 gbc 1 roverlap 0 endcov 100 \
Tim Edwards8469aa62020-11-29 12:42:25 -05002246 full_metal 1 hv_guard 0 vias 1 \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002247 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002248}
2249
2250# "term" is rho * 0.06, the distance between xpc edge and CONT.
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002251proc sky130::sky130_fd_pr__res_high_po_0p35_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002252 return {w 0.350 l 0.50 m 1 nx 1 wmin 0.350 lmin 0.50 \
2253 rho 319.8 val 456.857 dummy 0 dw 0.0 term 19.188 \
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002254 sterm 0.0 caplen 0 guard 1 glc 1 grc 1 gtc 1 gbc 1 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002255 compatible {sky130_fd_pr__res_high_po_0p35 \
2256 sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \
2257 sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002258 full_metal 1 wmax 0.350 vias 1 \
2259 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002260}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002261proc sky130::sky130_fd_pr__res_high_po_0p69_defaults {} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002262 return {w 0.690 l 1.00 m 1 nx 1 wmin 0.690 lmin 0.50 \
2263 rho 319.8 val 463.480 dummy 0 dw 0.0 term 19.188 \
2264 sterm 0.0 caplen 0 guard 1 glc 1 grc 1 gtc 1 gbc 1 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002265 compatible {sky130_fd_pr__res_high_po_0p35 \
2266 sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \
2267 sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002268 full_metal 1 wmax 0.690 vias 1 \
2269 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002270}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002271proc sky130::sky130_fd_pr__res_high_po_1p41_defaults {} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002272 return {w 1.410 l 2.00 m 1 nx 1 wmin 1.410 lmin 0.50 \
2273 rho 319.8 val 453.620 dummy 0 dw 0.0 term 19.188 \
2274 sterm 0.0 caplen 0 guard 1 glc 1 grc 1 gtc 1 gbc 1 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002275 compatible {sky130_fd_pr__res_high_po_0p35 \
2276 sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \
2277 sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002278 full_metal 1 wmax 1.410 vias 1 \
2279 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002280}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002281proc sky130::sky130_fd_pr__res_high_po_2p85_defaults {} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002282 return {w 2.850 l 3.00 m 1 nx 1 wmin 2.850 lmin 0.50 \
2283 rho 319.8 val 336.630 dummy 0 dw 0.0 term 19.188 \
2284 sterm 0.0 caplen 0 guard 1 glc 1 grc 1 gtc 1 gbc 1 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002285 compatible {sky130_fd_pr__res_high_po_0p35 \
2286 sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \
2287 sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002288 full_metal 1 wmax 2.850 vias 1 \
2289 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002290}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002291proc sky130::sky130_fd_pr__res_high_po_5p73_defaults {} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002292 return {w 5.730 l 6.00 m 1 nx 1 wmin 5.730 lmin 0.50 \
2293 rho 319.8 val 334.870 dummy 0 dw 0.0 term 19.188 \
2294 sterm 0.0 caplen 0 guard 1 glc 1 grc 1 gtc 1 gbc 1 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002295 compatible {sky130_fd_pr__res_high_po_0p35 \
2296 sky130_fd_pr__res_high_po_0p69 sky130_fd_pr__res_high_po_1p41 \
2297 sky130_fd_pr__res_high_po_2p85 sky130_fd_pr__res_high_po_5p73} \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002298 full_metal 1 wmax 5.730 vias 1 \
2299 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002300}
2301
2302# "term" is rho * 0.06, the distance between xpc edge and CONT.
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002303proc sky130::sky130_fd_pr__res_xhigh_po_0p35_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002304 return {w 0.350 l 0.50 m 1 nx 1 wmin 0.350 lmin 0.50 \
2305 rho 2000 val 2875.143 dummy 0 dw 0.0 term 120 \
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002306 sterm 0.0 caplen 0 wmax 0.350 \
2307 guard 1 glc 1 grc 1 gtc 1 gbc 1 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002308 compatible {sky130_fd_pr__res_xhigh_po_0p35 \
2309 sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \
2310 sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002311 full_metal 1 vias 1 \
2312 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002313}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002314proc sky130::sky130_fd_pr__res_xhigh_po_0p69_defaults {} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002315 return {w 0.690 l 1.00 m 1 nx 1 wmin 0.690 lmin 0.50 \
2316 rho 2000 val 2898.600 dummy 0 dw 0.0 term 120 \
2317 sterm 0.0 caplen 0 wmax 0.690 \
2318 guard 1 glc 1 grc 1 gtc 1 gbc 1 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002319 compatible {sky130_fd_pr__res_xhigh_po_0p35 \
2320 sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \
2321 sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002322 full_metal 1 vias 1 \
2323 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002324}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002325proc sky130::sky130_fd_pr__res_xhigh_po_1p41_defaults {} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002326 return {w 1.410 l 2.00 m 1 nx 1 wmin 1.410 lmin 0.50 \
2327 rho 2000 val 2836.900 dummy 0 dw 0.0 term 120 \
2328 sterm 0.0 caplen 0 wmax 1.410 \
2329 guard 1 glc 1 grc 1 gtc 1 gbc 1 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002330 compatible {sky130_fd_pr__res_xhigh_po_0p35 \
2331 sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \
2332 sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002333 full_metal 1 vias 1 \
2334 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002335}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002336proc sky130::sky130_fd_pr__res_xhigh_po_2p85_defaults {} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002337 return {w 2.850 l 3.00 m 1 nx 1 wmin 2.850 lmin 0.50 \
2338 rho 2000 val 2105.300 dummy 0 dw 0.0 term 120 \
2339 sterm 0.0 caplen 0 wmax 2.850 \
2340 guard 1 glc 1 grc 1 gtc 1 gbc 1 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002341 compatible {sky130_fd_pr__res_xhigh_po_0p35 \
2342 sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \
2343 sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002344 full_metal 1 vias 1 \
2345 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002346}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002347proc sky130::sky130_fd_pr__res_xhigh_po_5p73_defaults {} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002348 return {w 5.730 l 6.00 m 1 nx 1 wmin 5.730 lmin 0.50 \
2349 rho 2000 val 2094.200 dummy 0 dw 0.0 term 120 \
2350 sterm 0.0 caplen 0 wmax 5.730 \
2351 guard 1 glc 1 grc 1 gtc 1 gbc 1 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002352 compatible {sky130_fd_pr__res_xhigh_po_0p35 \
2353 sky130_fd_pr__res_xhigh_po_0p69 sky130_fd_pr__res_xhigh_po_1p41 \
2354 sky130_fd_pr__res_xhigh_po_2p85 sky130_fd_pr__res_xhigh_po_5p73} \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002355 full_metal 1 vias 1 \
2356 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002357}
2358
2359#----------------------------------------------------------------
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002360# sky130_fd_pr__res_generic_nd: Specify all user-editable default values and those
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002361# needed by rdn_check
2362#----------------------------------------------------------------
2363
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002364proc sky130::sky130_fd_pr__res_generic_nd_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002365 return {w 0.420 l 2.100 m 1 nx 1 wmin 0.42 lmin 2.10 \
2366 rho 120 val 600.0 dummy 0 dw 0.05 term 0.0 \
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002367 sterm 0.0 caplen 0.4 snake 0 guard 1 \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002368 glc 1 grc 1 gtc 1 gbc 1 roverlap 0 endcov 100 \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002369 full_metal 1 vias 1 \
2370 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002371}
2372
Tim Edwards0ee0f182020-11-21 16:15:07 -05002373proc sky130::sky130_fd_pr__res_generic_nd__hv_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002374 return {w 0.420 l 2.100 m 1 nx 1 wmin 0.42 lmin 2.10 \
2375 rho 120 val 600.0 dummy 0 dw 0.02 term 0.0 \
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002376 sterm 0.0 caplen 0.4 snake 0 guard 1 \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002377 glc 1 grc 1 gtc 1 gbc 1 roverlap 0 endcov 100 \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002378 full_metal 1 vias 1 \
2379 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002380}
2381
2382#----------------------------------------------------------------
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002383# sky130_fd_pr__res_generic_pd: Specify all user-editable default values and those
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002384# needed by rdp_check
2385#----------------------------------------------------------------
2386
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002387proc sky130::sky130_fd_pr__res_generic_pd_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002388 return {w 0.420 l 2.100 m 1 nx 1 wmin 0.42 lmin 2.10 \
2389 rho 197 val 985.0 dummy 0 dw 0.02 term 0.0 \
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002390 sterm 0.0 caplen 0.60 snake 0 guard 1 \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002391 glc 1 grc 1 gtc 1 gbc 1 roverlap 0 endcov 100 \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002392 full_metal 1 vias 1 \
2393 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002394}
2395
Tim Edwards0ee0f182020-11-21 16:15:07 -05002396proc sky130::sky130_fd_pr__res_generic_pd__hv_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002397 return {w 0.420 l 2.100 m 1 nx 1 wmin 0.42 lmin 2.10 \
2398 rho 197 val 985.0 dummy 0 dw 0.02 term 0.0 \
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002399 sterm 0.0 caplen 0.60 snake 0 guard 1 \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002400 glc 1 grc 1 gtc 1 gbc 1 roverlap 0 endcov 100 \
Tim Edwards0ee0f182020-11-21 16:15:07 -05002401 full_metal 1 vias 1 \
2402 viagb 0 viagt 0 viagl 0 viagr 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002403}
2404
2405#----------------------------------------------------------------
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002406# sky130_fd_pr__res_generic_l1: Specify all user-editable default values and those needed
2407# by sky130_fd_pr__res_generic_l1_check
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002408#----------------------------------------------------------------
2409
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002410proc sky130::sky130_fd_pr__res_generic_l1_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002411 return {w 0.170 l 0.170 m 1 nx 1 wmin 0.17 lmin 0.17 \
2412 rho 12.8 val 12.8 dummy 0 dw 0.0 term 0.0 snake 0 \
2413 roverlap 0}
2414}
2415
2416#----------------------------------------------------------------
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002417# sky130_fd_pr__res_generic_m1: Specify all user-editable default values and those needed
2418# by sky130_fd_pr__res_generic_m1_check
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002419#----------------------------------------------------------------
2420
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002421proc sky130::sky130_fd_pr__res_generic_m1_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002422 return {w 0.140 l 0.140 m 1 nx 1 wmin 0.14 lmin 0.14 \
2423 rho 0.125 val 0.125 dummy 0 dw 0.0 term 0.0 \
2424 roverlap 0}
2425}
2426
2427#----------------------------------------------------------------
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002428# sky130_fd_pr__res_generic_m2: Specify all user-editable default values and those needed
2429# by sky130_fd_pr__res_generic_m2_check
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002430#----------------------------------------------------------------
2431
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002432proc sky130::sky130_fd_pr__res_generic_m2_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002433 return {w 0.140 l 0.140 m 1 nx 1 wmin 0.14 lmin 0.14 \
2434 rho 0.125 val 0.125 dummy 0 dw 0.0 term 0.0 \
2435 roverlap 0}
2436}
2437
2438#----------------------------------------------------------------
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002439# sky130_fd_pr__res_generic_m3: Specify all user-editable default values and those needed
2440# by sky130_fd_pr__res_generic_m3_check
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002441#----------------------------------------------------------------
2442
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002443proc sky130::sky130_fd_pr__res_generic_m3_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002444 return {w 0.300 l 0.300 m 1 nx 1 wmin 0.30 lmin 0.30 \
2445 rho 0.047 val 0.047 dummy 0 dw 0.0 term 0.0 \
2446 roverlap 0}
2447}
2448
2449#----------------------------------------------------------------
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002450# Additional entries for sky130_fd_pr__res_generic_m4 and sky130_fd_pr__res_generic_m5, depending on the
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002451# back-end metal stack.
2452#----------------------------------------------------------------
2453
2454#ifdef METAL5
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002455proc sky130::sky130_fd_pr__res_generic_m4_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002456 return {w 0.300 l 0.300 m 1 nx 1 wmin 0.30 lmin 0.30 \
2457 rho 0.047 val 0.047 dummy 0 dw 0.0 term 0.0 \
2458 roverlap 0}
2459}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002460proc sky130::sky130_fd_pr__res_generic_m5_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002461 return {w 1.600 l 1.600 m 1 nx 1 wmin 1.60 lmin 1.60 \
2462 rho 0.029 val 0.029 dummy 0 dw 0.0 term 0.0 \
2463 roverlap 0}
2464}
2465#endif (METAL5)
2466
2467#----------------------------------------------------------------
2468# resistor: Conversion from SPICE netlist parameters to toolkit
2469#----------------------------------------------------------------
2470
2471proc sky130::res_convert {parameters} {
2472 set pdkparams [dict create]
2473 dict for {key value} $parameters {
2474 switch -nocase $key {
2475 l -
2476 w {
2477 # Length and width are converted to units of microns
2478 set value [magic::spice2float $value]
2479 # set value [expr $value * 1e6]
2480 set value [magic::3digitpastdecimal $value]
2481 dict set pdkparams [string tolower $key] $value
2482 }
2483 }
2484 }
2485 return $pdkparams
2486}
2487
2488#----------------------------------------------------------------
2489
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002490proc sky130::sky130_fd_pr__res_iso_pw_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002491 return [sky130::res_convert $parameters]
2492}
2493
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002494proc sky130::sky130_fd_pr__res_generic_po_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002495 return [sky130::res_convert $parameters]
2496}
2497
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002498proc sky130::sky130_fd_pr__res_high_po_0p35_convert {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002499 return [sky130::res_convert $parameters]
2500}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002501proc sky130::sky130_fd_pr__res_high_po_0p69_convert {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002502 return [sky130::res_convert $parameters]
2503}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002504proc sky130::sky130_fd_pr__res_high_po_1p41_convert {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002505 return [sky130::res_convert $parameters]
2506}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002507proc sky130::sky130_fd_pr__res_high_po_2p85_convert {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002508 return [sky130::res_convert $parameters]
2509}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002510proc sky130::sky130_fd_pr__res_high_po_5p73_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002511 return [sky130::res_convert $parameters]
2512}
2513
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002514proc sky130::sky130_fd_pr__res_xhigh_po_0p35_convert {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002515 return [sky130::res_convert $parameters]
2516}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002517proc sky130::sky130_fd_pr__res_xhigh_po_0p69_convert {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002518 return [sky130::res_convert $parameters]
2519}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002520proc sky130::sky130_fd_pr__res_xhigh_po_1p41_convert {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002521 return [sky130::res_convert $parameters]
2522}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002523proc sky130::sky130_fd_pr__res_xhigh_po_2p85_convert {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002524 return [sky130::res_convert $parameters]
2525}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002526proc sky130::sky130_fd_pr__res_xhigh_po_5p73_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002527 return [sky130::res_convert $parameters]
2528}
2529
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002530proc sky130::sky130_fd_pr__res_generic_nd_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002531 return [sky130::res_convert $parameters]
2532}
2533
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002534proc sky130::sky130_fd_pr__res_generic_pd_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002535 return [sky130::res_convert $parameters]
2536}
2537
Tim Edwards0ee0f182020-11-21 16:15:07 -05002538proc sky130::sky130_fd_pr__res_generic_nd__hv_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002539 return [sky130::res_convert $parameters]
2540}
2541
Tim Edwards0ee0f182020-11-21 16:15:07 -05002542proc sky130::sky130_fd_pr__res_generic_pd__hv_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002543 return [sky130::res_convert $parameters]
2544}
2545
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002546proc sky130::sky130_fd_pr__res_generic_l1_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002547 return [sky130::res_convert $parameters]
2548}
2549
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002550proc sky130::sky130_fd_pr__res_generic_m1_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002551 return [sky130::res_convert $parameters]
2552}
2553
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002554proc sky130::sky130_fd_pr__res_generic_m2_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002555 return [sky130::res_convert $parameters]
2556}
2557
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002558proc sky130::sky130_fd_pr__res_generic_m3_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002559 return [sky130::res_convert $parameters]
2560}
2561
2562#ifdef METAL5
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002563proc sky130::sky130_fd_pr__res_generic_m4_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002564 return [sky130::res_convert $parameters]
2565}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002566proc sky130::sky130_fd_pr__res_generic_m5_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002567 return [sky130::res_convert $parameters]
2568}
2569#endif (METAL5)
2570
2571#----------------------------------------------------------------
2572# resistor: Interactively specifies the fixed layout parameters
2573#----------------------------------------------------------------
2574
2575proc sky130::res_dialog {device parameters} {
2576 # Editable fields: w, l, t, nx, m, val
2577 # Checked fields:
2578
2579 magic::add_entry val "Value (ohms)" $parameters
2580 if {[dict exists $parameters snake]} {
2581 sky130::compute_ltot $parameters
2582 magic::add_message ltot "Total length (um)" $parameters
2583 }
2584 magic::add_entry l "Length (um)" $parameters
2585 magic::add_entry w "Width (um)" $parameters
2586 magic::add_entry nx "X Repeat" $parameters
2587 magic::add_entry m "Y Repeat" $parameters
2588 if {[dict exists $parameters endcov]} {
2589 magic::add_entry endcov "End contact coverage (%)" $parameters
2590 }
2591
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002592 if {[dict exists $parameters compatible]} {
2593 set sellist [dict get $parameters compatible]
2594 magic::add_selectlist gencell "Device type" $sellist $parameters $device
2595 }
2596
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002597 # magic::add_checkbox dummy "Add dummy" $parameters
2598
2599 if {[dict exists $parameters snake]} {
2600 magic::add_checkbox snake "Use snake geometry" $parameters
2601 }
2602 if {[dict exists $parameters roverlap]} {
2603 if {[dict exists $parameters endcov]} {
2604 magic::add_checkbox roverlap "Overlap at end contact" $parameters
2605 } else {
2606 magic::add_checkbox roverlap "Overlap at ends" $parameters
2607 }
2608 }
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002609 if {[dict exists $parameters guard]} {
2610 magic::add_checkbox guard "Add guard ring" $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002611
Tim Edwards8469aa62020-11-29 12:42:25 -05002612 if {[dict exists $parameters hv_guard]} {
2613 magic::add_checkbox hv_guard "High-voltage guard ring" $parameters
2614 }
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002615 if {[dict exists $parameters full_metal]} {
2616 magic::add_checkbox full_metal "Full metal guard ring" $parameters
2617 }
2618 if {[dict exists $parameters glc]} {
2619 magic::add_checkbox glc "Add left guard ring contact" $parameters
2620 }
2621 if {[dict exists $parameters grc]} {
2622 magic::add_checkbox grc "Add right guard ring contact" $parameters
2623 }
2624 if {[dict exists $parameters gtc]} {
2625 magic::add_checkbox gtc "Add top guard ring contact" $parameters
2626 }
2627 if {[dict exists $parameters gbc]} {
2628 magic::add_checkbox gbc "Add bottom guard ring contact" $parameters
2629 }
Tim Edwards0ee0f182020-11-21 16:15:07 -05002630
2631 magic::add_entry viagb "Bottom guard ring via coverage \[+/-\](%)" $parameters
2632 magic::add_entry viagt "Top guard ring via coverage \[+/-\](%)" $parameters
2633 magic::add_entry viagr "Right guard ring via coverage \[+/-\](%)" $parameters
2634 magic::add_entry viagl "Left guard ring via coverage \[+/-\](%)" $parameters
2635 }
2636
2637 if {[dict exists $parameters vias]} {
2638 magic::add_checkbox vias "Add vias over contacts" $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002639 }
2640
2641 if {[dict exists $parameters snake]} {
2642 magic::add_dependency sky130::res_recalc $device sky130 l w val nx snake
2643 } else {
2644 magic::add_dependency sky130::res_recalc $device sky130 l w val nx
2645 }
2646}
2647
2648#----------------------------------------------------------------
2649
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002650proc sky130::sky130_fd_pr__res_iso_pw_dialog {parameters} {
2651 sky130::res_dialog sky130_fd_pr__res_iso_pw $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002652}
2653
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002654proc sky130::sky130_fd_pr__res_generic_po_dialog {parameters} {
2655 sky130::res_dialog sky130_fd_pr__res_generic_po $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002656}
2657
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002658proc sky130::sky130_fd_pr__res_high_po_0p35_dialog {parameters} {
2659 sky130::res_dialog sky130_fd_pr__res_high_po_0p35 $parameters
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002660}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002661proc sky130::sky130_fd_pr__res_high_po_0p69_dialog {parameters} {
2662 sky130::res_dialog sky130_fd_pr__res_high_po_0p69 $parameters
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002663}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002664proc sky130::sky130_fd_pr__res_high_po_1p41_dialog {parameters} {
2665 sky130::res_dialog sky130_fd_pr__res_high_po_1p41 $parameters
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002666}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002667proc sky130::sky130_fd_pr__res_high_po_2p85_dialog {parameters} {
2668 sky130::res_dialog sky130_fd_pr__res_high_po_2p85 $parameters
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002669}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002670proc sky130::sky130_fd_pr__res_high_po_5p73_dialog {parameters} {
2671 sky130::res_dialog sky130_fd_pr__res_high_po_5p73 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002672}
2673
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002674proc sky130::sky130_fd_pr__res_xhigh_po_0p35_dialog {parameters} {
2675 sky130::res_dialog sky130_fd_pr__res_xhigh_po_0p35 $parameters
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002676}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002677proc sky130::sky130_fd_pr__res_xhigh_po_0p69_dialog {parameters} {
2678 sky130::res_dialog sky130_fd_pr__res_xhigh_po_0p69 $parameters
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002679}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002680proc sky130::sky130_fd_pr__res_xhigh_po_1p41_dialog {parameters} {
2681 sky130::res_dialog sky130_fd_pr__res_xhigh_po_1p41 $parameters
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002682}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002683proc sky130::sky130_fd_pr__res_xhigh_po_2p85_dialog {parameters} {
2684 sky130::res_dialog sky130_fd_pr__res_xhigh_po_2p85 $parameters
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002685}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002686proc sky130::sky130_fd_pr__res_xhigh_po_5p73_dialog {parameters} {
2687 sky130::res_dialog sky130_fd_pr__res_xhigh_po_5p73 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002688}
2689
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002690proc sky130::sky130_fd_pr__res_generic_nd_dialog {parameters} {
2691 sky130::res_dialog sky130_fd_pr__res_generic_nd $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002692}
2693
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002694proc sky130::sky130_fd_pr__res_generic_pd_dialog {parameters} {
2695 sky130::res_dialog sky130_fd_pr__res_generic_pd $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002696}
2697
Tim Edwards0ee0f182020-11-21 16:15:07 -05002698proc sky130::sky130_fd_pr__res_generic_nd__hv_dialog {parameters} {
2699 sky130::res_dialog sky130_fd_pr__res_generic_nd__hv $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002700}
2701
Tim Edwards0ee0f182020-11-21 16:15:07 -05002702proc sky130::sky130_fd_pr__res_generic_pd__hv_dialog {parameters} {
2703 sky130::res_dialog sky130_fd_pr__res_generic_pd__hv $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002704}
2705
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002706proc sky130::sky130_fd_pr__res_generic_l1_dialog {parameters} {
2707 sky130::res_dialog sky130_fd_pr__res_generic_l1 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002708}
2709
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002710proc sky130::sky130_fd_pr__res_generic_m1_dialog {parameters} {
2711 sky130::res_dialog sky130_fd_pr__res_generic_m1 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002712}
2713
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002714proc sky130::sky130_fd_pr__res_generic_m2_dialog {parameters} {
2715 sky130::res_dialog sky130_fd_pr__res_generic_m2 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002716}
2717
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002718proc sky130::sky130_fd_pr__res_generic_m3_dialog {parameters} {
2719 sky130::res_dialog sky130_fd_pr__res_generic_m3 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002720}
2721
2722#ifdef METAL5
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002723proc sky130::sky130_fd_pr__res_generic_m4_dialog {parameters} {
2724 sky130::res_dialog sky130_fd_pr__res_generic_m4 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002725}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04002726proc sky130::sky130_fd_pr__res_generic_m5_dialog {parameters} {
2727 sky130::res_dialog sky130_fd_pr__res_generic_m5 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002728}
2729#endif (METAL5)
2730
2731#----------------------------------------------------------------
2732# Resistor: Draw a single device in straight geometry
2733#----------------------------------------------------------------
2734
2735proc sky130::res_device {parameters} {
2736 # Epsilon for avoiding round-off errors
2737 set eps 0.0005
2738
2739 # Set local default values if they are not in parameters
2740 set endcov 0 ;# percent coverage of end contacts
2741 set roverlap 0 ;# overlap resistors at end contacts
2742 set well_res_overlap 0 ;# not a well resistor
2743 set end_contact_type "" ;# no contacts for metal resistors
2744 set end_overlap_cont 0 ;# additional end overlap on sides
Tim Edwards0ee0f182020-11-21 16:15:07 -05002745 set vias 0 ;# add vias over contacts
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002746 set res_idtype none
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002747
2748 # Set a local variable for each parameter (e.g., $l, $w, etc.)
2749 foreach key [dict keys $parameters] {
2750 set $key [dict get $parameters $key]
2751 }
2752
2753 if {![dict exists $parameters end_contact_size]} {
2754 set end_contact_size $contact_size
2755 }
2756
2757 # Draw the resistor and endcaps
2758 pushbox
2759 box size 0 0
2760 pushbox
2761 set hw [/ $w 2.0]
2762 set hl [/ $l 2.0]
2763 box grow n ${hl}um
2764 box grow s ${hl}um
2765 box grow e ${hw}um
2766 box grow w ${hw}um
2767
2768 pushbox
2769 box grow n ${res_to_endcont}um
2770 box grow s ${res_to_endcont}um
2771 if {$well_res_overlap > 0} {
2772 set well_extend [+ ${well_res_overlap} [/ ${end_contact_size} 2.0] ${end_surround}]
2773 box grow n ${well_extend}um
2774 box grow s ${well_extend}um
2775 paint ${well_res_type}
2776 } else {
2777 paint ${end_type}
2778 }
2779 set cext [sky130::getbox]
2780 popbox
2781
2782 if {$well_res_overlap > 0} {
2783 erase ${well_res_type}
2784 } else {
2785 erase ${end_type}
2786 }
2787 paint ${res_type}
Tim Edwardsbf5ec172020-08-09 14:04:00 -04002788 if {"$res_idtype" != "none"} {
2789 box grow c 2
2790 paint ${res_idtype}
2791 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002792 popbox
2793
2794 # Reduce contact sizes by (end type) surround so that
2795 # the contact area edges match the device type width.
2796 # (Minimum dimensions will be enforced by the contact drawing routine)
2797 set epl [- ${w} [* ${end_surround} 2]] ;# end contact width
2798
2799 # Reduce end material size for well resistor types
2800 if {$well_res_overlap > 0} {
2801 set epl [- ${epl} [* ${well_res_overlap} 2]]
2802 }
2803
2804 # Reduce by coverage percentage unless overlapping at contacts
2805 if {(${roverlap} == 0) && (${endcov} > 0)} {
2806 set cpl [* ${epl} [/ ${endcov} 100.0]]
2807 } else {
2808 set cpl $epl
2809 }
2810
2811 # Ensure additional overlap of diffusion contact if required
2812 set dov [* ${end_overlap_cont} 2]
2813 if {[- ${epl} ${cpl}] < $dov} {
2814 set cpl [- ${epl} $dov] ;# additional end contact width
2815 }
2816
2817 set hepl [+ [/ ${epl} 2.0] ${end_surround}]
2818 set hesz [/ ${end_contact_size} 2.0]
2819
2820 # LV substrate diffusion types have a different surround requirement
2821 set lv_sub_types {"psd" "nsd"}
2822 if {[lsearch $lv_sub_types $end_type] < 0} {
2823 set hesz [+ ${hesz} ${end_surround}]
2824 }
2825
2826 # Top end material & contact
2827 pushbox
2828 box move n ${hl}um
2829 box move n ${res_to_endcont}um
2830
2831 pushbox
2832 box size 0 0
2833 box grow n ${hesz}um
2834 box grow s ${hesz}um
2835 box grow e ${hepl}um
2836 box grow w ${hepl}um
2837 paint ${end_type}
2838 set cext [sky130::unionbox $cext [sky130::getbox]]
2839 popbox
2840
2841 if {${end_contact_type} != ""} {
Tim Edwards0ee0f182020-11-21 16:15:07 -05002842 # Draw via over contact first
2843 if {$vias != 0} {
2844 pushbox
2845 set ch $res_to_endcont
2846 if {$ch < $via_size} {set ch $via_size}
2847 set cw $epl
2848 if {$cw < $via_size} {set cw $via_size}
2849 box grow n [/ $via_size 2]um
2850 box grow s [- $ch [/ $via_size 2]]um
2851 box grow w [/ $cw 2]um
2852 box grow e [/ $cw 2]um
2853 sky130::mcon_draw
2854 popbox
2855 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002856 set cext [sky130::unionbox $cext [sky130::draw_contact ${cpl} 0 \
2857 ${end_surround} ${metal_surround} ${end_contact_size} \
2858 ${end_type} ${end_contact_type} li horz]]
2859 }
2860 popbox
2861
2862 # Bottom end material & contact
2863 pushbox
2864 box move s ${hl}um
2865 box move s ${res_to_endcont}um
2866
2867 pushbox
2868 box size 0 0
2869 box grow n ${hesz}um
2870 box grow s ${hesz}um
2871 box grow e ${hepl}um
2872 box grow w ${hepl}um
2873 paint ${end_type}
2874 set cext [sky130::unionbox $cext [sky130::getbox]]
2875 popbox
2876
2877 if {${end_contact_type} != ""} {
Tim Edwards0ee0f182020-11-21 16:15:07 -05002878 # Draw via over contact first
2879 if {$vias != 0} {
2880 pushbox
2881 set ch $res_to_endcont
2882 if {$ch < $via_size} {set ch $via_size}
2883 set cw $epl
2884 if {$cw < $via_size} {set cw $via_size}
2885 box grow n [- $ch [/ $via_size 2]]um
2886 box grow s [/ $via_size 2]um
2887 box grow w [/ $cw 2]um
2888 box grow e [/ $cw 2]um
2889 sky130::mcon_draw
2890 popbox
2891 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -04002892 set cext [sky130::unionbox $cext [sky130::draw_contact ${cpl} 0 \
2893 ${end_surround} ${metal_surround} ${end_contact_size} \
2894 ${end_type} ${end_contact_type} li horz]]
2895 }
2896 popbox
2897
2898 popbox
2899 return $cext
2900}
2901
2902#----------------------------------------------------------------
2903# Resistor: Draw a single device in snake geometry
2904#----------------------------------------------------------------
2905
2906proc sky130::res_snake_device {nf parameters} {
2907 # nf is the number of fingers of the snake geometry
2908
2909 # Epsilon for avoiding round-off errors
2910 set eps 0.0005
2911
2912 # Set local default values if they are not in parameters
2913 set endcov 100 ;# percent coverage of end contacts
2914 set well_res_overlap 0 ;# not a well resistor
2915 set end_contact_type "" ;# no contacts for metal resistors
2916 set mask_clearance 0 ;# additional length to clear mask
2917
2918 # Set a local variable for each parameter (e.g., $l, $w, etc.)
2919 foreach key [dict keys $parameters] {
2920 set $key [dict get $parameters $key]
2921 }
2922
2923 if {![dict exists $parameters end_contact_size]} {
2924 set end_contact_size $contact_size
2925 }
2926
2927 # Compute half width and length
2928 set hw [/ $w 2.0]
2929 set hl [/ $l 2.0]
2930
2931 # Reduce contact sizes by (end type) surround so that
2932 # the contact area edges match the device type width.
2933 # (Minimum dimensions will be enforced by the contact drawing routine)
2934 set epl [- ${w} [* ${end_surround} 2]] ;# end contact width
2935
2936 # Reduce contact size for well resistor types
2937 if {$well_res_overlap > 0} {
2938 set epl [- ${epl} [* ${well_res_overlap} 2]]
2939 }
2940
2941 # Reduce contact part of end by coverage percentage
2942 if {${endcov} > 0} {
2943 set cpl [* ${epl} [/ ${endcov} 100.0]]
2944 } else {
2945 set cpl $epl
2946 }
2947
2948 set hepl [+ [/ ${epl} 2.0] ${end_surround}]
2949 set hesz [+ [/ ${end_contact_size} 2.0] ${end_surround}]
2950
2951 pushbox
2952 box size 0 0 ;# Position is taken from caller
2953
2954 # Front end contact (always bottom)
2955 pushbox
2956 box move s ${hl}um
2957 pushbox
2958 box move s ${mask_clearance}um
2959 box move s ${res_to_endcont}um
2960
2961 pushbox
2962 box size 0 0
2963 box grow n ${hesz}um
2964 box grow s ${hesz}um
2965 box grow e ${hepl}um
2966 box grow w ${hepl}um
2967 paint ${end_type}
2968 set cext [sky130::getbox]
2969 popbox
2970
2971 if {${end_contact_type} != ""} {
2972 set cext [sky130::draw_contact ${cpl} 0 \
2973 ${end_surround} ${metal_surround} ${end_contact_size} \
2974 ${end_type} ${end_contact_type} li horz]
2975 }
2976 popbox
2977
2978 # Draw portion between resistor end and contact.
2979 box grow e ${hw}um
2980 box grow w ${hw}um
2981 pushbox
2982 box grow s ${mask_clearance}um
2983 paint ${res_type}
2984 popbox
2985 box move s ${mask_clearance}um
2986 box grow s ${res_to_endcont}um
2987 if {$well_res_overlap > 0} {
2988 set well_extend [+ ${well_res_overlap} [/ ${end_contact_size} 2.0] ${end_surround}]
2989 box grow s ${well_extend}um
2990 paint ${well_res_type}
2991 } else {
2992 paint ${end_type}
2993 }
2994 set cext [sky130::unionbox $cext [sky130::getbox]]
2995 popbox
2996
2997 # Draw the resistor and endcaps
2998 pushbox
2999 box grow n ${hl}um
3000 box grow s ${hl}um
3001 box grow e ${hw}um
3002 box grow w ${hw}um
3003
3004 # Capture these extents in the bounding box in case both contacts
3005 # are on one side.
3006 set cext [sky130::unionbox $cext [sky130::getbox]]
3007
3008 set deltax [+ ${res_spacing} ${w}]
3009 set deltay [- ${l} ${w}]
3010 for {set i 0} {$i < [- $nf 1]} {incr i} {
3011 paint ${res_type}
3012 pushbox
3013 if {[% $i 2] == 0} {
3014 box move n ${deltay}um
3015 }
3016 box height ${w}um
3017 box width ${deltax}um
3018 paint ${res_type}
3019 popbox
3020 box move e ${deltax}um
3021 }
3022 paint ${res_type}
3023 # Capture these extents in the bounding box
3024 set cext [sky130::unionbox $cext [sky130::getbox]]
3025 popbox
3026
3027 # Move box to last finger
3028 set lastf [* [- $nf 1] $deltax]
3029 box move e ${lastf}um
3030
3031 # Back-end contact (top or bottom, depending if odd or even turns)
3032 pushbox
3033
3034 if {[% $nf 2] == 1} {
3035 set dir n
3036 } else {
3037 set dir s
3038 }
3039 box move $dir ${hl}um
3040 pushbox
3041 box move $dir ${mask_clearance}um
3042 box move $dir ${res_to_endcont}um
3043
3044 pushbox
3045 box size 0 0
3046 box grow n ${hesz}um
3047 box grow s ${hesz}um
3048 box grow e ${hepl}um
3049 box grow w ${hepl}um
3050 paint ${end_type}
3051 set cext [sky130::unionbox $cext [sky130::getbox]]
3052 popbox
3053
3054 if {${end_contact_type} != ""} {
3055 set cext [sky130::unionbox $cext [sky130::draw_contact ${cpl} 0 \
3056 ${end_surround} ${metal_surround} ${end_contact_size} \
3057 ${end_type} ${end_contact_type} li horz]]
3058 }
3059 popbox
3060 # Draw portion between resistor end and contact.
3061 box grow e ${hw}um
3062 box grow w ${hw}um
3063 pushbox
3064 box grow $dir ${mask_clearance}um
3065 paint ${res_type}
3066 popbox
3067 box move $dir ${mask_clearance}um
3068 box grow $dir ${res_to_endcont}um
3069
3070 if {$well_res_overlap > 0} {
3071 set well_extend [+ ${well_res_overlap} [/ ${end_contact_size} 2.0] ${end_surround}]
3072 box grow $dir ${well_extend}um
3073 paint ${well_res_type}
3074 } else {
3075 paint ${end_type}
3076 }
3077 popbox
3078
3079 popbox
3080 return $cext
3081}
3082
3083#----------------------------------------------------------------
3084# Resistor: Draw the tiled device
3085#----------------------------------------------------------------
3086
3087proc sky130::res_draw {parameters} {
3088 tech unlock *
3089 set savesnap [snap]
3090 snap internal
3091
3092 # Set defaults if they are not in parameters
3093 set snake 0 ;# some resistors don't allow snake geometry
3094 set roverlap 0 ;# overlap resistors at contacts
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003095 set guard 0 ;# draw a guard ring
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003096 set plus_diff_type nsd ;# guard ring diffusion type
3097 set overlap_compress 0 ;# special Y distance compression
3098 set well_res_overlap 0 ;# additional well extension behind contact
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003099 set res_diff_spacing 0 ;# spacing from resistor to diffusion
3100 set res_idtype none
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003101
3102 # Set a local variable for each parameter (e.g., $l, $w, etc.)
3103 foreach key [dict keys $parameters] {
3104 set $key [dict get $parameters $key]
3105 }
3106
3107 # For devices where inter-device space is smaller than device-to-guard ring
3108 if {![dict exists $parameters end_to_end_space]} {
3109 set end_to_end_space $end_spacing
3110 }
3111
3112 if {![dict exists $parameters end_contact_size]} {
3113 set end_contact_size $contact_size
3114 }
3115
3116 # Normalize distance units to microns
3117 set w [magic::spice2float $w]
3118 set l [magic::spice2float $l]
3119
3120 pushbox
3121 box values 0 0 0 0
3122
3123 # Determine the base device dimensions by drawing one device
3124 # while all layers are locked (nothing drawn). This allows the
3125 # base drawing routine to do complicated geometry without having
3126 # to duplicate it here with calculations.
3127
3128 tech lock *
3129 set nf $nx
3130 if {($snake == 1) && ($nx == 1)} {set snake 0}
3131 if {$snake == 1} {
3132 set bbox [sky130::res_snake_device $nf $parameters]
3133 set nx 1
3134 } else {
3135 set bbox [sky130::res_device $parameters]
3136 }
3137 # puts stdout "Diagnostic: Device bounding box e $bbox (um)"
3138 tech unlock *
3139
3140 set fw [- [lindex $bbox 2] [lindex $bbox 0]]
3141 set fh [- [lindex $bbox 3] [lindex $bbox 1]]
3142 set lw [+ [lindex $bbox 2] [lindex $bbox 0]]
3143 set lh [+ [lindex $bbox 3] [lindex $bbox 1]]
3144
3145 # Determine tile width and height (depends on overlap)
3146 # Snake resistors cannot overlap.
3147 # However, snake resistors with an odd number of fingers can
3148 # compress the space if overlap_compress is defined
3149
3150 if {($roverlap == 1) && ($snake == 1) && ([% $nf 2] == 1) && ($m > 1)} {
3151 set dy [- $fh $overlap_compress]
3152 } elseif {($roverlap == 0) || ($snake == 1)} {
3153 set dy [+ $fh $end_to_end_space]
3154 } else {
3155 # overlap poly
3156 set dy [- $fh [+ [* [+ $end_surround $well_res_overlap] 2.0] $end_contact_size]]
3157 }
3158 set dx [+ $fw $res_spacing]
3159
3160 # Determine core width and height
3161 set corex [+ [* [- $nx 1] $dx] $fw]
3162 set corey [+ [* [- $m 1] $dy] $fh]
3163 set corellx [/ [+ [- $corex $fw] $lw] 2.0]
3164 set corelly [/ [+ [- $corey $fh] $lh] 2.0]
3165
3166 set lv_sub_types {"psd" "nsd"}
3167 if {[lsearch $lv_sub_types $plus_diff_type] >= 0} {
3168 set guard_diff_surround 0
3169 } else {
3170 set guard_diff_surround ${diff_surround}
3171 }
3172
3173 if {$guard != 0} {
3174 # Calculate guard ring size (measured to contact center)
3175 set gx [+ $corex [* 2.0 [+ $res_diff_spacing $guard_diff_surround]] $contact_size]
3176 set gy [+ $corey [* 2.0 [+ $end_spacing $guard_diff_surround]] $contact_size]
3177
3178 # Draw the guard ring first, because well resistors are on the substrate plane
3179 sky130::guard_ring $gx $gy $parameters
3180 }
3181
3182 pushbox
3183 box move w ${corellx}um
3184 box move s ${corelly}um
3185 # puts "Device position at = [sky130::getbox]"
3186 for {set xp 0} {$xp < $nx} {incr xp} {
3187 pushbox
3188 for {set yp 0} {$yp < $m} {incr yp} {
3189 if {$snake == 1} {
3190 sky130::res_snake_device $nf $parameters
3191 } else {
3192 sky130::res_device $parameters
3193 }
3194 box move n ${dy}um
3195 }
3196 popbox
3197 box move e ${dx}um
3198 }
3199 popbox
3200 popbox
3201
3202 snap $savesnap
3203 tech revert
3204}
3205
3206#----------------------------------------------------------------
3207
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003208proc sky130::sky130_fd_pr__res_generic_po_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003209
3210 # Set a local variable for each rule in ruleset
3211 foreach key [dict keys $sky130::ruleset] {
3212 set $key [dict get $sky130::ruleset $key]
3213 }
3214
Tim Edwards8469aa62020-11-29 12:42:25 -05003215 if {[dict exists $parameters hv_guard]} {
3216 if {[dict get $parameters hv_guard] == 1} {
3217 set gdifftype mvnsd
3218 set gdiffcont mvnsc
3219 set gsurround 0.33
3220 } else {
3221 set gdifftype nsd
3222 set gdiffcont nsc
3223 set gsurround $sub_surround
3224 }
3225 }
3226
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003227 set newdict [dict create \
3228 res_type npres \
3229 end_type poly \
3230 end_contact_type pc \
Tim Edwards8469aa62020-11-29 12:42:25 -05003231 plus_diff_type $gdifftype \
3232 plus_contact_type $gdiffcont \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003233 sub_type nwell \
Tim Edwards8469aa62020-11-29 12:42:25 -05003234 guard_sub_surround $gsurround \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003235 end_surround $poly_surround \
3236 end_spacing 0.48 \
3237 end_to_end_space 0.52 \
3238 res_to_endcont $res_to_cont \
3239 res_spacing $poly_spacing \
3240 res_diff_spacing 0.48 \
3241 mask_clearance 0.52 \
3242 overlap_compress 0.36 \
3243 ]
Tim Edwards8469aa62020-11-29 12:42:25 -05003244
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003245 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3246 return [sky130::res_draw $drawdict]
3247}
3248
3249#----------------------------------------------------------------
3250
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003251proc sky130::sky130_fd_pr__res_high_po_0p35_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003252
3253 # Set a local variable for each rule in ruleset
3254 foreach key [dict keys $sky130::ruleset] {
3255 set $key [dict get $sky130::ruleset $key]
3256 }
3257
3258 set newdict [dict create \
3259 res_type ppres \
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003260 res_idtype res0p35 \
3261 end_type xpc \
3262 end_contact_type xpc \
3263 end_contact_size 0 \
3264 plus_diff_type psd \
3265 plus_contact_type psc \
3266 sub_type psub \
3267 end_surround $poly_surround \
3268 end_spacing 0.48 \
3269 end_to_end_space 0.52 \
3270 end_contact_size 0.19 \
3271 res_to_endcont 1.985 \
3272 res_spacing 1.24 \
3273 res_diff_spacing 0.48 \
3274 mask_clearance 0.52 \
3275 overlap_compress 0.36 \
3276 ]
3277 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3278 return [sky130::res_draw $drawdict]
3279}
3280
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003281proc sky130::sky130_fd_pr__res_high_po_0p69_draw {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003282
3283 # Set a local variable for each rule in ruleset
3284 foreach key [dict keys $sky130::ruleset] {
3285 set $key [dict get $sky130::ruleset $key]
3286 }
3287
3288 set newdict [dict create \
3289 res_type ppres \
3290 res_idtype res0p69 \
3291 end_type xpc \
3292 end_contact_type xpc \
3293 end_contact_size 0 \
3294 plus_diff_type psd \
3295 plus_contact_type psc \
3296 sub_type psub \
3297 end_surround $poly_surround \
3298 end_spacing 0.48 \
3299 end_to_end_space 0.52 \
3300 end_contact_size 0.19 \
3301 res_to_endcont 1.985 \
3302 res_spacing 1.24 \
3303 res_diff_spacing 0.48 \
3304 mask_clearance 0.52 \
3305 overlap_compress 0.36 \
3306 ]
3307 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3308 return [sky130::res_draw $drawdict]
3309}
3310
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003311proc sky130::sky130_fd_pr__res_high_po_1p41_draw {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003312
3313 # Set a local variable for each rule in ruleset
3314 foreach key [dict keys $sky130::ruleset] {
3315 set $key [dict get $sky130::ruleset $key]
3316 }
3317
3318 set newdict [dict create \
3319 res_type ppres \
3320 res_idtype res1p41 \
3321 end_type xpc \
3322 end_contact_type xpc \
3323 end_contact_size 0 \
3324 plus_diff_type psd \
3325 plus_contact_type psc \
3326 sub_type psub \
3327 end_surround $poly_surround \
3328 end_spacing 0.48 \
3329 end_to_end_space 0.52 \
3330 end_contact_size 0.19 \
3331 res_to_endcont 1.985 \
3332 res_spacing 1.24 \
3333 res_diff_spacing 0.48 \
3334 mask_clearance 0.52 \
3335 overlap_compress 0.36 \
3336 ]
3337 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3338 return [sky130::res_draw $drawdict]
3339}
3340
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003341proc sky130::sky130_fd_pr__res_high_po_2p85_draw {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003342
3343 # Set a local variable for each rule in ruleset
3344 foreach key [dict keys $sky130::ruleset] {
3345 set $key [dict get $sky130::ruleset $key]
3346 }
3347
3348 set newdict [dict create \
3349 res_type ppres \
3350 res_idtype res2p85 \
3351 end_type xpc \
3352 end_contact_type xpc \
3353 end_contact_size 0 \
3354 plus_diff_type psd \
3355 plus_contact_type psc \
3356 sub_type psub \
3357 end_surround $poly_surround \
3358 end_spacing 0.48 \
3359 end_to_end_space 0.52 \
3360 end_contact_size 0.19 \
3361 res_to_endcont 1.985 \
3362 res_spacing 1.24 \
3363 res_diff_spacing 0.48 \
3364 mask_clearance 0.52 \
3365 overlap_compress 0.36 \
3366 ]
3367 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3368 return [sky130::res_draw $drawdict]
3369}
3370
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003371proc sky130::sky130_fd_pr__res_high_po_5p73_draw {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003372
3373 # Set a local variable for each rule in ruleset
3374 foreach key [dict keys $sky130::ruleset] {
3375 set $key [dict get $sky130::ruleset $key]
3376 }
3377
3378 set newdict [dict create \
3379 res_type ppres \
3380 res_idtype res5p73 \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003381 end_type xpc \
3382 end_contact_type xpc \
3383 end_contact_size 0 \
3384 plus_diff_type psd \
3385 plus_contact_type psc \
3386 sub_type psub \
3387 end_surround $poly_surround \
3388 end_spacing 0.48 \
3389 end_to_end_space 0.52 \
3390 end_contact_size 0.19 \
3391 res_to_endcont 1.985 \
3392 res_spacing 1.24 \
3393 res_diff_spacing 0.48 \
3394 mask_clearance 0.52 \
3395 overlap_compress 0.36 \
3396 ]
3397 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3398 return [sky130::res_draw $drawdict]
3399}
3400
3401#----------------------------------------------------------------
3402
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003403proc sky130::sky130_fd_pr__res_xhigh_po_0p35_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003404
3405 # Set a local variable for each rule in ruleset
3406 foreach key [dict keys $sky130::ruleset] {
3407 set $key [dict get $sky130::ruleset $key]
3408 }
3409
3410 set newdict [dict create \
3411 res_type xpres \
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003412 res_idtype res0p35 \
3413 end_type xpc \
3414 end_contact_type xpc \
3415 end_contact_size 0 \
3416 plus_diff_type psd \
3417 plus_contact_type psc \
3418 sub_type psub \
3419 end_surround $poly_surround \
3420 end_spacing 0.48 \
3421 end_to_end_space 0.52 \
3422 end_contact_size 0.19 \
3423 res_to_endcont 1.985 \
3424 res_spacing 1.24 \
3425 res_diff_spacing 0.48 \
3426 mask_clearance 0.52 \
3427 overlap_compress 0.36 \
3428 ]
3429 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3430 return [sky130::res_draw $drawdict]
3431}
3432
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003433proc sky130::sky130_fd_pr__res_xhigh_po_0p69_draw {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003434
3435 # Set a local variable for each rule in ruleset
3436 foreach key [dict keys $sky130::ruleset] {
3437 set $key [dict get $sky130::ruleset $key]
3438 }
3439
3440 set newdict [dict create \
3441 res_type xpres \
3442 res_idtype res0p69 \
3443 end_type xpc \
3444 end_contact_type xpc \
3445 end_contact_size 0 \
3446 plus_diff_type psd \
3447 plus_contact_type psc \
3448 sub_type psub \
3449 end_surround $poly_surround \
3450 end_spacing 0.48 \
3451 end_to_end_space 0.52 \
3452 end_contact_size 0.19 \
3453 res_to_endcont 1.985 \
3454 res_spacing 1.24 \
3455 res_diff_spacing 0.48 \
3456 mask_clearance 0.52 \
3457 overlap_compress 0.36 \
3458 ]
3459 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3460 return [sky130::res_draw $drawdict]
3461}
3462
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003463proc sky130::sky130_fd_pr__res_xhigh_po_1p41_draw {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003464
3465 # Set a local variable for each rule in ruleset
3466 foreach key [dict keys $sky130::ruleset] {
3467 set $key [dict get $sky130::ruleset $key]
3468 }
3469
3470 set newdict [dict create \
3471 res_type xpres \
3472 res_idtype res1p41 \
3473 end_type xpc \
3474 end_contact_type xpc \
3475 end_contact_size 0 \
3476 plus_diff_type psd \
3477 plus_contact_type psc \
3478 sub_type psub \
3479 end_surround $poly_surround \
3480 end_spacing 0.48 \
3481 end_to_end_space 0.52 \
3482 end_contact_size 0.19 \
3483 res_to_endcont 1.985 \
3484 res_spacing 1.24 \
3485 res_diff_spacing 0.48 \
3486 mask_clearance 0.52 \
3487 overlap_compress 0.36 \
3488 ]
3489 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3490 return [sky130::res_draw $drawdict]
3491}
3492
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003493proc sky130::sky130_fd_pr__res_xhigh_po_2p85_draw {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003494
3495 # Set a local variable for each rule in ruleset
3496 foreach key [dict keys $sky130::ruleset] {
3497 set $key [dict get $sky130::ruleset $key]
3498 }
3499
3500 set newdict [dict create \
3501 res_type xpres \
3502 res_idtype res2p85 \
3503 end_type xpc \
3504 end_contact_type xpc \
3505 end_contact_size 0 \
3506 plus_diff_type psd \
3507 plus_contact_type psc \
3508 sub_type psub \
3509 end_surround $poly_surround \
3510 end_spacing 0.48 \
3511 end_to_end_space 0.52 \
3512 end_contact_size 0.19 \
3513 res_to_endcont 1.985 \
3514 res_spacing 1.24 \
3515 res_diff_spacing 0.48 \
3516 mask_clearance 0.52 \
3517 overlap_compress 0.36 \
3518 ]
3519 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3520 return [sky130::res_draw $drawdict]
3521}
3522
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003523proc sky130::sky130_fd_pr__res_xhigh_po_5p73_draw {parameters} {
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003524
3525 # Set a local variable for each rule in ruleset
3526 foreach key [dict keys $sky130::ruleset] {
3527 set $key [dict get $sky130::ruleset $key]
3528 }
3529
3530 set newdict [dict create \
3531 res_type xpres \
3532 res_idtype res5p73 \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003533 end_type xpc \
3534 end_contact_type xpc \
3535 end_contact_size 0 \
3536 plus_diff_type psd \
3537 plus_contact_type psc \
3538 sub_type psub \
3539 end_surround $poly_surround \
3540 end_spacing 0.48 \
3541 end_to_end_space 0.52 \
3542 end_contact_size 0.19 \
3543 res_to_endcont 1.985 \
3544 res_spacing 1.24 \
3545 res_diff_spacing 0.48 \
3546 mask_clearance 0.52 \
3547 overlap_compress 0.36 \
3548 ]
3549 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3550 return [sky130::res_draw $drawdict]
3551}
3552
3553#----------------------------------------------------------------
3554
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003555proc sky130::sky130_fd_pr__res_generic_nd_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003556
3557 # Set a local variable for each rule in ruleset
3558 foreach key [dict keys $sky130::ruleset] {
3559 set $key [dict get $sky130::ruleset $key]
3560 }
3561
3562 set newdict [dict create \
3563 res_type rdn \
3564 end_type ndiff \
3565 end_contact_type ndc \
3566 plus_diff_type psd \
3567 plus_contact_type psc \
3568 sub_type psub \
3569 end_surround $diff_surround \
3570 end_spacing 0.44 \
3571 res_to_endcont 0.37 \
3572 res_spacing 0.30 \
3573 res_diff_spacing 0.44 \
3574 mask_clearance 0.22 \
3575 overlap_compress 0.36 \
3576 ]
3577 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3578 return [sky130::res_draw $drawdict]
3579}
3580
3581#----------------------------------------------------------------
3582
Tim Edwards0ee0f182020-11-21 16:15:07 -05003583proc sky130::sky130_fd_pr__res_generic_nd__hv_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003584
3585 # Set a local variable for each rule in ruleset
3586 foreach key [dict keys $sky130::ruleset] {
3587 set $key [dict get $sky130::ruleset $key]
3588 }
3589
3590 set newdict [dict create \
3591 res_type mvrdn \
3592 end_type mvndiff \
3593 end_contact_type mvndc \
3594 plus_diff_type mvpsd \
3595 plus_contact_type mvpsc \
3596 sub_type psub \
3597 end_surround $diff_surround \
3598 end_spacing 0.44 \
3599 res_to_endcont 0.37 \
3600 res_spacing 0.30 \
3601 res_diff_spacing 0.44 \
3602 mask_clearance 0.22 \
3603 overlap_compress 0.36 \
3604 ]
3605 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3606 return [sky130::res_draw $drawdict]
3607}
3608
3609#----------------------------------------------------------------
3610
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003611proc sky130::sky130_fd_pr__res_generic_pd_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003612
3613 # Set a local variable for each rule in ruleset
3614 foreach key [dict keys $sky130::ruleset] {
3615 set $key [dict get $sky130::ruleset $key]
3616 }
3617
3618 set newdict [dict create \
3619 res_type rdp \
3620 end_type pdiff \
3621 end_contact_type pdc \
3622 plus_diff_type nsd \
3623 plus_contact_type nsc \
3624 sub_type nwell \
3625 end_surround $diff_surround \
3626 end_spacing 0.44 \
3627 res_to_endcont 0.37 \
3628 res_spacing $diff_spacing \
3629 res_diff_spacing 0.44 \
3630 mask_clearance 0.22 \
3631 overlap_compress 0.36 \
3632 ]
3633 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3634 return [sky130::res_draw $drawdict]
3635}
3636
3637#----------------------------------------------------------------
3638
Tim Edwards0ee0f182020-11-21 16:15:07 -05003639proc sky130::sky130_fd_pr__res_generic_pd__hv_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003640
3641 # Set a local variable for each rule in ruleset
3642 foreach key [dict keys $sky130::ruleset] {
3643 set $key [dict get $sky130::ruleset $key]
3644 }
3645
3646 set newdict [dict create \
3647 res_type mvrdp \
3648 end_type mvpdiff \
3649 end_contact_type mvpdc \
3650 plus_diff_type mvnsd \
3651 plus_contact_type mvnsc \
3652 sub_type nwell \
3653 end_surround $diff_surround \
3654 guard_sub_surround 0.33 \
3655 end_spacing 0.44 \
3656 res_to_endcont 0.37 \
3657 res_spacing 0.30 \
3658 res_diff_spacing 0.44 \
3659 mask_clearance 0.22 \
3660 overlap_compress 0.36 \
3661 ]
3662 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3663 return [sky130::res_draw $drawdict]
3664}
3665
3666#----------------------------------------------------------------
3667
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003668proc sky130::sky130_fd_pr__res_iso_pw_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003669
3670 # Set a local variable for each rule in ruleset
3671 foreach key [dict keys $sky130::ruleset] {
3672 set $key [dict get $sky130::ruleset $key]
3673 }
3674
3675 set newdict [dict create \
3676 well_res_type pwell \
3677 res_type rpw \
3678 end_type psd \
3679 end_contact_type psc \
3680 plus_diff_type nsd \
3681 plus_contact_type nsc \
3682 sub_type dnwell \
3683 sub_surround 0.23 \
3684 guard_sub_type nwell \
3685 guard_sub_surround 0.63 \
3686 end_surround $diff_surround \
3687 end_spacing 0.63 \
3688 end_to_end_space 1.15 \
3689 end_overlap_cont 0.06 \
3690 end_contact_size 0.53 \
3691 overlap_compress -0.17 \
3692 res_to_endcont 0.265 \
3693 res_spacing 1.4 \
3694 res_diff_spacing 0.63 \
3695 well_res_overlap 0.2 \
3696 ]
3697 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3698 return [sky130::res_draw $drawdict]
3699}
3700
3701#----------------------------------------------------------------
3702
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003703proc sky130::sky130_fd_pr__res_generic_l1_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003704
3705 # Set a local variable for each rule in ruleset
3706 foreach key [dict keys $sky130::ruleset] {
3707 set $key [dict get $sky130::ruleset $key]
3708 }
3709
3710 set newdict [dict create \
3711 guard 0 \
3712 res_type rli \
3713 end_type li \
3714 end_surround 0.0 \
3715 end_spacing 0.0 \
3716 res_to_endcont 0.2 \
3717 end_to_end_space 0.23 \
3718 res_spacing $metal_spacing \
3719 ]
3720 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3721 return [sky130::res_draw $drawdict]
3722}
3723
3724#----------------------------------------------------------------
3725
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003726proc sky130::sky130_fd_pr__res_generic_m1_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003727
3728 # Set a local variable for each rule in ruleset
3729 foreach key [dict keys $sky130::ruleset] {
3730 set $key [dict get $sky130::ruleset $key]
3731 }
3732
3733 set newdict [dict create \
3734 guard 0 \
3735 res_type rm1 \
3736 end_type m1 \
3737 end_surround 0.0 \
3738 end_spacing 0.0 \
3739 end_to_end_space 0.28 \
3740 res_to_endcont 0.2 \
3741 res_spacing $mmetal_spacing \
3742 ]
3743 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3744 return [sky130::res_draw $drawdict]
3745}
3746
3747#----------------------------------------------------------------
3748
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003749proc sky130::sky130_fd_pr__res_generic_m2_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003750
3751 # Set a local variable for each rule in ruleset
3752 foreach key [dict keys $sky130::ruleset] {
3753 set $key [dict get $sky130::ruleset $key]
3754 }
3755
3756 set newdict [dict create \
3757 guard 0 \
3758 res_type rm2 \
3759 end_type m2 \
3760 end_surround 0.0 \
3761 end_spacing 0.0 \
3762 end_to_end_space 0.28 \
3763 res_to_endcont 0.2 \
3764 res_spacing $mmetal_spacing \
3765 ]
3766 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3767 return [sky130::res_draw $drawdict]
3768}
3769
3770#----------------------------------------------------------------
3771
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003772proc sky130::sky130_fd_pr__res_generic_m3_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003773
3774 # Set a local variable for each rule in ruleset
3775 foreach key [dict keys $sky130::ruleset] {
3776 set $key [dict get $sky130::ruleset $key]
3777 }
3778
3779 set newdict [dict create \
3780 guard 0 \
3781 res_type rm3 \
3782 end_type m3 \
3783 end_surround 0.0 \
3784 end_spacing 0.0 \
3785 end_to_end_space 0.28 \
3786 res_to_endcont 0.2 \
3787 res_spacing $mmetal_spacing \
3788 ]
3789 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3790 return [sky130::res_draw $drawdict]
3791}
3792
3793#----------------------------------------------------------------
3794
3795#ifdef METAL5
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003796proc sky130::sky130_fd_pr__res_generic_m4_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003797
3798 # Set a local variable for each rule in ruleset
3799 foreach key [dict keys $sky130::ruleset] {
3800 set $key [dict get $sky130::ruleset $key]
3801 }
3802
3803 set newdict [dict create \
3804 guard 0 \
3805 res_type rm4 \
3806 end_type m4 \
3807 end_surround 0.0 \
3808 end_spacing 0.0 \
3809 end_to_end_space 0.28 \
3810 res_to_endcont 0.2 \
3811 res_spacing $mmetal_spacing \
3812 ]
3813 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3814 return [sky130::res_draw $drawdict]
3815}
3816
Tim Edwardsd7289eb2020-09-10 21:48:31 -04003817proc sky130::sky130_fd_pr__res_generic_m5_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003818 # Set a local variable for each rule in ruleset
3819 foreach key [dict keys $sky130::ruleset] {
3820 set $key [dict get $sky130::ruleset $key]
3821 }
3822
3823 set newdict [dict create \
3824 guard 0 \
3825 res_type rm5 \
3826 end_type m5 \
3827 end_surround 0.0 \
3828 end_spacing 0.0 \
3829 end_to_end_space 1.6 \
3830 res_to_endcont 0.2 \
3831 res_spacing $mmetal_spacing \
3832 ]
3833 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
3834 return [sky130::res_draw $drawdict]
3835}
3836#endif (METAL5)
3837
3838#----------------------------------------------------------------
3839# Resistor total length computation
3840#----------------------------------------------------------------
3841
3842proc sky130::compute_ltot {parameters} {
3843 # In case snake not defined
3844 set snake 0
3845 set caplen 0
3846
3847 foreach key [dict keys $parameters] {
3848 set $key [dict get $parameters $key]
3849 }
3850
3851 set l [magic::spice2float $l]
3852 set l [magic::3digitpastdecimal $l]
3853
3854 # Compute total length. Use catch to prevent error in batch/scripted mode.
3855 if {$snake == 1} {
3856 catch {set magic::ltot_val [expr ($caplen * ($nx - 1)) + ($l * $nx) + ($nx - 1)]}
3857 } else {
3858 catch {set magic::ltot_val $l}
3859 }
3860}
3861
3862#----------------------------------------------------------------
3863# resistor: Check device parameters for out-of-bounds values
3864#----------------------------------------------------------------
3865
3866proc sky130::res_check {device parameters} {
3867
3868 # Set a local variable for each parameter (e.g., $l, $w, etc.)
3869 set snake 0
Tim Edwards0ee0f182020-11-21 16:15:07 -05003870 set guard 0
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003871 set sterm 0.0
3872 set caplen 0
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003873 set wmax 0
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003874
3875 foreach key [dict keys $parameters] {
3876 set $key [dict get $parameters $key]
3877 }
3878
3879 # Normalize distance units to microns
3880 set w [magic::spice2float $w]
3881 set w [magic::3digitpastdecimal $w]
3882 set l [magic::spice2float $l]
3883 set l [magic::3digitpastdecimal $l]
3884
3885 set val [magic::spice2float $val]
3886 set rho [magic::spice2float $rho]
3887
3888 # nf, m must be integer
3889 if {![string is int $nx]} {
3890 puts stderr "X repeat must be an integer!"
3891 dict set parameters nx 1
3892 }
3893 if {![string is int $m]} {
3894 puts stderr "Y repeat must be an integer!"
3895 dict set parameters m 1
3896 }
3897
3898 # Width always needs to be specified
3899 if {$w < $wmin} {
3900 puts stderr "Resistor width must be >= $wmin um"
3901 dict set parameters w $wmin
3902 }
Tim Edwardsbf5ec172020-08-09 14:04:00 -04003903 if {$wmax > 0 && $w > $wmax} {
3904 puts stderr "Resistor width must be <= $wmax um"
3905 dict set parameters w $wmax
3906 }
3907
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003908 # Val and W specified - no L
3909 if {$l == 0} {
3910 set l [expr ($w - $dw) * $val / $rho]
3911 set l [magic::3digitpastdecimal $l]
3912 set stringval [magic::float2spice $val]
3913 dict set parameters l [magic::float2spice [expr $l * 1e-6]]
3914 # L and W specified - ignore Val if specified
3915 } else {
3916 if {$snake == 0} {
3917 set val [expr (2 * $term + $l * $rho) / ($w - $dw)]
3918 } else {
3919 set val [expr $rho * ($nx - 1) + ((2 * ($term + $sterm)) \
3920 + ($rho * $l * $nx) + ($rho * $caplen * ($nx - 1))) \
3921 / ($w - $dw)]
3922 }
3923 set val [magic::float2spice $val]
3924 dict set parameters val $val
3925 }
3926 if {$l < $lmin} {
3927 puts stderr "Resistor length must be >= $lmin um"
3928 dict set parameters l $lmin
3929 }
3930 if {$nx < 1} {
3931 puts stderr "X repeat must be >= 1"
3932 dict set parameters nx 1
3933 }
3934 if {$m < 1} {
3935 puts stderr "Y repeat must be >= 1"
3936 dict set parameters m 1
3937 }
3938
3939 # Snake resistors cannot have width greater than length
3940 if {$snake == 1} {
3941 if {$w > $l} {
3942 puts stderr "Snake resistor width must be < length"
3943 dict set parameters w $l
3944 }
3945 }
3946
Tim Edwards0ee0f182020-11-21 16:15:07 -05003947 # Check via coverage for syntax
3948 if {$guard == 1} {
3949 if {[catch {expr abs($viagb)}]} {
3950 puts stderr "Guard ring bottom via coverage must be numeric!"
3951 dict set parameters viagb 0
3952 } elseif {[expr abs($viagb)] > 100} {
3953 puts stderr "Guard ring bottom via coverage can't be more than 100%"
3954 dict set parameters viagb 100
3955 }
3956 if {[catch {expr abs($viagt)}]} {
3957 puts stderr "Guard ring top via coverage must be numeric!"
3958 dict set parameters viagt 0
3959 } elseif {[expr abs($viagt)] > 100} {
3960 puts stderr "Guard ring top via coverage can't be more than 100%"
3961 dict set parameters viagt 100
3962 }
3963 if {[catch {expr abs($viagr)}]} {
3964 puts stderr "Guard ring right via coverage must be numeric!"
3965 dict set parameters viagr 0
3966 } elseif {[expr abs($viagr)] > 100} {
3967 puts stderr "Guard ring right via coverage can't be more than 100%"
3968 dict set parameters viagr 100
3969 }
3970 if {[catch {expr abs($viagl)}]} {
3971 puts stderr "Guard ring left via coverage must be numeric!"
3972 dict set parameters viagl 0
3973 } elseif {[expr abs($viagl)] > 100} {
3974 puts stderr "Guard ring left via coverage can't be more than 100%"
3975 dict set parameters viagl 100
3976 }
3977 }
3978
Tim Edwards55f4d0e2020-07-05 15:41:02 -04003979 # Diffusion resistors must satisfy diffusion-to-tap spacing of 20um.
3980 # Therefore the maximum of guard ring width or height cannot exceed 40um.
3981 # If in violation, reduce counts first, as these are easiest to recover
3982 # by duplicating the device and overlapping the wells.
3983 if {$device == "rdn" || $device == "rdp"} {
3984 set origm $m
3985 set orignx $nx
3986 while true {
3987 set xext [expr ($w + 0.8) * $nx + 1.0]
3988 set yext [expr ($l + 1.7) * $m + 1.7]
3989 if {[expr min($xext, $yext)] > 40.0} {
3990 if {$yext > 40.0 && $m > 1} {
3991 incr m -1
3992 } elseif {$xext > 40.0 && $nx > 1} {
3993 incr nx -1
3994 } elseif {$yext > 40.0} {
3995 set l 36.6
3996 puts -nonewline stderr "Diffusion resistor length must be < 36.6 um"
3997 puts stderr " to avoid tap spacing violation."
3998 dict set parameters l $l
3999 } elseif {$xext > 40.0} {
4000 set w 38.2
4001 puts -nonewline stderr "Diffusion resistor width must be < 38.2 um"
4002 puts stderr " to avoid tap spacing violation."
4003 dict set parameters w $w
4004 }
4005 } else {
4006 break
4007 }
4008 }
4009 if {$m != $origm} {
4010 puts stderr "Y repeat reduced to prevent tap distance violation"
4011 dict set parameters m $m
4012 }
4013 if {$nx != $orignx} {
4014 puts stderr "X repeat reduced to prevent tap distance violation"
4015 dict set parameters nx $nx
4016 }
4017 }
4018 sky130::compute_ltot $parameters
4019 return $parameters
4020}
4021
4022#----------------------------------------------------------------
4023
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004024proc sky130::sky130_fd_pr__res_iso_pw_check {parameters} {
4025 return [sky130::res_check sky130_fd_pr__res_iso_pw $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004026}
4027
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004028proc sky130::sky130_fd_pr__res_generic_po_check {parameters} {
4029 return [sky130::res_check sky130_fd_pr__res_generic_po $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004030}
4031
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004032proc sky130::sky130_fd_pr__res_high_po_0p35_check {parameters} {
4033 return [sky130::res_check sky130_fd_pr__res_high_po_0p35 $parameters]
Tim Edwardsbf5ec172020-08-09 14:04:00 -04004034}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004035proc sky130::sky130_fd_pr__res_high_po_0p69_check {parameters} {
4036 return [sky130::res_check sky130_fd_pr__res_high_po_0p69 $parameters]
Tim Edwardsbf5ec172020-08-09 14:04:00 -04004037}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004038proc sky130::sky130_fd_pr__res_high_po_1p41_check {parameters} {
4039 return [sky130::res_check sky130_fd_pr__res_high_po_1p41 $parameters]
Tim Edwardsbf5ec172020-08-09 14:04:00 -04004040}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004041proc sky130::sky130_fd_pr__res_high_po_2p85_check {parameters} {
4042 return [sky130::res_check sky130_fd_pr__res_high_po_2p85 $parameters]
Tim Edwardsbf5ec172020-08-09 14:04:00 -04004043}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004044proc sky130::sky130_fd_pr__res_high_po_5p73_check {parameters} {
4045 return [sky130::res_check sky130_fd_pr__res_high_po_5p73 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004046}
4047
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004048proc sky130::sky130_fd_pr__res_xhigh_po_0p35_check {parameters} {
4049 return [sky130::res_check sky130_fd_pr__res_xhigh_po_0p35 $parameters]
Tim Edwardsbf5ec172020-08-09 14:04:00 -04004050}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004051proc sky130::sky130_fd_pr__res_xhigh_po_0p69_check {parameters} {
4052 return [sky130::res_check sky130_fd_pr__res_xhigh_po_0p69 $parameters]
Tim Edwardsbf5ec172020-08-09 14:04:00 -04004053}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004054proc sky130::sky130_fd_pr__res_xhigh_po_1p41_check {parameters} {
4055 return [sky130::res_check sky130_fd_pr__res_xhigh_po_1p41 $parameters]
Tim Edwardsbf5ec172020-08-09 14:04:00 -04004056}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004057proc sky130::sky130_fd_pr__res_xhigh_po_2p85_check {parameters} {
4058 return [sky130::res_check sky130_fd_pr__res_xhigh_po_2p85 $parameters]
Tim Edwardsbf5ec172020-08-09 14:04:00 -04004059}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004060proc sky130::sky130_fd_pr__res_xhigh_po_5p73_check {parameters} {
4061 return [sky130::res_check sky130_fd_pr__res_xhigh_po_5p73 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004062}
4063
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004064proc sky130::sky130_fd_pr__res_generic_nd_check {parameters} {
4065 return [sky130::res_check sky130_fd_pr__res_generic_nd $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004066}
4067
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004068proc sky130::sky130_fd_pr__res_generic_pd_check {parameters} {
4069 return [sky130::res_check sky130_fd_pr__res_generic_pd $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004070}
4071
Tim Edwards0ee0f182020-11-21 16:15:07 -05004072proc sky130::sky130_fd_pr__res_generic_nd__hv_check {parameters} {
4073 return [sky130::res_check sky130_fd_pr__res_generic_nd__hv $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004074}
4075
Tim Edwards0ee0f182020-11-21 16:15:07 -05004076proc sky130::sky130_fd_pr__res_generic_pd__hv_check {parameters} {
4077 return [sky130::res_check sky130_fd_pr__res_generic_pd__hv $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004078}
4079
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004080proc sky130::sky130_fd_pr__res_generic_l1_check {parameters} {
4081 return [sky130::res_check sky130_fd_pr__res_generic_l1 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004082}
4083
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004084proc sky130::sky130_fd_pr__res_generic_m1_check {parameters} {
4085 return [sky130::res_check sky130_fd_pr__res_generic_m1 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004086}
4087
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004088proc sky130::sky130_fd_pr__res_generic_m2_check {parameters} {
4089 return [sky130::res_check sky130_fd_pr__res_generic_m2 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004090}
4091
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004092proc sky130::sky130_fd_pr__res_generic_m3_check {parameters} {
4093 return [sky130::res_check sky130_fd_pr__res_generic_m3 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004094}
4095
4096#ifdef METAL5
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004097proc sky130::sky130_fd_pr__res_generic_m4_check {parameters} {
4098 return [sky130::res_check sky130_fd_pr__res_generic_m4 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004099}
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004100proc sky130::sky130_fd_pr__res_generic_m5_check {parameters} {
4101 return [sky130::res_check sky130_fd_pr__res_generic_m5 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004102}
4103#endif (METAL5)
4104
4105#----------------------------------------------------------------
4106# MOS defaults:
4107#----------------------------------------------------------------
4108# w = Gate width
4109# l = Gate length
4110# m = Multiplier
4111# nf = Number of fingers
4112# diffcov = Diffusion contact coverage
4113# polycov = Poly contact coverage
4114# topc = Top gate contact
4115# botc = Bottom gate contact
4116# guard = Guard ring
4117#
4118# (not user-editable)
4119#
4120# lmin = Gate minimum length
4121# wmin = Gate minimum width
4122#----------------------------------------------------------------
4123
4124#----------------------------------------------------------------
4125# pmos: Specify all user-editable default values and those
4126# needed by mos_check
4127#----------------------------------------------------------------
4128
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004129proc sky130::sky130_fd_pr__pfet_01v8_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004130 return {w 0.42 l 0.15 m 1 nf 1 diffcov 100 polycov 100 \
4131 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4132 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.15 wmin 0.42 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004133 compatible {sky130_fd_pr__pfet_01v8 \
4134 sky130_fd_pr__pfet_01v8_lvt sky130_fd_pr__pfet_01v8_hvt \
4135 sky130_fd_pr__pfet_g5v0d10v5} full_metal 1}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004136}
4137
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004138proc sky130::sky130_fd_pr__pfet_01v8_lvt_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004139 return {w 0.42 l 0.35 m 1 nf 1 diffcov 100 polycov 100 \
4140 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4141 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.35 wmin 0.42 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004142 compatible {sky130_fd_pr__pfet_01v8 \
4143 sky130_fd_pr__pfet_01v8_lvt sky130_fd_pr__pfet_01v8_hvt \
4144 sky130_fd_pr__pfet_g5v0d10v5} full_metal 1}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004145}
4146
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004147proc sky130::sky130_fd_pr__pfet_01v8_hvt_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004148 return {w 0.42 l 0.15 m 1 nf 1 diffcov 100 polycov 100 \
4149 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4150 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.15 wmin 0.42 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004151 compatible {sky130_fd_pr__pfet_01v8 \
4152 sky130_fd_pr__pfet_01v8_lvt sky130_fd_pr__pfet_01v8_hvt \
4153 sky130_fd_pr__pfet_g5v0d10v5} full_metal 1}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004154}
4155
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004156proc sky130::sky130_fd_pr__pfet_g5v0d10v5_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004157 return {w 0.42 l 0.50 m 1 nf 1 diffcov 100 polycov 100 \
4158 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4159 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.50 wmin 0.42 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004160 compatible {sky130_fd_pr__pfet_01v8 \
4161 sky130_fd_pr__pfet_01v8_lvt sky130_fd_pr__pfet_01v8_hvt \
4162 sky130_fd_pr__pfet_g5v0d10v5} full_metal 1}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004163}
4164
4165#----------------------------------------------------------------
4166# nmos: Specify all user-editable default values and those
4167# needed by mos_check
4168#----------------------------------------------------------------
4169
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004170proc sky130::sky130_fd_pr__nfet_01v8_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004171 return {w 0.420 l 0.150 m 1 nf 1 diffcov 100 polycov 100 \
4172 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4173 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.15 wmin 0.42 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004174 compatible {sky130_fd_pr__nfet_01v8 sky130_fd_pr__nfet_01v8_lvt \
4175 sky130_fd_bs_flash__special_sonosfet_star \
Tim Edwards0ee0f182020-11-21 16:15:07 -05004176 sky130_fd_pr__nfet_g5v0d10v5 sky130_fd_pr__nfet_05v0_nvt} \
4177 full_metal 1 viasrc 100 viadrn 100 viagate 100 \
4178 viagb 0 viagr 0 viagl 0 viagt 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004179}
4180
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004181proc sky130::sky130_fd_pr__nfet_01v8_lvt_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004182 return {w 0.420 l 0.150 m 1 nf 1 diffcov 100 polycov 100 \
4183 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4184 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.15 wmin 0.42 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004185 compatible {sky130_fd_pr__nfet_01v8 sky130_fd_pr__nfet_01v8_lvt \
4186 sky130_fd_bs_flash__special_sonosfet_star \
Tim Edwards0ee0f182020-11-21 16:15:07 -05004187 sky130_fd_pr__nfet_g5v0d10v5 sky130_fd_pr__nfet_05v0_nvt} \
4188 full_metal 1 viasrc 100 viadrn 100 viagate 100 \
4189 viagb 0 viagr 0 viagl 0 viagt 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004190}
4191
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004192proc sky130::sky130_fd_bs_flash__special_sonosfet_star_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004193 return {w 0.420 l 0.150 m 1 nf 1 diffcov 100 polycov 100 \
4194 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4195 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.15 wmin 0.42 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004196 compatible {sky130_fd_pr__nfet_01v8 sky130_fd_pr__nfet_01v8_lvt \
4197 sky130_fd_bs_flash__special_sonosfet_star \
Tim Edwards0ee0f182020-11-21 16:15:07 -05004198 sky130_fd_pr__nfet_g5v0d10v5 sky130_fd_pr__nfet_05v0_nvt} \
4199 full_metal 1 viasrc 100 viadrn 100 viagate 100 \
4200 viagb 0 viagr 0 viagl 0 viagt 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004201}
4202
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004203proc sky130::sky130_fd_pr__nfet_g5v0d10v5_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004204 return {w 0.42 l 0.50 m 1 nf 1 diffcov 100 polycov 100 \
4205 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4206 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.50 wmin 0.42 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004207 compatible {sky130_fd_pr__nfet_01v8 sky130_fd_pr__nfet_01v8_lvt \
4208 sky130_fd_bs_flash__special_sonosfet_star \
Tim Edwards0ee0f182020-11-21 16:15:07 -05004209 sky130_fd_pr__nfet_g5v0d10v5 sky130_fd_pr__nfet_05v0_nvt} \
4210 full_metal 1 viasrc 100 viadrn 100 viagate 100 \
4211 viagb 0 viagr 0 viagl 0 viagt 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004212}
4213
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004214proc sky130::sky130_fd_pr__nfet_05v0_nvt_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004215 return {w 0.42 l 0.50 m 1 nf 1 diffcov 100 polycov 100 \
4216 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4217 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.50 wmin 0.42 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004218 compatible {sky130_fd_pr__nfet_01v8 sky130_fd_pr__nfet_01v8_lvt \
4219 sky130_fd_bs_flash__special_sonosfet_star \
Tim Edwards0ee0f182020-11-21 16:15:07 -05004220 sky130_fd_pr__nfet_g5v0d10v5 sky130_fd_pr__nfet_05v0_nvt} \
4221 full_metal 1 viasrc 100 viadrn 100 viagate 100 \
4222 viagb 0 viagr 0 viagl 0 viagt 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004223}
4224
4225#----------------------------------------------------------------
4226# mos varactor: Specify all user-editable default values and those
4227# needed by mosvc_check
4228#----------------------------------------------------------------
4229
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004230proc sky130::sky130_fd_pr__cap_var_lvt_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004231 return {w 1.0 l 0.18 m 1 nf 1 diffcov 100 polycov 100 \
4232 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4233 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.18 wmin 1.0 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004234 compatible {sky130_fd_pr__cap_var_lvt \
Tim Edwards0ee0f182020-11-21 16:15:07 -05004235 sky130_fd_pr__cap_var_hvt sky130_fd_pr__cap_var} \
4236 full_metal 1 viasrc 100 viadrn 100 viagate 100 \
4237 viagb 0 viagr 0 viagl 0 viagt 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004238}
4239
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004240proc sky130::sky130_fd_pr__cap_var_hvt_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004241 return {w 1.0 l 0.18 m 1 nf 1 diffcov 100 polycov 100 \
4242 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4243 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.18 wmin 1.0 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004244 compatible {sky130_fd_pr__cap_var_lvt \
Tim Edwards0ee0f182020-11-21 16:15:07 -05004245 sky130_fd_pr__cap_var_hvt sky130_fd_pr__cap_var} \
4246 full_metal 1 viasrc 100 viadrn 100 viagate 100 \
4247 viagb 0 viagr 0 viagl 0 viagt 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004248}
4249
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004250proc sky130::sky130_fd_pr__cap_var_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004251 return {w 1.0 l 0.50 m 1 nf 1 diffcov 100 polycov 100 \
4252 guard 1 glc 1 grc 1 gtc 1 gbc 1 tbcov 100 rlcov 100 \
4253 topc 1 botc 1 poverlap 0 doverlap 1 lmin 0.50 wmin 1.0 \
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004254 compatible {sky130_fd_pr__cap_var_lvt \
Tim Edwards0ee0f182020-11-21 16:15:07 -05004255 sky130_fd_pr__cap_var_hvt sky130_fd_pr__cap_var} \
4256 full_metal 1 viasrc 100 viadrn 100 viagate 100 \
4257 viagb 0 viagr 0 viagl 0 viagt 0}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004258}
4259
4260#----------------------------------------------------------------
4261# mos: Conversion from SPICE netlist parameters to toolkit
4262#----------------------------------------------------------------
4263
4264proc sky130::mos_convert {parameters} {
4265 set pdkparams [dict create]
4266 dict for {key value} $parameters {
4267 switch -nocase $key {
4268 l -
4269 w {
4270 # Length and width are converted to units of microns
4271 set value [magic::spice2float $value]
4272 # set value [expr $value * 1e6]
4273 set value [magic::3digitpastdecimal $value]
4274 dict set pdkparams [string tolower $key] $value
4275 }
4276 m {
Tim Edwards23c97662020-08-09 11:57:32 -04004277 dict set pdkparams [string tolower $key] $value
4278 }
4279 nf {
4280 # Adjustment ot W will be handled below
4281 dict set pdkparams [string tolower $key] $value
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004282 }
4283 }
4284 }
Tim Edwards23c97662020-08-09 11:57:32 -04004285
4286 # Magic does not understand "nf" as a parameter, but expands to
4287 # "nf" number of devices connected horizontally. The "w" value
4288 # must be divided down accordingly, as the "nf" parameter implies
4289 # that the total width "w" is divided into "nf" fingers.
4290
4291 catch {
4292 set w [dict get $pdkparams w]
4293 set nf [dict get $pdkparams nf]
4294 if {$nf > 1} {
4295 dict set pdkparams w [expr $w / $nf]
4296 }
4297 }
4298
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004299 return $pdkparams
4300}
4301
4302#----------------------------------------------------------------
4303
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004304proc sky130::sky130_fd_pr__nfet_01v8_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004305 return [sky130::mos_convert $parameters]
4306}
4307
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004308proc sky130::sky130_fd_pr__nfet_01v8_lvt_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004309 return [sky130::mos_convert $parameters]
4310}
4311
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004312proc sky130::sky130_fd_bs_flash__special_sonosfet_star_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004313 return [sky130::mos_convert $parameters]
4314}
4315
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004316proc sky130::sky130_fd_pr__nfet_g5v0d10v5_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004317 return [sky130::mos_convert $parameters]
4318}
4319
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004320proc sky130::sky130_fd_pr__nfet_05v0_nvt_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004321 return [sky130::mos_convert $parameters]
4322}
4323
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004324proc sky130::sky130_fd_pr__pfet_01v8_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004325 return [sky130::mos_convert $parameters]
4326}
4327
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004328proc sky130::sky130_fd_pr__pfet_01v8_lvt_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004329 return [sky130::mos_convert $parameters]
4330}
4331
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004332proc sky130::sky130_fd_pr__pfet_01v8_hvt_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004333 return [sky130::mos_convert $parameters]
4334}
4335
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004336proc sky130::sky130_fd_pr__pfet_g5v0d10v5_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004337 return [sky130::mos_convert $parameters]
4338}
4339
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004340proc sky130::sky130_fd_pr__cap_var_lvt_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004341 return [sky130::mos_convert $parameters]
4342}
4343
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004344proc sky130::sky130_fd_pr__cap_var_hvt_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004345 return [sky130::mos_convert $parameters]
4346}
4347
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004348proc sky130::sky130_fd_pr__cap_var_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004349 return [sky130::mos_convert $parameters]
4350}
4351
4352#----------------------------------------------------------------
4353# mos: Interactively specifies the fixed layout parameters
4354#----------------------------------------------------------------
4355
4356proc sky130::mos_dialog {device parameters} {
4357 # Editable fields: w, l, nf, m, diffcov, polycov
4358 # Checked fields: topc, botc
4359 # For specific devices, gate type is a selection list
4360
4361 magic::add_entry w "Width (um)" $parameters
4362 magic::add_entry l "Length (um)" $parameters
4363 magic::add_entry nf "Fingers" $parameters
4364 magic::add_entry m "M" $parameters
4365
4366 if {[dict exists $parameters compatible]} {
4367 set sellist [dict get $parameters compatible]
4368 magic::add_selectlist gencell "Device type" $sellist $parameters $device
4369 }
4370
4371 magic::add_entry diffcov "Diffusion contact coverage (%)" $parameters
4372 magic::add_entry polycov "Poly contact coverage (%)" $parameters
4373 magic::add_entry rlcov "Guard ring contact coverage (%)" $parameters
4374 if {[dict exists $parameters gbc]} {
4375 magic::add_entry tbcov "Guard ring top/bottom contact coverage (%)" $parameters
4376 }
4377
4378 magic::add_checkbox poverlap "Overlap at poly contact" $parameters
4379 magic::add_checkbox doverlap "Overlap at diffusion contact" $parameters
4380 magic::add_checkbox topc "Add top gate contact" $parameters
4381 magic::add_checkbox botc "Add bottom gate contact" $parameters
4382
4383 magic::add_checkbox guard "Add guard ring" $parameters
4384 magic::add_checkbox full_metal "Full metal guard ring" $parameters
4385 magic::add_checkbox glc "Add left guard ring contact" $parameters
4386 magic::add_checkbox grc "Add right guard ring contact" $parameters
4387 if {[dict exists $parameters gbc]} {
4388 magic::add_checkbox gbc "Add bottom guard ring contact" $parameters
4389 }
4390 if {[dict exists $parameters gtc]} {
4391 magic::add_checkbox gtc "Add top guard ring contact" $parameters
4392 }
Tim Edwards0ee0f182020-11-21 16:15:07 -05004393
4394 magic::add_entry viasrc "Source via coverage \[+/-\](%)" $parameters
4395 magic::add_entry viadrn "Drain via coverage \[+/-\](%)" $parameters
4396 magic::add_entry viagate "Gate via coverage \[+/-\](%)" $parameters
4397 magic::add_entry viagb "Bottom guard ring via coverage \[+/-\](%)" $parameters
4398 magic::add_entry viagt "Top guard ring via coverage \[+/-\](%)" $parameters
4399 magic::add_entry viagr "Right guard ring via coverage \[+/-\](%)" $parameters
4400 magic::add_entry viagl "Left guard ring via coverage \[+/-\](%)" $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004401}
4402
4403#----------------------------------------------------------------
4404
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004405proc sky130::sky130_fd_pr__nfet_01v8_dialog {parameters} {
4406 sky130::mos_dialog sky130_fd_pr__nfet_01v8 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004407}
4408
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004409proc sky130::sky130_fd_pr__nfet_01v8_lvt_dialog {parameters} {
4410 sky130::mos_dialog sky130_fd_pr__nfet_01v8_lvt $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004411}
4412
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004413proc sky130::sky130_fd_bs_flash__special_sonosfet_star_dialog {parameters} {
4414 sky130::mos_dialog sky130_fd_bs_flash__special_sonosfet_star $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004415}
4416
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004417proc sky130::sky130_fd_pr__nfet_g5v0d10v5_dialog {parameters} {
4418 sky130::mos_dialog sky130_fd_pr__nfet_g5v0d10v5 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004419}
4420
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004421proc sky130::sky130_fd_pr__nfet_05v0_nvt_dialog {parameters} {
4422 sky130::mos_dialog sky130_fd_pr__nfet_05v0_nvt $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004423}
4424
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004425proc sky130::sky130_fd_pr__pfet_01v8_dialog {parameters} {
4426 sky130::mos_dialog sky130_fd_pr__pfet_01v8 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004427}
4428
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004429proc sky130::sky130_fd_pr__pfet_01v8_lvt_dialog {parameters} {
4430 sky130::mos_dialog sky130_fd_pr__pfet_01v8_lvt $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004431}
4432
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004433proc sky130::sky130_fd_pr__pfet_01v8_hvt_dialog {parameters} {
4434 sky130::mos_dialog sky130_fd_pr__pfet_01v8_hvt $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004435}
4436
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004437proc sky130::sky130_fd_pr__pfet_g5v0d10v5_dialog {parameters} {
4438 sky130::mos_dialog sky130_fd_pr__pfet_g5v0d10v5 $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004439}
4440
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004441proc sky130::sky130_fd_pr__cap_var_lvt_dialog {parameters} {
4442 sky130::mos_dialog sky130_fd_pr__cap_var_lvt $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004443}
4444
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004445proc sky130::sky130_fd_pr__cap_var_hvt_dialog {parameters} {
4446 sky130::mos_dialog sky130_fd_pr__cap_var_hvt $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004447}
4448
Tim Edwardsd7289eb2020-09-10 21:48:31 -04004449proc sky130::sky130_fd_pr__cap_var_dialog {parameters} {
4450 sky130::mos_dialog sky130_fd_pr__cap_var $parameters
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004451}
4452
4453#----------------------------------------------------------------
4454# getbox: Get the current cursor box, in microns
4455#----------------------------------------------------------------
4456
4457proc sky130::getbox {} {
4458 set curbox [box values]
4459 set newbox []
4460 set oscale [cif scale out]
4461 for {set i 0} {$i < 4} {incr i} {
4462 set v [* [lindex $curbox $i] $oscale]
4463 lappend newbox $v
4464 }
4465 return $newbox
4466}
4467
4468#----------------------------------------------------------------
4469# unionbox: Get the union bounding box of box1 and box2
4470#----------------------------------------------------------------
4471
4472proc sky130::unionbox {box1 box2} {
4473 set newbox []
4474 for {set i 0} {$i < 2} {incr i} {
4475 set v [lindex $box1 $i]
4476 set o [lindex $box2 $i]
4477 if {$v < $o} {
4478 lappend newbox $v
4479 } else {
4480 lappend newbox $o
4481 }
4482 }
4483 for {set i 2} {$i < 4} {incr i} {
4484 set v [lindex $box1 $i]
4485 set o [lindex $box2 $i]
4486 if {$v > $o} {
4487 lappend newbox $v
4488 } else {
4489 lappend newbox $o
4490 }
4491 }
4492 return $newbox
4493}
4494
4495#----------------------------------------------------------------
4496# Draw a contact
4497#----------------------------------------------------------------
4498
4499proc sky130::draw_contact {w h s o x atype ctype mtype {orient vert}} {
4500
4501 # Draw a minimum-size diff contact centered at current position
4502 # w is width, h is height. Minimum size ensured.
4503 # x is contact size
4504 # s is contact diffusion (or poly) surround
4505 # o is contact metal surround
4506 # atype is active (e.g., ndiff) or bottom metal if a via
4507 # ctype is contact (e.g., ndc)
4508 # mtype is metal (e.g., m1) or top metal if a via
4509 # orient is the orientation of the contact
4510
4511 # Set orientations for the bottom material based on material type.
4512 # Substrate diffusions (tap) need not overlap the contact in all
4513 # directions, but other (diff) types do. The metal (local
4514 # interconnect) layer always overlaps in two directions only.
4515
4516 set lv_sub_types {"psd" "nsd"}
4517 if {[lsearch $lv_sub_types $atype] >= 0} {
4518 set aorient $orient
4519 } else {
4520 set aorient "full"
4521 }
4522
4523 pushbox
4524 box size 0 0
4525 if {$w < $x} {set w $x}
4526 if {$h < $x} {set h $x}
4527 set hw [/ $w 2.0]
4528 set hh [/ $h 2.0]
4529 box grow n ${hh}um
4530 box grow s ${hh}um
4531 box grow e ${hw}um
4532 box grow w ${hw}um
4533 paint ${ctype}
4534 pushbox
4535 # Bottom layer surrounded on sides as declared by aorient
4536 if {($aorient == "vert") || ($aorient == "full")} {
4537 box grow n ${s}um
4538 box grow s ${s}um
4539 }
4540 if {($aorient == "horz") || ($aorient == "full")} {
4541 box grow e ${s}um
4542 box grow w ${s}um
4543 }
4544 paint ${atype}
4545 set extents [sky130::getbox]
4546 popbox
4547 # Top layer surrounded on sides as declared by orient
4548 if {($orient == "vert") || ($orient == "full")} {
4549 box grow n ${o}um
4550 box grow s ${o}um
4551 }
4552 if {($orient == "horz") || ($orient == "full")} {
4553 box grow e ${o}um
4554 box grow w ${o}um
4555 }
4556 paint ${mtype}
4557 popbox
4558 return $extents
4559}
4560
4561#----------------------------------------------------------------
4562# Draw a guard ring
4563#----------------------------------------------------------------
4564
4565proc sky130::guard_ring {gw gh parameters} {
4566
4567 # Set local default values if they are not in parameters
4568 set rlcov 100 ;# Right-left contact coverage percentage
4569 set tbcov 100 ;# Top-bottom contact coverage percentage
4570 set grc 1 ;# Draw right side contact
4571 set glc 1 ;# Draw left side contact
4572 set gtc 1 ;# Draw right side contact
4573 set gbc 1 ;# Draw left side contact
Tim Edwards0ee0f182020-11-21 16:15:07 -05004574 set viagb 0 ;# Draw bottom side via
4575 set viagt 0 ;# Draw top side via
4576 set viagr 0 ;# Draw right side via
4577 set viagl 0 ;# Draw left side via
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004578 set full_metal 1 ;# Draw full (continuous) metal ring
4579 set guard_sub_type pwell ;# substrate type under guard ring
4580 set guard_sub_surround 0 ;# substrate type surrounds guard ring
4581 set plus_diff_type nsd ;# guard ring diffusion type
4582 set plus_contact_type nsc ;# guard ring diffusion contact type
4583 set sub_type pwell ;# substrate type
4584
4585 # Set a local variable for each parameter (e.g., $l, $w, etc.)
4586 foreach key [dict keys $parameters] {
4587 set $key [dict get $parameters $key]
4588 }
4589
4590 # Set guard_sub_type to sub_type if it is not defined
4591 if {![dict exists $parameters guard_sub_type]} {
4592 set guard_sub_type $sub_type
4593 }
4594
4595 set hx [/ $contact_size 2.0]
4596 set hw [/ $gw 2.0]
4597 set hh [/ $gh 2.0]
4598
4599 # Watch for (LV) substrate diffusion types, which have a different
4600 # contact surround amount depending on the direction
4601
4602 set lv_sub_types {"psd" "nsd"}
4603 if {[lsearch $lv_sub_types $plus_diff_type] >= 0} {
4604 set diff_surround 0
4605 }
4606
4607 # Compute diffusion width
4608 set difft [+ $contact_size $diff_surround $diff_surround]
4609 set hdifft [/ $difft 2.0]
4610 # Compute guard ring diffusion width and height
4611 set hdiffw [/ [+ $gw $difft] 2.0]
4612 set hdiffh [/ [+ $gh $difft] 2.0]
4613
4614 pushbox
4615 box size 0 0
4616
4617 pushbox
4618 box move n ${hh}um
4619 box grow n ${hdifft}um
4620 box grow s ${hdifft}um
4621 box grow e ${hdiffw}um
4622 box grow w ${hdiffw}um
4623 paint $plus_diff_type
4624 if {$guard_sub_surround > 0} {
4625 box grow c ${guard_sub_surround}um
4626 paint $guard_sub_type
4627 }
4628 popbox
4629 pushbox
4630 box move s ${hh}um
4631 box grow n ${hdifft}um
4632 box grow s ${hdifft}um
4633 box grow e ${hdiffw}um
4634 box grow w ${hdiffw}um
4635 paint $plus_diff_type
4636 if {$guard_sub_surround > 0} {
4637 box grow c ${guard_sub_surround}um
4638 paint $guard_sub_type
4639 }
4640 popbox
4641 pushbox
4642 box move e ${hw}um
4643 box grow e ${hdifft}um
4644 box grow w ${hdifft}um
4645 box grow n ${hdiffh}um
4646 box grow s ${hdiffh}um
4647 paint $plus_diff_type
4648 if {$guard_sub_surround > 0} {
4649 box grow c ${guard_sub_surround}um
4650 paint $guard_sub_type
4651 }
4652 popbox
4653 pushbox
4654 box move w ${hw}um
4655 box grow e ${hdifft}um
4656 box grow w ${hdifft}um
4657 box grow n ${hdiffh}um
4658 box grow s ${hdiffh}um
4659 paint $plus_diff_type
4660 if {$guard_sub_surround > 0} {
4661 box grow c ${guard_sub_surround}um
4662 paint $guard_sub_type
4663 }
4664 popbox
4665
4666 if {$full_metal} {
4667 set hmetw [/ [+ $gw $contact_size] 2.0]
4668 set hmeth [/ [+ $gh $contact_size] 2.0]
4669 pushbox
4670 box move n ${hh}um
4671 box grow n ${hx}um
4672 box grow s ${hx}um
4673 box grow e ${hmetw}um
4674 box grow w ${hmetw}um
4675 paint li
4676 popbox
4677 pushbox
4678 box move s ${hh}um
4679 box grow n ${hx}um
4680 box grow s ${hx}um
4681 box grow e ${hmetw}um
4682 box grow w ${hmetw}um
4683 paint li
4684 popbox
4685 pushbox
4686 box move e ${hw}um
4687 box grow e ${hx}um
4688 box grow w ${hx}um
4689 box grow n ${hmeth}um
4690 box grow s ${hmeth}um
4691 paint li
4692 popbox
4693 pushbox
4694 box move w ${hw}um
4695 box grow e ${hx}um
4696 box grow w ${hx}um
4697 box grow n ${hmeth}um
4698 box grow s ${hmeth}um
4699 paint li
4700 popbox
4701 }
4702
4703 # Set guard ring height so that contact metal reaches to end, scale by $per
4704 # set ch [* [+ $gh $contact_size [* $metal_surround -2.0]] [/ $rlcov 100.0]]
4705 set ch [* [- $gh $contact_size [* [+ $metal_surround $metal_spacing] \
4706 2.0]] [/ $rlcov 100.0]]
4707 if {$ch < $contact_size} {set ch $contact_size}
4708
4709 # Set guard ring width so that contact metal reaches to side contacts
4710 set cw [* [- $gw $contact_size [* [+ $metal_surround $metal_spacing] \
4711 2.0]] [/ $tbcov 100.0]]
4712 if {$cw < $contact_size} {set cw $contact_size}
4713
4714 if {$tbcov > 0.0} {
4715 if {$gtc == 1} {
4716 pushbox
4717 box move n ${hh}um
4718 sky130::draw_contact $cw 0 $diff_surround $metal_surround \
4719 $contact_size $plus_diff_type $plus_contact_type li horz
4720 popbox
4721 }
4722 if {$gbc == 1} {
4723 pushbox
4724 box move s ${hh}um
4725 sky130::draw_contact $cw 0 $diff_surround $metal_surround \
4726 $contact_size $plus_diff_type $plus_contact_type li horz
4727 popbox
4728 }
4729 }
4730 if {$rlcov > 0.0} {
4731 if {$grc == 1} {
4732 pushbox
4733 box move e ${hw}um
4734 sky130::draw_contact 0 $ch $diff_surround $metal_surround \
4735 $contact_size $plus_diff_type $plus_contact_type li vert
4736 popbox
4737 }
4738 if {$glc == 1} {
4739 pushbox
4740 box move w ${hw}um
4741 sky130::draw_contact 0 $ch $diff_surround $metal_surround \
4742 $contact_size $plus_diff_type $plus_contact_type li vert
4743 popbox
4744 }
4745 }
4746
Tim Edwards0ee0f182020-11-21 16:15:07 -05004747 # Vias
4748 if {$viagb != 0} {
4749 pushbox
4750 set ch $via_size
4751 set cw [* [- $gw $via_size] [/ [expr abs($viagb)] 100.0]]
4752 if {$cw < $via_size} {set cw $via_size}
4753 box move s ${hh}um
4754 box grow n [/ $ch 2]um
4755 box grow s [/ $ch 2]um
4756 set anchor [string index $viagb 0]
4757 if {$anchor == "+"} {
4758 box move w [/ [- $gw $via_size] 2]um
4759 box grow e ${cw}um
4760 } elseif {$anchor == "-"} {
4761 box move e [/ [- $gw $via_size] 2]um
4762 box grow w ${cw}um
4763 } else {
4764 box grow e [/ $cw 2]um
4765 box grow w [/ $cw 2]um
4766 }
4767 sky130::mcon_draw horz
4768 popbox
4769 }
4770 if {$viagt != 0} {
4771 pushbox
4772 set ch $via_size
4773 set cw [* [- $gw $via_size] [/ [expr abs($viagt)] 100.0]]
4774 if {$cw < $via_size} {set cw $via_size}
4775 box move n ${hh}um
4776 box grow n [/ $ch 2]um
4777 box grow s [/ $ch 2]um
4778 set anchor [string index $viagt 0]
4779 if {$anchor == "+"} {
4780 box move w [/ [- $gw $via_size] 2]um
4781 box grow e ${cw}um
4782 } elseif {$anchor == "-"} {
4783 box move e [/ [- $gw $via_size] 2]um
4784 box grow w ${cw}um
4785 } else {
4786 box grow e [/ $cw 2]um
4787 box grow w [/ $cw 2]um
4788 }
4789 sky130::mcon_draw horz
4790 popbox
4791 }
4792 if {$viagr != 0} {
4793 pushbox
4794 set ch [* [- $gh $via_size] [/ [expr abs($viagr)] 100.0]]
4795 if {$ch < $via_size} {set ch $via_size}
4796 set cw $via_size
4797 box move e ${hw}um
4798 box grow e [/ $cw 2]um
4799 box grow w [/ $cw 2]um
4800 set anchor [string index $viagr 0]
4801 if {$anchor == "+"} {
Tim Edwards933e61e2020-11-21 16:50:06 -05004802 box move s [/ [- $gh $via_size] 2]um
Tim Edwards0ee0f182020-11-21 16:15:07 -05004803 box grow n ${ch}um
4804 } elseif {$anchor == "-"} {
Tim Edwards933e61e2020-11-21 16:50:06 -05004805 box move n [/ [- $gh $via_size] 2]um
Tim Edwards0ee0f182020-11-21 16:15:07 -05004806 box grow s ${ch}um
4807 } else {
4808 box grow n [/ $ch 2]um
4809 box grow s [/ $ch 2]um
4810 }
4811 sky130::mcon_draw vert
4812 popbox
4813 }
4814 if {$viagl != 0} {
4815 pushbox
4816 set ch [* [- $gh $via_size] [/ [expr abs($viagl)] 100.0]]
4817 if {$ch < $via_size} {set ch $via_size}
4818 set cw $via_size
4819 box move w ${hw}um
4820 box grow e [/ $cw 2]um
4821 box grow w [/ $cw 2]um
4822 set anchor [string index $viagl 0]
4823 if {$anchor == "+"} {
Tim Edwards933e61e2020-11-21 16:50:06 -05004824 box move s [/ [- $gh $via_size] 2]um
Tim Edwards275e28d2020-11-21 16:43:41 -05004825 box grow n ${ch}um
Tim Edwards0ee0f182020-11-21 16:15:07 -05004826 } elseif {$anchor == "-"} {
Tim Edwards933e61e2020-11-21 16:50:06 -05004827 box move n [/ [- $gh $via_size] 2]um
Tim Edwards0ee0f182020-11-21 16:15:07 -05004828 box grow s ${ch}um
4829 } else {
4830 box grow n [/ $ch 2]um
4831 box grow s [/ $ch 2]um
4832 }
4833 sky130::mcon_draw vert
4834 popbox
4835 }
4836
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004837 pushbox
4838 box grow e ${hw}um
4839 box grow w ${hw}um
4840 box grow n ${hh}um
4841 box grow s ${hh}um
4842 # Create boundary using properties
4843 property FIXED_BBOX [box values]
4844 box grow c ${hx}um ;# to edge of contact
4845 box grow c ${diff_surround}um ;# to edge of diffusion
4846 box grow c ${sub_surround}um ;# sub/well overlap of diff (NOT guard_sub)
4847 paint $sub_type
4848 set cext [sky130::getbox]
4849 popbox
4850 popbox
4851
4852 return $cext
4853}
4854
4855#----------------------------------------------------------------
4856# MOSFET: Draw a single device
4857#----------------------------------------------------------------
4858
4859proc sky130::mos_device {parameters} {
4860
4861 # Epsilon for avoiding round-off errors
4862 set eps 0.0005
4863
4864 # Set local default values if they are not in parameters
4865 set diffcov 100 ;# percent coverage of diffusion contact
4866 set polycov 100 ;# percent coverage of poly contact
4867 set topc 1 ;# draw top poly contact
4868 set botc 1 ;# draw bottom poly contact
Tim Edwards0ee0f182020-11-21 16:15:07 -05004869 set viasrc 100 ;# draw source vias
4870 set viadrn 100 ;# draw drain vias
4871 set viagate 100 ;# draw gate vias
4872 set evens 1 ;# even or odd numbered device finger, in X
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004873 set dev_sub_type "" ;# device substrate type (if different from guard ring)
Tim Edwards0ee0f182020-11-21 16:15:07 -05004874 set dev_sub_dist 0 ;# device substrate distance (if nondefault dev_sub_type)
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004875 set min_effl 0 ;# gate length below which finger pitch must be stretched
4876 set diff_overlap_cont 0 ;# extra overlap of end contact by diffusion
4877
4878 # Set a local variable for each parameter (e.g., $l, $w, etc.)
4879 foreach key [dict keys $parameters] {
4880 set $key [dict get $parameters $key]
4881 }
4882
4883 # Draw the diffusion and poly
4884 pushbox
4885 box size 0 0
4886 pushbox
4887 set hw [/ $w 2.0]
4888 set hl [/ $l 2.0]
4889 set he [/ $min_effl 2.0]
4890 if {$nf == 1 || $he < $hl} {set he $hl}
4891 box grow n ${hw}um
4892 box grow s ${hw}um
4893 box grow e ${hl}um
4894 box grow w ${hl}um
4895 pushbox
4896 if {${diff_extension} > ${gate_to_diffcont}} {
4897 box grow e ${diff_extension}um
4898 box grow w ${diff_extension}um
4899 } else {
4900 box grow e ${gate_to_diffcont}um
4901 box grow w ${gate_to_diffcont}um
4902 }
4903 paint ${diff_type}
4904 popbox
4905 pushbox
4906 if {${gate_extension} > ${gate_to_polycont}} {
4907 box grow n ${gate_extension}um
4908 box grow s ${gate_extension}um
4909 } else {
4910 if {$topc} {
4911 box grow n ${gate_to_polycont}um
4912 } else {
4913 box grow n ${gate_extension}um
4914 }
4915 if {$botc} {
4916 box grow s ${gate_to_polycont}um
4917 } else {
4918 box grow s ${gate_extension}um
4919 }
4920 }
4921 paint ${poly_type}
4922 set cext [sky130::getbox]
4923 popbox
4924 # save gate area now and paint later, so that diffusion surrounding the
4925 # contact does not paint over the gate area, in case the gate type is
4926 # not part of a "compose" entry in the techfile.
4927 set gaterect [box values]
4928 popbox
4929
4930 # Adjust position of contacts for dogbone geometry
4931 # Rule 1: Minimize diffusion length. Contacts only move out
4932 # if width < contact diffusion height. They move out enough
4933 # that the diffusion-to-poly spacing is satisfied.
4934
4935 set ddover 0
4936 set cdwmin [+ ${contact_size} [* ${diff_surround} 2]]
4937 set cstem [- ${gate_to_diffcont} [/ ${cdwmin} 2.0]]
4938 set cgrow [- ${diff_poly_space} ${cstem}]
4939 if {[+ ${w} ${eps}] < ${cdwmin}} {
4940 if {${cgrow} > 0} {
4941 set gate_to_diffcont [+ ${gate_to_diffcont} ${cgrow}]
4942 }
4943 set ddover [/ [- ${cdwmin} ${w}] 2.0]
4944 }
4945
4946 # Rule 2: Minimum poly width. Poly contacts only move out
4947 # if length < contact poly width. They move out enough
4948 # that the diffusion-to-poly spacing is satisfied.
4949
4950 set gporig ${gate_to_polycont}
4951 set cplmin [+ ${contact_size} [* ${poly_surround} 2]]
4952 set cstem [- ${gate_to_polycont} [/ ${cplmin} 2.0]]
4953 set cgrow [- ${diff_poly_space} ${cstem}]
4954 if {[+ ${l} ${eps}] < ${cplmin}} {
4955 if {${cgrow} > 0} {
4956 set gate_to_polycont [+ ${gate_to_polycont} ${cgrow}]
4957 }
4958 }
4959
4960 # Rule 3: If both poly and diffusion are dogboned, then move
4961 # poly out further to clear spacing to the diffusion contact
4962
4963 if {[+ ${w} ${eps}] < ${cdwmin}} {
4964 if {[+ ${l} ${eps}] < ${cplmin}} {
4965 set cgrow [/ [- ${cplmin} ${w}] 2.0]
4966 set gate_to_polycont [+ ${gate_to_polycont} ${cgrow}]
4967 }
4968 }
4969
4970 # Rule 4: If M > 1 and poly contacts overlap, then increase the
4971 # transistor-to-poly-contact distance by the amount of any
4972 # diffusion dogbone overhang.
4973
4974 if {($poverlap == 1) && ($m > 1)} {
4975 if {${gate_to_polycont} - $gporig < $ddover} {
4976 set gate_to_polycont [+ ${gporig} ${ddover}]
4977 }
4978 }
4979
4980 # Reduce contact sizes by poly or diffusion surround so that
4981 # the contact area edges match the device diffusion or poly.
4982 # (Minimum dimensions will be enforced by the contact drawing routine)
4983 set tsurround [+ ${diff_surround} ${diff_overlap_cont}]
4984 set cdw [- ${w} [* ${tsurround} 2]] ;# diff contact height
4985 set cpl [- ${l} [* ${poly_surround} 2]] ;# poly contact width
4986
Tim Edwards0ee0f182020-11-21 16:15:07 -05004987 # Save the full diffusion (source/drain) and poly (gate) lengths
4988 set cdwfull $cdw
4989 set cplfull $cpl
4990
Tim Edwards55f4d0e2020-07-05 15:41:02 -04004991 # Reduce by coverage percentage. NOTE: If overlapping multiple devices,
4992 # keep maximum poly contact coverage.
4993
4994 set cdw [* ${cdw} [/ ${diffcov} 100.0]]
4995 if {($poverlap == 0) || ($m == 1)} {
4996 set cpl [* ${cpl} [/ ${polycov} 100.0]]
4997 }
4998
4999 # Right diffusion contact
5000 pushbox
5001 box move e ${he}um
5002 box move e ${gate_to_diffcont}um
Tim Edwards0ee0f182020-11-21 16:15:07 -05005003
5004 # Source via on top of contact
5005 if {$evens == 1} {set viatype $viasrc} else {set viatype $viadrn}
5006 if {$viatype != 0} {
5007 pushbox
5008 set cw $via_size
5009 set ch [* $cdwfull [/ [expr abs($viatype)] 100.0]]
5010 if {$ch < $via_size} {set ch $via_size}
5011 box grow e [/ $cw 2]um
5012 box grow w [/ $cw 2]um
5013 set anchor [string index $viatype 0]
5014 if {$anchor == "+"} {
5015 box move s [/ [- $cdwfull $via_size] 2]um
5016 box grow n ${ch}um
5017 } elseif {$anchor == "-"} {
5018 box move n [/ [- $cdwfull $via_size] 2]um
5019 box grow s ${ch}um
5020 } else {
5021 box grow n [/ $ch 2]um
5022 box grow s [/ $ch 2]um
5023 }
5024 sky130::mcon_draw vert
5025 popbox
5026 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005027 set cext [sky130::unionbox $cext [sky130::draw_contact 0 ${cdw} \
5028 ${diff_surround} ${metal_surround} ${contact_size}\
5029 ${diff_type} ${diff_contact_type} li vert]]
5030 popbox
5031 # Left diffusion contact
5032 pushbox
5033 box move w ${he}um
5034 box move w ${gate_to_diffcont}um
Tim Edwards0ee0f182020-11-21 16:15:07 -05005035
5036 # Drain via on top of contact
5037 if {$evens == 1} {set viatype $viadrn} else {set viatype $viasrc}
5038 if {$viatype != 0} {
5039 pushbox
5040 set cw $via_size
5041 set ch [* $cdwfull [/ [expr abs($viatype)] 100.0]]
5042 if {$ch < $via_size} {set ch $via_size}
5043 box grow e [/ $cw 2]um
5044 box grow w [/ $cw 2]um
5045 set anchor [string index $viatype 0]
5046 if {$anchor == "+"} {
5047 box move s [/ [- $cdwfull $via_size] 2]um
5048 box grow n ${ch}um
5049 } elseif {$anchor == "-"} {
5050 box move n [/ [- $cdwfull $via_size] 2]um
5051 box grow s ${ch}um
5052 } else {
5053 box grow n [/ $ch 2]um
5054 box grow s [/ $ch 2]um
5055 }
5056 sky130::mcon_draw vert
5057 popbox
5058 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005059 set cext [sky130::unionbox $cext [sky130::draw_contact 0 ${cdw} \
5060 ${diff_surround} ${metal_surround} ${contact_size} \
5061 ${diff_type} ${diff_contact_type} li vert]]
5062 set diffarea $cext
5063 popbox
5064 # Top poly contact
5065 if {$topc} {
5066 pushbox
5067 box move n ${hw}um
5068 box move n ${gate_to_polycont}um
Tim Edwards0ee0f182020-11-21 16:15:07 -05005069
5070 # Gate via on top of contact
5071 if {$viagate != 0} {
5072 pushbox
5073 set ch $via_size
5074 set cw [* $cplfull [/ [expr abs($viagate)] 100.0]]
5075 if {$cw < $via_size} {set cw $via_size}
5076 box grow n [/ $ch 2]um
5077 box grow s [/ $ch 2]um
5078 set anchor [string index $viagate 0]
5079 if {$anchor == "+"} {
5080 box move w [/ [- $cplfull $via_size] 2]um
5081 box grow e ${cw}um
5082 } elseif {$anchor == "-"} {
5083 box move e [/ [- $cplfull $via_size] 2]um
5084 box grow w ${cw}um
5085 } else {
5086 box grow e [/ $cw 2]um
5087 box grow w [/ $cw 2]um
5088 }
5089 sky130::mcon_draw horz
5090 popbox
5091 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005092 set cext [sky130::unionbox $cext [sky130::draw_contact ${cpl} 0 \
5093 ${poly_surround} ${metal_surround} ${contact_size} \
5094 ${poly_type} ${poly_contact_type} li horz]]
5095 popbox
5096 }
5097 # Bottom poly contact
5098 if {$botc} {
5099 pushbox
5100 box move s ${hw}um
5101 box move s ${gate_to_polycont}um
Tim Edwards0ee0f182020-11-21 16:15:07 -05005102
5103 # Gate via on top of contact
5104 if {$viagate != 0} {
5105 pushbox
5106 set ch $via_size
5107 set cw [* $cplfull [/ [expr abs($viagate)] 100.0]]
5108 if {$cw < $via_size} {set cw $via_size}
5109 box grow n [/ $ch 2]um
5110 box grow s [/ $ch 2]um
5111 set anchor [string index $viagate 0]
5112 if {$anchor == "+"} {
5113 box move w [/ [- $cplfull $via_size] 2]um
5114 box grow e ${cw}um
5115 } elseif {$anchor == "-"} {
5116 box move e [/ [- $cplfull $via_size] 2]um
5117 box grow w ${cw}um
5118 } else {
5119 box grow e [/ $cw 2]um
5120 box grow w [/ $cw 2]um
5121 }
5122 sky130::mcon_draw horz
5123 popbox
5124 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005125 set cext [sky130::unionbox $cext [sky130::draw_contact ${cpl} 0 \
5126 ${poly_surround} ${metal_surround} ${contact_size} \
5127 ${poly_type} ${poly_contact_type} li horz]]
5128 popbox
5129 }
5130
5131 # Now draw the gate, after contacts have been drawn
5132 pushbox
5133 box values {*}${gaterect}
5134 # gate_type need not be defined if poly over diff paints the right type.
5135 catch {paint ${gate_type}}
5136 # sub_surround_dev, if defined, may create a larger area around the gate
5137 # than sub_surround creates around the diffusion/poly area.
5138 if [dict exists $parameters sub_surround_dev] {
5139 box grow n ${sub_surround_dev}um
5140 box grow s ${sub_surround_dev}um
5141 box grow e ${sub_surround_dev}um
5142 box grow w ${sub_surround_dev}um
5143 paint ${dev_sub_type}
5144 set cext [sky130::unionbox $cext [sky130::getbox]]
5145 }
5146 popbox
5147
5148 if {$dev_sub_type != ""} {
5149 box values [lindex $diffarea 0]um [lindex $diffarea 1]um \
5150 [lindex $diffarea 2]um [lindex $diffarea 3]um
5151 box grow n ${sub_surround}um
5152 box grow s ${sub_surround}um
5153 box grow e ${sub_surround}um
5154 box grow w ${sub_surround}um
5155 paint ${dev_sub_type}
Tim Edwards0ee0f182020-11-21 16:15:07 -05005156 if {$dev_sub_dist > 0} {
5157 set cext [sky130::unionbox $cext [sky130::getbox]]
5158 }
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005159 # puts stdout "Diagnostic: bounding box is $cext"
5160 }
5161
5162 popbox
5163 return $cext
5164}
5165
5166#----------------------------------------------------------------
5167# MOSFET: Draw the tiled device
5168#----------------------------------------------------------------
5169
5170proc sky130::mos_draw {parameters} {
5171 tech unlock *
5172 set savesnap [snap]
5173 snap internal
5174
5175 # Set defaults if they are not in parameters
5176 set poverlap 0 ;# overlap poly contacts when tiling
5177 set doverlap 1 ;# overlap diffusion contacts when tiling
5178 set dev_sub_dist 0 ;# substrate to guard ring, if dev_sub_type defined
5179 set dev_sub_space 0 ;# distance between substrate areas for arrayed devices
5180 set min_allc 0 ;# gate length below which poly contacts must be interleaved
5181 set id_type "" ;# additional type covering everything
5182 set id_surround 0 ;# amount of surround on above type
5183 set id2_type "" ;# additional type covering everything
5184 set id2_surround 0 ;# amount of surround on above type
5185
5186 # Set a local variable for each parameter (e.g., $l, $w, etc.)
5187 foreach key [dict keys $parameters] {
5188 set $key [dict get $parameters $key]
5189 }
5190
5191 # Diff-to-tap spacing is by default the same as diff spacing
5192 if {![dict exist $parameters diff_tap_space]} {
5193 set diff_tap_space $diff_spacing
5194 }
5195
5196 # If poverlap is 1 then both poly contacts must be present
5197 if {$poverlap == 1} {
5198 set topc 1
5199 set botc 1
5200 dict set parameters topc 1
5201 dict set parameters botc 1
5202 }
5203
5204 # Normalize distance units to microns
5205 set w [magic::spice2float $w]
5206 set l [magic::spice2float $l]
5207
5208 pushbox
5209 box values 0 0 0 0
5210
5211 # If dx < (poly contact space + poly contact width), then there is not
5212 # enough room for a row of contacts, so force alternating contacts
5213
Tim Edwards0ee0f182020-11-21 16:15:07 -05005214 set evens 1
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005215 if {$nf > 1 && $l < $min_allc} {
5216 set intc 1
5217 set evenodd 1
5218 set topc 1
5219 set botc 1
5220 dict set parameters topc 1
5221 dict set parameters botc 1
5222 set poverlap 0
5223 } else {
5224 set intc 0
5225 }
5226
5227 # Determine the base device dimensions by drawing one device
5228 # while all layers are locked (nothing drawn). This allows the
5229 # base drawing routine to do complicated geometry without having
5230 # to duplicate it here with calculations.
5231
5232 tech lock *
5233 set bbox [sky130::mos_device $parameters]
5234 # puts stdout "Diagnostic: Device bounding box e $bbox (um)"
5235 tech unlock *
5236
5237 set fw [- [lindex $bbox 2] [lindex $bbox 0]]
5238 set fh [- [lindex $bbox 3] [lindex $bbox 1]]
5239 set lw [+ [lindex $bbox 2] [lindex $bbox 0]]
5240 set lh [+ [lindex $bbox 3] [lindex $bbox 1]]
5241
5242 # If dev_sub_dist > 0 then each device must be in its own substrate
5243 # (well) area, and overlaps are disallowed. dev_sub_space determines
5244 # the distance between individual devices in an array.
5245
5246 if {$dev_sub_dist > 0} {
5247 set poverlap 0
5248 set doverlap 0
5249
5250 if {$dev_sub_space > $poly_spacing} {
5251 set dx [+ $fw $dev_sub_space]
5252 set dy [+ $fh $dev_sub_space]
5253 } else {
5254 set dx [+ $fw $poly_spacing]
5255 set dy [+ $fh $poly_spacing]
5256 }
5257
5258 } else {
5259
5260 # Determine tile width and height (depends on overlap)
5261 if {$poverlap == 0} {
5262 set dy [+ $fh $poly_spacing]
5263 } else {
5264 # overlap poly
5265 set dy [- $fh [+ $poly_surround $poly_surround $contact_size]]
5266 }
5267
5268 if {$doverlap == 0} {
5269 set dx [+ $fw $diff_spacing]
5270 } else {
5271 # overlap diffusions
5272 set dx [- $fw [+ $diff_surround $diff_surround $contact_size]]
5273 }
5274 }
5275
5276 # Determine core width and height
5277 set corex [+ [* [- $nf 1] $dx] $fw]
5278 set corey [+ [* [- $m 1] $dy] $fh]
5279 set corellx [/ [+ [- $corex $fw] $lw] 2.0]
5280 set corelly [/ [+ [- $corey $fh] $lh] 2.0]
5281
5282 # If there is a diffusion dogbone, and no top poly contact, then
5283 # increase the core height by the amount of the dogbone overhang.
5284
5285 if {$topc == 0} {
5286 set cdwmin [+ ${contact_size} [* ${diff_surround} 2]]
5287 if {${w} < ${cdwmin}} {
5288 set corey [+ $corey [/ [- ${cdwmin} ${w}] 2.0]]
5289 }
5290 }
5291
Tim Edwards0ee0f182020-11-21 16:15:07 -05005292 # Calculate guard ring size (measured to contact center)
5293 if {($guard != 0) || (${id_type} != "")} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005294 if {($dev_sub_dist > 0) && ([+ $dev_sub_dist $sub_surround] > $diff_tap_space)} {
5295 set gx [+ $corex [* 2.0 [+ $dev_sub_dist $diff_surround]] $contact_size]
5296 } else {
5297 set gx [+ $corex [* 2.0 [+ $diff_tap_space $diff_surround]] $contact_size]
5298 }
5299 if {($dev_sub_dist > 0) && ([+ $dev_sub_dist $sub_surround] > $diff_gate_space)} {
5300 set gy [+ $corey [* 2.0 [+ $dev_sub_dist $diff_surround]] $contact_size]
5301 } else {
5302 set gy [+ $corey [* 2.0 [+ $diff_gate_space $diff_surround]] $contact_size]
5303 }
5304
5305 # Somewhat tricky. . . if the width is small and the diffusion is
5306 # a dogbone, and the top or bottom poly contact is missing, then
5307 # the spacing to the guard ring may be limited by diffusion spacing, not
5308 # poly to diffusion.
5309
5310 set inset [/ [+ $contact_size [* 2.0 $diff_surround] -$w] 2.0]
5311 set sdiff [- [+ $inset $diff_tap_space] [+ $gate_extension $diff_gate_space]]
5312
5313 if {$sdiff > 0} {
5314 if {$topc == 0} {
5315 set gy [+ $gy $sdiff]
5316 set corelly [+ $corelly [/ $sdiff 2.0]]
5317 }
5318 if {$botc == 0} {
5319 set gy [+ $gy $sdiff]
5320 set corelly [- $corelly [/ $sdiff 2.0]]
5321 }
5322 }
Tim Edwards0ee0f182020-11-21 16:15:07 -05005323 }
5324 if {$guard != 0} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005325 # Draw the guard ring first, as MOS well may interact with guard ring substrate
5326 sky130::guard_ring $gx $gy $parameters
5327 }
5328
5329 pushbox
5330 # If any surrounding identifier type is defined, draw it
5331 if {${id_type} != ""} {
5332 set hw [/ $gx 2]
5333 set hh [/ $gy 2]
5334 box grow e ${hw}um
5335 box grow w ${hw}um
5336 box grow n ${hh}um
5337 box grow s ${hh}um
5338 box grow c ${id_surround}um
5339 paint ${id_type}
5340 }
5341 popbox
5342 pushbox
5343 box move w ${corellx}um
5344 box move s ${corelly}um
5345 for {set xp 0} {$xp < $nf} {incr xp} {
Tim Edwards0ee0f182020-11-21 16:15:07 -05005346 dict set parameters evens $evens
5347 set evens [- 1 $evens]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005348 pushbox
5349 if {$intc == 1} {
5350 set evenodd [- 1 $evenodd]
5351 if {$evenodd == 1} {
5352 dict set parameters topc 1
5353 dict set parameters botc 0
5354 } else {
5355 dict set parameters topc 0
5356 dict set parameters botc 1
5357 }
5358 set saveeo $evenodd
5359 }
5360 for {set yp 0} {$yp < $m} {incr yp} {
5361 sky130::mos_device $parameters
5362 box move n ${dy}um
5363 if {$intc == 1} {
5364 set evenodd [- 1 $evenodd]
5365 if {$evenodd == 1} {
5366 dict set parameters topc 1
5367 dict set parameters botc 0
5368 } else {
5369 dict set parameters topc 0
5370 dict set parameters botc 1
5371 }
5372 }
5373 }
5374 if {$intc == 1} {
5375 set evenodd $saveeo
5376 }
5377 popbox
5378 box move e ${dx}um
5379 }
5380 popbox
5381 popbox
5382
5383 snap $savesnap
5384 tech revert
5385}
5386
5387#-------------------
5388# nMOS 1.8V
5389#-------------------
5390
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005391proc sky130::sky130_fd_pr__nfet_01v8_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005392 set newdict [dict create \
5393 gate_type nfet \
5394 diff_type ndiff \
5395 diff_contact_type ndc \
5396 plus_diff_type psd \
5397 plus_contact_type psc \
5398 poly_type poly \
5399 poly_contact_type pc \
5400 sub_type psub \
5401 min_effl 0.185 \
5402 min_allc 0.26 \
5403 ]
5404 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5405 return [sky130::mos_draw $drawdict]
5406}
5407
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005408proc sky130::sky130_fd_pr__nfet_01v8_lvt_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005409 set newdict [dict create \
5410 gate_type nfetlvt \
5411 diff_type ndiff \
5412 diff_contact_type ndc \
5413 plus_diff_type psd \
5414 plus_contact_type psc \
5415 poly_type poly \
5416 poly_contact_type pc \
5417 sub_type psub \
5418 min_effl 0.185 \
5419 min_allc 0.26 \
5420 ]
5421 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5422 return [sky130::mos_draw $drawdict]
5423}
5424
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005425proc sky130::sky130_fd_bs_flash__special_sonosfet_star_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005426 set newdict [dict create \
5427 gate_type nsonos \
5428 diff_type ndiff \
5429 diff_contact_type ndc \
5430 plus_diff_type psd \
5431 plus_contact_type psc \
5432 poly_type poly \
5433 poly_contact_type pc \
5434 sub_type psub \
5435 id_type dnwell \
5436 id_surround 1.355 \
5437 min_effl 0.185 \
5438 min_allc 0.26 \
5439 ]
5440 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5441 return [sky130::mos_draw $drawdict]
5442}
5443
5444#-------------------
5445# pMOS 1.8V
5446#-------------------
5447
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005448proc sky130::sky130_fd_pr__pfet_01v8_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005449 set newdict [dict create \
5450 gate_type pfet \
5451 diff_type pdiff \
5452 diff_contact_type pdc \
5453 plus_diff_type nsd \
5454 plus_contact_type nsc \
5455 poly_type poly \
5456 poly_contact_type pc \
5457 sub_type nwell \
Tim Edwards2788f172020-10-14 22:32:33 -04005458 dev_sub_type nwell \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005459 gate_to_polycont 0.32 \
5460 min_effl 0.185 \
5461 min_allc 0.26 \
5462 ]
5463 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5464 return [sky130::mos_draw $drawdict]
5465}
5466
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005467proc sky130::sky130_fd_pr__pfet_01v8_lvt_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005468 set newdict [dict create \
5469 gate_type pfetlvt \
5470 diff_type pdiff \
5471 diff_contact_type pdc \
5472 plus_diff_type nsd \
5473 plus_contact_type nsc \
5474 poly_type poly \
5475 poly_contact_type pc \
5476 sub_type nwell \
Tim Edwards2788f172020-10-14 22:32:33 -04005477 dev_sub_type nwell \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005478 gate_to_polycont 0.32 \
5479 min_effl 0.185 \
5480 min_allc 0.26 \
5481 ]
5482 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5483 return [sky130::mos_draw $drawdict]
5484}
5485
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005486proc sky130::sky130_fd_pr__pfet_01v8_hvt_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005487 set newdict [dict create \
5488 gate_type pfethvt \
5489 diff_type pdiff \
5490 diff_contact_type pdc \
5491 plus_diff_type nsd \
5492 plus_contact_type nsc \
5493 poly_type poly \
5494 poly_contact_type pc \
5495 sub_type nwell \
Tim Edwards2788f172020-10-14 22:32:33 -04005496 dev_sub_type nwell \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005497 gate_to_polycont 0.32 \
5498 min_effl 0.185 \
5499 min_allc 0.26 \
5500 ]
5501 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5502 return [sky130::mos_draw $drawdict]
5503}
5504
5505#-------------------
5506# pMOS 5.0V
5507#-------------------
5508
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005509proc sky130::sky130_fd_pr__pfet_g5v0d10v5_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005510 set newdict [dict create \
5511 gate_type mvpfet \
5512 diff_type mvpdiff \
5513 diff_contact_type mvpdc \
5514 plus_diff_type mvnsd \
5515 plus_contact_type mvnsc \
5516 poly_type poly \
5517 poly_contact_type pc \
5518 sub_type nwell \
Tim Edwards2788f172020-10-14 22:32:33 -04005519 dev_sub_type nwell \
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005520 guard_sub_surround 0.33 \
5521 gate_to_polycont 0.32 \
5522 diff_spacing 0.31 \
5523 diff_tap_space 0.38 \
5524 diff_gate_space 0.38 \
5525 ]
5526 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5527 return [sky130::mos_draw $drawdict]
5528}
5529
5530#-------------------
5531# nMOS 5.0V
5532#-------------------
5533
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005534proc sky130::sky130_fd_pr__nfet_g5v0d10v5_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005535 set newdict [dict create \
5536 gate_type mvnfet \
5537 diff_type mvndiff \
5538 diff_contact_type mvndc \
5539 plus_diff_type mvpsd \
5540 plus_contact_type mvpsc \
5541 poly_type poly \
5542 poly_contact_type pc \
5543 sub_type psub \
5544 diff_spacing 0.31 \
5545 diff_tap_space 0.38 \
5546 diff_gate_space 0.38 \
5547 ]
5548 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5549 return [sky130::mos_draw $drawdict]
5550}
5551
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005552proc sky130::sky130_fd_pr__nfet_05v0_nvt_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005553 set newdict [dict create \
5554 gate_type mvnnfet \
5555 diff_type mvndiff \
5556 diff_contact_type mvndc \
5557 plus_diff_type mvpsd \
5558 plus_contact_type mvpsc \
5559 poly_type poly \
5560 poly_contact_type pc \
5561 sub_type psub \
5562 diff_spacing 0.30 \
5563 diff_tap_space 0.38 \
5564 diff_gate_space 0.38 \
5565 ]
5566 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5567 return [sky130::mos_draw $drawdict]
5568}
5569
5570#------------------------
5571# MOS varactor (1.8V)
5572#------------------------
5573
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005574proc sky130::sky130_fd_pr__cap_var_lvt_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005575 set newdict [dict create \
5576 gate_type var \
5577 diff_type nnd \
5578 diff_contact_type nsc \
5579 plus_diff_type psd \
5580 plus_contact_type psc \
5581 poly_type poly \
5582 poly_contact_type pc \
5583 sub_type psub \
5584 dev_sub_type nwell \
5585 diff_overlap_cont 0.06 \
5586 dev_sub_dist 0.14 \
5587 dev_sub_space 1.27 \
5588 gate_to_diffcont 0.34 \
5589 diff_extension 0.485 \
5590 ]
5591 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5592 return [sky130::mos_draw $drawdict]
5593}
5594
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005595proc sky130::sky130_fd_pr__cap_var_hvt_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005596 set newdict [dict create \
5597 gate_type varhvt \
5598 diff_type nnd \
5599 diff_contact_type nsc \
5600 plus_diff_type psd \
5601 plus_contact_type psc \
5602 poly_type poly \
5603 poly_contact_type pc \
5604 sub_type psub \
5605 dev_sub_type nwell \
5606 diff_overlap_cont 0.06 \
5607 dev_sub_dist 0.14 \
5608 dev_sub_space 1.27 \
5609 gate_to_diffcont 0.34 \
5610 diff_extension 0.485 \
5611 ]
5612 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5613 return [sky130::mos_draw $drawdict]
5614}
5615
5616#---------------------------------------------------------
5617# MOS varactor (5.0V)
5618# NOTE: dev_sub_space set to 2.0 assuming different nets.
5619# Should have option for same-net with merged wells.
5620#---------------------------------------------------------
5621
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005622proc sky130::sky130_fd_pr__cap_var_draw {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005623 set newdict [dict create \
5624 gate_type mvvar \
5625 diff_type mvnsd \
5626 diff_contact_type mvnsc \
5627 plus_diff_type mvpsd \
5628 plus_contact_type mvpsc \
5629 poly_type poly \
5630 poly_contact_type pc \
5631 sub_type psub \
5632 dev_sub_type nwell \
5633 sub_surround 0.38 \
5634 sub_surround_dev 0.56 \
5635 guard_sub_surround 0.18 \
5636 diff_overlap_cont 0.06 \
5637 dev_sub_dist 0.785 \
5638 dev_sub_space 2.0 \
5639 gate_to_diffcont 0.34 \
5640 diff_extension 0.485 \
5641 ]
5642 set drawdict [dict merge $sky130::ruleset $newdict $parameters]
5643 return [sky130::mos_draw $drawdict]
5644}
5645
5646#----------------------------------------------------------------
5647# MOSFET: Check device parameters for out-of-bounds values
5648#----------------------------------------------------------------
5649
5650proc sky130::mos_check {device parameters} {
5651
5652 # Set a local variable for each parameter (e.g., $l, $w, etc.)
5653 foreach key [dict keys $parameters] {
5654 set $key [dict get $parameters $key]
5655 }
5656
5657 # Normalize distance units to microns
5658 set l [magic::spice2float $l]
5659 set l [magic::3digitpastdecimal $l]
5660 set w [magic::spice2float $w]
5661 set w [magic::3digitpastdecimal $w]
5662
5663 # nf, m must be integer
5664 if {![string is int $nf]} {
5665 puts stderr "NF must be an integer!"
5666 dict set parameters nf 1
5667 }
5668 if {![string is int $m]} {
5669 puts stderr "M must be an integer!"
5670 dict set parameters m 1
5671 }
5672 # diffcov, polycov must be numeric
5673 if {[catch {expr abs($diffcov)}]} {
5674 puts stderr "diffcov must be numeric!"
5675 set diffcov 100
Tim Edwards0ee0f182020-11-21 16:15:07 -05005676 dict set parameters diffcov $diffcov
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005677 }
5678 if {[catch {expr abs($polycov)}]} {
5679 puts stderr "polycov must be numeric!"
5680 set polycov 100
Tim Edwards0ee0f182020-11-21 16:15:07 -05005681 dict set parameters polycov $polycov
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005682 }
5683
5684 if {$l < $lmin} {
5685 puts stderr "Mos length must be >= $lmin um"
5686 dict set parameters l $lmin
5687 }
5688 if {$w < $wmin} {
5689 puts stderr "Mos width must be >= $wmin um"
5690 dict set parameters w $wmin
5691 }
5692 if {$nf < 1} {
5693 puts stderr "NF must be >= 1"
5694 dict set parameters nf 1
5695 }
5696 if {$m < 1} {
5697 puts stderr "M must be >= 1"
5698 dict set parameters m 1
5699 }
5700 if {$diffcov < 20 } {
5701 puts stderr "Diffusion contact coverage must be at least 20%"
5702 dict set parameters diffcov 20
5703 } elseif {$diffcov > 100 } {
5704 puts stderr "Diffusion contact coverage can't be more than 100%"
5705 dict set parameters diffcov 100
5706 }
5707 if {$polycov < 20 } {
5708 puts stderr "Poly contact coverage must be at least 20%"
5709 dict set parameters polycov 20
5710 } elseif {$polycov > 100 } {
5711 puts stderr "Poly contact coverage can't be more than 100%"
5712 dict set parameters polycov 100
5713 }
5714
Tim Edwards0ee0f182020-11-21 16:15:07 -05005715 if {[catch {expr abs($viasrc)}]} {
5716 puts stderr "Source via coverage must be numeric!"
5717 dict set parameters viasrc 100
5718 } elseif {[expr abs($viasrc)] > 100} {
5719 puts stderr "Source via coverage can't be more than 100%"
5720 dict set parameters viasrc 100
5721 }
5722 if {[catch {expr abs($viadrn)}]} {
5723 puts stderr "Drain via coverage must be numeric!"
5724 dict set parameters viadrn 100
5725 } elseif {[expr abs($viadrn)] > 100} {
5726 puts stderr "Drain via coverage can't be more than 100%"
5727 dict set parameters viadrn 100
5728 }
5729 if {[catch {expr abs($viagate)}]} {
5730 puts stderr "Gate via coverage must be numeric!"
5731 dict set parameters viagate 100
5732 } elseif {[expr abs($viagate)] > 100} {
5733 puts stderr "Gate via coverage can't be more than 100%"
5734 dict set parameters viagate 100
5735 }
5736 if {[catch {expr abs($viagb)}]} {
5737 puts stderr "Guard ring bottom via coverage must be numeric!"
5738 dict set parameters viagb 0
5739 } elseif {[expr abs($viagb)] > 100} {
5740 puts stderr "Guard ring bottom via coverage can't be more than 100%"
5741 dict set parameters viagb 100
5742 }
5743 if {[catch {expr abs($viagt)}]} {
5744 puts stderr "Guard ring top via coverage must be numeric!"
5745 dict set parameters viagt 0
5746 } elseif {[expr abs($viagt)] > 100} {
5747 puts stderr "Guard ring top via coverage can't be more than 100%"
5748 dict set parameters viagt 100
5749 }
5750 if {[catch {expr abs($viagr)}]} {
5751 puts stderr "Guard ring right via coverage must be numeric!"
5752 dict set parameters viagr 0
5753 } elseif {[expr abs($viagr)] > 100} {
5754 puts stderr "Guard ring right via coverage can't be more than 100%"
5755 dict set parameters viagr 100
5756 }
5757 if {[catch {expr abs($viagl)}]} {
5758 puts stderr "Guard ring left via coverage must be numeric!"
5759 dict set parameters viagl 0
5760 } elseif {[expr abs($viagl)] > 100} {
5761 puts stderr "Guard ring left via coverage can't be more than 100%"
5762 dict set parameters viagl 100
5763 }
5764
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005765 # Values must satisfy diffusion-to-tap spacing of 20um.
5766 # Therefore the maximum of guard ring width or height cannot exceed 40um.
5767 # If in violation, reduce counts first, as these are easiest to recover
5768 # by duplicating the device and overlapping the wells.
5769 set origm $m
5770 set orignf $nf
5771 while true {
5772 set yext [expr ($w + 3.0) * $m]
5773 set xext [expr ($l + 1.0) * $nf + 1.1]
5774 if {[expr min($xext, $yext)] > 40.0} {
5775 if {$yext > 40.0 && $m > 1} {
5776 incr m -1
5777 } elseif {$xext > 40.0 && $nf > 1} {
5778 incr nf -1
5779 } elseif {$yext > 40.0} {
5780 set w 37
5781 puts -nonewline stderr "Transistor width must be < 37 um"
5782 puts stderr " to avoid tap spacing violation."
5783 dict set parameters w $w
5784 } elseif {$xext > 40.0} {
5785 set l 37.9
5786 puts -nonewline stderr "Transistor length must be < 37.9 um"
5787 puts stderr " to avoid tap spacing violation."
5788 dict set parameters l $l
5789 }
5790 } else {
5791 break
5792 }
5793 }
5794 if {$m != $origm} {
5795 puts stderr "Y repeat reduced to prevent tap distance violation"
5796 dict set parameters m $m
5797 }
5798 if {$nf != $orignf} {
5799 puts stderr "X repeat reduced to prevent tap distance violation"
5800 dict set parameters nf $nf
5801 }
5802
5803 return $parameters
5804}
5805
5806#----------------------------------------------------------------
5807
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005808proc sky130::sky130_fd_pr__nfet_01v8_check {parameters} {
5809 return [sky130::mos_check sky130_fd_pr__nfet_01v8 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005810}
5811
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005812proc sky130::sky130_fd_pr__nfet_01v8_lvt_check {parameters} {
5813 return [sky130::mos_check sky130_fd_pr__nfet_01v8_lvt $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005814}
5815
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005816proc sky130::sky130_fd_bs_flash__special_sonosfet_star_check {parameters} {
5817 return [sky130::mos_check sky130_fd_bs_flash__special_sonosfet_star $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005818}
5819
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005820proc sky130::sky130_fd_pr__nfet_g5v0d10v5_check {parameters} {
5821 return [sky130::mos_check sky130_fd_pr__nfet_g5v0d10v5 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005822}
5823
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005824proc sky130::sky130_fd_pr__nfet_05v0_nvt_check {parameters} {
5825 return [sky130::mos_check sky130_fd_pr__nfet_05v0_nvt $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005826}
5827
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005828proc sky130::sky130_fd_pr__pfet_01v8_check {parameters} {
5829 return [sky130::mos_check sky130_fd_pr__pfet_01v8 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005830}
5831
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005832proc sky130::sky130_fd_pr__pfet_01v8_lvt_check {parameters} {
5833 return [sky130::mos_check sky130_fd_pr__pfet_01v8_lvt $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005834}
5835
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005836proc sky130::sky130_fd_pr__pfet_01v8_hvt_check {parameters} {
5837 return [sky130::mos_check sky130_fd_pr__pfet_01v8_hvt $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005838}
5839
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005840proc sky130::sky130_fd_pr__pfet_g5v0d10v5_check {parameters} {
5841 return [sky130::mos_check sky130_fd_pr__pfet_g5v0d10v5 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005842}
5843
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005844proc sky130::sky130_fd_pr__cap_var_lvt_check {parameters} {
5845 return [sky130::mos_check sky130_fd_pr__cap_var_lvt $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005846}
5847
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005848proc sky130::sky130_fd_pr__cap_var_hvt_check {parameters} {
5849 return [sky130::mos_check sky130_fd_pr__cap_var_hvt $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005850}
5851
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005852proc sky130::sky130_fd_pr__cap_var_check {parameters} {
5853 return [sky130::mos_check sky130_fd_pr__cap_var $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005854}
5855
5856#----------------------------------------------------------------
5857# Fixed device: Specify all user-editable default values
5858#
5859# deltax --- Additional horizontal space between devices
5860# deltay --- Additional vertical space between devices
5861# nx --- Number of arrayed devices in X
5862# ny --- Number of arrayed devices in Y
5863#
5864# Note that these values, specifically nx, ny, deltax,
5865# and deltay, are properties of the instance, not the cell.
5866# They translate to the instance array x and y counts; while
5867# deltax is the x pitch less the cell width, and deltay is the
5868# y pitch less the cell height.
5869#
5870# non-user-editable
5871#
5872# nocell --- Indicates that this cell has a predefined layout
5873# and therefore there is no cell to draw.
5874# xstep --- Width of the cell (nominal array pitch in X)
5875# ystep --- Height of the cell (nominal array pitch in Y)
5876#----------------------------------------------------------------
5877
5878# Fixed-layout devices (from sky130_fd_pr_base, _rf, and _rf2 libraries)
5879#
5880# Bipolar transistors:
5881#
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005882# sky130_fd_pr__rf_npn_05v5_W1p00L1p00
5883# sky130_fd_pr__rf_npn_05v5_W1p00L2p00
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005884# sky130_fd_pr__pnp_05v5_W3p40L3p40
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005885#
5886# Parallel Plate Capacitors:
5887#
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005888# sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldlim5
5889# sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_noshield
5890# sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_lishield
5891# sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_lishield
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005892#
5893# Inductors:
5894#
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005895# sky130_fd_pr__rf_test_coil1
5896# sky130_fd_pr__rf_test_coil2
5897# sky130_fd_pr__rf_test_coil3
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005898
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005899proc sky130::sky130_fd_pr__rf_npn_05v5_W1p00L1p00_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005900 return {nx 1 ny 1 deltax 0 deltay 0 nocell 1 xstep 7.03 ystep 7.03}
5901}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005902proc sky130::sky130_fd_pr__rf_npn_05v5_W1p00L2p00_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005903 return {nx 1 ny 1 deltax 0 deltay 0 nocell 1 xstep 7.03 ystep 8.03}
5904}
5905
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005906proc sky130::sky130_fd_pr__pnp_05v5_W3p40L3p40_defaults {} {
5907 return {nx 1 ny 1 deltax 0 deltay 0 nocell 1 xstep 6.44 ystep 6.44}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005908}
5909
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005910proc sky130::sky130_fd_pr__rf_test_coil1 {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005911 return {nx 1 ny 1 deltax 0 deltay 0 nocell 1 xstep 258 ystep 258}
5912}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005913proc sky130::sky130_fd_pr__rf_test_coil2 {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005914 return {nx 1 ny 1 deltax 0 deltay 0 nocell 1 xstep 290 ystep 404}
5915}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005916proc sky130::sky130_fd_pr__rf_test_coil3 {} {
5917 return {nx 1 ny 1 deltax 0 deltay 0 nocell 1 xstep 290 ystep 404}
5918}
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005919
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005920proc sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldl1m5_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005921 return {nx 1 ny 1 deltax 0 deltay 0 nocell 1 xstep 11.08 ystep 11.36}
5922}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005923proc sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_noshield_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005924 return {nx 1 ny 1 deltax 0 deltay 0 nocell 1 xstep 11.08 ystep 11.36}
5925}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005926proc sky130::sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_lishield_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005927 return {nx 1 ny 1 deltax 0 deltay 0 nocell 1 xstep 11.08 ystep 11.36}
5928}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005929proc sky130::sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_lishield_defaults {} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005930 return {nx 1 ny 1 deltax 0 deltay 0 nocell 1 xstep 11.08 ystep 11.36}
5931}
5932
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005933#----------------------------------------------------------------
5934# Fixed device: Conversion from SPICE netlist parameters to toolkit
5935#----------------------------------------------------------------
5936
5937proc sky130::fixed_convert {parameters} {
5938 set pdkparams [dict create]
5939 dict for {key value} $parameters {
5940 switch -nocase $key {
5941 m {
5942 dict set pdkparams nx $value
5943 }
5944 }
5945 }
5946 return $pdkparams
5947}
5948
5949#----------------------------------------------------------------
5950
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005951proc sky130::sky130_fd_pr__rf_npn_05v5_W1p00L1p00_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005952 return [sky130::fixed_convert $parameters]
5953}
5954
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005955proc sky130::sky130_fd_pr__rf_npn_05v5_W1p00L2p00_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005956 return [sky130::fixed_convert $parameters]
5957}
5958
Tim Edwardsd7289eb2020-09-10 21:48:31 -04005959proc sky130::sky130_fd_pr__pnp_05v5_W3p40L3p40_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005960 return [sky130::fixed_convert $parameters]
5961}
5962
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005963proc sky130::sky130_fd_pr__rf_test_coil1 {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005964 return [sky130::fixed_convert $parameters]
5965}
5966
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005967proc sky130::sky130_fd_pr__rf_test_coil2 {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005968 return [sky130::fixed_convert $parameters]
5969}
5970
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005971proc sky130::sky130_fd_pr__rf_test_coil3 {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005972 return [sky130::fixed_convert $parameters]
5973}
5974
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005975proc sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldl1m5_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005976 return [sky130::fixed_convert $parameters]
5977}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005978proc sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_noshield_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005979 return [sky130::fixed_convert $parameters]
5980}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005981proc sky130::sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_lishield_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005982 return [sky130::fixed_convert $parameters]
5983}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04005984proc sky130::sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_lishield_convert {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04005985 return [sky130::fixed_convert $parameters]
5986}
5987
5988#----------------------------------------------------------------
5989# Fixed device: Interactively specifies the fixed layout parameters
5990#----------------------------------------------------------------
5991
5992proc sky130::fixed_dialog {parameters} {
5993 # Instance fields: nx, ny, pitchx, pitchy
5994 # Editable fields: nx, ny, deltax, deltay
5995 # Non-editable fields: nocell, xstep, ystep
5996
5997 # Set a local variable for each parameter (e.g., $l, $w, etc.)
5998 foreach key [dict keys $parameters] {
5999 set $key [dict get $parameters $key]
6000 }
6001
6002 # "nocell" field causes nx and ny to be dropped in from
6003 # "array count". Also "pitchx" and "pitchy" are passed
6004 # in internal units. Convert these to microns and generate
6005 # If there is no pitchx and pitchy, then the device has not
6006 # yet been created, so keep the deltax and deltay defaults.
6007
6008 if [dict exists $parameters pitchx] {
6009 set pitchux [magic::i2u $pitchx]
6010 set stepux [magic::spice2float $xstep]
6011 set deltax [magic::3digitpastdecimal [expr $pitchux - $stepux]]
6012 # An array size 1 should not cause deltax to go negative
6013 if {$deltax < 0.0} {set deltax 0.0}
6014 dict set parameters deltax $deltax
6015 }
6016 if [dict exists $parameters pitchy] {
6017 set pitchuy [magic::i2u $pitchy]
6018 set stepuy [magic::spice2float $ystep]
6019 set deltay [magic::3digitpastdecimal [expr $pitchuy - $stepuy]]
6020 # An array size 1 should not cause deltay to go negative
6021 if {$deltay < 0.0} {set deltay 0.0}
6022 dict set parameters deltay $deltay
6023 }
6024
6025 magic::add_entry nx "NX" $parameters
6026 magic::add_entry ny "NY" $parameters
6027 magic::add_entry deltax "X step (um)" $parameters
6028 magic::add_entry deltay "Y step (um)" $parameters
6029}
6030
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006031proc sky130::sky130_fd_pr__rf_npn_05v5_W1p00L1p00_dialog {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006032 sky130::fixed_dialog $parameters
6033}
6034
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006035proc sky130::sky130_fd_pr__rf_npn_05v5_W1p00L2p00_dialog {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006036 sky130::fixed_dialog $parameters
6037}
6038
Tim Edwardsd7289eb2020-09-10 21:48:31 -04006039proc sky130::sky130_fd_pr__pnp_05v5_W3p40L3p40_dialog {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006040 sky130::fixed_dialog $parameters
6041}
6042
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006043proc sky130::sky130_fd_pr__rf_test_coil1 {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006044 sky130::fixed_dialog $parameters
6045}
6046
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006047proc sky130::sky130_fd_pr__rf_test_coil2 {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006048 sky130::fixed_dialog $parameters
6049}
6050
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006051proc sky130::sky130_fd_pr__rf_test_coil3 {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006052 sky130::fixed_dialog $parameters
6053}
6054
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006055proc sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldl1m5_dialog {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006056 sky130::fixed_dialog $parameters
6057}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006058proc sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_noshield_dialog {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006059 sky130::fixed_dialog $parameters
6060}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006061proc sky130::sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_lishield_dialog {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006062 sky130::fixed_dialog $parameters
6063}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006064proc sky130::sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_lishield_dialog {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006065 sky130::fixed_dialog $parameters
6066}
6067
6068#----------------------------------------------------------------
6069# Fixed device: Draw the device
6070#----------------------------------------------------------------
6071
6072proc sky130::fixed_draw {devname parameters} {
6073
6074 # Set a local variable for each parameter (e.g., $l, $w, etc.)
6075 foreach key [dict keys $parameters] {
6076 set $key [dict get $parameters $key]
6077 }
6078
6079 # This cell declares "nocell" in parameters, so it needs to
6080 # instance the cell and set properties.
6081
6082 # Instantiate the cell. The name corresponds to the cell in the sky130_fd_pr_* directory.
6083 set instname [getcell ${devname}]
6084
6085 set deltax [magic::spice2float $deltax]
6086 set deltay [magic::spice2float $deltay]
6087 set xstep [magic::spice2float $xstep]
6088 set ystep [magic::spice2float $ystep]
6089
6090 # Array stepping
6091 if {$nx > 1 || $ny > 1} {
6092 set xstep [expr $xstep + $deltax]
6093 set ystep [expr $ystep + $deltay]
6094 box size ${xstep}um ${ystep}um
6095 array $nx $ny
6096 }
6097 select cell $instname
6098 expand
6099 return $instname
6100}
6101
6102#----------------------------------------------------------------
6103# No additional parameters declared for drawing
6104#----------------------------------------------------------------
6105
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006106proc sky130::sky130_fd_pr__rf_npn_05v5_W1p00L1p00_draw {parameters} {
6107 return [sky130::fixed_draw sky130_fd_pr__rf_npn_05v5_W1p00L1p00 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006108}
6109
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006110proc sky130::sky130_fd_pr__rf_npn_05v5_W1p00L2p00_draw {parameters} {
6111 return [sky130::fixed_draw sky130_fd_pr__rf_npn_05v5_W1p00L2p00 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006112}
6113
Tim Edwardsd7289eb2020-09-10 21:48:31 -04006114proc sky130::sky130_fd_pr__pnp_05v5_W3p40L3p40_draw {parameters} {
6115 return [sky130::fixed_draw sky130_fd_pr__pnp_05v5_W3p40L3p40 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006116}
6117
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006118proc sky130::sky130_fd_pr__rf_test_coil1 {parameters} {
6119 return [sky130::fixed_draw sky130_fd_pr__rf_test_coil1 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006120}
6121
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006122proc sky130::sky130_fd_pr__rf_test_coil2 {parameters} {
6123 return [sky130::fixed_draw sky130_fd_pr__rf_test_coil2 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006124}
6125
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006126proc sky130::sky130_fd_pr__rf_test_coil3 {parameters} {
6127 return [sky130::fixed_draw sky130_fd_pr__rf_test_coil3 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006128}
6129
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006130proc sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldl1m5_draw {parameters} {
6131 return [sky130::fixed_draw sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldl1m5 $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006132}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006133proc sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_noshield_draw {parameters} {
6134 return [sky130::fixed_draw sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_noshield $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006135}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006136proc sky130::sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_lishield_draw {parameters} {
6137 return [sky130::fixed_draw sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_lishield $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006138}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006139proc sky130::sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_lishield_draw {parameters} {
6140 return [sky130::fixed_draw sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_lishield $parameters]
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006141}
6142
6143#----------------------------------------------------------------
6144# Fixed device: Check device parameters for out-of-bounds values
6145#----------------------------------------------------------------
6146
6147proc sky130::fixed_check {parameters} {
6148
6149 # Set a local variable for each parameter (e.g., $l, $w, etc.)
6150 foreach key [dict keys $parameters] {
6151 set $key [dict get $parameters $key]
6152 }
6153
6154 # Normalize distance units to microns
6155 set deltax [magic::spice2float $deltax -1]
6156 set deltax [magic::3digitpastdecimal $deltax]
6157 set deltay [magic::spice2float $deltay -1]
6158 set deltay [magic::3digitpastdecimal $deltay]
6159
6160 # nx, ny must be integer
6161 if {![string is int $nx]} {
6162 puts stderr "NX must be an integer!"
6163 dict set parameters nx 1
6164 }
6165 if {![string is int $ny]} {
6166 puts stderr "NY must be an integer!"
6167 dict set parameters nx 1
6168 }
6169
6170 # Number of devices in X and Y must be at least 1
6171 if {$nx < 1} {
6172 puts stderr "NX must be >= 1"
6173 dict set parameters nx 1
6174 }
6175 if {$ny < 1} {
6176 puts stderr "NY must be >= 1"
6177 dict set parameters nx 1
6178 }
6179 # Step less than zero violates DRC
6180 if {$deltax < 0} {
6181 puts stderr "X step must be >= 0"
6182 dict set parameters deltax 0
6183 }
6184 if {$deltay < 0} {
6185 puts stderr "Y step must be >= 0"
6186 dict set parameters deltay 0
6187 }
6188 return $parameters
6189}
6190
6191#----------------------------------------------------------------
6192
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006193proc sky130::sky130_fd_pr__rf_npn_05v5_W1p00L1p00_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006194 return [sky130::fixed_check $parameters]
6195}
6196
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006197proc sky130::sky130_fd_pr__rf_npn_05v5_W1p00L2p00_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006198 return [sky130::fixed_check $parameters]
6199}
6200
Tim Edwardsd7289eb2020-09-10 21:48:31 -04006201proc sky130::sky130_fd_pr__pnp_05v5_W0p68L0p68_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006202 return [sky130::fixed_check $parameters]
6203}
6204
Tim Edwardsd7289eb2020-09-10 21:48:31 -04006205proc sky130::sky130_fd_pr__pnp_05v5_W3p40L3p40_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006206 return [sky130::fixed_check $parameters]
6207}
6208
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006209proc sky130::sky130_fd_pr__rf_test_coil1 {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006210 return [sky130::fixed_check $parameters]
6211}
6212
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006213proc sky130::sky130_fd_pr__rf_test_coil2 {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006214 return [sky130::fixed_check $parameters]
6215}
6216
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006217proc sky130::sky130_fd_pr__rf_test_coil3 {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006218 return [sky130::fixed_check $parameters]
6219}
6220
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006221proc sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2m3m4_shieldl1m5_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006222 return [sky130::fixed_check $parameters]
6223}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006224proc sky130::sky130_fd_pr__cap_vpp_11p5x11p7_m1m2_noshield_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006225 return [sky130::fixed_check $parameters]
6226}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006227proc sky130::sky130_fd_pr__cap_vpp_08p6x07p8_m1m2_lishield_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006228 return [sky130::fixed_check $parameters]
6229}
Tim Edwardsc6202ef2020-09-20 17:16:33 -04006230proc sky130::sky130_fd_pr__cap_vpp_04p4x04p6_m1m2_lishield_check {parameters} {
Tim Edwards55f4d0e2020-07-05 15:41:02 -04006231 return [sky130::fixed_check $parameters]
6232}