Reader LEF/DEF

edited December 2009 in File Formats
Hi Matthias,

Christmas is coming soon...

So, one thing which will be helpful, its a reader of LEF/DEF.

In a 1st step, the LEF reader, like that we will can easely verify our LEFs

I think that this topic goes w/ the other one: GDS to LEF.

Regards,
Joaquim

Comments

  • edited November -1

    Hi Joaquim,

    I received that request already a couple of times.

    However, I am lacking a good example currently. Do you have a link to a public source of LEF/DEF sample files?

    Best regards,

    Matthias

  • edited November -1
    Hi Matthias,

    for the specifications of the format (they have also a LEF/DEF Toolkit but I don't know really if you can use it):
    http://www.si2.org/openeda.si2.org/help/group_ld.php?group=6

    for a free library (you have to register but its free):
    http://www.nangate.com/index.php?option=com_content&task=view&id=137&Itemid=137

    if you need some others LEF examples or if you have questions, you can send me directly a mail if you want.

    Regards,
    Joaquim
  • edited December 2009

    Thanks for the links. I'll have a look.

    Best regards,

    Matthias

  • edited January 2010
    Will be good!
    Now I'm using simple ruby script (not universal but enough for my purposes).

    1. I run 'klayout -r script.rb';
    2. File -> Open LEF

    Script below (only for LEF observing)

    Thanks. Sergey.
    -------------------------------------

    <pre>
    # Ruby file for KLayout for work with LEF.
    # klayout -r LEF.rb
    ######################################

    $app = RBA::Application.instance
    $mw = $app.main_window

    ######################################

    class MenuHandler < RBA::Action
    def initialize( t, k, &action )
    self.title = t
    self.shortcut = k
    @action = action
    end
    def triggered
    @action.call( self )
    end
    private
    @action
    end

    ######################################

    class LEFCell
    def initialize(macro)
    @name = macro
    @bb = LEFRect.new("prBoundary", 0, 0, 0, 0)
    @pins = Array.new
    @obs = Array.new

    @cell = $layout.add_cell(@name)
    end

    def render
    @bb.draw
    @pins.each { |pin|
    pin.draw
    pin.label
    }
    @obs.each { |blockage|
    blockage.draw
    }
    end

    def name
    return @name
    end

    def pins
    return @pins
    end

    def obs
    return @obs
    end

    def cell
    return @cell
    end

    def bb(rect)
    @bb = rect
    return @bb
    end
    end

    ######################################

    class LEFRect
    def initialize(layer, x1, y1, x2, y2)
    @layer = layer
    @rect = RBA::DBox.new(x1, y1, x2, y2)
    end

    def draw
    @layer_id = 0
    @layer_tmp = @layer + ":bnd"
    if defined? self.name
    @layer_tmp = @layer + ":net"
    end
    @layer_id = $lid[@layer_tmp]
    if ! @layer_id
    @layer_id = create_layer(@layer_tmp, 0x000000, 0x0000ff, 1)
    end
    @intbox = RBA::Box.from_dbox(@rect)
    $layout.cell($cell).shapes(@layer_id).insert_box(@intbox)
    end

    def layer
    return @layer
    end

    def rect
    return @rect
    end
    end

    ######################################

    class LEFPin < LEFRect
    def initialize(name, box)
    @name = name
    @box = box

    @layer = @box.layer
    @rect = @box.rect
    end

    def label
    @orig = RBA::DTrans.new(@rect.center.x, @rect.center.y)
    @text = RBA::Text.new(@name, RBA::Trans.from_dtrans(@orig))
    # if @name =~ /vdd/
    # print "vdd ", (@rect.center.x/1000).to_s, " ", (@rect.center.y/1000).to_s, "\n"
    # end
    # if @name =~ /vss/
    # print "vss ", (@rect.center.x/1000).to_s, " ", (@rect.center.y/1000).to_s, "\n"
    # end

    @layer_id = $lid["text:net"]
    if ! @layer_id
    @layer_id = create_layer("text:net", 0xffffff, 0xffffff, 1)
    end
    $layout.cell($cell).shapes(@layer_id).insert_text(@text)
    end

    def name
    return @name
    end
    end

    ######################################

    def get_layers
    if ENV['lvlyp']
    f = $cv.load_layer_props(ENV['lvlyp'])
    l = $cv.begin_layers
    while ! l.at_end?
    l.current.name =~ /^\s*(\S+)\s*/
    $lid[$1] = l.current.source_layer_index(0)
    l.next
    end
    end
    end

    ######################################

    def create_layer(name, frame, fill, stipple)
    $lid[name] = $layout.insert_layer(RBA::LayerInfo.new)

    ln = RBA::LayerPropertiesNode::new
    ln.name = name
    ln.dither_pattern = stipple
    ln.fill_color = frame
    ln.frame_color = fill
    ln.width = 1
    ln.source_layer_index = $lid[name]
    $cv.insert_layer($cv.end_layers, ln)

    return $lid[name]
    end

    #####################################

    def parseLEF(lef)
    cellList = Array.new
    cell = 0
    layer = ""
    rect = 0
    pin_name = ""
    flag = 0
    macro = 0
    coeff = 1000
    x1 = 0
    y1 = 0
    x2 = 0
    y2 = 0
    x_origin = 0
    y_origin = 0

    lef.each { |line|
    case line
    when /^\s*DATABASE\s+MICRONS\s+(\d+)/
    coeff = $1.to_f
    flag = 0
    when /^\s*MACRO\s+(\S+)/
    macro = LEFCell.new($1)
    cellList.push(macro)
    flag = 0
    when /^\s*FOREIGN\s+\S+\s+(\S+)\s+(\S+?)\s*;/
    x1 = $1.to_f * coeff
    y1 = $2.to_f * coeff
    flag = 0
    when /^\s*ORIGIN\s+(\S+)\s+(\S+?)\s*;/
    x_origin = $1.to_f * coeff
    y_origin = $2.to_f * coeff
    flag = 0
    when /^\s*SIZE\s+(\S+)\s+BY\s+(\S+?)\s*;/
    if macro != 0
    x2 = $1.to_f * coeff - x_origin
    y2 = $2.to_f * coeff - y_origin
    macro.bb(LEFRect.new("prBoundary", x1, y1, x2, y2))
    end
    flag = 0
    when /^\s*LAYER\s+(\S+?)\s*;/
    layer = $1
    flag = flag & 3
    when /\s*RECT\s+(\S+)\s+(\S+)\s+(\S+)\s(\S+?)\s*;/
    rect = LEFRect.new(layer, ($1.to_f * coeff), ($2.to_f * coeff), ($3.to_f * coeff), ($4.to_f * coeff))
    flag = flag | 4
    when /^\s*PIN\s+(\S+)/
    pin_name = $1
    flag = 1
    when /^\s*END\s+(\S+)/
    if $1 == pin_name then flag = 0 end
    when /^\s*OBS/
    flag = 2
    when /^\s*END\s*$/
    if flag == 6 || flag == 2
    flag = 2
    elsif flag == 5
    flag = 1
    end
    else
    flag = flag & 3
    end

    # print flag.to_s, " - ", line

    case flag
    when 5
    pin = LEFPin.new(pin_name, rect)
    macro.pins.push(pin)
    # print pin_name, "\n"
    when 6
    macro.obs.push(rect)
    end
    }

    return cellList
    end

    ######################################

    def openLEF
    $clv = $mw.create_layout(0)
    $cv = $mw.current_view
    $layout = $cv.cellview(0).layout

    $lid = Hash.new
    get_layers()

    file = RBA::FileDialog.get_open_file_name("Open LEF", ".", "LEF File (*.lef *.plef)")
    if file.has_value? == false
    return
    end

    lef = IO.readlines(file.value)

    $cellList = parseLEF(lef)

    $cellList.each { |item|
    $cell = item.cell
    item.render
    }

    $cv.select_cell_path( [$cell], 0 )
    $cv.zoom_fit
    $cv.max_hier
    end

    ######################################

    menu = $mw.menu

    $open_LEF = MenuHandler.new("Open LEF", "Ctrl+Shift+L") { openLEF }
    menu.insert_item("file_menu.#2", "rba_test", $open_LEF)

    $app.exec
    </pre>
  • edited November -1
    I'm not a ruby programmer, so ... But it works!
  • edited January 2010

    How to format code?
    I have a problem with "Markdown" radio button.

    Thanks. Sergey.

  • edited January 2010

    Hi Sergey,

    Thanks for providing the script. Great job!

    Since I think it's useful for many users, I have (hopefully) restored the formatting and put it on the server. It can be downloaded here: LEF.rb.

    BTW: "Markdown" is one of those Wiki-style plain text markup languages. It's documented here. Code formatting can be achieved by indenting with 4 spaces.

    Best regards,

    Matthias

  • edited November -1
    Hi All,
    the script works very well.
    I would like to define a different color for each lef-layer when I read the .lef.
    How can I do?

    thanks,
    Salvatore
  • edited November -1
    ...other question..
    Some of my pins aren't define as RECT but :

    PIN A
    DIRECTION INPUT ;
    USE SIGNAL ;
    PORT
    LAYER M1 ;
    POLYGON 0.140 0.980 0.255 0.980 0.255 1.710 0.140 1.710 ;
    END
    END A

    In the Lef.rb script the POLYGON case doesn't exist.

    How to draw a polygon?

    Thanks,
    Salvatore
  • edited January 2010

    Hi Salvatore,

    You can specify a layer properties file to use with the LEF import script by defining an environment variable named "lvlyp". The values of this variable should be the absolute path of a layer properties file. This file will be loaded when the LEF file has been imported.

    Regarding the POLYGON problem I changed the LEF.rb script so it supports these shape types as well. I hope I didn't spoil it.

    Best regards,

    Matthias

  • edited November -1
    Hi Matthias,
    thank you, now it works for the POLYGON too but only if the POLYGON definition is on the same line
    of the .LEF.
    For example :

    PIN vdd
    DIRECTION INOUT ;
    USE POWER ;
    SHAPE ABUTMENT ;
    PORT
    LAYER M1 ;
    POLYGON 0.000 2.240 0.610 2.240 0.610 1.640 0.730 1.640
    0.730 2.240 1.945 2.240 1.945 1.610 2.085 1.610 2.085 2.240
    3.325 2.240 3.325 1.600 3.455 1.600 3.455 2.240 3.800 2.240
    3.800 2.800 0.000 2.800 ;
    END
    END vdd

    In this case the POLYGON end (;) is on a different line and so it doesn't work.

    Best regards,
    Salvatore.
  • edited January 2010

    Hi Salvatore,

    I tried to fix the script accordingly. Hopefully it's working now. The download link is the same than before (LEF.rb).

    Best regards,

    Matthias

  • edited November -1
    Hi Matthias,
    great! It's working. But there is a last issue :

    - the pin name label position is in the center of the polygon boundary box so sometime it isn't over the pin polygon.

    Thank you for your support.

    Salvatore
  • edited November -1

    Hi Salvatore,

    I tried to fix that issue by using the leftmost bottom point and putting a text close to this point (displaced by 5 DBU's). I hope that is a useful heuristics to provide a point "inside" the polygon.

    I replaced the file already. The download link remains the same.

    Best regards,

    Matthias

  • edited November -1
    Hi,

    Great script ! I have slightly modified the LEF.rb script to map the LEF layers to GDS metal layers.

    I now want to load the default "layer properties" as specified in the setup. What is the ruby code to load the default layer map file ?

    Nick
  • edited March 2010

    Hi Nick,

    I have not tested it myself yet, but this code should work:

    def get_layers
      lyr_file = RBA::Application.instance.get_config("default-layer-properties")
      if lyr_file != ""
        f = $cv.load_layer_props(lyr_file)
        l = $cv.begin_layers
        while ! l.at_end?
          l.current.name =~ /^\s*(\S+)\s*/
          $lid[$1] = l.current.source_layer_index(0)
          l.next
        end
      end
    end
    

    A more elaborate version should do some more error checking and try to resolve relative paths.

    Best regards,

    Matthias

  • edited November -1
    Hi Matthias,

    It works perfectly ! Many many thanks. If you want the new code feel free to contact me.

    Nick
Sign In or Register to comment.