| ################################################################################################ |
| # Copyright 2022 GlobalFoundries PDK Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| ################################################################################################ |
| |
| #======================================================================================================================= |
| #--------------------------------------------- GF 0.18um BCDLite LVS RULE DECK --------------------------------------------- |
| #======================================================================================================================= |
| require 'time' |
| require 'logger' |
| require 'etc' |
| |
| exec_start_time = Time.now |
| |
| logger = Logger.new($stdout) |
| |
| logger.formatter = proc do |_severity, datetime, _progname, msg| |
| "#{datetime}: Memory Usage (" + `pmap #{Process.pid} | tail -1`[10, 40].strip + ") : #{msg} |
| " |
| end |
| |
| |
| #================================================ |
| #----------------- FILE SETUP ------------------- |
| #================================================ |
| logger.info("Starting running GF180BCDLite Klayout LVS runset on #{$input}") |
| logger.info("Ruby Version for klayout: #{RUBY_VERSION}") |
| |
| if $input |
| if $topcell |
| source($input, $topcell) |
| else |
| source($input) |
| end |
| end |
| |
| logger.info('Loading database to memory is complete.') |
| |
| if $report |
| logger.info("GF180BCDLite Klayout LVS runset output at: #{$report}") |
| report_lvs($report) |
| else |
| layout_dir = Pathname.new(RBA::CellView.active.filename).parent.realpath |
| report_path = layout_dir.join("#{source.cell_name}.lvsdb").to_s |
| logger.info("GF180BCDLite Klayout LVS runset output at default location: #{source.cell_name}.lvsdb") |
| report_lvs($report_path) |
| end |
| |
| if $target_netlist |
| logger.info("LVS extracted netlist at: #{$target_netlist}") |
| target_netlist($target_netlist) |
| else |
| layout_dir = Pathname.new(RBA::CellView.active.filename).parent.realpath |
| netlist_path = layout_dir.join("#{source.cell_name}_extracted.cir").to_s |
| logger.info("GF180BCDLite Klayout LVS extracted netlist file at: #{source.cell_name}_extracted.cir") |
| target_netlist($netlist_path, |
| write_spice(spice_with_net_names, spice_with_comments), 'Extracted by KLayout with GF180 LVS runset') |
| end |
| |
| |
| #================================================ |
| #------------------ SWITCHES -------------------- |
| #================================================ |
| logger.info('Evaluate switches.') |
| |
| def bool_check?(obj) |
| obj.to_s.downcase == 'true' |
| end |
| |
| #=== GET SUBSTRATE NAME === |
| substrate_name = $lvs_sub || 'gf180BCDLite_gnd' |
| |
| logger.info("Substrate name used: #{$lvs_sub}") |
| |
| #=== NET NAMES OPTION === |
| # true: use net names instead of numbers |
| # false: use numbers for nets |
| SPICE_WITH_NET_NAMES = bool_check?($spice_net_names) |
| |
| logger.info("Extracted netlist with net names: #{SPICE_WITH_NET_NAMES}") |
| |
| #=== COMMENTS OPTION === |
| # true: put in comments with details |
| # false: no comments |
| SPICE_WITH_COMMENTS = bool_check?($spice_comments) |
| |
| logger.info("Extracted netlist with comments in details: #{SPICE_WITH_COMMENTS}") |
| |
| #=== EXTRACTION SCALE === |
| DEV_SCALE = bool_check?($scale) |
| |
| device_scaling(1_000_000) if $DEV_SCALE |
| |
| logger.info("LVS device_scaling option: #{DEV_SCALE}") |
| |
| # SCH_SIMPLE |
| SCH_SIMPLE = bool_check?($schematic_simplify) |
| |
| logger.info("Selected SCH_SIMPLE option: #{SCH_SIMPLE}") |
| |
| # NET_ONLY |
| NET_ONLY = bool_check?($net_only) |
| |
| logger.info("Selected NET_ONLY option: #{NET_ONLY}") |
| |
| # TOP_LVL_PINS |
| TOP_LVL_PINS = bool_check?($top_lvl_pins) |
| |
| logger.info("Selected TOP_LVL_PINS option: #{TOP_LVL_PINS}") |
| |
| # COMBINE |
| COMBINE = bool_check?($combine) |
| |
| logger.info("Selected COMBINE option: #{COMBINE}") |
| |
| # PURGE |
| PURGE = bool_check?($purge) |
| |
| logger.info("Selected PURGE option: #{PURGE}") |
| |
| # PURGE_NETS |
| PURGE_NETS = bool_check?($purge_nets) |
| |
| logger.info("Selected PURGE_NETS option: #{PURGE_NETS}") |
| |
| # SIMPLIFY |
| SIMPLIFY = if NET_ONLY || TOP_LVL_PINS || COMBINE || PURGE || PURGE_NETS |
| false |
| else |
| true |
| end |
| |
| logger.info("Selected SIMPLIFY option: #{SIMPLIFY}") |
| |
| #=== PRINT DETAILS === |
| logger.info("Verbose mode: #{$verbose}") |
| if $verbose == 'true' |
| verbose(true) |
| else |
| verbose(false) |
| end |
| |
| # === TILING MODE === |
| case $run_mode |
| when 'tiling' |
| tiles(500.um) |
| tile_borders(10.um) |
| logger.info('Tiling mode is enabled.') |
| |
| when 'deep' |
| #=== HIER MODE === |
| deep |
| logger.info('deep mode is enabled.') |
| else |
| #=== FLAT MODE === |
| flat |
| logger.info('flat mode is enabled.') |
| end |
| |
| # METAL_TOP |
| METAL_TOP = $metal_top || '9K' |
| |
| logger.info("METAL_TOP Selected is #{METAL_TOP}") |
| |
| # METAL_LEVEL |
| METAL_LEVEL = $metal_level || '6LM' |
| |
| logger.info("METAL_STACK Selected is #{METAL_LEVEL}") |
| |
| # POLY_RES |
| POLY_RES = $poly_res || '1k' |
| |
| logger.info("POLY_RES Selected is #{POLY_RES}") |
| |
| # MIM |
| MIM_OPTION = $mim_option || 'B' |
| |
| logger.info("MIM Option selected: #{MIM_OPTION}") |
| |
| # MIM |
| MIM_CAP = $mim_cap || '2' |
| |
| logger.info("MIM CAP selected: #{MIM_CAP}") |
| |
| #================================================ |
| # --------------- CUSTOM CLASSES ---------------- |
| #================================================ |
| |
| # %include rule_decks/custom_classes.lvs |
| |
| # Instantiate a reader using the new delegate |
| reader = RBA::NetlistSpiceReader.new(SubcircuitModelsReader.new) |
| |
| #=== GET NETLIST === |
| if $schematic |
| schematic($schematic, reader) |
| logger.info("Netlist file: #{$schematic}") |
| else |
| exts = ["spice", "cdl"] |
| candidates = exts.map{|ext| "#{source.cell_name}.#{ext}"} |
| netlists = candidates.select{|f| File.exist?(f)} |
| if netlists.empty? |
| error("Netlist not found, tried: #{candidates}") |
| else |
| schematic(netlists[0], reader) |
| logger.info("Netlist file: #{netlists[0]}") |
| end |
| end |
| |
| #================================================ |
| #------------- LAYERS DEFINITIONS --------------- |
| #================================================ |
| |
| # %include rule_decks/layers_definition.lvs |
| |
| #================================================================ |
| #------------------------- MAIN RUNSET -------------------------- |
| #================================================================ |
| |
| logger.info('GF180 LVS rules started') |
| |
| #================================================ |
| #------------- LAYERS DERIVATIONS --------------- |
| #================================================ |
| |
| logger.info('Starting base layers derivations') |
| |
| #================================== |
| # ------ GENERAL DERIVATIONS ------ |
| #================================== |
| |
| # %include rule_decks/general_derivations.lvs |
| |
| #================================ |
| # ------ BJT DERIVATIONS -------- |
| #================================ |
| |
| # %include rule_decks/mos_derivations.lvs |
| |
| #================================ |
| # ------ BJT DERIVATIONS -------- |
| #================================ |
| |
| # %include rule_decks/bjt_derivations.lvs |
| |
| #================================= |
| # ------ DIODE DERIVATIONS ------- |
| #================================= |
| |
| # %include rule_decks/diode_derivations.lvs |
| |
| #================================= |
| # ------ DIODE DERIVATIONS ------- |
| #================================= |
| |
| # %include rule_decks/res_derivations.lvs |
| |
| #================================== |
| # ------ MIMCAP DERIVATIONS ------- |
| #================================== |
| |
| # %include rule_decks/mimcap_derivations.lvs |
| |
| #================================== |
| # ------ MOSCAP DERIVATIONS ------- |
| #================================== |
| |
| # %include rule_decks/moscap_derivations.lvs |
| |
| #==================================== |
| # ------ VARACTOR DERIVATIONS ------- |
| #==================================== |
| |
| # %include rule_decks/varactor_derivations.lvs |
| |
| #================================== |
| # ------ PISCAP DERIVATIONS ------- |
| #================================== |
| |
| # %include rule_decks/piscap_derivations.lvs |
| |
| #================================== |
| # ----- MOS-SAB DERIVATIONS ------- |
| #================================== |
| |
| # %include rule_decks/mos_sab_derivations.lvs |
| |
| #================================================ |
| #------------ DEVICES CONNECTIVITY -------------- |
| #================================================ |
| |
| # %include rule_decks/devices_connections.lvs |
| |
| #================================================ |
| #------------- DEVICES EXTRACTION --------------- |
| #================================================ |
| |
| logger.info('Starting GF180 LVS DEVICES EXTRACTION') |
| |
| #================================ |
| # ------- BJT EXTRACTION -------- |
| #================================ |
| |
| # %include rule_decks/mos_extraction.lvs |
| |
| #================================ |
| # ------- BJT EXTRACTION -------- |
| #================================ |
| |
| # %include rule_decks/bjt_extraction.lvs |
| |
| #================================= |
| # ------- DIODE EXTRACTION ------- |
| #================================= |
| |
| # %include rule_decks/diode_extraction.lvs |
| |
| #================================= |
| # ------- DIODE EXTRACTION ------- |
| #================================= |
| |
| # %include rule_decks/res_extraction.lvs |
| |
| #================================== |
| # ------- MIMCAP EXTRACTION ------- |
| #================================== |
| |
| # %include rule_decks/mimcap_extraction.lvs |
| |
| #================================== |
| # ------- MOSCAP EXTRACTION ------- |
| #================================== |
| |
| # %include rule_decks/moscap_extraction.lvs |
| |
| #==================================== |
| # ------- VARACTOR EXTRACTION ------- |
| #==================================== |
| |
| # %include rule_decks/varactor_extraction.lvs |
| |
| #================================= |
| # ------- PICAP EXTRACTION ------- |
| #================================= |
| |
| # %include rule_decks/piscap_extraction.lvs |
| |
| #================================= |
| # ------ MOS-SAB EXTRACTION ------ |
| #================================= |
| |
| # %include rule_decks/mos_sab_extraction.lvs |
| |
| #================================================ |
| #------------- COMPARISON OPTIONS --------------- |
| #================================================ |
| |
| logger.info('Starting GF180 LVS comparison section') |
| |
| #=== FLATTEN CELLS === |
| align |
| |
| #=== NETLIST EXTRACTION === |
| netlist.simplify if SIMPLIFY |
| |
| #=== NETLIST OPTIONS === |
| netlist if NET_ONLY |
| |
| netlist.make_top_level_pins if TOP_LVL_PINS |
| |
| netlist.combine_devices if COMBINE |
| |
| netlist.purge if PURGE |
| |
| netlist.purge_nets if PURGE_NETS |
| |
| #=== SCHEMATIC OPTIONS === |
| schematic.simplify if SCH_SIMPLE |
| |
| #=== IGNORE EXTREME VALUES === |
| max_res(1e7) |
| min_caps(1e-16) |
| |
| compare |
| |
| exec_end_time = Time.now |
| run_time = exec_end_time - exec_start_time |
| logger.info(format('LVS Total Run time %f seconds', run_time)) |
| |
| if !compare |
| logger.info('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') |
| logger.error("ERROR : Netlists don't match") |
| logger.info('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx') |
| else |
| logger.info('==========================================') |
| logger.info('INFO : Congratulations! Netlists match.') |
| logger.info('==========================================') |
| end |