Implemented LayerInfo for DRC input/output

- Added a "layers" function too
- Updated tests
- Updated documentation
This commit is contained in:
Matthias Koefferlein 2017-07-11 00:36:51 +02:00
parent be20bdd9cc
commit e2bcac657a
52 changed files with 1260 additions and 24 deletions

View File

@ -0,0 +1,572 @@
# Run with:
# ./klayout -z -r ./create_drc_samples.rb -t -c klayoutrc_drc_samples
def run_demo(gen, cmd, out)
img_path = "src/lay/doc/images"
mw = RBA::Application::instance::main_window
cv = mw.create_layout(0)
ly = cv.layout
view = mw.current_view
l0 = ly.insert_layer(RBA::LayerInfo::new(0, 0))
l1 = ly.insert_layer(RBA::LayerInfo::new(1, 0))
l2 = ly.insert_layer(RBA::LayerInfo::new(2, 0))
lout_poly = ly.insert_layer(RBA::LayerInfo::new(101, 0))
lout = ly.insert_layer(RBA::LayerInfo::new(100, 0))
cell = ly.create_cell("TOP")
view.select_cell(0, cell.cell_index)
lp = RBA::LayerProperties::new
lp.fill_color = lp.frame_color = 0xffffff
lp.source_layer = 0
lp.source_datatype = 0
lp.dither_pattern = 5
lp.width = 0
lp.name = "TXT"
view.insert_layer(view.end_layers, lp)
lp = RBA::LayerProperties::new
lp.fill_color = lp.frame_color = 0xff8080
lp.source_layer = 1
lp.source_datatype = 0
lp.dither_pattern = 5
lp.name = "IN1"
view.insert_layer(view.end_layers, lp)
lp = RBA::LayerProperties::new
lp.fill_color = lp.frame_color = 0x8080ff
lp.source_layer = 2
lp.source_datatype = 0
lp.dither_pattern = 9
lp.name = "IN2"
view.insert_layer(view.end_layers, lp)
lp = RBA::LayerProperties::new
lp.fill_color = lp.frame_color = 0x404040
lp.source_layer = 101
lp.source_datatype = 0
lp.width = 0
lp.dither_pattern = 0
lp.transparent = true
lp.name = "OUT_POLY"
view.insert_layer(view.end_layers, lp)
lp = RBA::LayerProperties::new
lp.fill_color = lp.frame_color = 0xffffff
lp.source_layer = 100
lp.source_datatype = 0
lp.width = 3
lp.name = "OUT"
view.insert_layer(view.end_layers, lp)
gen.produce(cell.shapes(l1), cell.shapes(l2))
view.zoom_box(RBA::DBox::new(-2.0, -1.0, 8.0, 9.0))
t = RBA::Text::new(cmd, -1500, 8500)
t.valign = 0
t.font = 0
t.size = 0.2 / ly.dbu
cell.shapes(l0).insert(t)
eng = DRC::DRCEngine::new
data = eng.instance_eval(<<SCRIPT)
silent
input1 = input(1, 0)
input = input1
input2 = input(2, 0)
#{cmd}.data
SCRIPT
if data.is_a?(RBA::Region)
cell.shapes(lout_poly).insert(data)
cell.shapes(lout).insert(data)
elsif data.is_a?(RBA::Edges)
data.each do |e|
v = e.p2 - e.p1
if v.length > 0
a1 = RBA::ICplxTrans::new(300.0 / v.length, 30, false, 0, 0).trans(v)
a2 = RBA::ICplxTrans::new(300.0 / v.length, -30, false, 0, 0).trans(v)
cell.shapes(lout).insert(RBA::Edge::new(e.p2 - a1, e.p2))
cell.shapes(lout).insert(RBA::Edge::new(e.p2 - a2, e.p2))
end
cell.shapes(lout).insert(e)
end
elsif data.is_a?(RBA::EdgePairs)
cell.shapes(lout_poly).insert_as_polygons(data, 1)
cell.shapes(lout).insert(data.edges)
end
view.update_content
view.save_image(img_path + "/" + out, 400, 400)
puts "---> written #{img_path}/#{out}"
mw.close_all
end
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(0, 0),
RBA::Point::new(3000, 0),
RBA::Point::new(3000, 4000),
RBA::Point::new(5000, 4000),
RBA::Point::new(5000, 7000),
RBA::Point::new(2000, 7000),
RBA::Point::new(2000, 3000),
RBA::Point::new(0, 3000)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input.width(1.2, euclidian)", "drc_width1.png"
run_demo gen, "input.width(1.2, projection)", "drc_width2.png"
run_demo gen, "input.width(1.2, square)", "drc_width3.png"
run_demo gen, "input.width(1.2, whole_edges)", "drc_width4.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(4000, 0),
RBA::Point::new(4000, 1000),
RBA::Point::new(6000, 1000),
RBA::Point::new(6000, 2000),
RBA::Point::new(4000, 2000),
RBA::Point::new(4000, 6000),
RBA::Point::new(7000, 6000),
RBA::Point::new(7000, 0)
];
s1.insert(RBA::Polygon::new(pts))
pts = [
RBA::Point::new(0, 4000),
RBA::Point::new(0, 7000),
RBA::Point::new(3000, 7000),
RBA::Point::new(3000, 4000)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input.space(1.2, euclidian)", "drc_space1.png"
run_demo gen, "input.notch(1.2, euclidian)", "drc_space2.png"
run_demo gen, "input.isolated(1.2, euclidian)", "drc_space3.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(4000, 0),
RBA::Point::new(4000, 1000),
RBA::Point::new(6000, 1000),
RBA::Point::new(6000, 2000),
RBA::Point::new(4000, 2000),
RBA::Point::new(4000, 6000),
RBA::Point::new(7000, 6000),
RBA::Point::new(7000, 0)
];
s1.insert(RBA::Polygon::new(pts))
pts = [
RBA::Point::new(0, 0),
RBA::Point::new(0, 3000),
RBA::Point::new(3000, 3000),
RBA::Point::new(3000, 0)
];
s1.insert(RBA::Polygon::new(pts))
pts = [
RBA::Point::new(0, 4000),
RBA::Point::new(0, 7000),
RBA::Point::new(3000, 7000),
RBA::Point::new(3000, 4000)
];
s2.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input1.separation(input2, 1.2, euclidian)", "drc_separation1.png"
# ...
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(5000, 0),
RBA::Point::new(5000, 2000),
RBA::Point::new(4000, 2000),
RBA::Point::new(4000, 5000),
RBA::Point::new(3000, 5000),
RBA::Point::new(3000, 7000),
RBA::Point::new(6000, 7000),
RBA::Point::new(6000, 0)
];
s1.insert(RBA::Polygon::new(pts))
pts = [
RBA::Point::new(0, 0),
RBA::Point::new(0, 7000),
RBA::Point::new(2000, 7000),
RBA::Point::new(2000, 0)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input.sized(1.8, 0.0).raw.merged(2)", "drc_raw1.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(0, 0),
RBA::Point::new(0, 4000),
RBA::Point::new(3000, 7000),
RBA::Point::new(3000, 0)
];
s1.insert(RBA::Polygon::new(pts))
pts = [
RBA::Point::new(3000, 0),
RBA::Point::new(3000, 7000),
RBA::Point::new(6000, 4000),
RBA::Point::new(6000, 0)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input.raw.sized(-0.5)", "drc_raw2.png"
run_demo gen, "input.sized(-0.5)", "drc_raw3.png"
class Gen
def produce(s1, s2)
s1.insert(RBA::Box::new(0, 1000, 6000, 7000))
s2.insert(RBA::Box::new(3000, 0, 6000, 6000))
end
end
gen = Gen::new
run_demo gen, "input1.enclosing(input2, 2.0.um)", "drc_enc1.png"
run_demo gen, "input1.enclosing(input2, 2.0.um, projection)", "drc_enc2.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(0, 1000),
RBA::Point::new(0, 7000),
RBA::Point::new(7000, 7000),
RBA::Point::new(7000, 3000),
RBA::Point::new(4000, 3000),
RBA::Point::new(4000, 5000),
RBA::Point::new(2000, 5000),
RBA::Point::new(2000, 2000),
RBA::Point::new(1000, 2000),
RBA::Point::new(1000, 1000)
];
s2.insert(RBA::Polygon::new(pts))
pts = [
RBA::Point::new(2000, 0),
RBA::Point::new(2000, 6000),
RBA::Point::new(6000, 6000),
RBA::Point::new(6000, 0)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input1.overlap(input2, 2.0.um)", "drc_overlap1.png"
run_demo gen, "input1.overlap(input2, 2.0.um, projection)", "drc_overlap2.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(1000, 0),
RBA::Point::new(1000, 2000),
RBA::Point::new(4000, 2000),
RBA::Point::new(4000, 5000),
RBA::Point::new(1000, 5000),
RBA::Point::new(1000, 7000),
RBA::Point::new(5000, 7000),
RBA::Point::new(5000, 0)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input.edges.start_segments(1.um)", "drc_start_segments1.png"
run_demo gen, "input.edges.start_segments(0, 0.5)", "drc_start_segments2.png"
run_demo gen, "input.edges.end_segments(1.um)", "drc_end_segments1.png"
run_demo gen, "input.edges.end_segments(0, 0.5)", "drc_end_segments2.png"
run_demo gen, "input.edges.centers(1.um)", "drc_centers1.png"
run_demo gen, "input.edges.centers(0, 0.5)", "drc_centers2.png"
run_demo gen, "input.edges.with_length(2.0)\n .extended(:out => 1.0)", "drc_extended1.png"
run_demo gen, "input.edges.with_length(0, 3.5)\n .extended(:out => 1.0)", "drc_extended2.png"
run_demo gen, "input.edges.with_length(0, 3.5)\n .extended(:out => 1.0, :joined => true)", "drc_extended3.png"
run_demo gen, "input.edges.with_length(2.0)\n .extended(0.0, -0.5, 1.0, -0.5)", "drc_extended4.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(2000, 0),
RBA::Point::new(2000, 2000),
RBA::Point::new(4000, 2000),
RBA::Point::new(4000, 6000),
RBA::Point::new(5000, 6000),
RBA::Point::new(5000, 0)
];
s1.insert(RBA::Polygon::new(pts))
pts = [
RBA::Point::new(0, 3000),
RBA::Point::new(3000, 3000),
RBA::Point::new(3000, 4000),
RBA::Point::new(1000, 4000),
RBA::Point::new(1000, 7000),
RBA::Point::new(0000, 7000)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input.extents", "drc_extents1.png"
run_demo gen, "input.edges.extents(0.1)", "drc_extents2.png"
class Gen
def produce(s1, s2)
s1.insert(RBA::Box::new(0, 1000, 2000, 3000))
s1.insert(RBA::Box::new(4000, 1000, 6000, 3000))
s1.insert(RBA::Box::new(4000, 5000, 6000, 7000))
s1.insert(RBA::Box::new(0, 4000, 2000, 6000))
s2.insert(RBA::Box::new(1000, 0, 6000, 4000))
end
end
gen = Gen::new
run_demo gen, "input1.inside(input2)", "drc_inside.png"
run_demo gen, "input1.not_inside(input2)", "drc_not_inside.png"
run_demo gen, "input1.outside(input2)", "drc_outside.png"
run_demo gen, "input1.not_outside(input2)", "drc_not_outside.png"
run_demo gen, "input1.interacting(input2)", "drc_interacting.png"
run_demo gen, "input1.not_interacting(input2)", "drc_not_interacting.png"
run_demo gen, "input1.overlapping(input2)", "drc_overlapping.png"
run_demo gen, "input1.not_overlapping(input2)", "drc_not_overlapping.png"
run_demo gen, "input1.and(input2)", "drc_and1.png"
run_demo gen, "input1.or(input2)", "drc_or1.png"
run_demo gen, "input1.xor(input2)", "drc_xor1.png"
run_demo gen, "input1.not(input2)", "drc_not1.png"
run_demo gen, "input1.join(input2)", "drc_join1.png"
run_demo gen, "input1.edges.and(input2.edges)", "drc_and2.png"
run_demo gen, "input1.edges.or(input2.edges)", "drc_or2.png"
run_demo gen, "input1.edges.xor(input2.edges)", "drc_xor2.png"
run_demo gen, "input1.edges.not(input2.edges)", "drc_not2.png"
run_demo gen, "input1.edges.join(input2.edges)", "drc_join2.png"
run_demo gen, "input1.edges.and(input2)", "drc_and3.png"
run_demo gen, "input1.edges.not(input2)", "drc_not3.png"
run_demo gen, "input1.edges.inside_part(input2)", "drc_inside_part.png"
run_demo gen, "input1.edges.outside_part(input2)", "drc_outside_part.png"
class Gen
def produce(s1, s2)
s1.insert(RBA::Box::new(0, 1000, 2000, 3000))
s1.insert(RBA::Box::new(4000, 1000, 6000, 3000))
s1.insert(RBA::Box::new(4000, 5000, 6000, 7000))
s1.insert(RBA::Box::new(0, 4000, 2000, 6000))
s2.insert(RBA::Box::new(4000, 1000, 6000, 3000))
s2.insert(RBA::Box::new(1000, 0, 3000, 2000))
end
end
gen = Gen::new
run_demo gen, "input1.in(input2)", "drc_in.png"
run_demo gen, "input1.not_in(input2)", "drc_not_in.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(0, 0),
RBA::Point::new(0, 4000),
RBA::Point::new(2000, 4000),
RBA::Point::new(2000, 7000),
RBA::Point::new(6000, 7000),
RBA::Point::new(6000, 0)
];
h1 = [
RBA::Point::new(1000, 1000),
RBA::Point::new(1000, 3000),
RBA::Point::new(3000, 3000),
RBA::Point::new(3000, 1000)
];
h2 = [
RBA::Point::new(3000, 4000),
RBA::Point::new(3000, 6000),
RBA::Point::new(5000, 6000),
RBA::Point::new(5000, 4000)
];
poly = RBA::Polygon::new(pts)
poly.insert_hole(h1)
poly.insert_hole(h2)
s1.insert(poly)
end
end
gen = Gen::new
run_demo gen, "input.hulls", "drc_hulls.png"
run_demo gen, "input.holes", "drc_holes.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(1000, 1000),
RBA::Point::new(4000, 1000),
RBA::Point::new(4000, 3000),
RBA::Point::new(1000, 3000)
];
s1.insert(RBA::Polygon::new(pts))
pts = [
RBA::Point::new(0, 0),
RBA::Point::new(0, 5000),
RBA::Point::new(3000, 5000),
RBA::Point::new(3000, 0)
];
s1.insert(RBA::Polygon::new(pts))
pts = [
RBA::Point::new(2000, 2000),
RBA::Point::new(6000, 2000),
RBA::Point::new(6000, 7000),
RBA::Point::new(2000, 7000)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input.merged", "drc_merged1.png"
run_demo gen, "input.merged(1)", "drc_merged2.png"
run_demo gen, "input.merged(2)", "drc_merged3.png"
run_demo gen, "input.merged(3)", "drc_merged4.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(3000, 0),
RBA::Point::new(3000, 2000),
RBA::Point::new(5000, 2000),
RBA::Point::new(5000, 6000),
RBA::Point::new(6000, 6000),
RBA::Point::new(6000, 0)
];
s1.insert(RBA::Polygon::new(pts))
pts = [
RBA::Point::new(1000, 3000),
RBA::Point::new(4000, 3000),
RBA::Point::new(4000, 4000),
RBA::Point::new(2000, 4000),
RBA::Point::new(2000, 7000),
RBA::Point::new(1000, 7000)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input.moved(-1.5.um, 0.5.um)", "drc_moved1.png"
run_demo gen, "input.rotated(15)", "drc_rotated1.png"
run_demo gen, "input.scaled(0.75)", "drc_scaled1.png"
run_demo gen, "t = RBA::DCplxTrans::new(0.75, 180.0, true, 7.0, 1.0)\ninput.transformed(t)", "drc_transformed1.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(2000, 1000),
RBA::Point::new(2000, 1000),
RBA::Point::new(4000, 5000),
RBA::Point::new(4000, 1000)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input.sized(1.um)", "drc_sized1.png"
run_demo gen, "input.sized(1.5.um, 0.5.um)", "drc_sized2.png"
run_demo gen, "input.sized(1.um, diamond_limit)", "drc_sized3.png"
run_demo gen, "input.sized(1.um, octagon_limit)", "drc_sized4.png"
run_demo gen, "input.sized(1.um, square_limit)", "drc_sized5.png"
run_demo gen, "input.sized(1.um, acute_limit)", "drc_sized6.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(0, 0),
RBA::Point::new(0, 1000),
RBA::Point::new(4000, 5000),
RBA::Point::new(4000, 7000),
RBA::Point::new(6000, 5000),
RBA::Point::new(6000, 0),
RBA::Point::new(5000, 0),
RBA::Point::new(5000, 4000),
RBA::Point::new(1000, 0)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input.edges.with_angle(45.degree)", "drc_with_angle1.png"
run_demo gen, "h = input.edges.with_angle(0)\nv = input.edges.with_angle(90)\n(h + v)", "drc_with_angle2.png"
run_demo gen, "input.with_angle(45.degree)", "drc_with_angle3.png"
run_demo gen, "input.without_angle(45.1.degree, 315.degree)", "drc_with_angle4.png"
class Gen
def produce(s1, s2)
pts = [
RBA::Point::new(0, 0),
RBA::Point::new(0, 7000),
RBA::Point::new(1000, 7000),
RBA::Point::new(1000, 1000),
RBA::Point::new(5000, 1000),
RBA::Point::new(5000, 7000),
RBA::Point::new(6000, 7000),
RBA::Point::new(6000, 0)
];
s1.insert(RBA::Polygon::new(pts))
end
end
gen = Gen::new
run_demo gen, "input.rounded_corners(1.um, 2.um, 16)", "drc_rounded_corners.png"

267
scripts/extract_doc.rb Executable file
View File

@ -0,0 +1,267 @@
#!/usr/bin/ruby
$script_call = $0 + " " + ARGV.join(" ")
$key="%DRC%"
$infile="src/lay/built_in_macros/drc.lym"
$loc = "about/drc_ref"
$outfiles="src/lay/doc"
$title="DRC Reference"
def create_ref(s)
if s =~ /(.*)#(.*)/
"<a href=\"/" + $loc + "_" + $1.downcase + ".xml#" + $2 + "\">#{s}</a>"
else
"<a href=\"#" + s + "\">#{s}</a>"
end
end
def create_class_doc_ref(s)
"<class_doc href=\"" + s + "\">#{s}</class_doc>"
end
def escape(s)
s.gsub("&", "&amp;").
gsub("<", "&lt;").
gsub(">", "&gt;").
gsub(/\\([\w#]+)/) { create_ref($1) }.
gsub(/RBA::([\w#]+)/) { create_class_doc_ref($1) }
end
def unescape(s)
s.gsub("&amp;", "&").gsub("&lt;", "<").gsub("&gt;", ">")
end
class DocItem
attr_accessor :brief
attr_accessor :synopsis
attr_accessor :name
attr_accessor :doc
def initialize(block)
@paragraphs = []
para = nil
self.synopsis = []
in_code = false
block.each do |b|
if in_code
if b =~ /@\/code/
in_code = false
end
para.push(b)
elsif b =~ /^@brief\s+(.*?)\s*$/
self.brief = $1
elsif b =~ /^@name\s+(.*?)\s*$/
self.name = $1
elsif b =~ /^@synopsis\s+(.*?)\s*$/
self.synopsis.push($1)
elsif b =~ /^@scope/
# ignore scope commands
elsif b =~ /^\s*$/
para && @paragraphs.push(para)
para = nil
else
para ||= []
para.push(b)
if b =~ /@code/
in_code = true
end
end
end
para && @paragraphs.push(para)
end
def produce_doc
if @paragraphs.empty?
return ""
end
doc = "<p>\n"
@paragraphs.each_with_index do |p, i|
i > 0 && doc += "</p><p>\n"
p.each do |pp|
doc += escape(pp).
gsub(/\\@/, "&at;").
gsub(/\s*@code\s*/, "<pre>").
gsub(/\s*@\/code\s*/, "</pre>").
gsub(/\s*@img\((.*)\)\s*/) { "<img src=\"" + $1 + "\"/>" }.
gsub(/\s*@\/img\s*/, "</img>").
gsub(/\s*@(\w+)\s*/) { "<" + $1 + ">" }.
gsub(/\s*@\/(\w+)\s*/) { "</" + $1 + ">" }.
gsub(/&at;/, "@")
doc += "\n"
end
end
doc += "</p>\n"
end
end
class Scope < DocItem
def initialize(block)
super(block)
@items = {}
end
def add_doc_item(block)
item = DocItem::new(block)
@items[item.name] = item
end
alias :super_produce_doc :produce_doc
def produce_doc
doc = <<HEAD
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
<!-- generated by #{$script_call} -->
<!-- DO NOT EDIT! -->
HEAD
doc += "<doc>\n"
doc += "<title>" + escape(self.brief) + "</title>\n"
doc += "<keyword name=\"" + escape(self.name) + "\"/>\n"
doc += super_produce_doc
doc += "<h2-index/>\n"
@items.keys.sort.each do |item_key|
item = @items[item_key]
item.name || raise("Missing @name for item #{item_key}")
item.brief || raise("Missing @brief for item #{item_key}")
doc += "<h2>\"" + escape(item.name) + "\" - " + escape(item.brief) + "</h2>\n"
doc += "<keyword name=\"" + escape(item.name) + "\"/>\n"
doc += "<a name=\"" + escape(item.name) + "\"/>"
if ! item.synopsis.empty?
doc += "<p>Usage:</p>\n"
doc += "<ul>\n"
item.synopsis.each do |s|
doc += "<li><tt>" + escape(s) + "</tt></li>\n"
end
doc += "</ul>\n"
end
doc += item.produce_doc
end
doc += "</doc>\n"
doc
end
end
class Collector
def add_block(block)
if block.find { |l| l =~ /^@scope/ }
# is a scope block
@scopes ||= {}
@current_scope = Scope::new(block)
@scopes[@current_scope.name] = @current_scope
else
@current_scope && @current_scope.add_doc_item(block)
end
end
def produce_doc
@scopes.keys.sort.each do |k|
suffix = k.downcase
outfile = $outfiles + "/" + $loc + "_" + suffix + ".xml"
File.open(outfile, "w") do |file|
file.write(@scopes[k].produce_doc)
puts "---> #{outfile} written."
end
end
end
def produce_index
outfile = $outfiles + "/" + $loc + ".xml"
File.open(outfile, "w") do |file|
doc = <<HEAD
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
<!-- generated by #{$script_call} -->
<!-- DO NOT EDIT! -->
HEAD
doc += "<doc>\n"
doc += "<title>#{escape($title)}</title>\n"
doc += "<topics>\n"
@scopes.keys.sort.each do |k|
suffix = k.downcase
doc += "<topic href=\"/#{$loc}_#{suffix}.xml\"/>\n"
end
doc += "</topics>\n"
doc += "</doc>\n"
file.write(doc)
end
puts "---> Index file #{outfile} written."
end
end
collector = Collector::new
File.open($infile, "r") do |file|
block = nil
file.each_line do |l|
l = unescape(l)
if l =~ /^\s*#\s*#{$key}/
block = []
elsif l =~ /^\s*#\s*(.*)\s*$/
block && block.push($1)
elsif l =~ /^\s*$/
block && collector.add_block(block)
block = nil
end
end
end
collector.produce_doc
collector.produce_index

File diff suppressed because one or more lines are too long

14
scripts/make_drc_doc.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh -e
inst=$(realpath $(dirname $0))
ld=$(realpath .)
bin="$ld/klayout"
export LD_LIBRARY_PATH=$ld
cd $inst/..
$bin -z -r $inst/create_drc_samples.rb -t -c $inst/klayoutrc_drc_samples
$inst/extract_doc.rb

View File

@ -805,16 +805,16 @@ CODE
# @name texts
# @brief Selects texts from an original layer
# @synopsis layer.texts
# @synopsis layer.texts(text)
# @synopsis layer.texts(text, true)
# @synopsis layer.texts(text, false)
# @synopsis layer.texts(pattern)
# @synopsis layer.texts(pattern, true)
# @synopsis layer.texts(string, false)
# This method can be applied to original layers - i.e. ones that have
# been created with \input. It will produce a small box (2x2 DBU) on each
# selected texts.
# selected text.
#
# Texts can be selected either by exact match or pattern match with a
# Texts can be selected either by exact match string or a pattern match with a
# glob-style pattern. The second argument selects pattern style (true)
# or exact match (false).
# or exact match (false). The default is pattern match.
#
# @code
# # Selects all texts
@ -2666,17 +2666,18 @@ CODE
# %DRC%
# @name output
# @brief Output the content of the layer
# @brief Outputs the content of the layer
# @synopsis layer.output(specs)
#
# This method will output the content of the layer to the specified output.
# This method will copy the content of the layer to the specified output.
#
# If a report database is selected for the output, the specification has to include a
# category name and optionally a category description.
#
# If the layout is selected for the output, the specification can consist of
# one to three parameters: a layer number, a data type (optional, default is 0)
# and a layer name (optional).
# and a layer name (optional). Alternatively, the output can be specified by
# a single RBA::LayerInfo object.
#
# See \global#report and \global#target on how to configure output to a target layout
# or report database.
@ -2987,10 +2988,12 @@ CODE
# @brief Specifies input from a source
# @synopsis source.input(layer)
# @synopsis source.input(layer, datatype)
# @synopsis source.input(layer_into)
# @synopsis source.input(filter, ...)
# Creates a layer with the shapes from the given layer of the source.
# The layer can be specified by layer and optionally datatype or by
# a sequence of filters. Filters are expressions describing ranges
# The layer can be specified by layer and optionally datatype, by a RBA::LayerInfo
# object or by a sequence of filters.
# Filters are expressions describing ranges
# of layers and/or datatype numbers or layer names. Multiple filters
# can be given and all layers matching at least one of these filter
# expressions are joined to render the input layer for the DRC engine.
@ -3015,6 +3018,11 @@ CODE
li &amp;&amp; layers.push(li)
li &amp;&amp; @tmp_layers.push(li)
elsif (args.size == 1 &amp;&amp; args[0].is_a?(RBA::LayerInfo))
li = @layout.find_layer(args[0])
li &amp;&amp; layers.push(li)
elsif (args.size == 1 || args.size == 2) &amp;&amp; args[0].is_a?(1.class)
li = @layout.find_layer(args[0], args[1] || 0)
@ -3041,6 +3049,31 @@ CODE
end
# %DRC%
# @name layers
# @brief Gets the layers the source contains
# @synopsis source.layers
# Delivers a list of RBA::LayerInfo objects representing the layers
# inside the source.
#
# One application is to read all layers from a source. In the following
# example, the "and" operation is used to perform a clip with the given
# rectangle. Note that this solution is not efficient - it's provided
# as an example only:
#
# @code
# output_cell("Clipped")
#
# clip_box = polygon_layer
# clip_box.insert(box(0.um, -4.um, 4.um, 0.um))
#
# layers.each { |l| (input(l) &amp; clip_box).output(l) }
# @/code
def layers
@layout.layer_indices.collect { |li| @layout.get_info(li) }
end
end
# The DRC engine
@ -3772,6 +3805,16 @@ CODE
layer.output(*args)
end
# %DRC%
# @name layers
# @brief Gets the layers contained in the default source
# @synopsis layers
# See \Source#layers for a description of that function.
def layers
layout.layers
end
# %DRC%
# @name cell
# @brief Selects a cell for input on the default source
@ -4172,6 +4215,8 @@ CODE
if args.size == 1
if args[0].is_a?(1.class)
info = RBA::LayerInfo::new(args[0], 0)
elsif args[0].is_a?(RBA::LayerInfo)
info = args[0]
elsif args[0].is_a?(String)
info = RBA::LayerInfo::from_string(args[0])
else

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
<!-- generated by ./scripts/extract_doc.rb -->
<!-- generated by /home/matthias/klayout/master/scripts/extract_doc.rb -->
<!-- DO NOT EDIT! -->
<doc>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
<!-- generated by ./scripts/extract_doc.rb -->
<!-- generated by /home/matthias/klayout/master/scripts/extract_doc.rb -->
<!-- DO NOT EDIT! -->
<doc>
@ -152,6 +152,15 @@ See <a href="/about/drc_ref_source.xml#input">Source#input</a> for a description
<ul>
<li><tt>is_tiled?</tt></li>
</ul>
<h2>"layers" - Gets the layers contained in the default source</h2>
<keyword name="layers"/>
<a name="layers"/><p>Usage:</p>
<ul>
<li><tt>layers</tt></li>
</ul>
<p>
See <a href="/about/drc_ref_source.xml#layers">Source#layers</a> for a description of that function.
</p>
<h2>"layout" - Specifies an additional layout for the input source.</h2>
<keyword name="layout"/>
<a name="layout"/><p>Usage:</p>
@ -339,7 +348,7 @@ is used as input.
<ul>
<li>A string "@n" specifying input from a layout in the current panel</li>
<li>A layout filename plus an optional cell name</li>
<li>A <class_doc href="Layout">Layout</class_doc> object</li>
<li>A <class_doc href="Layout">Layout</class_doc> object plus an optional cell name</li>
<li>A <class_doc href="Cell">Cell</class_doc> object</li>
</ul>
</p><p>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
<!-- generated by ./scripts/extract_doc.rb -->
<!-- generated by /home/matthias/klayout/master/scripts/extract_doc.rb -->
<!-- DO NOT EDIT! -->
<doc>
@ -960,21 +960,22 @@ on polygons and egdes (layer1: red, layer2: blue):
</tr>
</table>
</p>
<h2>"output" - Output the content of the layer</h2>
<h2>"output" - Outputs the content of the layer</h2>
<keyword name="output"/>
<a name="output"/><p>Usage:</p>
<ul>
<li><tt>layer.output(specs)</tt></li>
</ul>
<p>
This method will output the content of the layer to the specified output.
This method will copy the content of the layer to the specified output.
</p><p>
If a report database is selected for the output, the specification has to include a
category name and optionally a category description.
</p><p>
If the layout is selected for the output, the specification can consist of
one to three parameters: a layer number, a data type (optional, default is 0)
and a layer name (optional).
and a layer name (optional). Alternatively, the output can be specified by
a single <class_doc href="LayerInfo">LayerInfo</class_doc> object.
</p><p>
See <a href="/about/drc_ref_global.xml#report">global#report</a> and <a href="/about/drc_ref_global.xml#target">global#target</a> on how to configure output to a target layout
or report database.
@ -1211,6 +1212,9 @@ The circles are approximated by polygons. "n" segments are used to approximate a
</p><p>
This method return a layer wit the modified polygons. Merged semantics applies for this
method (see <a href="#raw">raw</a> and <a href="#clean">clean</a>).
If used with tiling, the rounded_corners function may render invalid results because
in tiling mode, not the whole merged region may be captured. In that case, inner
edges may appear as outer ones and their corners will receive rounding.
</p><p>
The following image shows the effect of the "rounded_corners" method. The upper ends of
the vertical bars are rounded with a smaller radius automatically because their width does not allow
@ -1499,6 +1503,20 @@ The following images show the effect of various forms of the "sized" method:
</tr>
</table>
</p>
<h2>"smoothed" - Smoothes the polygons of the region</h2>
<keyword name="smoothed"/>
<a name="smoothed"/><p>Usage:</p>
<ul>
<li><tt>layer.smoothed(d)</tt></li>
</ul>
<p>
"Smoothing" returns a simplified version of the polygons. Simplification is
achieved by removing vertices unless the resulting polygon deviates by more
than the given distance d from the original polygon.
</p><p>
This method return a layer wit the modified polygons. Merged semantics applies for this
method (see <a href="#raw">raw</a> and <a href="#clean">clean</a>).
</p>
<h2>"snap" - Brings each vertex on the given grid (g or gx/gy for x or y direction)</h2>
<keyword name="snap"/>
<a name="snap"/><p>Usage:</p>
@ -1614,6 +1632,34 @@ See <a href="#strict">strict</a> for a discussion of strict handling.
</p><p>
This feature has been introduced in version 0.23.2.
</p>
<h2>"texts" - Selects texts from an original layer</h2>
<keyword name="texts"/>
<a name="texts"/><p>Usage:</p>
<ul>
<li><tt>layer.texts</tt></li>
<li><tt>layer.texts(pattern)</tt></li>
<li><tt>layer.texts(pattern, true)</tt></li>
<li><tt>layer.texts(string, false)</tt></li>
</ul>
<p>
This method can be applied to original layers - i.e. ones that have
been created with <a href="#input">input</a>. It will produce a small box (2x2 DBU) on each
selected text.
</p><p>
Texts can be selected either by exact match string or a pattern match with a
glob-style pattern. The second argument selects pattern style (true)
or exact match (false). The default is pattern match.
</p><p>
<pre>
# Selects all texts
t = input(1, 0).texts
# Selects all texts beginning with an "A"
t = input(1, 0).texts("A*")
t = input(1, 0).texts("A*", true)
# Selects all texts whose string is "A*"
t = input(1, 0).texts("A*", false)
</pre>
</p>
<h2>"transform" - Transforms a layer (modifies the layer)</h2>
<keyword name="transform"/>
<a name="transform"/><p>Usage:</p>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
<!-- generated by ./scripts/extract_doc.rb -->
<!-- generated by /home/matthias/klayout/master/scripts/extract_doc.rb -->
<!-- DO NOT EDIT! -->
<doc>
@ -73,12 +73,14 @@ inverse_1 = extent.sized(100.0) - input(1, 0)
<ul>
<li><tt>source.input(layer)</tt></li>
<li><tt>source.input(layer, datatype)</tt></li>
<li><tt>source.input(layer_into)</tt></li>
<li><tt>source.input(filter, ...)</tt></li>
</ul>
<p>
Creates a layer with the shapes from the given layer of the source.
The layer can be specified by layer and optionally datatype or by
a sequence of filters. Filters are expressions describing ranges
The layer can be specified by layer and optionally datatype, by a <class_doc href="LayerInfo">LayerInfo</class_doc>
object or by a sequence of filters.
Filters are expressions describing ranges
of layers and/or datatype numbers or layer names. Multiple filters
can be given and all layers matching at least one of these filter
expressions are joined to render the input layer for the DRC engine.
@ -93,6 +95,30 @@ Some filter expressions are:
not have names)</li>
</ul>
</p>
<h2>"layers" - Gets the layers the source contains</h2>
<keyword name="layers"/>
<a name="layers"/><p>Usage:</p>
<ul>
<li><tt>source.layers</tt></li>
</ul>
<p>
Delivers a list of <class_doc href="LayerInfo">LayerInfo</class_doc> objects representing the layers
inside the source.
</p><p>
One application is to read all layers from a source. In the following
example, the "and" operation is used to perform a clip with the given
rectangle. Note that this solution is not efficient - it's provided
as an example only:
</p><p>
<pre>
output_cell("Clipped")
clip_box = polygon_layer
clip_box.insert(box(0.um, -4.um, 4.um, 0.um))
layers.each { |l| (input(l) &amp; clip_box).output(l) }
</pre>
</p>
<h2>"layout" - Returns the <class_doc href="Layout">Layout</class_doc> object associated with this source</h2>
<keyword name="layout"/>
<a name="layout"/><p>Usage:</p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -1,4 +1,6 @@
big_tests = false
verbose(true)
source(File.dirname(__FILE__) + "/drctest.gds", "TOPTOP")
@ -23,11 +25,15 @@ def run_testsuite(dm, ic, tiled = false)
lb = 100
a = input(1)
a = input(RBA::LayerInfo::new(1, 0))
b = input(2)
c = input(3)
x = input(10)
y = input(11)
h = {}
layers.each { |l| h[l] = true }
h[RBA::LayerInfo::new(1, 0)] || raise("missing layer 1/0 in layers list")
c.is_merged? == false || raise("unexpected value")
@ -40,7 +46,7 @@ def run_testsuite(dm, ic, tiled = false)
a.and(b).xor(l1).is_empty? || raise("xor not empty")
tiled || (a.and(b).is_merged? == true || raise("unexpected value"))
a.xor(b).output(lb + 1, dm)
a.xor(b).output(RBA::LayerInfo::new(lb + 1, dm))
a.xor(b).xor(a ^ b).is_empty? || raise("xor not empty")
a.not(b).output(lb + 2, dm)
a.not(b).xor(a - b).is_empty? || raise("xor not empty")

View File

@ -4,7 +4,7 @@
inst=$(dirname $0)
export LD_LIBRARY_PATH=.
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
make klayout