From 51bf17a039a75ddf5f9d1d20008fc6a4752f57be Mon Sep 17 00:00:00 2001 From: RehabSayed-G Date: Thu, 3 Aug 2023 19:18:42 +0300 Subject: [PATCH] updating klayout dropdown menues --- rules/klayout/macros/drc_options.yml | 11 + rules/klayout/macros/gf180mcu_drc.lydrc | 52 +- rules/klayout/macros/gf180mcu_lvs.lylvs | 52 +- rules/klayout/macros/gf180mcu_options.lym | 670 +++++++++------------- rules/klayout/macros/lvs_options.yml | 16 + 5 files changed, 389 insertions(+), 412 deletions(-) create mode 100644 rules/klayout/macros/drc_options.yml create mode 100644 rules/klayout/macros/lvs_options.yml diff --git a/rules/klayout/macros/drc_options.yml b/rules/klayout/macros/drc_options.yml new file mode 100644 index 00000000..490c8f38 --- /dev/null +++ b/rules/klayout/macros/drc_options.yml @@ -0,0 +1,11 @@ +--- +drc_mode: '' +run_mode: "--run_mode=flat" +variant: "--variant=C" +top_cell_name: '' +run_dir: '' +verbose: '' +feol: '' +beol: '' +offgrid: '' +connectivity: '' diff --git a/rules/klayout/macros/gf180mcu_drc.lydrc b/rules/klayout/macros/gf180mcu_drc.lydrc index 180dd4b3..e4650d3c 100644 --- a/rules/klayout/macros/gf180mcu_drc.lydrc +++ b/rules/klayout/macros/gf180mcu_drc.lydrc @@ -8,6 +8,7 @@ false false + 0 true @@ -29,7 +30,56 @@ # See the License for the specific language governing permissions and # limitations under the License. +require 'yaml' + + +## reading the parent directory of the current file +run_dir = File.expand_path("..", __dir__) + +## reading the loaded gds file path +layout_path = Pathname.new(RBA::CellView.active.filename) +layout_dir = layout_path.split()[0] + +## read saved options from yaml file +options = YAML.load(File.read(__dir__ + "/drc_options.yml")) + +## create options passed to run_drc.py +options_str = "#{options["drc_mode"]} #{options["run_mode"]} #{options["variant"]} #{options["top_cell_name"]} #{options["verbose"]} #{options["feol"]} #{options["beol"]} #{options["offgrid"]} #{options["connectivity"]} #{options["run_dir"]}" + +## run_drc command line +cmd = "python3 #{run_dir}/drc/run_drc.py --path=#{layout_path} #{options_str}" + +## start running drc +puts "######### running #{cmd}" +drc_res = `#{cmd}` + +## read the log of drc run to get output lydb file paths if run_dir option is disables +gds_name = layout_path.split()[1].to_s.split(".")[0] + +if options["run_dir"] == "" + File.open(__dir__ + "/drc_res.txt", "w") { |file| file.write(drc_res) } + lydb_path = File.readlines(__dir__ + "/drc_res.txt")[3].split(/ /)[-1] + File.delete(__dir__ + "/drc_res.txt") + lydb_dir = lydb_path.to_s().split("/#{gds_name}")[0] +else + lydb_dir = options["run_dir"].split("=")[1] +end + + +## choose the displayed database file +if options["drc_mode"] == "--antenna_only" + lydb_file = "#{gds_name}_antenna.lyrdb" + +elsif options["drc_mode"] == "--density_only" + lydb_file = "#{gds_name}_density.lyrdb" + +else + lydb_file = "#{gds_name}_main.lyrdb" + + end + +## open a klayout window with database loaded +`klayout #{layout_path} -m #{lydb_dir}/#{lydb_file}` -# %include ../drc/gf180mcu.drc diff --git a/rules/klayout/macros/gf180mcu_lvs.lylvs b/rules/klayout/macros/gf180mcu_lvs.lylvs index 4b0b2e54..eab12b8d 100644 --- a/rules/klayout/macros/gf180mcu_lvs.lylvs +++ b/rules/klayout/macros/gf180mcu_lvs.lylvs @@ -8,6 +8,7 @@ false false + 0 true @@ -30,6 +31,55 @@ # limitations under the License. -# %include ../lvs/gf180mcu.lvs +require 'yaml' + +## reading the parent directory of the current file +run_dir = File.expand_path("..", __dir__) + +## reading the loaded gds file path +layout_path = Pathname.new(RBA::CellView.active.filename) + +## read saved options from yaml file +options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) + +## reading netlist option to get netlist_path +if options["netlist"] == "" + net_name = layout_path.split()[1].to_s().split(".")[0] + + net_dir = "#{layout_path.split()[0]}/#{net_name}.cdl" + +else + net_dir = options["netlist"] + +end + +## create options passed to run_drc.py +options_str = "--lvs_sub=#{options["sub_name"]} #{options["run_mode"]} #{options["variant"]} #{options["top_cell_name"]} #{options["spice_net"]} #{options["spice_comment"]} #{options["verbose"]} #{options["schematic_simple"]} #{options["net_only"]} #{options["top_lvl_pins"]} #{options["combine"]} #{options["purge"]} #{options["purge_nets"]} #{options["run_dir"]}" + +## run_drc command line +cmd = "python3 #{run_dir}/lvs/run_lvs.py --layout=#{layout_path} --netlist=#{net_dir} #{options_str}" + +## start running drc +puts "######### running #{cmd}" +lvs_res = `#{cmd}` + +## read the log of lvs run to get output lydb file paths if run_dir option is disables +gds_name = layout_path.split()[1].to_s.split(".")[0] + +if options["run_dir"] == "" + File.open(__dir__ + "/lvs_res.txt", "w") { |file| file.write(lvs_res) } + lydb_path = File.readlines(__dir__ + "/lvs_res.txt")[3].split(/ /)[-1] + File.delete(__dir__ + "/lvs_res.txt") + lydb_dir = lydb_path.to_s().split("/#{gds_name}")[0] +else + lydb_dir = options["run_dir"].split("=")[1] +end + +lydb_file = "#{gds_name}.lvsdb" + + +## open a klayout window with database loaded +`klayout #{layout_path} -mn #{lydb_dir}/#{lydb_file}` + diff --git a/rules/klayout/macros/gf180mcu_options.lym b/rules/klayout/macros/gf180mcu_options.lym index 7bf29b40..065b8ccd 100644 --- a/rules/klayout/macros/gf180mcu_options.lym +++ b/rules/klayout/macros/gf180mcu_options.lym @@ -8,6 +8,7 @@ false false + 0 true Load PDK options @@ -15,14 +16,15 @@ ruby module MyMacro +require 'yaml' include RBA - + ##################################################################################### # Loading options ##################################################################################### mw = RBA::MainWindow::instance - + # create a toolbar submenu mw.menu.insert_menu("submenu.end", "drc_menu", "Klayout DRC Options") mw.menu.insert_menu("submenu.end", "lvs_menu", "Klayout LVS Options") @@ -38,112 +40,107 @@ drc_mode_action = RBA::Action::new drc_mode_action.title = "DRC type" drc_mode_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_drc.lydrc", 'w') { |f| - text = File.read(f) - drc_mode_select = RBA::InputDialog::ask_item("DRC modes options", "Select DRC mode:", [ "Antenna only", "Density only", "Antenna & Density only", "Main only", "Main & Antenna only", "Main & Density only", "Main, Antenna & Density" ], 3) - if drc_mode_select == "Antenna only" - new_contents = text.gsub(/\# \%.*drc/m, "# %include ../tech/GF180/drc/gf180mcu_antenna.drc") - File.open(f, "w") {|file| file.puts new_contents } + + drc_mode_select = RBA::InputDialog::ask_item("DRC modes options", "Select DRC mode:", [ "Antenna only", "Density only", "Main only", "Main & Antenna only", "Main & Density only", "Main, Antenna & Density" ], 3) + options = YAML.load(File.read(__dir__ + "/drc_options.yml")) + if drc_mode_select == "Antenna only" + options["drc_mode"] = "--antenna_only" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } elsif drc_mode_select == "Density only" - new_contents = text.gsub(/\# \%.*drc/m, "# %include ../tech/GF180/drc/gf180mcu_density.drc") - File.open(f, "w") {|file| file.puts new_contents } - elsif drc_mode_select == "Antenna & Density only" - new_contents = text.gsub(/\# \%.*drc/m, "# %include ../tech/GF180/drc/gf180mcu_antenna.drc\n# %include ../tech/GF180/drc/gf180mcu_density.drc") - File.open(f, "w") {|file| file.puts new_contents } + options["drc_mode"] = "--density_only" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } elsif drc_mode_select == "Main only" - new_contents = text.gsub(/\# \%.*drc/m, "# %include ../tech/GF180/drc/gf180mcu.drc") - File.open(f, "w") {|file| file.puts new_contents } - elsif drc_mode_select == "Main & Antenna only" - new_contents = text.gsub(/\# \%.*drc/m, "# %include ../tech/GF180/drc/gf180mcu.drc\n# %include ../tech/GF180/drc/gf180mcu_antenna.drc") - File.open(f, "w") {|file| file.puts new_contents } - elsif drc_mode_select == "Main & Density only" - new_contents = text.gsub(/\# \%.*drc/m, "# %include ../tech/GF180/drc/gf180mcu.drc\n# %include ../tech/GF180/drc/gf180mcu_density.drc") - File.open(f, "w") {|file| file.puts new_contents } - elsif drc_mode_select == "Main, Antenna & Density" - new_contents = text.gsub(/\# \%.*drc/m, "# %include ../tech/GF180/drc/gf180mcu.drc\n# %include ../tech/GF180/drc/gf180mcu_antenna.drc\n# %include ../tech/GF180/drc/gf180mcu_density.drc") - File.open(f, "w") {|file| file.puts new_contents } - end - } + options["drc_mode"] = " " + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } + elsif drc_mode_select == "Main & Antenna only" + options["drc_mode"] = "--antenna" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } + elsif drc_mode_select == "Main & Density only" + options["drc_mode"] = "--density" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } + elsif drc_mode_select == "Main, Antenna & Density" + options["drc_mode"] = "--antenna --density" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } + end + end - mw.menu.insert_item("submenu.drc_menu.end", "drc_mode", drc_mode_action) + +mw.menu.insert_item("submenu.drc_menu.end", "drc_mode", drc_mode_action) #1 Setting run mode run_mode_drc_action = RBA::Action::new run_mode_drc_action.title = "Run mode" run_mode_drc_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_drc.lydrc", 'w') { |f| - text = File.read(f) + run_mode_select = RBA::InputDialog::ask_item("Run mode", "Select run mode:", [ "tiling", "deep", "flat" ], 1) + options = YAML.load(File.read(__dir__ + "/drc_options.yml")) if run_mode_select - if text.include?("$run_mode") - new_contents = text.gsub(/\$run_mode = \".*\"/, '$run_mode = "'+ run_mode_select + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*drc)/m, '$run_mode = "'+ run_mode_select +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end + options["run_mode"]= "--drc_mode=#{run_mode_select}" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } + else + options["run_mode"]= "" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } end - } + end mw.menu.insert_item("submenu.drc_menu.end", "run_mode", run_mode_drc_action) - #2 Setting stack - stack_drc_action = RBA::Action::new - stack_drc_action.title = "Stack options" - stack_drc_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_drc.lydrc", 'w') { |f| - text = File.read(f) - stack_select = RBA::InputDialog::ask_item("Stack options", "Select stack option:", [ "gf180mcuA", "gf180mcuB", "gf180mcuC" ], 2) - if stack_select == "gf180mcuA" - if text.include?("$metal_top") && text.include?("$metal_level") && text.include?("$mim_option") - new_contents = text.gsub(/\$metal_top = \".*\"\n\$metal_level = \".*\"\n\$mim_option = \".*\"/, '$metal_top = "30K"'+"\n"+'$metal_level = "3LM"'+"\n"+'$mim_option = "A"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*drc)/m, '$metal_top = "30K"'+"\n"+'$metal_level = "3LM"'+"\n"+'$mim_option = "A"'+"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - elsif stack_select == "gf180mcuB" - if text.include?("$metal_top") && text.include?("$metal_level") && text.include?("$mim_option") - new_contents = text.gsub(/\$metal_top = \".*\"\n\$metal_level = \".*\"\n\$mim_option = \".*\"/, '$metal_top = "11K"'+"\n"+'$metal_level = "4LM"'+"\n"+'$mim_option = "B"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*drc)/m, '$metal_top = "11K"'+"\n"+'$metal_level = "4LM"'+"\n"+'$mim_option = "B"'+"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - elsif stack_select == "gf180mcuC" - if text.include?("$metal_top") && text.include?("$metal_level") && text.include?("$mim_option") - new_contents = text.gsub(/\$metal_top = \".*\"\n\$metal_level = \".*\"\n\$mim_option = \".*\"/, '$metal_top = "9K"'+"\n"+'$metal_level = "5LM"'+"\n"+'$mim_option = "B"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*drc)/m, '$metal_top = "9K"'+"\n"+'$metal_level = "5LM"'+"\n"+'$mim_option = "B"'+"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - end - } + #2 Setting variant + variant_drc_action = RBA::Action::new + variant_drc_action.title = "Variant options" + variant_drc_action.on_triggered do + + variant_select = RBA::InputDialog::ask_item("Variant options", "Select variant option:", [ "A", "B", "C" , "D", "E"], 2) + options = YAML.load(File.read(__dir__ + "/drc_options.yml")) + if variant_select + options["variant"] = "--variant=#{variant_select}" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } + end + end - mw.menu.insert_item("submenu.drc_menu.end", "stack", stack_drc_action) + mw.menu.insert_item("submenu.drc_menu.end", "variant", variant_drc_action) + + #3 Adding Top cell name + top_cell_action = RBA::Action::new + top_cell_action.title = "Top_cell name" + top_cell_action.on_triggered do + top_cell_name = RBA::InputDialog::ask_string("Top cell name", "Please enter Top_cell name", "TOP") + options = YAML.load(File.read(__dir__ + "/drc_options.yml")) + if top_cell_name + options["top_cell_name"] = "--topcell=#{top_cell_name}" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } + end + + end + mw.menu.insert_item("submenu.drc_menu.end", "TOP_cell_name", top_cell_action) - #3 Setting verbose mode + #4 Adding run_dir path + run_dir_action = RBA::Action::new + run_dir_action.title = "Run_dir Path" + run_dir_action.on_triggered do + run_dir_path = RBA::InputDialog::ask_string("Run dir Path", "Please enter Run dir Path", "#{__dir__}") + options = YAML.load(File.read(__dir__ + "/drc_options.yml")) + if run_dir_path + options["run_dir"] = "--run_dir=#{run_dir_path}" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } + end + + end + mw.menu.insert_item("submenu.drc_menu.end", "run_dir_path", run_dir_action) + + #5 Setting verbose mode verbose_drc_action = RBA::Action::new verbose_drc_action.title = "Verbose mode" verbose_drc_action.checkable=(true) verbose_drc_action.checked=(false) verbose_drc_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_drc.lydrc", 'w') { |f| - text = File.read(f) + + options = YAML.load(File.read(__dir__ + "/drc_options.yml")) if verbose_drc_action.is_checked? - verbose_bool = "true" - else - verbose_bool = "false" - end - if text.include?("$verbose") - new_contents = text.gsub(/\$verbose = \".*\"/, '$verbose = "'+ verbose_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*drc)/m, '$verbose = "'+ verbose_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } + options["verbose"] = "--verbose" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } end - } + end mw.menu.insert_item("submenu.drc_menu.end", "verbose", verbose_drc_action) @@ -153,93 +150,57 @@ feol_action.checkable=(true) feol_action.checked=(true) feol_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_drc.lydrc", 'w') { |f| - text = File.read(f) - if feol_action.is_checked? - feol_bool = "true" - else - feol_bool = "false" - end - if text.include?("$feol") - new_contents = text.gsub(/\$feol = \".*\"/, '$feol = "'+ feol_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*drc)/m, '$feol = "'+ feol_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } + options = YAML.load(File.read(__dir__ + "/drc_options.yml")) + unless feol_action.is_checked? + options["feol"] = "--no_feol" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } end - } + end mw.menu.insert_item("submenu.drc_menu.end", "feol", feol_action) - #5 Setting BEOL rules + #6 Setting BEOL rules beol_action = RBA::Action::new beol_action.title = "BEOL rules" beol_action.checkable=(true) beol_action.checked=(true) beol_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_drc.lydrc", 'w') { |f| - text = File.read(f) - if beol_action.is_checked? - beol_bool = "true" - else - beol_bool = "false" + options = YAML.load(File.read(__dir__ + "/drc_options.yml")) + unless beol_action.is_checked? + options["beol"] = "--no_beol" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } end - if text.include?("$feol") - new_contents = text.gsub(/\$beol = \".*\"/, '$beol = "'+ beol_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*drc)/m, '$beol = "'+ beol_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - } + end mw.menu.insert_item("submenu.drc_menu.end", "beol", beol_action) - #6 Setting offgrid rules + #7 Setting offgrid rules offgrid_action = RBA::Action::new offgrid_action.title = "Offgrid rules" offgrid_action.checkable=(true) offgrid_action.checked=(true) offgrid_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_drc.lydrc", 'w') { |f| - text = File.read(f) - if offgrid_action.is_checked? - offgrid_bool = "true" - else - offgrid_bool = "false" - end - if text.include?("$offgrid") - new_contents = text.gsub(/\$offgrid = \".*\"/, '$offgrid = "'+ offgrid_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*drc)/m, '$offgrid = "'+ offgrid_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } + options = YAML.load(File.read(__dir__ + "/drc_options.yml")) + unless offgrid_action.is_checked? + options["offgrid"] = "--no_offgrid" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } end - } + end mw.menu.insert_item("submenu.drc_menu.end", "offgrid", offgrid_action) - #7 Setting connectivity rules + #8 Setting connectivity rules connectivity_action = RBA::Action::new connectivity_action.title = "Connectivity rules" connectivity_action.checkable=(true) - connectivity_action.checked=(true) + connectivity_action.checked=(false) connectivity_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_drc.lydrc", 'w') { |f| - text = File.read(f) + options = YAML.load(File.read(__dir__ + "/drc_options.yml")) if connectivity_action.is_checked? - connectivity_bool = "true" - else - connectivity_bool = "false" + options["connectivity"] = "--connectivity" + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(options.to_yaml) } end - if text.include?("$connectivity") - new_contents = text.gsub(/\$connectivity = \".*\"/, '$connectivity = "'+ connectivity_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*drc)/m, '$connectivity = "'+ connectivity_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - } + end mw.menu.insert_item("submenu.drc_menu.end", "connectivity", connectivity_action) @@ -252,19 +213,12 @@ run_action.title = "Substrate name" run_action.on_triggered do sub_name = RBA::InputDialog::ask_string("Substrate name", "Please enter substrate name", "gf180mcu_gnd") - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) if sub_name - if text.include?("$lvs_sub") - new_contents = text.gsub(/\$lvs_sub = \".*\"/, '$lvs_sub = "'+ sub_name + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$lvs_sub = "'+ sub_name +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end + options["sub_name"] = "--lvs_sub=#{sub_name}" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } end - } - #system( "klayout -r #{File.expand_path File.dirname(__FILE__)}/sky130.lvs -rd input=#{RBA::CellView::active.filename}" ) + end mw.menu.insert_item("submenu.lvs_menu.end", "SUB_name", run_action) @@ -272,295 +226,233 @@ run_mode_action = RBA::Action::new run_mode_action.title = "Run mode" run_mode_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) run_mode_select = RBA::InputDialog::ask_item("Run mode", "Select run mode:", [ "tiling", "deep", "flat" ], 1) if run_mode_select - if text.include?("$run_mode") - new_contents = text.gsub(/\$run_mode = \".*\"/, '$run_mode = "'+ run_mode_select + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$run_mode = "'+ run_mode_select +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end + options["run_mode"] = "--run_mode=#{run_mode_select}" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } end - } + end mw.menu.insert_item("submenu.lvs_menu.end", "run_mode", run_mode_action) #3 Setting stack - stack_action = RBA::Action::new - stack_action.title = "Stack options" - stack_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) - stack_select = RBA::InputDialog::ask_item("Stack options", "Select stack option:", [ "gf180mcuA", "gf180mcuB", "gf180mcuC" ], 2) - if stack_select == "gf180mcuA" - if text.include?("$metal_top") && text.include?("$metal_level") && text.include?("$mim_option") - new_contents = text.gsub(/\$metal_top = \".*\"\n\$metal_level = \".*\"\n\$mim_option = \".*\"/, '$metal_top = "30K"'+"\n"+'$metal_level = "3LM"'+"\n"+'$mim_option = "A"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$metal_top = "30K"'+"\n"+'$metal_level = "3LM"'+"\n"+'$mim_option = "A"'+"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - elsif stack_select == "gf180mcuB" - if text.include?("$metal_top") && text.include?("$metal_level") && text.include?("$mim_option") - new_contents = text.gsub(/\$metal_top = \".*\"\n\$metal_level = \".*\"\n\$mim_option = \".*\"/, '$metal_top = "11K"'+"\n"+'$metal_level = "4LM"'+"\n"+'$mim_option = "B"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$metal_top = "11K"'+"\n"+'$metal_level = "4LM"'+"\n"+'$mim_option = "B"'+"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - elsif stack_select == "gf180mcuC" - if text.include?("$metal_top") && text.include?("$metal_level") && text.include?("$mim_option") - new_contents = text.gsub(/\$metal_top = \".*\"\n\$metal_level = \".*\"\n\$mim_option = \".*\"/, '$metal_top = "9K"'+"\n"+'$metal_level = "5LM"'+"\n"+'$mim_option = "B"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$metal_top = "9K"'+"\n"+'$metal_level = "5LM"'+"\n"+'$mim_option = "B"'+"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - end - } + variant_action = RBA::Action::new + variant_action.title = "variant options" + variant_action.on_triggered do + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) + variant_select = RBA::InputDialog::ask_item("Variant options", "Select variant option:", [ "A", "B", "C", "D" ], 2) + if variant_select + options["variant"] = "--variant=#{variant_select}" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } + end + + end + mw.menu.insert_item("submenu.lvs_menu.end", "variant", variant_action) + + #4 Adding netlist path + netlist_action = RBA::Action::new + netlist_action.title = "Netlist Path" + netlist_action.on_triggered do + netlist_path = RBA::InputDialog::ask_string("Netlist Path", "Please enter Netlist Path", "") + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) + if netlist_path + options["netlist"] = netlist_path + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } + end + end - mw.menu.insert_item("submenu.lvs_menu.end", "stack", stack_action) + mw.menu.insert_item("submenu.lvs_menu.end", "Netlist_path", netlist_action) + + #5 Adding Top cell name + top_cell_action = RBA::Action::new + top_cell_action.title = "Top_cell name" + top_cell_action.on_triggered do + top_cell_name = RBA::InputDialog::ask_string("Top cell name", "Please enter Top_cell name", "TOP") + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) + if top_cell_name + options["top_cell_name"] = "--topcell=#{top_cell_name}" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } + end + + end + mw.menu.insert_item("submenu.lvs_menu.end", "TOP_cell_name", top_cell_action) + + #6 Adding run_dir path + run_dir_action = RBA::Action::new + run_dir_action.title = "Run_dir Path" + run_dir_action.on_triggered do + run_dir_path = RBA::InputDialog::ask_string("Run dir Path", "Please enter Run dir Path", "#{__dir__}") + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) + if run_dir_path + options["run_dir"] = "--run_dir=#{run_dir_path}" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } + end + + end + mw.menu.insert_item("submenu.lvs_menu.end", "run_dir_path", run_dir_action) - #4 Setting spice net names + #7 Setting spice net names spice_net_action = RBA::Action::new spice_net_action.title = "SPICE net name" spice_net_action.checkable=(true) spice_net_action.checked=(true) spice_net_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) - if spice_net_action.is_checked? - spice_net_bool = "true" - else - spice_net_bool = "false" - end - if text.include?("$spice_net_names") - new_contents = text.gsub(/\$spice_net_names = \".*\"/, '$spice_net_names = "'+ spice_net_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$spice_net_names = "'+ spice_net_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) + unless spice_net_action.is_checked? + options["spice_net"] = "--no_net_names" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } end - } + end mw.menu.insert_item("submenu.lvs_menu.end", "SPICE_net_name", spice_net_action) - #5 Setting spice comments + #8 Setting spice comments spice_comment_action = RBA::Action::new spice_comment_action.title = "SPICE comments" spice_comment_action.checkable=(true) spice_comment_action.checked=(false) spice_comment_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) if spice_comment_action.is_checked? - spice_comment_bool = "true" - else - spice_comment_bool = "false" + options["spice_comment"] = "--spice_comments" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } + end - if text.include?("$spice_with_comments") - new_contents = text.gsub(/\$spice_with_comments = \".*\"/, '$spice_with_comments = "'+ spice_comment_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$spice_with_comments = "'+ spice_comment_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - } + end mw.menu.insert_item("submenu.lvs_menu.end", "SPICE_comments", spice_comment_action) - #6 Setting scaling + #9 Setting scaling scale_action = RBA::Action::new scale_action.title = "Scaling x10^6" scale_action.checkable=(true) scale_action.checked=(false) scale_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) if scale_action.is_checked? - scale_bool = "true" - else - scale_bool = "false" - end - if text.include?("$scale") - new_contents = text.gsub(/\$scale = \".*\"/, '$scale = "'+ scale_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$scale = "'+ scale_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } + options["scale"] = "--scale " + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } end - } + end mw.menu.insert_item("submenu.lvs_menu.end", "scale", scale_action) - #7 Setting verbose mode + #10 Setting verbose mode verbose_action = RBA::Action::new verbose_action.title = "Verbose mode" verbose_action.checkable=(true) verbose_action.checked=(false) verbose_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) if verbose_action.is_checked? - verbose_bool = "true" - else - verbose_bool = "false" + options["verbose"] = "--verbose " + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } end - if text.include?("$verbose") - new_contents = text.gsub(/\$verbose = \".*\"/, '$verbose = "'+ verbose_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$verbose = "'+ verbose_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - } + end mw.menu.insert_item("submenu.lvs_menu.end", "verbose", verbose_action) - #8 Setting schematic simplification + #11 Setting schematic simplification schematic_simple_action = RBA::Action::new schematic_simple_action.title = "Schematic simplify" schematic_simple_action.checkable=(true) schematic_simple_action.checked=(false) schematic_simple_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) if schematic_simple_action.is_checked? - schematic_simple_bool = "true" - else - schematic_simple_bool = "false" - end - if text.include?("$schematic_simplify") - new_contents = text.gsub(/\$schematic_simplify = \".*\"/, '$schematic_simplify = "'+ schematic_simple_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$schematic_simplify = "'+ schematic_simple_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } + options["schematic_simple"] = "--schematic_simplify " + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } end - } + end mw.menu.insert_item("submenu.lvs_menu.end", "schematic_simple", schematic_simple_action) - #9 Setting netlist only + #12 Setting netlist only net_only_action = RBA::Action::new net_only_action.title = "Netlist only" net_only_action.checkable=(true) net_only_action.checked=(false) net_only_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) if net_only_action.is_checked? - net_only_bool = "true" - else - net_only_bool = "false" + options["net_only"] = "--net_only" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } end - if text.include?("$net_only") - new_contents = text.gsub(/\$net_only = \".*\"/, '$net_only = "'+ net_only_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$net_only = "'+ net_only_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - } + end mw.menu.insert_item("submenu.lvs_menu.end", "net_only", net_only_action) - #10 Setting top level pins + #13 Setting top level pins top_lvl_pins_action = RBA::Action::new top_lvl_pins_action.title = "Top level pins" top_lvl_pins_action.checkable=(true) top_lvl_pins_action.checked=(false) top_lvl_pins_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) if top_lvl_pins_action.is_checked? - top_lvl_pins_bool = "true" - else - top_lvl_pins_bool = "false" - end - if text.include?("$top_lvl_pins") - new_contents = text.gsub(/\$top_lvl_pins = \".*\"/, '$top_lvl_pins = "'+ top_lvl_pins_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$top_lvl_pins = "'+ top_lvl_pins_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } + options["top_lvl_pins"] = "--top_lvl_pins" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } end - } + end mw.menu.insert_item("submenu.lvs_menu.end", "top_lvl_pins", top_lvl_pins_action) - #11 Setting device combine + #14 Setting device combine combine_action = RBA::Action::new combine_action.title = "Devices combine" combine_action.checkable=(true) combine_action.checked=(false) combine_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) if combine_action.is_checked? - combine_bool = "true" - else - combine_bool = "false" - end - if text.include?("$combine") - new_contents = text.gsub(/\$combine = \".*\"/, '$combine = "'+ combine_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$combine = "'+ combine_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } + options["combine"] = "--combine" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } end - } + end mw.menu.insert_item("submenu.lvs_menu.end", "combine", combine_action) - #12 Setting purge + #15 Setting purge purge_action = RBA::Action::new purge_action.title = "Purge" purge_action.checkable=(true) purge_action.checked=(false) purge_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) + if purge_action.is_checked? - purge_bool = "true" - else - purge_bool = "false" - end - if text.include?("$verbose") - new_contents = text.gsub(/\$purge = \".*\"/, '$purge = "'+ purge_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$purge = "'+ purge_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } + options["purge"] = "--purge" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } end - } + end mw.menu.insert_item("submenu.lvs_menu.end", "purge", purge_action) - #13 Setting purge nets + #16 Setting purge nets purge_nets_action = RBA::Action::new purge_nets_action.title = "Purge nets" purge_nets_action.checkable=(true) purge_nets_action.checked=(false) purge_nets_action.on_triggered do - File.open(File.expand_path File.dirname(__FILE__) + "/gf180mcu_lvs.lylvs", 'w') { |f| - text = File.read(f) + + options = YAML.load(File.read(__dir__ + "/lvs_options.yml")) if purge_nets_action.is_checked? - purge_nets_bool = "true" - else - purge_nets_bool = "false" + options["purge_nets"] = "--purge_nets" + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(options.to_yaml) } end - if text.include?("$purge_nets") - new_contents = text.gsub(/\$purge_nets = \".*\"/, '$purge_nets = "'+ purge_nets_bool + '"') - File.open(f, "w") {|file| file.puts new_contents } - else - new_contents = text.gsub(/(\# \%.*lvs)/m, '$purge_nets = "'+ purge_nets_bool +'"' +"\n"+'\1') - File.open(f, "w") {|file| file.puts new_contents } - end - } + end mw.menu.insert_item("submenu.lvs_menu.end", "purge_nets", purge_nets_action) @@ -570,77 +462,35 @@ ##################################################################################### mw.on_view_closed do - str = '<?xml version="1.0" encoding="utf-8"?> -<klayout-macro> - <description>Run Klayout LVS</description> - <version>0.1</version> - <category>lvs</category> - <prolog/> - <epilog/> - <doc/> - <autorun>false</autorun> - <autorun-early>false</autorun-early> - <shortcut/> - <show-in-menu>true</show-in-menu> - <group-name/> - <menu-path>submenu&gt;end("gf180mcu PDK").end</menu-path> - <interpreter>dsl</interpreter> - <dsl-interpreter-name>lvs-dsl-xml</dsl-interpreter-name> - <text> -# 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. - -' - str = str + "\n# %include ../lvs/gf180mcu.lvs\n</text>\n</klayout-macro>" - - File.open(File.expand_path(File.dirname(__FILE__)) + "/gf180mcu_lvs.lylvs", 'w') { |f| f.write(str) } - - str = '<?xml version="1.0" encoding="utf-8"?> -<klayout-macro> - <description>Run Klayout DRC</description> - <version>0.1</version> - <category>drc</category> - <prolog/> - <epilog/> - <doc/> - <autorun>false</autorun> - <autorun-early>false</autorun-early> - <shortcut/> - <show-in-menu>true</show-in-menu> - <group-name/> - <menu-path>submenu&gt;end("gf180mcu PDK").end</menu-path> - <interpreter>dsl</interpreter> - <dsl-interpreter-name>drc-dsl-xml</dsl-interpreter-name> - <text> -# 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. - -' - str = str + "\n# %include ../drc/gf180mcu.drc\n</text>\n</klayout-macro>" - - File.open(File.expand_path(File.dirname(__FILE__)) + "/gf180mcu_drc.lydrc", 'w') { |f| f.write(str) } + ## write default options + drc_options = {"drc_mode"=>"", + "run_mode"=>"--run_mode=flat", + "variant"=>"--variant=C" , + "top_cell_name"=>"", + "run_dir"=>"", + "verbose"=>"", + "feol"=>"", + "beol"=>"", + "offgrid"=> "", + "connectivity"=>"" } + lvs_options = {"sub_name"=>"--lvs_sub=gf180mcu_gnd", + "run_mode"=>"--run_mode=flat", + "variant"=>"--variant=C" , + "netlist"=>"" , + "spice_net"=>"", + "top_cell_name"=>"", + "run_dir"=>"", + "spice_comment"=>"", + "verbose"=>"", + "schematic_simple"=>"", + "net_only"=>"", + "top_lvl_pins"=>"", + "combine"=>"", + "purge"=>"", + "purge_nets"=>"" + } + File.open(__dir__ + "/drc_options.yml", "w") { |file| file.write(drc_options.to_yaml) } + File.open(__dir__ + "/lvs_options.yml", "w") { |file| file.write(lvs_options.to_yaml) } end end diff --git a/rules/klayout/macros/lvs_options.yml b/rules/klayout/macros/lvs_options.yml new file mode 100644 index 00000000..befbd993 --- /dev/null +++ b/rules/klayout/macros/lvs_options.yml @@ -0,0 +1,16 @@ +--- +sub_name: "--lvs_sub=gf180mcu_gnd" +run_mode: "--run_mode=flat" +variant: "--variant=C" +netlist: '' +spice_net: '' +top_cell_name: '' +run_dir: '' +spice_comment: '' +verbose: '' +schematic_simple: '' +net_only: '' +top_lvl_pins: '' +combine: '' +purge: '' +purge_nets: ''