Implemented LayerInfo for DRC input/output
- Added a "layers" function too - Updated tests - Updated documentation
|
|
@ -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"
|
||||||
|
|
||||||
|
|
@ -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("&", "&").
|
||||||
|
gsub("<", "<").
|
||||||
|
gsub(">", ">").
|
||||||
|
gsub(/\\([\w#]+)/) { create_ref($1) }.
|
||||||
|
gsub(/RBA::([\w#]+)/) { create_class_doc_ref($1) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def unescape(s)
|
||||||
|
s.gsub("&", "&").gsub("<", "<").gsub(">", ">")
|
||||||
|
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
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
@ -805,16 +805,16 @@ CODE
|
||||||
# @name texts
|
# @name texts
|
||||||
# @brief Selects texts from an original layer
|
# @brief Selects texts from an original layer
|
||||||
# @synopsis layer.texts
|
# @synopsis layer.texts
|
||||||
# @synopsis layer.texts(text)
|
# @synopsis layer.texts(pattern)
|
||||||
# @synopsis layer.texts(text, true)
|
# @synopsis layer.texts(pattern, true)
|
||||||
# @synopsis layer.texts(text, false)
|
# @synopsis layer.texts(string, false)
|
||||||
# This method can be applied to original layers - i.e. ones that have
|
# 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
|
# 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)
|
# glob-style pattern. The second argument selects pattern style (true)
|
||||||
# or exact match (false).
|
# or exact match (false). The default is pattern match.
|
||||||
#
|
#
|
||||||
# @code
|
# @code
|
||||||
# # Selects all texts
|
# # Selects all texts
|
||||||
|
|
@ -2666,17 +2666,18 @@ CODE
|
||||||
|
|
||||||
# %DRC%
|
# %DRC%
|
||||||
# @name output
|
# @name output
|
||||||
# @brief Output the content of the layer
|
# @brief Outputs the content of the layer
|
||||||
# @synopsis layer.output(specs)
|
# @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
|
# If a report database is selected for the output, the specification has to include a
|
||||||
# category name and optionally a category description.
|
# category name and optionally a category description.
|
||||||
#
|
#
|
||||||
# If the layout is selected for the output, the specification can consist of
|
# 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)
|
# 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
|
# See \global#report and \global#target on how to configure output to a target layout
|
||||||
# or report database.
|
# or report database.
|
||||||
|
|
@ -2987,10 +2988,12 @@ CODE
|
||||||
# @brief Specifies input from a source
|
# @brief Specifies input from a source
|
||||||
# @synopsis source.input(layer)
|
# @synopsis source.input(layer)
|
||||||
# @synopsis source.input(layer, datatype)
|
# @synopsis source.input(layer, datatype)
|
||||||
|
# @synopsis source.input(layer_into)
|
||||||
# @synopsis source.input(filter, ...)
|
# @synopsis source.input(filter, ...)
|
||||||
# Creates a layer with the shapes from the given layer of the source.
|
# 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
|
# The layer can be specified by layer and optionally datatype, by a RBA::LayerInfo
|
||||||
# a sequence of filters. Filters are expressions describing ranges
|
# object or by a sequence of filters.
|
||||||
|
# Filters are expressions describing ranges
|
||||||
# of layers and/or datatype numbers or layer names. Multiple filters
|
# of layers and/or datatype numbers or layer names. Multiple filters
|
||||||
# can be given and all layers matching at least one of these filter
|
# 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.
|
# expressions are joined to render the input layer for the DRC engine.
|
||||||
|
|
@ -3015,6 +3018,11 @@ CODE
|
||||||
li && layers.push(li)
|
li && layers.push(li)
|
||||||
li && @tmp_layers.push(li)
|
li && @tmp_layers.push(li)
|
||||||
|
|
||||||
|
elsif (args.size == 1 && args[0].is_a?(RBA::LayerInfo))
|
||||||
|
|
||||||
|
li = @layout.find_layer(args[0])
|
||||||
|
li && layers.push(li)
|
||||||
|
|
||||||
elsif (args.size == 1 || args.size == 2) && args[0].is_a?(1.class)
|
elsif (args.size == 1 || args.size == 2) && args[0].is_a?(1.class)
|
||||||
|
|
||||||
li = @layout.find_layer(args[0], args[1] || 0)
|
li = @layout.find_layer(args[0], args[1] || 0)
|
||||||
|
|
@ -3041,6 +3049,31 @@ CODE
|
||||||
|
|
||||||
end
|
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) & clip_box).output(l) }
|
||||||
|
# @/code
|
||||||
|
|
||||||
|
def layers
|
||||||
|
@layout.layer_indices.collect { |li| @layout.get_info(li) }
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# The DRC engine
|
# The DRC engine
|
||||||
|
|
@ -3772,6 +3805,16 @@ CODE
|
||||||
layer.output(*args)
|
layer.output(*args)
|
||||||
end
|
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%
|
# %DRC%
|
||||||
# @name cell
|
# @name cell
|
||||||
# @brief Selects a cell for input on the default source
|
# @brief Selects a cell for input on the default source
|
||||||
|
|
@ -4172,6 +4215,8 @@ CODE
|
||||||
if args.size == 1
|
if args.size == 1
|
||||||
if args[0].is_a?(1.class)
|
if args[0].is_a?(1.class)
|
||||||
info = RBA::LayerInfo::new(args[0], 0)
|
info = RBA::LayerInfo::new(args[0], 0)
|
||||||
|
elsif args[0].is_a?(RBA::LayerInfo)
|
||||||
|
info = args[0]
|
||||||
elsif args[0].is_a?(String)
|
elsif args[0].is_a?(String)
|
||||||
info = RBA::LayerInfo::from_string(args[0])
|
info = RBA::LayerInfo::from_string(args[0])
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
<!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! -->
|
<!-- DO NOT EDIT! -->
|
||||||
|
|
||||||
<doc>
|
<doc>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
<!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! -->
|
<!-- DO NOT EDIT! -->
|
||||||
|
|
||||||
<doc>
|
<doc>
|
||||||
|
|
@ -152,6 +152,15 @@ See <a href="/about/drc_ref_source.xml#input">Source#input</a> for a description
|
||||||
<ul>
|
<ul>
|
||||||
<li><tt>is_tiled?</tt></li>
|
<li><tt>is_tiled?</tt></li>
|
||||||
</ul>
|
</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>
|
<h2>"layout" - Specifies an additional layout for the input source.</h2>
|
||||||
<keyword name="layout"/>
|
<keyword name="layout"/>
|
||||||
<a name="layout"/><p>Usage:</p>
|
<a name="layout"/><p>Usage:</p>
|
||||||
|
|
@ -339,7 +348,7 @@ is used as input.
|
||||||
<ul>
|
<ul>
|
||||||
<li>A string "@n" specifying input from a layout in the current panel</li>
|
<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 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>
|
<li>A <class_doc href="Cell">Cell</class_doc> object</li>
|
||||||
</ul>
|
</ul>
|
||||||
</p><p>
|
</p><p>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
<!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! -->
|
<!-- DO NOT EDIT! -->
|
||||||
|
|
||||||
<doc>
|
<doc>
|
||||||
|
|
@ -960,21 +960,22 @@ on polygons and egdes (layer1: red, layer2: blue):
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</p>
|
</p>
|
||||||
<h2>"output" - Output the content of the layer</h2>
|
<h2>"output" - Outputs the content of the layer</h2>
|
||||||
<keyword name="output"/>
|
<keyword name="output"/>
|
||||||
<a name="output"/><p>Usage:</p>
|
<a name="output"/><p>Usage:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><tt>layer.output(specs)</tt></li>
|
<li><tt>layer.output(specs)</tt></li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<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>
|
</p><p>
|
||||||
If a report database is selected for the output, the specification has to include a
|
If a report database is selected for the output, the specification has to include a
|
||||||
category name and optionally a category description.
|
category name and optionally a category description.
|
||||||
</p><p>
|
</p><p>
|
||||||
If the layout is selected for the output, the specification can consist of
|
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)
|
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>
|
</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
|
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.
|
or report database.
|
||||||
|
|
@ -1211,6 +1212,9 @@ The circles are approximated by polygons. "n" segments are used to approximate a
|
||||||
</p><p>
|
</p><p>
|
||||||
This method return a layer wit the modified polygons. Merged semantics applies for this
|
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>).
|
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>
|
</p><p>
|
||||||
The following image shows the effect of the "rounded_corners" method. The upper ends of
|
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
|
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>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</p>
|
</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>
|
<h2>"snap" - Brings each vertex on the given grid (g or gx/gy for x or y direction)</h2>
|
||||||
<keyword name="snap"/>
|
<keyword name="snap"/>
|
||||||
<a name="snap"/><p>Usage:</p>
|
<a name="snap"/><p>Usage:</p>
|
||||||
|
|
@ -1614,6 +1632,34 @@ See <a href="#strict">strict</a> for a discussion of strict handling.
|
||||||
</p><p>
|
</p><p>
|
||||||
This feature has been introduced in version 0.23.2.
|
This feature has been introduced in version 0.23.2.
|
||||||
</p>
|
</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>
|
<h2>"transform" - Transforms a layer (modifies the layer)</h2>
|
||||||
<keyword name="transform"/>
|
<keyword name="transform"/>
|
||||||
<a name="transform"/><p>Usage:</p>
|
<a name="transform"/><p>Usage:</p>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE language SYSTEM "klayout_doc.dtd">
|
<!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! -->
|
<!-- DO NOT EDIT! -->
|
||||||
|
|
||||||
<doc>
|
<doc>
|
||||||
|
|
@ -73,12 +73,14 @@ inverse_1 = extent.sized(100.0) - input(1, 0)
|
||||||
<ul>
|
<ul>
|
||||||
<li><tt>source.input(layer)</tt></li>
|
<li><tt>source.input(layer)</tt></li>
|
||||||
<li><tt>source.input(layer, datatype)</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>
|
<li><tt>source.input(filter, ...)</tt></li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
Creates a layer with the shapes from the given layer of the source.
|
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
|
The layer can be specified by layer and optionally datatype, by a <class_doc href="LayerInfo">LayerInfo</class_doc>
|
||||||
a sequence of filters. Filters are expressions describing ranges
|
object or by a sequence of filters.
|
||||||
|
Filters are expressions describing ranges
|
||||||
of layers and/or datatype numbers or layer names. Multiple filters
|
of layers and/or datatype numbers or layer names. Multiple filters
|
||||||
can be given and all layers matching at least one of these filter
|
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.
|
expressions are joined to render the input layer for the DRC engine.
|
||||||
|
|
@ -93,6 +95,30 @@ Some filter expressions are:
|
||||||
not have names)</li>
|
not have names)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</p>
|
</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) & clip_box).output(l) }
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
<h2>"layout" - Returns the <class_doc href="Layout">Layout</class_doc> object associated with this source</h2>
|
<h2>"layout" - Returns the <class_doc href="Layout">Layout</class_doc> object associated with this source</h2>
|
||||||
<keyword name="layout"/>
|
<keyword name="layout"/>
|
||||||
<a name="layout"/><p>Usage:</p>
|
<a name="layout"/><p>Usage:</p>
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 3.6 KiB |
|
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
big_tests = false
|
||||||
|
|
||||||
verbose(true)
|
verbose(true)
|
||||||
|
|
||||||
source(File.dirname(__FILE__) + "/drctest.gds", "TOPTOP")
|
source(File.dirname(__FILE__) + "/drctest.gds", "TOPTOP")
|
||||||
|
|
@ -23,12 +25,16 @@ def run_testsuite(dm, ic, tiled = false)
|
||||||
|
|
||||||
lb = 100
|
lb = 100
|
||||||
|
|
||||||
a = input(1)
|
a = input(RBA::LayerInfo::new(1, 0))
|
||||||
b = input(2)
|
b = input(2)
|
||||||
c = input(3)
|
c = input(3)
|
||||||
x = input(10)
|
x = input(10)
|
||||||
y = input(11)
|
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")
|
c.is_merged? == false || raise("unexpected value")
|
||||||
|
|
||||||
puts "--- general #{lb}"
|
puts "--- general #{lb}"
|
||||||
|
|
@ -40,7 +46,7 @@ def run_testsuite(dm, ic, tiled = false)
|
||||||
a.and(b).xor(l1).is_empty? || raise("xor not empty")
|
a.and(b).xor(l1).is_empty? || raise("xor not empty")
|
||||||
tiled || (a.and(b).is_merged? == true || raise("unexpected value"))
|
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.xor(b).xor(a ^ b).is_empty? || raise("xor not empty")
|
||||||
a.not(b).output(lb + 2, dm)
|
a.not(b).output(lb + 2, dm)
|
||||||
a.not(b).xor(a - b).is_empty? || raise("xor not empty")
|
a.not(b).xor(a - b).is_empty? || raise("xor not empty")
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
inst=$(dirname $0)
|
inst=$(dirname $0)
|
||||||
|
|
||||||
export LD_LIBRARY_PATH=.
|
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
|
||||||
|
|
||||||
make klayout
|
make klayout
|
||||||
|
|
||||||
|
|
|
||||||