Limbo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Limbo.Parsers.GdsiiParser

Table of Contents

Introduction

GDSII is an industry standard for data exchange of integrated circuits (IC) layout artwork. It is a binary file format representing planar geometric shapes, text labels, and other information about the layout in hierarchical form. The manual can be found in here. The parser consists of three parts, reader, writer and database for full chip parsing. GdsParser::GdsReader provides API to read GDSII files (.gds or .gds.gz with Boost and Zlib support). GdsParser::GdsWriter provides API to write GDSII files (.gds or .gds.gz with Boost and Zlib support). These two parts are basic functionalities for read and write in GDSII format. GdsParser::GdsDB is a database to store layout elements and provides easy API to read, write and flatten full layouts.

Examples

Stream Reader

See documented version: test/parsers/gdsii/test_reader.cpp

#include <iostream>
using std::cout;
using std::endl;
{
{
cout << "constructing AsciiDataBase" << endl;
}
virtual void bit_array_cbk(const char* ascii_record_type, const char* ascii_data_type, vector<int> const& vBitArray)
{
cout << __func__ << endl;
this->general_cbk(ascii_record_type, ascii_data_type, vBitArray);
}
virtual void integer_2_cbk(const char* ascii_record_type, const char* ascii_data_type, vector<int> const& vInteger)
{
cout << __func__ << endl;
this->general_cbk(ascii_record_type, ascii_data_type, vInteger);
}
virtual void integer_4_cbk(const char* ascii_record_type, const char* ascii_data_type, vector<int> const& vInteger)
{
cout << __func__ << endl;
this->general_cbk(ascii_record_type, ascii_data_type, vInteger);
}
virtual void real_4_cbk(const char* ascii_record_type, const char* ascii_data_type, vector<double> const& vFloat)
{
cout << __func__ << endl;
this->general_cbk(ascii_record_type, ascii_data_type, vFloat);
}
virtual void real_8_cbk(const char* ascii_record_type, const char* ascii_data_type, vector<double> const& vFloat)
{
cout << __func__ << endl;
this->general_cbk(ascii_record_type, ascii_data_type, vFloat);
}
virtual void string_cbk(const char* ascii_record_type, const char* ascii_data_type, string const& str)
{
cout << __func__ << endl;
this->general_cbk(ascii_record_type, ascii_data_type, str);
}
virtual void begin_end_cbk(const char* ascii_record_type)
{
cout << __func__ << endl;
this->general_cbk(ascii_record_type, "", vector<int>(0));
}
template <typename ContainerType>
void general_cbk(string const& ascii_record_type, string const& ascii_data_type, ContainerType const& data)
{
cout << "ascii_record_type: " << ascii_record_type << endl
<< "ascii_data_type: " << ascii_data_type << endl
<< "data size: " << data.size() << endl;
if (ascii_record_type == "UNITS")
{
}
else if (ascii_record_type == "BOUNDARY")
{
}
else if (ascii_record_type == "LAYER")
{
}
else if (ascii_record_type == "XY")
{
cout << data.size() << endl;
}
else if (ascii_record_type == "ENDEL")
{
}
}
};
{
{
cout << "constructing EnumDataBase" << endl;
}
virtual void bit_array_cbk(GdsParser::GdsRecords::EnumType record_type, GdsParser::GdsData::EnumType data_type, vector<int> const& vBitArray)
{
cout << __func__ << endl;
this->general_cbk(record_type, data_type, vBitArray);
}
virtual void integer_2_cbk(GdsParser::GdsRecords::EnumType record_type, GdsParser::GdsData::EnumType data_type, vector<int> const& vInteger)
{
cout << __func__ << endl;
this->general_cbk(record_type, data_type, vInteger);
}
virtual void integer_4_cbk(GdsParser::GdsRecords::EnumType record_type, GdsParser::GdsData::EnumType data_type, vector<int> const& vInteger)
{
cout << __func__ << endl;
this->general_cbk(record_type, data_type, vInteger);
}
virtual void real_4_cbk(GdsParser::GdsRecords::EnumType record_type, GdsParser::GdsData::EnumType data_type, vector<double> const& vFloat)
{
cout << __func__ << endl;
this->general_cbk(record_type, data_type, vFloat);
}
virtual void real_8_cbk(GdsParser::GdsRecords::EnumType record_type, GdsParser::GdsData::EnumType data_type, vector<double> const& vFloat)
{
cout << __func__ << endl;
this->general_cbk(record_type, data_type, vFloat);
}
virtual void string_cbk(GdsParser::GdsRecords::EnumType record_type, GdsParser::GdsData::EnumType data_type, string const& str)
{
cout << __func__ << endl;
this->general_cbk(record_type, data_type, str);
}
{
cout << __func__ << endl;
this->general_cbk(record_type, GdsParser::GdsData::NO_DATA, vector<int>(0));
}
template <typename ContainerType>
void general_cbk(GdsParser::GdsRecords::EnumType record_type, GdsParser::GdsData::EnumType data_type, ContainerType const& data)
{
cout << "ascii_record_type: " << GdsParser::gds_record_ascii(record_type) << endl
<< "ascii_data_type: " << GdsParser::gds_data_ascii(data_type) << endl
<< "data size: " << data.size() << endl;
switch (record_type)
{
case GdsParser::GdsRecords::UNITS:
break;
case GdsParser::GdsRecords::BOUNDARY:
break;
case GdsParser::GdsRecords::LAYER:
cout << "LAYER = " << data[0] << endl;
break;
case GdsParser::GdsRecords::XY:
for (typename ContainerType::const_iterator it = data.begin(); it != data.end(); ++it)
cout << *it << " ";
cout << endl;
cout << data.size() << endl;
break;
case GdsParser::GdsRecords::ENDEL:
break;
default:
break;
}
}
};
/* ===========================================
example to read .gds.gz
#include <boost/iostreams/filter/gzip.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
EnumDataBase edb;
boost::iostreams::filtering_istream in;
in.push(boost::iostreams::gzip_decompressor());
in.push(boost::iostreams::file_source(argv[1]));
cout << "test enum api\n" << GdsParser::read(edb, in) << endl;
=========================================== */
int main(int argc, char** argv)
{
if (argc > 1)
{
cout << "test ascii api\n" << GdsParser::read(adb, argv[1]) << endl;
cout << "test enum api\n" << GdsParser::read(edb, argv[1]) << endl;
}
else cout << "at least 1 argument is required" << endl;
return 0;
}

Compiling and running commands (assuming LIMBO_DIR is exported as the environment variable to the path where limbo library is installed)

1 g++ -o test_reader test_reader.cpp -I $LIMBO_DIR/include -L $LIMBO_DIR/lib -lgdsparser
2 # read a file
3 ./test_reader benchmarks/test_reader.gds

If BOOST_DIR and ZLIB_DIR have been defined as environment variables when building Limbo library, one can compile with support to compression files.

1 g++ -o test_reader test_reader.cpp -I $LIMBO_DIR/include -L $LIMBO_DIR/lib -lgdsparser -L $BOOST_DIR/lib -lboost_iostreams -L $ZLIB_DIR -lz
2 # read a compressed file
3 ./test_reader benchmarks/test_reader_gz.gds.gz

Stream Writer

See documented version: test/parsers/gdsii/test_writer.cpp

#include <vector>
int main( int argc, char *argv[] )
{
int
x[5],
y[5];
if (argc < 2)
{
printf("need a output file name\n");
return 1;
}
// start the gds library with HEADER, BGNLIB, LIBNAME, and UNITS
GdsParser::GdsWriter gw (argv[1]);
// two different wrappers
//gw.gds_create_lib( "dogs", 0.001 /* um per bit */ );
gw.create_lib("dogs", 0.001, 1.0e-9);
// create a cell called "hotdogs"
gw.gds_write_bgnstr( );
gw.gds_write_strname( "hotdogs" );
//-----------------------------------------------------------------------------
// create a polygon 1
gw.gds_write_boundary( ); // write just the token
gw.gds_write_layer( 10001 ); // layer 0, for example
gw.gds_write_datatype( 0 ); // datatype 1, for example
x[0] = 0; y[0] = 0; // signed four-byte integers
x[1] = 0; y[1] = 500;
x[2] = 1000; y[2] = 500; // in this example 1 integer unit = 1 nm
x[3] = 1000; y[3] = 0;
x[4] = 0; y[4] = 0; // required repetition of first point (yup, that's stupid)
gw.gds_write_xy( x, y, 5 ); // polygon, four vertices, first vertex repeated => 5 points
gw.gds_write_endel( ); // end of element
//-----------------------------------------------------------------------------
// create a polygon 2
// use high-level interfaces
std::vector<int> vx(4);
std::vector<int> vy(4);
vx[0] = 0; vy[0] = 0; // signed four-byte integers
vx[1] = 0; vy[1] = 500;
vx[2] = 1000; vy[2] = 500; // in this example 1 integer unit = 1 nm
vx[3] = 1000; vy[3] = 0;
gw.write_boundary(10002, 0, vx, vy, false);
//-----------------------------------------------------------------------------
// create a polygon 3
// for rectangles
// use high-level interfaces
for (int i = 0; i < 1; ++i)
gw.write_box(10003, 0, 10, 10, 20, 20);
//-----------------------------------------------------------------------------
// create some text, reflected about the x axis
gw.gds_write_text( );
gw.gds_write_layer( 1 );
gw.gds_write_texttype( 0 );
gw.gds_write_presentation( 0, 1, 1 ); // font, hp, vp
gw.gds_write_width( 500 );
gw.gds_write_strans( 1, 0, 0 ); // reflect, abs_angle, abs_mag
x[0] = 2000;
y[0] = 2000;
gw.gds_write_xy( x, y, 1 );
gw.gds_write_string( "reflected" );
gw.gds_write_endel( );
//-----------------------------------------------------------------------------
// create some text, using the helper function instead.
// arguments: file-descriptor, string, x, y, layer, size
// where x, y, and size are in database units (nanometers, usually)
gw.gds_create_text( "not reflected", 2000, 1500, 2, 500 );
//-----------------------------------------------------------------------------
// create a path
gw.gds_write_path( );
gw.gds_write_layer( 3 ); // layer 3
gw.gds_write_datatype( 4 ); // datatype 4
gw.gds_write_pathtype( 2 ); // extended square ends
gw.gds_write_width( 200 ); // 200 nm wide
x[0] = 2000; y[0] = 3000;
x[1] = 2000; y[1] = 4000;
x[2] = 2500; y[2] = 3500;
gw.gds_write_xy( x, y, 3 );
gw.gds_write_endel( );
//-----------------------------------------------------------------------------
// create a box, which is stupid
gw.gds_write_box( ); // write just the token
gw.gds_write_layer( 6 ); // layer 6, for example
gw.gds_write_boxtype( 12 ); // boxtype 12, for example same as datatype
x[0] = 3000; y[0] = 0; // signed four-byte integers
x[1] = 3000; y[1] = 500;
x[2] = 4000; y[2] = 500; // in this example 1 integer unit = 1 nm
x[3] = 4000; y[3] = 0;
x[4] = 3000; y[4] = 0; // required repetition of first point (yup, that's stupid)
gw.gds_write_xy( x, y, 5 ); // polygon, four vertices, first vertex repeated => 5 points
gw.gds_write_endel( ); // end of element
// end the structure (the cell hotdogs)
gw.gds_write_endstr( );
//-----------------------------------------------------------------------------
// Create a new cell, which will contain an instance of the previous cell
gw.gds_write_bgnstr( ); // new cell (structure)
gw.gds_write_strname( "sausage" ); // called "sausage"
gw.gds_write_sref( ); // contains an instance of...
gw.gds_write_sname( "hotdogs" ); // the cell hotdogs
gw.gds_write_mag( 5.0 ); // which will be 5 times larger
gw.gds_write_angle( 15.4 ); // and tilted at some weird angle
x[0] = 2000;
y[0] = -2000;
gw.gds_write_xy( x, y, 1 ); // at these coordinates (database units)
gw.gds_write_endel( ); // end of element
gw.gds_write_endstr( ); // end of structure (cell)
//-----------------------------------------------------------------------------
// Create a new cell "meatball" containing an array of the cell "sausage"
gw.gds_write_bgnstr( ); // new cell
gw.gds_write_strname( "meatball" ); // called "meatball"
gw.gds_write_aref( ); // containing an array of...
gw.gds_write_sname( "sausage" ); // the cell "sausage"
gw.gds_write_colrow( 2, 5 ); // 2 columns, 5 rows
x[0] = 5000; y[0] = 5000; // array anchor point
x[1] = 85000; y[1] = 5000; // displacement from anchor plus ncols*pitch
// which makes the column pitch 40 um
x[2] = 5000; y[2] = 205000; // displacement from anchor plus nrows*pitch
// which makes the row pitch 40 um
gw.gds_write_xy( x, y, 3 ); // See how you could have a diagonal matrix?
// That would be so goofy!
gw.gds_write_endel( ); // end of element
gw.gds_write_endstr( ); // end of structure (cell) "meatball"
// end of library
gw.gds_write_endlib( );
printf( "\nDone. Look at %s\n\n", argv[1] );
return 0;
}

Compiling and running commands (assuming LIMBO_DIR is exported as the environment variable to the path where limbo library is installed)

1 g++ -o test_writer test_writer.cpp -I $LIMBO_DIR/include -L $LIMBO_DIR/lib -lgdsparser
2 # write to a file
3 ./test_writer test_writer.gds

If BOOST_DIR and ZLIB_DIR have been defined as environment variables when building Limbo library, one can compile with support to compression files.

1 g++ -o test_writer test_writer.cpp -I $LIMBO_DIR/include -L $LIMBO_DIR/lib -lgdsparser -L $BOOST_DIR/lib -lboost_iostreams -L $ZLIB_DIR -lz
2 # write to a compressed file
3 ./test_writer test_writer_gz.gds.gz

Stream GDSII Database

See documented version: test/parsers/gdsii/test_gdsdb.cpp

#include <iostream>
int main(int argc, char** argv)
{
if (argc > 2 && argc <= 4)
{
// test simple read and write
limboAssert(reader(argv[1]));
for (std::vector<GdsParser::GdsDB::GdsCell>::const_iterator it = db.cells().begin(); it != db.cells().end(); ++it)
std::cout << "cell: " << it->name() << std::endl;
// write
gw(argv[2]);
std::cout << "4 arguments to test flatten: input gds, output gds, flat output gds, flat cell name" << std::endl;
}
else if (argc > 4)
{
// test flatten
GdsParser::GdsDB::GdsCell flatCell = db.extractCell(argv[4]);
flatDB.addCell(flatCell);
// write flatten cell
GdsParser::GdsDB::GdsWriter flatGw (flatDB);
flatGw(argv[3]);
}
else std::cout << "at least 4 arguments are required: input gds, output gds, flat output gds, flat cell name" << std::endl;
return 0;
}

Compiling and running commands (assuming LIMBO_DIR is exported as the environment variable to the path where limbo library is installed)

1 g++ -o test_gdsdb test_gdsdb.cpp -I $LIMBO_DIR/include -I $BOOST_DIR/include -L $LIMBO_DIR/lib -lgdsparser -lgdsdb
2 # read a file and test flatten
3 ./test_gdsdb benchmarks/test_reader.gds test_gdsdb.gds test_gdsdb_flat.gds TOPCELL

If BOOST_DIR and ZLIB_DIR have been defined as environment variables when building Limbo library, one can compile with support to compression files.

1 g++ -o test_gdsdb test_gdsdb.cpp -I $LIMBO_DIR/include -I $BOOST_DIR/include -L $LIMBO_DIR/lib -lgdsparser -lgdsdb -L $BOOST_DIR/lib -lboost_iostreams -L $ZLIB_DIR -lz
2 # read a compressed file and test flatten
3 ./test_gdsdb benchmarks/test_reader_gz.gds.gz test_gdsdb_gz.gds.gz test_gdsdb_gz_flat.gds.gz TOPCELL

All Examples

References