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>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>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: ''