DRC Radius check with perpendicalur segments

edited June 2018 in Ruby Scripting

To verify a radius I check for a notch on a polygon selecting all edges perpendicalur to each other:

GRID=0.1
IN    = input(1, 0)
IN_EDGES = IN.edges
IN_EDGE_90  = IN_EDGES.with_angle(90)
radiusInner=4.0
drc_mrk = IN_EDGE_90.notch(radiusInner*1.41421356-GRID/2)
drc_mrk.output( "Inner Radius smaller 4.0" )

I can't use an edge layer to verify a notch but I struggle to rebuild a polygon out of the extracted edges. Is the collect command to be used for it?
In addition I try to use math::sqrt(2) as a function (rather then 1.41..) - but it works only when RBA is defined. Is there a way to use the math function in a DRC deck ?

Thanks a lot,
Andy

Comments

  • Hi Andy,

    With edge layers there is no difference between space, notch and isolated because these methods act on edges depending on whether they belong to the same polygon or not. So for edge layers there is only "space".

    But I wonder if your approach is the right one: with_angle(90) will only select vertical edges. To get the horizontal ones, you'd need width_angle(0). You could then do a separation test. For the separation use an angle limit to make sure 90 perpendicular edges are included:

    r = input(1, 0).rounded_corners(0.5.um, 0.5.um, 64)
    r.output(10, 0)
    re = r.edges
    rv = re.with_angle(90)
    rh = re.with_angle(0)
    rv.output(11, 0)
    rh.output(12, 0)
    rv.sep(rh, 0.8.um, angle_limit(91)).output(20, 0)
    

  • edited June 2018

    Hello Matthias,
    thanks a lot for your feedback. The sep check provides me the same result as used in a 3rd party tool - this is great! Target was to migrate the rules into KL and the Radius check was a critical one missing. Especially the combination with the DRC browser makes KL an incredible tool for DRC checking.
    By the way - congrats to the new Forum. Now it's quite easy with a png file to describe the issue tobe solved.

    Best Regards,
    Andy

  • Here the final script to run a quick-drc:

    include RBA
    
            app = RBA::Application.instance
            mw = app.main_window
            view = mw.current_view
            cv = view.cellview(view.active_cellview_index)
            layoutView=view.active_cellview().layout()
    
    
            if !view
               raise "No view selected"
            end
    
    # pre- settings
    
            dialog = QDialog.new(Application.instance.main_window)
            dialog.windowTitle = "Quick DRC check"
    
            layout = QVBoxLayout::new(dialog)
            dialog.setLayout(layout)
    
    # separation line
            label = QLabel.new(dialog)
            layout.addWidget(label)
            label.text = "Quick DRC on SAME layer ...\n\n >> Please select at least one Layer << \n"
    
    # variable text input :
            label = QLabel.new(dialog)
            layout.addWidget(label)
            label.text = "min. width [um] (0: No check)"
            variable1 = QLineEdit.new(dialog)
            layout.addWidget(variable1)
            variable1.text = "0"
    
            label = QLabel.new(dialog)
            layout.addWidget(label)
            label.text = "min spacing [um] (0: No check)"
            variable2 = QLineEdit.new(dialog)
            layout.addWidget(variable2)
            variable2.text = "0"
    
    # separation line
            label = QLabel.new(dialog)
            layout.addWidget(label)
            label.text = "\n"
    
            label = QLabel.new(dialog)
            layout.addWidget(label)
            label.text = "Inner Radius [um] (0: No check)"
            variable4 = QLineEdit.new(dialog)
            layout.addWidget(variable4)
            variable4.text = "0"
    
    
            label = QLabel.new(dialog)
            layout.addWidget(label)
            label.text = "Outer Radius [um] (0: No check)"
            variable5 = QLineEdit.new(dialog)
            layout.addWidget(variable5)
            variable5.text = "0"
    
    
    # separation line
            label = QLabel.new(dialog)
            layout.addWidget(label)
            label.text = "\n"
    
    
    # radio buttons
            check1 = QCheckBox.new(dialog)
            layout.addWidget(check1)
            check1.text = "Speed up (tiling 1mm/1mm) 8 cores"
    
    
    # separation line
            label = QLabel.new(dialog)
            layout.addWidget(label)
            label.text = "\n"
    
    # OK button 
            buttonOK = QPushButton.new(dialog)
            layout.addWidget(buttonOK)
            buttonOK.text = " ok "
            buttonOK.clicked do 
             dialog.accept()
             myText = {}
    
    #v1 - width
    #v2 - space
    #v3 -  layer layer
    #v33 - layer datatype
    #v4 - inner radius
    #v5 - outer radius
    
    
             v1=(variable1.text).to_f
             v2=(variable2.text).to_f
             v4=(variable4.text).to_f
             v5=(variable5.text).to_f
    
    
    # get selected layers
                sel_layers = view.selected_layers
                if !sel_layers || sel_layers.size == 0
                    raise "No layer(s) selected"
                end
                myText = "report(\"DRC_Check.rpt\")\n"
    
                sel_layers.each do |l|
                    li = l.current.layer_index
                    if cv.layout.is_valid_layer?(li)
                        layer_info=layoutView.get_info(li) 
                        v3=layer_info.layer
                        v33=layer_info.datatype
                myText += "layerDRC = input(#{v3}, #{v33})\n"
                if (check1.isChecked()) 
                   myText += "tiles(1.mm, 1.mm) \n"
                   myText += "threads(8) \n"
                end
    
                if (v2>0)
                  myText += "drc_mrk = layerDRC.space(#{v2}, projection, angle_limit(90)) \n"
                  myText += "drc_mrk.output( \"Quick-DRC Same layer spacing: Layer layerDRC (#{v3},#{v33}) < #{v2} um\" ) \n"
                end
    
                if (v1>0)
                  myText += "drc_mrk = layerDRC.width(#{v1}, projection, angle_limit(90)) \n"
                  myText += "drc_mrk.output( \"Quick-DRC Layer width: Layer layerDRC (#{v3},#{v33}) < #{v2} um\" ) \n"
                end             
    
                if (v4>0)
                  myText += "layerDRC_edges = layerDRC.edges \n"
                  myText += "layerDRC_edgeV = layerDRC_edges.with_angle(90) \n"
                  myText += "layerDRC_edgeH = layerDRC_edges.with_angle(0) \n"
                  myText += "drc_mrk = layerDRC_edgeV.sep(layerDRC_edgeH, #{v4}, angle_limit(91)) \n"
                  myText += "drc_mrk.output( \"Quick-DRC Layer Inner Radius: layerDRC (#{v3},#{v33})< #{v4} um\" ) \n"
                end             
    
                if (v5>0)
                  myText += "layerDRCtmp = extent - layerDRC \n"
                  myText += "layerDRCtmp_edges = layerDRCtmp.edges \n"
                  myText += "layerDRCtmp_edgeV = layerDRCtmp_edges.with_angle(90) \n"
                  myText += "layerDRCtmp_edgeH = layerDRCtmp_edges.with_angle(0) \n"
                  myText += "drc_mrk = layerDRCtmp_edgeV.sep(layerDRCtmp_edgeH, #{v5}, angle_limit(91)) \n"
                  myText += "drc_mrk.output( \"Quick-DRC Layer Outer Radius: layerDRC (#{v3},#{v33}) < #{v5} um\" ) \n"
                end             
    
              end # end if layer vaild
            end # end selected layers    
    
                if ((v5>0)||(v4>0) ||(v2>0)||(v1>0))
                print(myText)             
                # Execute the DRC script
                eng = DRC::DRCEngine::new
                eng.instance_eval(myText)
                eng._finish
                else
                print"\n No valid vlaue to check \n"
                errorText = "Error: No valid value for DRC specified. At least one must be larger 0."
                RBA::MessageBox::info("Klayout QuickDRC", errorText, RBA::MessageBox::b_ok)
                end
    
    
        end #end press ok procedure 
    
    
    
    # cancel button
            cbutton = QPushButton.new(dialog)
            layout.addWidget(cbutton)
            cbutton.text = " Cancel "
            cbutton.clicked do 
            dialog.accept()
            end
    
    #dialog.exec
    dialog.show
    
Sign In or Register to comment.