module Gdsii

There are two approaches to interacting with a GDSII file using this module:

  1. At the record level (low-level)

  2. At the record group level (high-level)

Approach #1

(See Record class for details)

Interaction at the record level is intended for streamlined file processing where the author has a good knowledge of the GDSII structure. A typical usage might be to streamline changes to a GDSII file such as changing bus bit characters on a node name from <> to [] format (see the samples directory of this library installation for an example). Here is a simple way to dump the all strings in a GDSII file using the Record class:

require 'gdsii'

# Note: 'rb' is required for DOS/Windows compatibility
File.open('mydesign.gds', 'rb') do |file|
  Gds::Record.read_each(file) do |record|
    puts record.data[0] if record.is_string?
  end
end

Approach #2

(See Group, Library, Structure, Element, Boundary, Path, Text, SRef, ARef, Node, and Box classes for details)

The second approach offers a high-level interface to the GDSII format which might be ideal in cases where the author may not be familiar with the details of the GDSII format. This example will write a small transistor cell:

require 'gdsii'

Gdsii::Library.new('MYLIB.DB') do |lib|

  Gdsii::Structure.new('trans') do |struct|

    # Diffusion layer
    struct.add Gdsii::Boundary.new(1, 0, [-2000,0, -2000,4000, 2000,4000, 2000,0, -2000,0])

    # Gate layer... add a property labling as "gate"
    Gdsii::Path.new(2, 0, 0, 800, [0,-600, 0,4600]) do |path|
      path.add Gdsii::Property.new(1, 'gate')
      struct.add path
    end

    # Add this structure to the library
    lib.add struct

  end

  # Write the library to a file
  lib.write('trans.gds')

end

Important notes

Look at inherited and mixed-in methods

The high-level classes in this GDSII library rely heavily upon inheritance and mixed-in modules to reduce code. When reviewing documentation, be sure to be aware of methods defined implicitly through class inheritance and through Module#include and Module#extend.

Use 'b' during R/W of files

Be sure to always use the 'b' read/write attribute when reading and writing GDSII files to ensure that read/write happens properly on DOS/Windows systems. For example (see IO#open for more details):

inf = File.open('mydesign.gds', 'rb')
outf = File.open('mydesign.gds', 'wb')

Improving performance

The low-level GDSII methods will offer significantly better GDSII read/write performance as compared to the high-level methods. For most streamlined manipulations of GDSII files, the low-level methods are probably the best option. For smaller GDSII files or when code re-use/readability is important, then the performance hit with the high-level methods may not be a concern.

Here are some benchmarks using both low and high level methods to read and immediately write a GDSII file:

High-level methods:      8m 45s    11m 23s
Low-level methods:       0m 45s     1m 29s

Constants

DATATYPE_INFO

Gdsii::DATATYPE_INFO is an array of Gdsii::RecDataTypeInfo objects. The array order is significant in that the index of the array is the value of the record data type constant. This allows easy validation lookup based upon the record data type constants. Example:

Gdsii::DATATYPE_INFO[Gdsii::GRT_REAL8].name         # => "REAL8"
Gdsii::DATATYPE_INFO[Gdsii::GRT_REAL8].valid        # => true
Gdsii::DATATYPE_INFO[Gdsii::GRT_REAL8].size         # => 8
DEF_LIB_UNITS
DEF_LIB_VERSION
FORMAT_EDSIII_ARCHIVE
FORMAT_EDSIII_FILTERED
FORMAT_GDSII_ARCHIVE

These numbers correspond to GDSII format

FORMAT_GDSII_FILTERED
GDT_ASCII
GDT_BITARRAY
GDT_INT2
GDT_INT4
GDT_NO_DATA

GDSII record data types

GDT_REAL4
GDT_REAL8
GRT_ANGLE
GRT_AREF
GRT_ATTRTABLE
GRT_BGNEXTN
GRT_BGNLIB
GRT_BGNSTR
GRT_BORDER
GRT_BOUNDARY
GRT_BOX
GRT_BOXTYPE
GRT_COLROW
GRT_CONTACT
GRT_DATATYPE
GRT_ELFLAGS
GRT_ELKEY
GRT_ENDEL
GRT_ENDEXTN
GRT_ENDLIB
GRT_ENDMASKS
GRT_ENDSTR
GRT_FONTS
GRT_FORMAT
GRT_GENERATIONS
GRT_HARDFENCE
GRT_HARDWIRE
GRT_HEADER

These are GDSII record numbers and correspond to the GDSII number in the GDSII file specification

GRT_LAYER
GRT_LIBDIRSIZE
GRT_LIBNAME
GRT_LIBSECUR
GRT_LINKKEYS
GRT_LINKTYPE
GRT_MAG
GRT_MASK
GRT_NODE
GRT_NODEPORT
GRT_NODETYPE
GRT_PATH
GRT_PATHPORT
GRT_PATHTYPE
GRT_PLEX
GRT_PRESENTATION
GRT_PROPATTR
GRT_PROPVALUE
GRT_REFLIBS
GRT_RESERVED
GRT_SNAME
GRT_SOFTFENCE
GRT_SOFTWIRE
GRT_SPACER_ERROR
GRT_SPACING
GRT_SREF
GRT_SRFNAME
GRT_STRANS
GRT_STRCLASS
GRT_STRING
GRT_STRNAME
GRT_STRTYPE
GRT_STYPTABLE
GRT_TAPECODE
GRT_TAPENUM
GRT_TEXT
GRT_TEXTNODE
GRT_TEXTTYPE
GRT_UINTEGER
GRT_UNITS
GRT_USERCONSTRAINT
GRT_USTRING
GRT_WIDTH
GRT_XY
PATHTYPE_CUSTOM
PATHTYPE_EXTEND
PATHTYPE_FLUSH
PATHTYPE_ROUND
RECORD_INFO

Gdsii::RECORD_INFO is an array of Gdsii::RecInfo objects. The array order is significant in that the index of the array is the value of the record and corresponds to the Gdsii::GRT_* constant values. This allows easy validation lookup based upon the record type constants. Example:

Gdsii::RECORD_INFO[Gdsii::GRT_HEADER].name         # => "HEADER"
Gdsii::RECORD_INFO[Gdsii::GRT_HEADER].valid        # => true
Gdsii::RECORD_INFO[Gdsii::GRT_HEADER].data_type    # => 2

Public Class Methods

gdt_name(gdt_number) click to toggle source

Returns the name for given record data type if it is found; if not, then the record data type number formatted as a String is returned

# File lib/gdsii/record/consts.rb, line 369
def gdt_name(gdt_number)
  if gdt_number.class == Fixnum
    if (0..DATATYPE_INFO.length-1).member?(gdt_number)
      DATATYPE_INFO[gdt_number].name
    else
      gdt_number.to_s
    end
  else
    gdt_number.inspect
  end
end
grt_name(grt_number) click to toggle source

Returns the name for given record type if it is found; if not, then the record number formatted as a String is returned

# File lib/gdsii/record/consts.rb, line 355
def grt_name(grt_number)
  if grt_number.class == Fixnum
    if (0..RECORD_INFO.length-1).member?(grt_number)
      RECORD_INFO[grt_number].name
    else
      grt_number.to_s
    end
  else
    grt_number.inspect
  end
end

Private Instance Methods

gdt_name(gdt_number) click to toggle source

Returns the name for given record data type if it is found; if not, then the record data type number formatted as a String is returned

# File lib/gdsii/record/consts.rb, line 369
def gdt_name(gdt_number)
  if gdt_number.class == Fixnum
    if (0..DATATYPE_INFO.length-1).member?(gdt_number)
      DATATYPE_INFO[gdt_number].name
    else
      gdt_number.to_s
    end
  else
    gdt_number.inspect
  end
end
grt_name(grt_number) click to toggle source

Returns the name for given record type if it is found; if not, then the record number formatted as a String is returned

# File lib/gdsii/record/consts.rb, line 355
def grt_name(grt_number)
  if grt_number.class == Fixnum
    if (0..RECORD_INFO.length-1).member?(grt_number)
      RECORD_INFO[grt_number].name
    else
      grt_number.to_s
    end
  else
    grt_number.inspect
  end
end