blob: f74a4c58fa632ef5cb9eef97b48013347ce8abc4 [file] [log] [blame]
Jeff DiCorpoc30047f2022-12-12 23:59:37 -08001################################################################################################
2# Copyright 2022 GlobalFoundries PDK Authors
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# https://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15################################################################################################
16
17#===========================================================================================================================
18#------------------------------------------- GF 0.18um MCU DRC RULE DECK --------------------------------------------------
19#===========================================================================================================================
20require 'time'
21require "logger"
22
23exec_start_time = Time.now
24
25logger = Logger.new(STDOUT)
26
27logger.formatter = proc do |severity, datetime, progname, msg|
28 "#{datetime}: Memory Usage (" + `pmap #{Process.pid} | tail -1`[10,40].strip + ") : #{msg}
29"
30end
31
32#================================================
33#----------------- FILE SETUP -------------------
34#================================================
35
36# optional for a batch launch : klayout -b -r gf_018mcu.drc -rd input=design.gds -rd report=gp180_drc.lyrdb
37
38logger.info("Starting running GF180MCU Klayout DRC runset on %s" % [$input])
39logger.info("Ruby Version for klayout: %s" % [RUBY_VERSION])
40
41if $input
42 if $topcell
43 source($input, $topcell)
44 else
45 source($input)
46 end
47end
48
49if $table_name
50 table_name = $table_name
51else
52 table_name = "main"
53end
54
55
56logger.info("Loading database to memory is complete.")
57
58if $report
59 logger.info("GF180MCU Klayout DRC runset output at: %s" % [$report])
60 report("DRC Run Report at", $report)
61else
62 logger.info("GF180MCU Klayout DRC runset output at default location." % [File.join(File.dirname(RBA::CellView::active.filename), "gf180_drc.lyrdb")])
63 report("DRC Run Report at", File.join(File.dirname(RBA::CellView::active.filename), "gf180_drc.lyrdb"))
64end
65
66#================================================
67#------------------ SWITCHES --------------------
68#================================================
69logger.info("Evaluate switches.")
70
71# connectivity rules
72if $conn_drc == "true"
73 CONNECTIVITY_RULES = $conn_drc
74 logger.info("connectivity rules are enabled.")
75else
76 CONNECTIVITY_RULES = false
77 logger.info("connectivity rules are disabled.")
78end # connectivity rules
79
80# WEDGE
81if $wedge == "false"
82 WEDGE = $wedge
83else
84 WEDGE = "true"
85end # WEDGE
86
87logger.info("Wedge enabled %s" % [WEDGE])
88
89# BALL
90if $ball == "false"
91 BALL = $ball
92else
93 BALL = "true"
94end # BALL
95
96logger.info("Ball enabled %s" % [BALL])
97
98# GOLD
99if $gold == "false"
100 GOLD = $gold
101else
102 GOLD = "true"
103end # GOLD
104
105logger.info("Gold enabled %s" % [GOLD])
106
107if $mim_option
108 MIM_OPTION = $mim_option
109else
110 MIM_OPTION = "B"
111end
112
113logger.info("MIM Option selected %s" % [MIM_OPTION])
114
115# OFFGRID
116if $offgrid == "false"
117 OFFGRID = false
118else
119 OFFGRID = true
120end # OFFGRID
121
122logger.info("Offgrid enabled %s" % [OFFGRID])
123
124if $thr
125 threads($thr)
126 logger.info("Number of threads to use %s" % [$thr])
127else
128 threads(%x("nproc"))
129 logger.info("Number of threads to use #{%x("nproc")}")
130end
131
132#=== PRINT DETAILS ===
133if $verbose == "true"
134 logger.info("Verbose mode: #{$verbose}")
135 verbose(true)
136else
137 verbose(false)
138 logger.info("Verbose mode: false")
139end
140
141# === TILING MODE ===
142if $run_mode == "tiling"
143 tiles(500.um)
144 tile_borders(10.um)
145 logger.info("Tiling mode is enabled.")
146
147elsif $run_mode == "deep"
148 #=== HIER MODE ===
149 deep
150 logger.info("deep mode is enabled.")
151else
152 #=== FLAT MODE ===
153 flat
154 logger.info("flat mode is enabled.")
155end # run_mode
156
157# METAL_TOP
158if $metal_top
159 METAL_TOP = $metal_top
160else
161 METAL_TOP = "9K"
162end # METAL_TOP
163
164logger.info("METAL_TOP Selected is %s" % [METAL_TOP])
165
166# METAL_LEVEL
167if $metal_level
168 METAL_LEVEL = $metal_level
169else
170 METAL_LEVEL = "5LM"
171end # METAL_LEVEL
172
173logger.info("METAL_STACK Selected is %s" % [METAL_LEVEL])
174
175# FEOL
176if $feol == "false"
177 FEOL = $feol
178 logger.info("FEOL is disabled.")
179else
180 FEOL = "true"
181 logger.info("FEOL is enabled.")
182end # FEOL
183
184# BEOL
185if $beol == "false"
186 BEOL = $beol
187 logger.info("BEOL is disabled.")
188else
189 BEOL = "true"
190 logger.info("BEOL is enabled.")
191end # BEOL
192
193#================================================
194#------------- LAYERS DEFINITIONS ---------------
195#================================================
196polygons_count = 0
197logger.info("Read in polygons from layers.")
198
199def get_polygons(l, d)
200 if $run_mode == "deep"
201 polygons(l, d)
202 else
203 polygons(l, d).merged
204 end
205end
206
207comp = get_polygons(22 , 0 )
208count = comp.count()
209logger.info("comp has %d polygons" % [count])
210polygons_count += count
211
212dnwell = get_polygons(12 , 0 )
213count = dnwell.count()
214logger.info("dnwell has %d polygons" % [count])
215polygons_count += count
216
217nwell = get_polygons(21 , 0 )
218count = nwell.count()
219logger.info("nwell has %d polygons" % [count])
220polygons_count += count
221
222lvpwell = get_polygons(204, 0 )
223count = lvpwell.count()
224logger.info("lvpwell has %d polygons" % [count])
225polygons_count += count
226
227dualgate = get_polygons(55 , 0 )
228count = dualgate.count()
229logger.info("dualgate has %d polygons" % [count])
230polygons_count += count
231
232poly2 = get_polygons(30 , 0 )
233count = poly2.count()
234logger.info("poly2 has %d polygons" % [count])
235polygons_count += count
236
237nplus = get_polygons(32 , 0 )
238count = nplus.count()
239logger.info("nplus has %d polygons" % [count])
240polygons_count += count
241
242pplus = get_polygons(31 , 0 )
243count = pplus.count()
244logger.info("pplus has %d polygons" % [count])
245polygons_count += count
246
247sab = get_polygons(49 , 0 )
248count = sab.count()
249logger.info("sab has %d polygons" % [count])
250polygons_count += count
251
252esd = get_polygons(24 , 0 )
253count = esd.count()
254logger.info("esd has %d polygons" % [count])
255polygons_count += count
256
257resistor = get_polygons(62 , 0 )
258count = resistor.count()
259logger.info("resistor has %d polygons" % [count])
260polygons_count += count
261
262fhres = get_polygons(227, 0 )
263count = fhres.count()
264logger.info("fhres has %d polygons" % [count])
265polygons_count += count
266
267fusetop = get_polygons(75 , 0 )
268count = fusetop.count()
269logger.info("fusetop has %d polygons" % [count])
270polygons_count += count
271
272fusewindow_d = get_polygons(96 , 1 )
273count = fusewindow_d.count()
274logger.info("fusewindow_d has %d polygons" % [count])
275polygons_count += count
276
277polyfuse = get_polygons(220, 0 )
278count = polyfuse.count()
279logger.info("polyfuse has %d polygons" % [count])
280polygons_count += count
281
282mvsd = get_polygons(210, 0 )
283count = mvsd.count()
284logger.info("mvsd has %d polygons" % [count])
285polygons_count += count
286
287mvpsd = get_polygons(11 , 39)
288count = mvpsd.count()
289logger.info("mvpsd has %d polygons" % [count])
290polygons_count += count
291
292nat = get_polygons(5 , 0 )
293count = nat.count()
294logger.info("nat has %d polygons" % [count])
295polygons_count += count
296
297comp_dummy = get_polygons(22 , 4 )
298count = comp_dummy.count()
299logger.info("comp_dummy has %d polygons" % [count])
300polygons_count += count
301
302poly2_dummy = get_polygons(30 , 4 )
303count = poly2_dummy.count()
304logger.info("poly2_dummy has %d polygons" % [count])
305polygons_count += count
306
307schottky_diode = get_polygons(241, 0 )
308count = schottky_diode.count()
309logger.info("schottky_diode has %d polygons" % [count])
310polygons_count += count
311
312zener = get_polygons(178, 0 )
313count = zener.count()
314logger.info("zener has %d polygons" % [count])
315polygons_count += count
316
317res_mk = get_polygons(110, 5 )
318count = res_mk.count()
319logger.info("res_mk has %d polygons" % [count])
320polygons_count += count
321
322opc_drc = get_polygons(124, 5 )
323count = opc_drc.count()
324logger.info("opc_drc has %d polygons" % [count])
325polygons_count += count
326
327ndmy = get_polygons(111, 5 )
328count = ndmy.count()
329logger.info("ndmy has %d polygons" % [count])
330polygons_count += count
331
332pmndmy = get_polygons(152, 5 )
333count = pmndmy.count()
334logger.info("pmndmy has %d polygons" % [count])
335polygons_count += count
336
337v5_xtor = get_polygons(112, 1 )
338count = v5_xtor.count()
339logger.info("v5_xtor has %d polygons" % [count])
340polygons_count += count
341
342cap_mk = get_polygons(117, 5 )
343count = cap_mk.count()
344logger.info("cap_mk has %d polygons" % [count])
345polygons_count += count
346
347mos_cap_mk = get_polygons(166, 5 )
348count = mos_cap_mk.count()
349logger.info("mos_cap_mk has %d polygons" % [count])
350polygons_count += count
351
352ind_mk = get_polygons(151, 5 )
353count = ind_mk.count()
354logger.info("ind_mk has %d polygons" % [count])
355polygons_count += count
356
357diode_mk = get_polygons(115, 5 )
358count = diode_mk.count()
359logger.info("diode_mk has %d polygons" % [count])
360polygons_count += count
361
362drc_bjt = get_polygons(127, 5 )
363count = drc_bjt.count()
364logger.info("drc_bjt has %d polygons" % [count])
365polygons_count += count
366
367lvs_bjt = get_polygons(118, 5 )
368count = lvs_bjt.count()
369logger.info("lvs_bjt has %d polygons" % [count])
370polygons_count += count
371
372mim_l_mk = get_polygons(117, 10)
373count = mim_l_mk.count()
374logger.info("mim_l_mk has %d polygons" % [count])
375polygons_count += count
376
377latchup_mk = get_polygons(137, 5 )
378count = latchup_mk.count()
379logger.info("latchup_mk has %d polygons" % [count])
380polygons_count += count
381
382guard_ring_mk = get_polygons(167, 5 )
383count = guard_ring_mk.count()
384logger.info("guard_ring_mk has %d polygons" % [count])
385polygons_count += count
386
387otp_mk = get_polygons(173, 5 )
388count = otp_mk.count()
389logger.info("otp_mk has %d polygons" % [count])
390polygons_count += count
391
392mtpmark = get_polygons(122, 5 )
393count = mtpmark.count()
394logger.info("mtpmark has %d polygons" % [count])
395polygons_count += count
396
397neo_ee_mk = get_polygons(88 , 17)
398count = neo_ee_mk.count()
399logger.info("neo_ee_mk has %d polygons" % [count])
400polygons_count += count
401
402sramcore = get_polygons(108, 5 )
403count = sramcore.count()
404logger.info("sramcore has %d polygons" % [count])
405polygons_count += count
406
407lvs_rf = get_polygons(100, 5 )
408count = lvs_rf.count()
409logger.info("lvs_rf has %d polygons" % [count])
410polygons_count += count
411
412lvs_drain = get_polygons(100, 7 )
413count = lvs_drain.count()
414logger.info("lvs_drain has %d polygons" % [count])
415polygons_count += count
416
417ind_mk = get_polygons(151, 5 )
418count = ind_mk.count()
419logger.info("ind_mk has %d polygons" % [count])
420polygons_count += count
421
422hvpolyrs = get_polygons(123, 5 )
423count = hvpolyrs.count()
424logger.info("hvpolyrs has %d polygons" % [count])
425polygons_count += count
426
427lvs_io = get_polygons(119, 5 )
428count = lvs_io.count()
429logger.info("lvs_io has %d polygons" % [count])
430polygons_count += count
431
432probe_mk = get_polygons(13 , 17)
433count = probe_mk.count()
434logger.info("probe_mk has %d polygons" % [count])
435polygons_count += count
436
437esd_mk = get_polygons(24 , 5 )
438count = esd_mk.count()
439logger.info("esd_mk has %d polygons" % [count])
440polygons_count += count
441
442lvs_source = get_polygons(100, 8 )
443count = lvs_source.count()
444logger.info("lvs_source has %d polygons" % [count])
445polygons_count += count
446
447well_diode_mk = get_polygons(153, 51)
448count = well_diode_mk.count()
449logger.info("well_diode_mk has %d polygons" % [count])
450polygons_count += count
451
452ldmos_xtor = get_polygons(226, 0 )
453count = ldmos_xtor.count()
454logger.info("ldmos_xtor has %d polygons" % [count])
455polygons_count += count
456
457plfuse = get_polygons(125, 5 )
458count = plfuse.count()
459logger.info("plfuse has %d polygons" % [count])
460polygons_count += count
461
462efuse_mk = get_polygons(80 , 5 )
463count = efuse_mk.count()
464logger.info("efuse_mk has %d polygons" % [count])
465polygons_count += count
466
467mcell_feol_mk = get_polygons(11 , 17)
468count = mcell_feol_mk.count()
469logger.info("mcell_feol_mk has %d polygons" % [count])
470polygons_count += count
471
472ymtp_mk = get_polygons(86 , 17)
473count = ymtp_mk.count()
474logger.info("ymtp_mk has %d polygons" % [count])
475polygons_count += count
476
477dev_wf_mk = get_polygons(128, 17)
478count = dev_wf_mk.count()
479logger.info("dev_wf_mk has %d polygons" % [count])
480polygons_count += count
481
482comp_label = get_polygons(22 , 10)
483count = comp_label.count()
484logger.info("comp_label has %d polygons" % [count])
485polygons_count += count
486
487poly2_label = get_polygons(30 , 10)
488count = poly2_label.count()
489logger.info("poly2_label has %d polygons" % [count])
490polygons_count += count
491
492mdiode = get_polygons(116, 5 )
493count = mdiode.count()
494logger.info("mdiode has %d polygons" % [count])
495polygons_count += count
496
497contact = get_polygons(33 , 0 )
498count = contact.count()
499logger.info("contact has %d polygons" % [count])
500polygons_count += count
501
502metal1_drawn = get_polygons(34 , 0 )
503count = metal1_drawn.count()
504logger.info("metal1_drawn has %d polygons" % [count])
505polygons_count += count
506
507metal1_dummy = get_polygons(34 , 4 )
508count = metal1_dummy.count()
509logger.info("metal1_dummy has %d polygons" % [count])
510polygons_count += count
511
512metal1 = metal1_drawn + metal1_dummy
513
514metal1_label = get_polygons(34 , 10)
515count = metal1_label.count()
516logger.info("metal1_label has %d polygons" % [count])
517polygons_count += count
518
519metal1_slot = get_polygons(34 , 3 )
520count = metal1_slot.count()
521logger.info("metal1_slot has %d polygons" % [count])
522polygons_count += count
523
524metal1_blk = get_polygons(34 , 5 )
525count = metal1_blk.count()
526logger.info("metal1_blk has %d polygons" % [count])
527polygons_count += count
528
529via1 = get_polygons(35 , 0 )
530count = via1.count()
531logger.info("via1 has %d polygons" % [count])
532polygons_count += count
533
534
535if METAL_LEVEL == "2LM"
536 metal2_drawn = get_polygons(36 , 0 )
537 count = metal2_drawn.count()
538 logger.info("metal2_drawn has %d polygons" % [count])
539 polygons_count += count
540
541 metal2_dummy = get_polygons(36 , 4 )
542 count = metal2_dummy.count()
543 logger.info("metal2_dummy has %d polygons" % [count])
544 polygons_count += count
545
546 metal2 = metal2_drawn + metal2_drawn
547
548 metal2_label = get_polygons(36 , 10)
549 count = metal2_label.count()
550 logger.info("metal2_label has %d polygons" % [count])
551 polygons_count += count
552
553 metal2_slot = get_polygons(36 , 3 )
554 count = metal2_slot.count()
555 logger.info("metal2_slot has %d polygons" % [count])
556 polygons_count += count
557
558 metal2_blk = get_polygons(36 , 5 )
559 count = metal2_blk.count()
560 logger.info("metal2_blk has %d polygons" % [count])
561 polygons_count += count
562
563 top_via = via1
564 topmin1_via = contact
565 top_metal = metal2
566 topmin1_metal = metal1
567
568else
569 metal2_drawn = get_polygons(36 , 0 )
570 count = metal2_drawn.count()
571 logger.info("metal2_drawn has %d polygons" % [count])
572 polygons_count += count
573
574 metal2_dummy = get_polygons(36 , 4 )
575 count = metal2_dummy.count()
576 logger.info("metal2_dummy has %d polygons" % [count])
577 polygons_count += count
578
579 metal2 = metal2_drawn + metal2_dummy
580
581 metal2_label = get_polygons(36 , 10)
582 count = metal2_label.count()
583 logger.info("metal2_label has %d polygons" % [count])
584 polygons_count += count
585
586 metal2_slot = get_polygons(36 , 3 )
587 count = metal2_slot.count()
588 logger.info("metal2_slot has %d polygons" % [count])
589 polygons_count += count
590
591 metal2_blk = get_polygons(36 , 5 )
592 count = metal2_blk.count()
593 logger.info("metal2_blk has %d polygons" % [count])
594 polygons_count += count
595
596 via2 = get_polygons(38 , 0 )
597 count = via2.count()
598 logger.info("via2 has %d polygons" % [count])
599 polygons_count += count
600
601 if METAL_LEVEL == "3LM"
602 metal3_drawn = get_polygons(42 , 0 )
603 count = metal3_drawn.count()
604 logger.info("metal3_drawn has %d polygons" % [count])
605 polygons_count += count
606
607 metal3_dummy = get_polygons(42 , 4 )
608 count = metal3_dummy.count()
609 logger.info("metal3_dummy has %d polygons" % [count])
610 polygons_count += count
611
612 metal3 = metal3_drawn + metal3_dummy
613
614 metal3_label = get_polygons(42 , 10)
615 count = metal3_label.count()
616 logger.info("metal3_label has %d polygons" % [count])
617 polygons_count += count
618
619 metal3_slot = get_polygons(42 , 3 )
620 count = metal3_slot.count()
621 logger.info("metal3_slot has %d polygons" % [count])
622 polygons_count += count
623
624 metal3_blk = get_polygons(42 , 5 )
625 count = metal3_blk.count()
626 logger.info("metal3_blk has %d polygons" % [count])
627 polygons_count += count
628
629 top_via = via2
630 topmin1_via = via1
631 top_metal = metal3
632 topmin1_metal = metal2
633 else
634 metal3_drawn = get_polygons(42 , 0 )
635 count = metal3_drawn.count()
636 logger.info("metal3_drawn has %d polygons" % [count])
637 polygons_count += count
638
639 metal3_dummy = get_polygons(42 , 4 )
640 count = metal3_dummy.count()
641 logger.info("metal3_dummy has %d polygons" % [count])
642 polygons_count += count
643
644 metal3 = metal3_drawn + metal3_dummy
645
646 metal3_label = get_polygons(42 , 10)
647 count = metal3_label.count()
648 logger.info("metal3_label has %d polygons" % [count])
649 polygons_count += count
650
651 metal3_slot = get_polygons(42 , 3 )
652 count = metal3_slot.count()
653 logger.info("metal3_slot has %d polygons" % [count])
654 polygons_count += count
655
656 metal3_blk = get_polygons(42 , 5 )
657 count = metal3_blk.count()
658 logger.info("metal3_blk has %d polygons" % [count])
659 polygons_count += count
660
661 via3 = get_polygons(40 , 0 )
662
663 if METAL_LEVEL == "4LM"
664 metal4_drawn = get_polygons(46 , 0 )
665 count = metal4_drawn.count()
666 logger.info("metal4_drawn has %d polygons" % [count])
667 polygons_count += count
668
669 metal4_dummy = get_polygons(46 , 4 )
670 count = metal4_dummy.count()
671 logger.info("metal4_dummy has %d polygons" % [count])
672 polygons_count += count
673
674 metal4 = metal4_drawn + metal4_dummy
675
676 metal4_label = get_polygons(46 , 10)
677 count = metal4_label.count()
678 logger.info("metal4_label has %d polygons" % [count])
679 polygons_count += count
680
681 metal4_slot = get_polygons(46 , 3 )
682 count = metal4_slot.count()
683 logger.info("metal4_slot has %d polygons" % [count])
684 polygons_count += count
685
686 metal4_blk = get_polygons(46 , 5 )
687 count = metal4_blk.count()
688 logger.info("metal4_blk has %d polygons" % [count])
689 polygons_count += count
690
691 top_via = via3
692 topmin1_via = via2
693 top_metal = metal4
694 topmin1_metal = metal3
695 else
696 metal4_drawn = get_polygons(46 , 0 )
697 count = metal4_drawn.count()
698 logger.info("metal4_drawn has %d polygons" % [count])
699 polygons_count += count
700
701 metal4_dummy = get_polygons(46 , 4 )
702 count = metal4_dummy.count()
703 logger.info("metal4_dummy has %d polygons" % [count])
704 polygons_count += count
705
706 metal4 = metal4_drawn + metal4_dummy
707
708 metal4_label = get_polygons(46 , 10)
709 count = metal4_label.count()
710 logger.info("metal4_label has %d polygons" % [count])
711 polygons_count += count
712
713 metal4_slot = get_polygons(46 , 3 )
714 count = metal4_slot.count()
715 logger.info("metal4_slot has %d polygons" % [count])
716 polygons_count += count
717
718 metal4_blk = get_polygons(46 , 5 )
719 count = metal4_blk.count()
720 logger.info("metal4_blk has %d polygons" % [count])
721 polygons_count += count
722
723 via4 = get_polygons(41 , 0 )
724 count = via4.count()
725 logger.info("via4 has %d polygons" % [count])
726 polygons_count += count
727
728 if METAL_LEVEL == "5LM"
729 metal5_drawn = get_polygons(81 , 0 )
730 count = metal5_drawn.count()
731 logger.info("metal5_drawn has %d polygons" % [count])
732 polygons_count += count
733
734 metal5_dummy = get_polygons(81 , 4 )
735 count = metal5_dummy.count()
736 logger.info("metal5_dummy has %d polygons" % [count])
737 polygons_count += count
738
739 metal5 = metal5_drawn + metal5_dummy
740
741 metal5_label = get_polygons(81 , 10)
742 count = metal5_label.count()
743 logger.info("metal5_label has %d polygons" % [count])
744 polygons_count += count
745
746 metal5_slot = get_polygons(81 , 3 )
747 count = metal5_slot.count()
748 logger.info("metal5_slot has %d polygons" % [count])
749 polygons_count += count
750
751 metal5_blk = get_polygons(81 , 5 )
752 count = metal5_blk.count()
753 logger.info("metal5_blk has %d polygons" % [count])
754 polygons_count += count
755
756 top_via = via4
757 topmin1_via = via3
758 top_metal = metal5
759 topmin1_metal = metal4
760 else
761 ## 6LM
762 metal5_drawn = get_polygons(81 , 0 )
763 count = metal5_drawn.count()
764 logger.info("metal5_drawn has %d polygons" % [count])
765 polygons_count += count
766
767 metal5_dummy = get_polygons(81 , 4 )
768 count = metal5_dummy.count()
769 logger.info("metal5_dummy has %d polygons" % [count])
770 polygons_count += count
771
772 metal5 = metal5_drawn + metal5_dummy
773
774 metal5_label = get_polygons(81 , 10)
775 count = metal5_label.count()
776 logger.info("metal5_label has %d polygons" % [count])
777 polygons_count += count
778
779 metal5_slot = get_polygons(81 , 3 )
780 count = metal5_slot.count()
781 logger.info("metal5_slot has %d polygons" % [count])
782 polygons_count += count
783
784 metal5_blk = get_polygons(81 , 5 )
785 count = metal5_blk.count()
786 logger.info("metal5_blk has %d polygons" % [count])
787 polygons_count += count
788
789 via5 = get_polygons(82 , 0 )
790 count = via5.count()
791 logger.info("via5 has %d polygons" % [count])
792 polygons_count += count
793
794
795 metaltop_drawn = get_polygons(53 , 0 )
796 count = metaltop_drawn.count()
797 logger.info("metaltop_drawn has %d polygons" % [count])
798 polygons_count += count
799
800 metaltop_dummy = get_polygons(53 , 4 )
801 count = metaltop_dummy.count()
802 logger.info("metaltop_dummy has %d polygons" % [count])
803 polygons_count += count
804
805 metaltop = metaltop_drawn + metaltop_dummy
806
807 metaltop_label = get_polygons(53 , 10)
808 count = metaltop_label.count()
809 logger.info("metaltop_label has %d polygons" % [count])
810 polygons_count += count
811
812 metaltop_slot = get_polygons(53 , 3 )
813 count = metaltop_slot.count()
814 logger.info("metaltop_slot has %d polygons" % [count])
815 polygons_count += count
816
817 metalt_blk = get_polygons(53 , 5 )
818 count = metalt_blk.count()
819 logger.info("metalt_blk has %d polygons" % [count])
820 polygons_count += count
821
822 top_via = via5
823 topmin1_via = via4
824 top_metal = metaltop
825 topmin1_metal = metal5
826 end
827 end
828 end
829end
830
831pad = get_polygons(37 , 0 )
832count = pad.count()
833logger.info("pad has %d polygons" % [count])
834polygons_count += count
835
836ubmpperi = get_polygons(183, 0 )
837count = ubmpperi.count()
838logger.info("ubmpperi has %d polygons" % [count])
839polygons_count += count
840
841ubmparray = get_polygons(184, 0 )
842count = ubmparray.count()
843logger.info("ubmparray has %d polygons" % [count])
844polygons_count += count
845
846ubmeplate = get_polygons(185, 0 )
847count = ubmeplate.count()
848logger.info("ubmeplate has %d polygons" % [count])
849polygons_count += count
850
851metal1_res = get_polygons(110, 11)
852count = metal1_res.count()
853logger.info("metal1_res has %d polygons" % [count])
854polygons_count += count
855
856metal2_res = get_polygons(110, 12)
857count = metal2_res.count()
858logger.info("metal2_res has %d polygons" % [count])
859polygons_count += count
860
861metal3_res = get_polygons(110, 13)
862count = metal3_res.count()
863logger.info("metal3_res has %d polygons" % [count])
864polygons_count += count
865
866metal4_res = get_polygons(110, 14)
867count = metal4_res.count()
868logger.info("metal4_res has %d polygons" % [count])
869polygons_count += count
870
871metal5_res = get_polygons(110, 15)
872count = metal5_res.count()
873logger.info("metal5_res has %d polygons" % [count])
874polygons_count += count
875
876metal6_res = get_polygons(110, 16)
877count = metal6_res.count()
878logger.info("metal6_res has %d polygons" % [count])
879polygons_count += count
880
881pr_bndry = get_polygons(0 , 0 )
882count = pr_bndry.count()
883logger.info("pr_bndry has %d polygons" % [count])
884polygons_count += count
885
886border = get_polygons(63 , 0 )
887count = border.count()
888logger.info("border has %d polygons" % [count])
889polygons_count += count
890logger.info("Total no. of polygons in the design is #{polygons_count}")
891
892logger.info("Starting deriving base layers.")
893#=====================================================
894#------------- BASE LAYERS DERIVATIONS ---------------
895#=====================================================
896
897ncomp = comp & nplus
898pcomp = comp & pplus
899tgate = poly2 & comp
900ngate = nplus & tgate
901pgate = pplus & tgate
902natcompsd = (nat & comp.interacting(poly2)) - tgate
903
904nom_gate = tgate.not(dualgate)
905thick_gate = tgate.and(dualgate)
906
907ngate_56V = ngate.and(dualgate)
908pgate_56V = pgate.and(dualgate)
909
910ngate_5V = ngate_56V.and(v5_xtor)
911pgate_5V = pgate_56V.and(v5_xtor)
912
913ngate_6V = ngate_56V.not(v5_xtor)
914pgate_6V = pgate_56V.not(v5_xtor)
915
916lvpwell_dn = lvpwell.interacting(dnwell)
917lvpwell_out = lvpwell.not_interacting(dnwell)
918
919
920#================================================
921#------------- LAYERS CONNECTIONS ---------------
922#================================================
923
924if CONNECTIVITY_RULES
925
926 logger.info("Construct connectivity for the design.")
927
928 connect(dnwell, ncomp)
929 connect(ncomp, contact)
930 connect(pcomp, contact)
931
932 connect(lvpwell_out, pcomp)
933 connect(lvpwell_dn, pcomp)
934
935 connect(nwell, ncomp)
936 connect(natcompsd, contact)
937 connect(mvsd, ncomp)
938 connect(mvpsd, pcomp)
939 connect(contact, metal1)
940 connect(metal1, via1)
941 connect(via1, metal2)
942 if METAL_LEVEL != "2LM"
943 connect(metal2, via2)
944 connect(via2, metal3)
945
946 if METAL_LEVEL != "3LM"
947 connect(metal3, via3)
948 connect(via3, metal4)
949
950 if METAL_LEVEL != "4LM"
951 connect(metal4, via4)
952 connect(via4, metal5)
953
954 if METAL_LEVEL != "5LM"
955 connect(metal5, via5)
956 connect(via5, metaltop)
957 end
958 end
959 end
960 end
961
962end #CONNECTIVITY_RULES
963
964#================================================
965#------------ PRE-DEFINED FUNCTIONS -------------
966#================================================
967
968def conn_space(layer,conn_val,not_conn_val, mode)
969 if conn_val > not_conn_val
970 raise "ERROR : Wrong connectivity implementation"
971 end
972 connected_output = layer.space(conn_val.um, mode).polygons(0.001)
973 unconnected_errors_unfiltered = layer.space(not_conn_val.um, mode)
974 singularity_errors = layer.space(0.001.um)
975 # Filter out the errors arising from the same net
976 unconnected_errors = DRC::DRCLayer::new(self, RBA::EdgePairs::new)
977 unconnected_errors_unfiltered.data.each do |ep|
978 net1 = l2n_data.probe_net(layer.data, ep.first.p1)
979 net2 = l2n_data.probe_net(layer.data, ep.second.p1)
980 if !net1 || !net2
981 puts "Should not happen ..."
982 elsif net1.circuit != net2.circuit || net1.cluster_id != net2.cluster_id
983 # unconnected
984 unconnected_errors.data.insert(ep)
985 end
986 end
987 unconnected_output = unconnected_errors.polygons.or(singularity_errors.polygons(0.001))
988 return connected_output, unconnected_output
989end
990
991def conn_separation(layer1, layer2, conn_val,not_conn_val, mode)
992 if conn_val > not_conn_val
993 raise "ERROR : Wrong connectivity implementation"
994 end
995 connected_output = layer1.separation(layer2, conn_val.um, mode).polygons(0.001)
996 unconnected_errors_unfiltered = layer1.separation(layer2, not_conn_val.um, mode)
997 # Filter out the errors arising from the same net
998 unconnected_errors = DRC::DRCLayer::new(self, RBA::EdgePairs::new)
999 unconnected_errors_unfiltered.data.each do |ep|
1000 net1 = l2n_data.probe_net(layer1.data, ep.first.p1)
1001 net2 = l2n_data.probe_net(layer2.data, ep.second.p1)
1002 if !net1 || !net2
1003 puts "Should not happen ..."
1004 elsif net1.circuit != net2.circuit || net1.cluster_id != net2.cluster_id
1005 # unconnected
1006 unconnected_errors.data.insert(ep)
1007 end
1008 end
1009 unconnected_output = unconnected_errors.polygons(0.001)
1010 return connected_output, unconnected_output
1011end
1012
1013# === IMPLICIT EXTRACTION ===
1014if CONNECTIVITY_RULES
1015 logger.info("Connectivity rules enabled, Netlist object will be generated.")
1016 netlist
1017end #CONNECTIVITY_RULES
1018
1019# === LAYOUT EXTENT ===
1020CHIP = extent.sized(0.0)
1021logger.info("Total area of the design is #{CHIP.area()} um^2.")
1022
1023#================================================
1024#----------------- MAIN RUNSET ------------------
1025#================================================
1026
1027logger.info("Starting GF180MCU DRC rules.")
1028if FEOL
1029 logger.info("Running all FEOL rules")
1030end #FEOL
1031
1032if BEOL
1033 logger.info("Running all BEOL rules")
1034end #BEOL
1035
1036
1037################################################################################################
1038# Copyright 2022 GlobalFoundries PDK Authors
1039#
1040# Licensed under the Apache License, Version 2.0 (the "License");
1041# you may not use this file except in compliance with the License.
1042# You may obtain a copy of the License at
1043#
1044# https://www.apache.org/licenses/LICENSE-2.0
1045#
1046# Unless required by applicable law or agreed to in writing, software
1047# distributed under the License is distributed on an "AS IS" BASIS,
1048# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1049# See the License for the specific language governing permissions and
1050# limitations under the License.
1051################################################################################################
1052
1053#===========================================================================================================================
1054#------------------------------------------- GF 0.18um MCU DRC RULE DECK --------------------------------------------------
1055#===========================================================================================================================
1056require 'time'
1057require "logger"
1058
1059exec_start_time = Time.now
1060
1061logger = Logger.new(STDOUT)
1062
1063logger.formatter = proc do |severity, datetime, progname, msg|
1064 "#{datetime}: Memory Usage (" + `pmap #{Process.pid} | tail -1`[10,40].strip + ") : #{msg}
1065"
1066end
1067
1068#================================================
1069#----------------- FILE SETUP -------------------
1070#================================================
1071
1072# optional for a batch launch : klayout -b -r gf_018mcu.drc -rd input=design.gds -rd report=gp180_drc.lyrdb
1073
1074logger.info("Starting running GF180MCU Klayout DRC runset on %s" % [$input])
1075logger.info("Ruby Version for klayout: %s" % [RUBY_VERSION])
1076
1077if $input
1078 if $topcell
1079 source($input, $topcell)
1080 else
1081 source($input)
1082 end
1083end
1084
1085if $table_name
1086 table_name = $table_name
1087else
1088 table_name = "main"
1089end
1090
1091
1092logger.info("Loading database to memory is complete.")
1093
1094if $report
1095 logger.info("GF180MCU Klayout DRC runset output at: %s" % [$report])
1096 report("DRC Run Report at", $report)
1097else
1098 logger.info("GF180MCU Klayout DRC runset output at default location." % [File.join(File.dirname(RBA::CellView::active.filename), "gf180_drc.lyrdb")])
1099 report("DRC Run Report at", File.join(File.dirname(RBA::CellView::active.filename), "gf180_drc.lyrdb"))
1100end
1101
1102#================================================
1103#------------------ SWITCHES --------------------
1104#================================================
1105logger.info("Evaluate switches.")
1106
1107# connectivity rules
1108if $conn_drc == "true"
1109 CONNECTIVITY_RULES = $conn_drc
1110 logger.info("connectivity rules are enabled.")
1111else
1112 CONNECTIVITY_RULES = false
1113 logger.info("connectivity rules are disabled.")
1114end # connectivity rules
1115
1116# WEDGE
1117if $wedge == "false"
1118 WEDGE = $wedge
1119else
1120 WEDGE = "true"
1121end # WEDGE
1122
1123logger.info("Wedge enabled %s" % [WEDGE])
1124
1125# BALL
1126if $ball == "false"
1127 BALL = $ball
1128else
1129 BALL = "true"
1130end # BALL
1131
1132logger.info("Ball enabled %s" % [BALL])
1133
1134# GOLD
1135if $gold == "false"
1136 GOLD = $gold
1137else
1138 GOLD = "true"
1139end # GOLD
1140
1141logger.info("Gold enabled %s" % [GOLD])
1142
1143if $mim_option
1144 MIM_OPTION = $mim_option
1145else
1146 MIM_OPTION = "B"
1147end
1148
1149logger.info("MIM Option selected %s" % [MIM_OPTION])
1150
1151# OFFGRID
1152if $offgrid == "false"
1153 OFFGRID = false
1154else
1155 OFFGRID = true
1156end # OFFGRID
1157
1158logger.info("Offgrid enabled %s" % [OFFGRID])
1159
1160if $thr
1161 threads($thr)
1162 logger.info("Number of threads to use %s" % [$thr])
1163else
1164 threads(%x("nproc"))
1165 logger.info("Number of threads to use #{%x("nproc")}")
1166end
1167
1168#=== PRINT DETAILS ===
1169if $verbose == "true"
1170 logger.info("Verbose mode: #{$verbose}")
1171 verbose(true)
1172else
1173 verbose(false)
1174 logger.info("Verbose mode: false")
1175end
1176
1177# === TILING MODE ===
1178if $run_mode == "tiling"
1179 tiles(500.um)
1180 tile_borders(10.um)
1181 logger.info("Tiling mode is enabled.")
1182
1183elsif $run_mode == "deep"
1184 #=== HIER MODE ===
1185 deep
1186 logger.info("deep mode is enabled.")
1187else
1188 #=== FLAT MODE ===
1189 flat
1190 logger.info("flat mode is enabled.")
1191end # run_mode
1192
1193# METAL_TOP
1194if $metal_top
1195 METAL_TOP = $metal_top
1196else
1197 METAL_TOP = "9K"
1198end # METAL_TOP
1199
1200logger.info("METAL_TOP Selected is %s" % [METAL_TOP])
1201
1202# METAL_LEVEL
1203if $metal_level
1204 METAL_LEVEL = $metal_level
1205else
1206 METAL_LEVEL = "5LM"
1207end # METAL_LEVEL
1208
1209logger.info("METAL_STACK Selected is %s" % [METAL_LEVEL])
1210
1211# FEOL
1212if $feol == "false"
1213 FEOL = $feol
1214 logger.info("FEOL is disabled.")
1215else
1216 FEOL = "true"
1217 logger.info("FEOL is enabled.")
1218end # FEOL
1219
1220# BEOL
1221if $beol == "false"
1222 BEOL = $beol
1223 logger.info("BEOL is disabled.")
1224else
1225 BEOL = "true"
1226 logger.info("BEOL is enabled.")
1227end # BEOL
1228
1229#================================================
1230#------------- LAYERS DEFINITIONS ---------------
1231#================================================
1232polygons_count = 0
1233logger.info("Read in polygons from layers.")
1234
1235def get_polygons(l, d)
1236 if $run_mode == "deep"
1237 polygons(l, d)
1238 else
1239 polygons(l, d).merged
1240 end
1241end
1242
1243comp = get_polygons(22 , 0 )
1244count = comp.count()
1245logger.info("comp has %d polygons" % [count])
1246polygons_count += count
1247
1248dnwell = get_polygons(12 , 0 )
1249count = dnwell.count()
1250logger.info("dnwell has %d polygons" % [count])
1251polygons_count += count
1252
1253nwell = get_polygons(21 , 0 )
1254count = nwell.count()
1255logger.info("nwell has %d polygons" % [count])
1256polygons_count += count
1257
1258lvpwell = get_polygons(204, 0 )
1259count = lvpwell.count()
1260logger.info("lvpwell has %d polygons" % [count])
1261polygons_count += count
1262
1263dualgate = get_polygons(55 , 0 )
1264count = dualgate.count()
1265logger.info("dualgate has %d polygons" % [count])
1266polygons_count += count
1267
1268poly2 = get_polygons(30 , 0 )
1269count = poly2.count()
1270logger.info("poly2 has %d polygons" % [count])
1271polygons_count += count
1272
1273nplus = get_polygons(32 , 0 )
1274count = nplus.count()
1275logger.info("nplus has %d polygons" % [count])
1276polygons_count += count
1277
1278pplus = get_polygons(31 , 0 )
1279count = pplus.count()
1280logger.info("pplus has %d polygons" % [count])
1281polygons_count += count
1282
1283sab = get_polygons(49 , 0 )
1284count = sab.count()
1285logger.info("sab has %d polygons" % [count])
1286polygons_count += count
1287
1288esd = get_polygons(24 , 0 )
1289count = esd.count()
1290logger.info("esd has %d polygons" % [count])
1291polygons_count += count
1292
1293resistor = get_polygons(62 , 0 )
1294count = resistor.count()
1295logger.info("resistor has %d polygons" % [count])
1296polygons_count += count
1297
1298fhres = get_polygons(227, 0 )
1299count = fhres.count()
1300logger.info("fhres has %d polygons" % [count])
1301polygons_count += count
1302
1303fusetop = get_polygons(75 , 0 )
1304count = fusetop.count()
1305logger.info("fusetop has %d polygons" % [count])
1306polygons_count += count
1307
1308fusewindow_d = get_polygons(96 , 1 )
1309count = fusewindow_d.count()
1310logger.info("fusewindow_d has %d polygons" % [count])
1311polygons_count += count
1312
1313polyfuse = get_polygons(220, 0 )
1314count = polyfuse.count()
1315logger.info("polyfuse has %d polygons" % [count])
1316polygons_count += count
1317
1318mvsd = get_polygons(210, 0 )
1319count = mvsd.count()
1320logger.info("mvsd has %d polygons" % [count])
1321polygons_count += count
1322
1323mvpsd = get_polygons(11 , 39)
1324count = mvpsd.count()
1325logger.info("mvpsd has %d polygons" % [count])
1326polygons_count += count
1327
1328nat = get_polygons(5 , 0 )
1329count = nat.count()
1330logger.info("nat has %d polygons" % [count])
1331polygons_count += count
1332
1333comp_dummy = get_polygons(22 , 4 )
1334count = comp_dummy.count()
1335logger.info("comp_dummy has %d polygons" % [count])
1336polygons_count += count
1337
1338poly2_dummy = get_polygons(30 , 4 )
1339count = poly2_dummy.count()
1340logger.info("poly2_dummy has %d polygons" % [count])
1341polygons_count += count
1342
1343schottky_diode = get_polygons(241, 0 )
1344count = schottky_diode.count()
1345logger.info("schottky_diode has %d polygons" % [count])
1346polygons_count += count
1347
1348zener = get_polygons(178, 0 )
1349count = zener.count()
1350logger.info("zener has %d polygons" % [count])
1351polygons_count += count
1352
1353res_mk = get_polygons(110, 5 )
1354count = res_mk.count()
1355logger.info("res_mk has %d polygons" % [count])
1356polygons_count += count
1357
1358opc_drc = get_polygons(124, 5 )
1359count = opc_drc.count()
1360logger.info("opc_drc has %d polygons" % [count])
1361polygons_count += count
1362
1363ndmy = get_polygons(111, 5 )
1364count = ndmy.count()
1365logger.info("ndmy has %d polygons" % [count])
1366polygons_count += count
1367
1368pmndmy = get_polygons(152, 5 )
1369count = pmndmy.count()
1370logger.info("pmndmy has %d polygons" % [count])
1371polygons_count += count
1372
1373v5_xtor = get_polygons(112, 1 )
1374count = v5_xtor.count()
1375logger.info("v5_xtor has %d polygons" % [count])
1376polygons_count += count
1377
1378cap_mk = get_polygons(117, 5 )
1379count = cap_mk.count()
1380logger.info("cap_mk has %d polygons" % [count])
1381polygons_count += count
1382
1383mos_cap_mk = get_polygons(166, 5 )
1384count = mos_cap_mk.count()
1385logger.info("mos_cap_mk has %d polygons" % [count])
1386polygons_count += count
1387
1388ind_mk = get_polygons(151, 5 )
1389count = ind_mk.count()
1390logger.info("ind_mk has %d polygons" % [count])
1391polygons_count += count
1392
1393diode_mk = get_polygons(115, 5 )
1394count = diode_mk.count()
1395logger.info("diode_mk has %d polygons" % [count])
1396polygons_count += count
1397
1398drc_bjt = get_polygons(127, 5 )
1399count = drc_bjt.count()
1400logger.info("drc_bjt has %d polygons" % [count])
1401polygons_count += count
1402
1403lvs_bjt = get_polygons(118, 5 )
1404count = lvs_bjt.count()
1405logger.info("lvs_bjt has %d polygons" % [count])
1406polygons_count += count
1407
1408mim_l_mk = get_polygons(117, 10)
1409count = mim_l_mk.count()
1410logger.info("mim_l_mk has %d polygons" % [count])
1411polygons_count += count
1412
1413latchup_mk = get_polygons(137, 5 )
1414count = latchup_mk.count()
1415logger.info("latchup_mk has %d polygons" % [count])
1416polygons_count += count
1417
1418guard_ring_mk = get_polygons(167, 5 )
1419count = guard_ring_mk.count()
1420logger.info("guard_ring_mk has %d polygons" % [count])
1421polygons_count += count
1422
1423otp_mk = get_polygons(173, 5 )
1424count = otp_mk.count()
1425logger.info("otp_mk has %d polygons" % [count])
1426polygons_count += count
1427
1428mtpmark = get_polygons(122, 5 )
1429count = mtpmark.count()
1430logger.info("mtpmark has %d polygons" % [count])
1431polygons_count += count
1432
1433neo_ee_mk = get_polygons(88 , 17)
1434count = neo_ee_mk.count()
1435logger.info("neo_ee_mk has %d polygons" % [count])
1436polygons_count += count
1437
1438sramcore = get_polygons(108, 5 )
1439count = sramcore.count()
1440logger.info("sramcore has %d polygons" % [count])
1441polygons_count += count
1442
1443lvs_rf = get_polygons(100, 5 )
1444count = lvs_rf.count()
1445logger.info("lvs_rf has %d polygons" % [count])
1446polygons_count += count
1447
1448lvs_drain = get_polygons(100, 7 )
1449count = lvs_drain.count()
1450logger.info("lvs_drain has %d polygons" % [count])
1451polygons_count += count
1452
1453ind_mk = get_polygons(151, 5 )
1454count = ind_mk.count()
1455logger.info("ind_mk has %d polygons" % [count])
1456polygons_count += count
1457
1458hvpolyrs = get_polygons(123, 5 )
1459count = hvpolyrs.count()
1460logger.info("hvpolyrs has %d polygons" % [count])
1461polygons_count += count
1462
1463lvs_io = get_polygons(119, 5 )
1464count = lvs_io.count()
1465logger.info("lvs_io has %d polygons" % [count])
1466polygons_count += count
1467
1468probe_mk = get_polygons(13 , 17)
1469count = probe_mk.count()
1470logger.info("probe_mk has %d polygons" % [count])
1471polygons_count += count
1472
1473esd_mk = get_polygons(24 , 5 )
1474count = esd_mk.count()
1475logger.info("esd_mk has %d polygons" % [count])
1476polygons_count += count
1477
1478lvs_source = get_polygons(100, 8 )
1479count = lvs_source.count()
1480logger.info("lvs_source has %d polygons" % [count])
1481polygons_count += count
1482
1483well_diode_mk = get_polygons(153, 51)
1484count = well_diode_mk.count()
1485logger.info("well_diode_mk has %d polygons" % [count])
1486polygons_count += count
1487
1488ldmos_xtor = get_polygons(226, 0 )
1489count = ldmos_xtor.count()
1490logger.info("ldmos_xtor has %d polygons" % [count])
1491polygons_count += count
1492
1493plfuse = get_polygons(125, 5 )
1494count = plfuse.count()
1495logger.info("plfuse has %d polygons" % [count])
1496polygons_count += count
1497
1498efuse_mk = get_polygons(80 , 5 )
1499count = efuse_mk.count()
1500logger.info("efuse_mk has %d polygons" % [count])
1501polygons_count += count
1502
1503mcell_feol_mk = get_polygons(11 , 17)
1504count = mcell_feol_mk.count()
1505logger.info("mcell_feol_mk has %d polygons" % [count])
1506polygons_count += count
1507
1508ymtp_mk = get_polygons(86 , 17)
1509count = ymtp_mk.count()
1510logger.info("ymtp_mk has %d polygons" % [count])
1511polygons_count += count
1512
1513dev_wf_mk = get_polygons(128, 17)
1514count = dev_wf_mk.count()
1515logger.info("dev_wf_mk has %d polygons" % [count])
1516polygons_count += count
1517
1518comp_label = get_polygons(22 , 10)
1519count = comp_label.count()
1520logger.info("comp_label has %d polygons" % [count])
1521polygons_count += count
1522
1523poly2_label = get_polygons(30 , 10)
1524count = poly2_label.count()
1525logger.info("poly2_label has %d polygons" % [count])
1526polygons_count += count
1527
1528mdiode = get_polygons(116, 5 )
1529count = mdiode.count()
1530logger.info("mdiode has %d polygons" % [count])
1531polygons_count += count
1532
1533contact = get_polygons(33 , 0 )
1534count = contact.count()
1535logger.info("contact has %d polygons" % [count])
1536polygons_count += count
1537
1538metal1_drawn = get_polygons(34 , 0 )
1539count = metal1_drawn.count()
1540logger.info("metal1_drawn has %d polygons" % [count])
1541polygons_count += count
1542
1543metal1_dummy = get_polygons(34 , 4 )
1544count = metal1_dummy.count()
1545logger.info("metal1_dummy has %d polygons" % [count])
1546polygons_count += count
1547
1548metal1 = metal1_drawn + metal1_dummy
1549
1550metal1_label = get_polygons(34 , 10)
1551count = metal1_label.count()
1552logger.info("metal1_label has %d polygons" % [count])
1553polygons_count += count
1554
1555metal1_slot = get_polygons(34 , 3 )
1556count = metal1_slot.count()
1557logger.info("metal1_slot has %d polygons" % [count])
1558polygons_count += count
1559
1560metal1_blk = get_polygons(34 , 5 )
1561count = metal1_blk.count()
1562logger.info("metal1_blk has %d polygons" % [count])
1563polygons_count += count
1564
1565via1 = get_polygons(35 , 0 )
1566count = via1.count()
1567logger.info("via1 has %d polygons" % [count])
1568polygons_count += count
1569
1570
1571if METAL_LEVEL == "2LM"
1572 metal2_drawn = get_polygons(36 , 0 )
1573 count = metal2_drawn.count()
1574 logger.info("metal2_drawn has %d polygons" % [count])
1575 polygons_count += count
1576
1577 metal2_dummy = get_polygons(36 , 4 )
1578 count = metal2_dummy.count()
1579 logger.info("metal2_dummy has %d polygons" % [count])
1580 polygons_count += count
1581
1582 metal2 = metal2_drawn + metal2_drawn
1583
1584 metal2_label = get_polygons(36 , 10)
1585 count = metal2_label.count()
1586 logger.info("metal2_label has %d polygons" % [count])
1587 polygons_count += count
1588
1589 metal2_slot = get_polygons(36 , 3 )
1590 count = metal2_slot.count()
1591 logger.info("metal2_slot has %d polygons" % [count])
1592 polygons_count += count
1593
1594 metal2_blk = get_polygons(36 , 5 )
1595 count = metal2_blk.count()
1596 logger.info("metal2_blk has %d polygons" % [count])
1597 polygons_count += count
1598
1599 top_via = via1
1600 topmin1_via = contact
1601 top_metal = metal2
1602 topmin1_metal = metal1
1603
1604else
1605 metal2_drawn = get_polygons(36 , 0 )
1606 count = metal2_drawn.count()
1607 logger.info("metal2_drawn has %d polygons" % [count])
1608 polygons_count += count
1609
1610 metal2_dummy = get_polygons(36 , 4 )
1611 count = metal2_dummy.count()
1612 logger.info("metal2_dummy has %d polygons" % [count])
1613 polygons_count += count
1614
1615 metal2 = metal2_drawn + metal2_dummy
1616
1617 metal2_label = get_polygons(36 , 10)
1618 count = metal2_label.count()
1619 logger.info("metal2_label has %d polygons" % [count])
1620 polygons_count += count
1621
1622 metal2_slot = get_polygons(36 , 3 )
1623 count = metal2_slot.count()
1624 logger.info("metal2_slot has %d polygons" % [count])
1625 polygons_count += count
1626
1627 metal2_blk = get_polygons(36 , 5 )
1628 count = metal2_blk.count()
1629 logger.info("metal2_blk has %d polygons" % [count])
1630 polygons_count += count
1631
1632 via2 = get_polygons(38 , 0 )
1633 count = via2.count()
1634 logger.info("via2 has %d polygons" % [count])
1635 polygons_count += count
1636
1637 if METAL_LEVEL == "3LM"
1638 metal3_drawn = get_polygons(42 , 0 )
1639 count = metal3_drawn.count()
1640 logger.info("metal3_drawn has %d polygons" % [count])
1641 polygons_count += count
1642
1643 metal3_dummy = get_polygons(42 , 4 )
1644 count = metal3_dummy.count()
1645 logger.info("metal3_dummy has %d polygons" % [count])
1646 polygons_count += count
1647
1648 metal3 = metal3_drawn + metal3_dummy
1649
1650 metal3_label = get_polygons(42 , 10)
1651 count = metal3_label.count()
1652 logger.info("metal3_label has %d polygons" % [count])
1653 polygons_count += count
1654
1655 metal3_slot = get_polygons(42 , 3 )
1656 count = metal3_slot.count()
1657 logger.info("metal3_slot has %d polygons" % [count])
1658 polygons_count += count
1659
1660 metal3_blk = get_polygons(42 , 5 )
1661 count = metal3_blk.count()
1662 logger.info("metal3_blk has %d polygons" % [count])
1663 polygons_count += count
1664
1665 top_via = via2
1666 topmin1_via = via1
1667 top_metal = metal3
1668 topmin1_metal = metal2
1669 else
1670 metal3_drawn = get_polygons(42 , 0 )
1671 count = metal3_drawn.count()
1672 logger.info("metal3_drawn has %d polygons" % [count])
1673 polygons_count += count
1674
1675 metal3_dummy = get_polygons(42 , 4 )
1676 count = metal3_dummy.count()
1677 logger.info("metal3_dummy has %d polygons" % [count])
1678 polygons_count += count
1679
1680 metal3 = metal3_drawn + metal3_dummy
1681
1682 metal3_label = get_polygons(42 , 10)
1683 count = metal3_label.count()
1684 logger.info("metal3_label has %d polygons" % [count])
1685 polygons_count += count
1686
1687 metal3_slot = get_polygons(42 , 3 )
1688 count = metal3_slot.count()
1689 logger.info("metal3_slot has %d polygons" % [count])
1690 polygons_count += count
1691
1692 metal3_blk = get_polygons(42 , 5 )
1693 count = metal3_blk.count()
1694 logger.info("metal3_blk has %d polygons" % [count])
1695 polygons_count += count
1696
1697 via3 = get_polygons(40 , 0 )
1698
1699 if METAL_LEVEL == "4LM"
1700 metal4_drawn = get_polygons(46 , 0 )
1701 count = metal4_drawn.count()
1702 logger.info("metal4_drawn has %d polygons" % [count])
1703 polygons_count += count
1704
1705 metal4_dummy = get_polygons(46 , 4 )
1706 count = metal4_dummy.count()
1707 logger.info("metal4_dummy has %d polygons" % [count])
1708 polygons_count += count
1709
1710 metal4 = metal4_drawn + metal4_dummy
1711
1712 metal4_label = get_polygons(46 , 10)
1713 count = metal4_label.count()
1714 logger.info("metal4_label has %d polygons" % [count])
1715 polygons_count += count
1716
1717 metal4_slot = get_polygons(46 , 3 )
1718 count = metal4_slot.count()
1719 logger.info("metal4_slot has %d polygons" % [count])
1720 polygons_count += count
1721
1722 metal4_blk = get_polygons(46 , 5 )
1723 count = metal4_blk.count()
1724 logger.info("metal4_blk has %d polygons" % [count])
1725 polygons_count += count
1726
1727 top_via = via3
1728 topmin1_via = via2
1729 top_metal = metal4
1730 topmin1_metal = metal3
1731 else
1732 metal4_drawn = get_polygons(46 , 0 )
1733 count = metal4_drawn.count()
1734 logger.info("metal4_drawn has %d polygons" % [count])
1735 polygons_count += count
1736
1737 metal4_dummy = get_polygons(46 , 4 )
1738 count = metal4_dummy.count()
1739 logger.info("metal4_dummy has %d polygons" % [count])
1740 polygons_count += count
1741
1742 metal4 = metal4_drawn + metal4_dummy
1743
1744 metal4_label = get_polygons(46 , 10)
1745 count = metal4_label.count()
1746 logger.info("metal4_label has %d polygons" % [count])
1747 polygons_count += count
1748
1749 metal4_slot = get_polygons(46 , 3 )
1750 count = metal4_slot.count()
1751 logger.info("metal4_slot has %d polygons" % [count])
1752 polygons_count += count
1753
1754 metal4_blk = get_polygons(46 , 5 )
1755 count = metal4_blk.count()
1756 logger.info("metal4_blk has %d polygons" % [count])
1757 polygons_count += count
1758
1759 via4 = get_polygons(41 , 0 )
1760 count = via4.count()
1761 logger.info("via4 has %d polygons" % [count])
1762 polygons_count += count
1763
1764 if METAL_LEVEL == "5LM"
1765 metal5_drawn = get_polygons(81 , 0 )
1766 count = metal5_drawn.count()
1767 logger.info("metal5_drawn has %d polygons" % [count])
1768 polygons_count += count
1769
1770 metal5_dummy = get_polygons(81 , 4 )
1771 count = metal5_dummy.count()
1772 logger.info("metal5_dummy has %d polygons" % [count])
1773 polygons_count += count
1774
1775 metal5 = metal5_drawn + metal5_dummy
1776
1777 metal5_label = get_polygons(81 , 10)
1778 count = metal5_label.count()
1779 logger.info("metal5_label has %d polygons" % [count])
1780 polygons_count += count
1781
1782 metal5_slot = get_polygons(81 , 3 )
1783 count = metal5_slot.count()
1784 logger.info("metal5_slot has %d polygons" % [count])
1785 polygons_count += count
1786
1787 metal5_blk = get_polygons(81 , 5 )
1788 count = metal5_blk.count()
1789 logger.info("metal5_blk has %d polygons" % [count])
1790 polygons_count += count
1791
1792 top_via = via4
1793 topmin1_via = via3
1794 top_metal = metal5
1795 topmin1_metal = metal4
1796 else
1797 ## 6LM
1798 metal5_drawn = get_polygons(81 , 0 )
1799 count = metal5_drawn.count()
1800 logger.info("metal5_drawn has %d polygons" % [count])
1801 polygons_count += count
1802
1803 metal5_dummy = get_polygons(81 , 4 )
1804 count = metal5_dummy.count()
1805 logger.info("metal5_dummy has %d polygons" % [count])
1806 polygons_count += count
1807
1808 metal5 = metal5_drawn + metal5_dummy
1809
1810 metal5_label = get_polygons(81 , 10)
1811 count = metal5_label.count()
1812 logger.info("metal5_label has %d polygons" % [count])
1813 polygons_count += count
1814
1815 metal5_slot = get_polygons(81 , 3 )
1816 count = metal5_slot.count()
1817 logger.info("metal5_slot has %d polygons" % [count])
1818 polygons_count += count
1819
1820 metal5_blk = get_polygons(81 , 5 )
1821 count = metal5_blk.count()
1822 logger.info("metal5_blk has %d polygons" % [count])
1823 polygons_count += count
1824
1825 via5 = get_polygons(82 , 0 )
1826 count = via5.count()
1827 logger.info("via5 has %d polygons" % [count])
1828 polygons_count += count
1829
1830
1831 metaltop_drawn = get_polygons(53 , 0 )
1832 count = metaltop_drawn.count()
1833 logger.info("metaltop_drawn has %d polygons" % [count])
1834 polygons_count += count
1835
1836 metaltop_dummy = get_polygons(53 , 4 )
1837 count = metaltop_dummy.count()
1838 logger.info("metaltop_dummy has %d polygons" % [count])
1839 polygons_count += count
1840
1841 metaltop = metaltop_drawn + metaltop_dummy
1842
1843 metaltop_label = get_polygons(53 , 10)
1844 count = metaltop_label.count()
1845 logger.info("metaltop_label has %d polygons" % [count])
1846 polygons_count += count
1847
1848 metaltop_slot = get_polygons(53 , 3 )
1849 count = metaltop_slot.count()
1850 logger.info("metaltop_slot has %d polygons" % [count])
1851 polygons_count += count
1852
1853 metalt_blk = get_polygons(53 , 5 )
1854 count = metalt_blk.count()
1855 logger.info("metalt_blk has %d polygons" % [count])
1856 polygons_count += count
1857
1858 top_via = via5
1859 topmin1_via = via4
1860 top_metal = metaltop
1861 topmin1_metal = metal5
1862 end
1863 end
1864 end
1865end
1866
1867pad = get_polygons(37 , 0 )
1868count = pad.count()
1869logger.info("pad has %d polygons" % [count])
1870polygons_count += count
1871
1872ubmpperi = get_polygons(183, 0 )
1873count = ubmpperi.count()
1874logger.info("ubmpperi has %d polygons" % [count])
1875polygons_count += count
1876
1877ubmparray = get_polygons(184, 0 )
1878count = ubmparray.count()
1879logger.info("ubmparray has %d polygons" % [count])
1880polygons_count += count
1881
1882ubmeplate = get_polygons(185, 0 )
1883count = ubmeplate.count()
1884logger.info("ubmeplate has %d polygons" % [count])
1885polygons_count += count
1886
1887metal1_res = get_polygons(110, 11)
1888count = metal1_res.count()
1889logger.info("metal1_res has %d polygons" % [count])
1890polygons_count += count
1891
1892metal2_res = get_polygons(110, 12)
1893count = metal2_res.count()
1894logger.info("metal2_res has %d polygons" % [count])
1895polygons_count += count
1896
1897metal3_res = get_polygons(110, 13)
1898count = metal3_res.count()
1899logger.info("metal3_res has %d polygons" % [count])
1900polygons_count += count
1901
1902metal4_res = get_polygons(110, 14)
1903count = metal4_res.count()
1904logger.info("metal4_res has %d polygons" % [count])
1905polygons_count += count
1906
1907metal5_res = get_polygons(110, 15)
1908count = metal5_res.count()
1909logger.info("metal5_res has %d polygons" % [count])
1910polygons_count += count
1911
1912metal6_res = get_polygons(110, 16)
1913count = metal6_res.count()
1914logger.info("metal6_res has %d polygons" % [count])
1915polygons_count += count
1916
1917pr_bndry = get_polygons(0 , 0 )
1918count = pr_bndry.count()
1919logger.info("pr_bndry has %d polygons" % [count])
1920polygons_count += count
1921
1922border = get_polygons(63 , 0 )
1923count = border.count()
1924logger.info("border has %d polygons" % [count])
1925polygons_count += count
1926logger.info("Total no. of polygons in the design is #{polygons_count}")
1927
1928logger.info("Starting deriving base layers.")
1929#=====================================================
1930#------------- BASE LAYERS DERIVATIONS ---------------
1931#=====================================================
1932
1933ncomp = comp & nplus
1934pcomp = comp & pplus
1935tgate = poly2 & comp
1936ngate = nplus & tgate
1937pgate = pplus & tgate
1938natcompsd = (nat & comp.interacting(poly2)) - tgate
1939
1940nom_gate = tgate.not(dualgate)
1941thick_gate = tgate.and(dualgate)
1942
1943ngate_56V = ngate.and(dualgate)
1944pgate_56V = pgate.and(dualgate)
1945
1946ngate_5V = ngate_56V.and(v5_xtor)
1947pgate_5V = pgate_56V.and(v5_xtor)
1948
1949ngate_6V = ngate_56V.not(v5_xtor)
1950pgate_6V = pgate_56V.not(v5_xtor)
1951
1952lvpwell_dn = lvpwell.interacting(dnwell)
1953lvpwell_out = lvpwell.not_interacting(dnwell)
1954
1955
1956#================================================
1957#------------- LAYERS CONNECTIONS ---------------
1958#================================================
1959
1960if CONNECTIVITY_RULES
1961
1962 logger.info("Construct connectivity for the design.")
1963
1964 connect(dnwell, ncomp)
1965 connect(ncomp, contact)
1966 connect(pcomp, contact)
1967
1968 connect(lvpwell_out, pcomp)
1969 connect(lvpwell_dn, pcomp)
1970
1971 connect(nwell, ncomp)
1972 connect(natcompsd, contact)
1973 connect(mvsd, ncomp)
1974 connect(mvpsd, pcomp)
1975 connect(contact, metal1)
1976 connect(metal1, via1)
1977 connect(via1, metal2)
1978 if METAL_LEVEL != "2LM"
1979 connect(metal2, via2)
1980 connect(via2, metal3)
1981
1982 if METAL_LEVEL != "3LM"
1983 connect(metal3, via3)
1984 connect(via3, metal4)
1985
1986 if METAL_LEVEL != "4LM"
1987 connect(metal4, via4)
1988 connect(via4, metal5)
1989
1990 if METAL_LEVEL != "5LM"
1991 connect(metal5, via5)
1992 connect(via5, metaltop)
1993 end
1994 end
1995 end
1996 end
1997
1998end #CONNECTIVITY_RULES
1999
2000#================================================
2001#------------ PRE-DEFINED FUNCTIONS -------------
2002#================================================
2003
2004def conn_space(layer,conn_val,not_conn_val, mode)
2005 if conn_val > not_conn_val
2006 raise "ERROR : Wrong connectivity implementation"
2007 end
2008 connected_output = layer.space(conn_val.um, mode).polygons(0.001)
2009 unconnected_errors_unfiltered = layer.space(not_conn_val.um, mode)
2010 singularity_errors = layer.space(0.001.um)
2011 # Filter out the errors arising from the same net
2012 unconnected_errors = DRC::DRCLayer::new(self, RBA::EdgePairs::new)
2013 unconnected_errors_unfiltered.data.each do |ep|
2014 net1 = l2n_data.probe_net(layer.data, ep.first.p1)
2015 net2 = l2n_data.probe_net(layer.data, ep.second.p1)
2016 if !net1 || !net2
2017 puts "Should not happen ..."
2018 elsif net1.circuit != net2.circuit || net1.cluster_id != net2.cluster_id
2019 # unconnected
2020 unconnected_errors.data.insert(ep)
2021 end
2022 end
2023 unconnected_output = unconnected_errors.polygons.or(singularity_errors.polygons(0.001))
2024 return connected_output, unconnected_output
2025end
2026
2027def conn_separation(layer1, layer2, conn_val,not_conn_val, mode)
2028 if conn_val > not_conn_val
2029 raise "ERROR : Wrong connectivity implementation"
2030 end
2031 connected_output = layer1.separation(layer2, conn_val.um, mode).polygons(0.001)
2032 unconnected_errors_unfiltered = layer1.separation(layer2, not_conn_val.um, mode)
2033 # Filter out the errors arising from the same net
2034 unconnected_errors = DRC::DRCLayer::new(self, RBA::EdgePairs::new)
2035 unconnected_errors_unfiltered.data.each do |ep|
2036 net1 = l2n_data.probe_net(layer1.data, ep.first.p1)
2037 net2 = l2n_data.probe_net(layer2.data, ep.second.p1)
2038 if !net1 || !net2
2039 puts "Should not happen ..."
2040 elsif net1.circuit != net2.circuit || net1.cluster_id != net2.cluster_id
2041 # unconnected
2042 unconnected_errors.data.insert(ep)
2043 end
2044 end
2045 unconnected_output = unconnected_errors.polygons(0.001)
2046 return connected_output, unconnected_output
2047end
2048
2049# === IMPLICIT EXTRACTION ===
2050if CONNECTIVITY_RULES
2051 logger.info("Connectivity rules enabled, Netlist object will be generated.")
2052 netlist
2053end #CONNECTIVITY_RULES
2054
2055# === LAYOUT EXTENT ===
2056CHIP = extent.sized(0.0)
2057logger.info("Total area of the design is #{CHIP.area()} um^2.")
2058
2059#================================================
2060#----------------- MAIN RUNSET ------------------
2061#================================================
2062
2063logger.info("Starting GF180MCU DRC rules.")
2064if FEOL
2065 logger.info("Running all FEOL rules")
2066end #FEOL
2067
2068if BEOL
2069 logger.info("Running all BEOL rules")
2070end #BEOL
2071
2072
2073################################################################################################
2074# Copyright 2022 GlobalFoundries PDK Authors
2075#
2076# Licensed under the Apache License, Version 2.0 (the "License");
2077# you may not use this file except in compliance with the License.
2078# You may obtain a copy of the License at
2079#
2080# https://www.apache.org/licenses/LICENSE-2.0
2081#
2082# Unless required by applicable law or agreed to in writing, software
2083# distributed under the License is distributed on an "AS IS" BASIS,
2084# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2085# See the License for the specific language governing permissions and
2086# limitations under the License.
2087################################################################################################
2088
2089
2090
2091exec_end_time = Time.now
2092run_time = exec_end_time - exec_start_time
2093logger.info("%s DRC Total Run time %f seconds" % [table_name, run_time])
2094
2095