mirror of https://github.com/KLayout/klayout.git
WIP: starting MAG writer.
This commit is contained in:
parent
a980332c76
commit
5c217b90b5
|
|
@ -107,7 +107,7 @@ CIFWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa
|
|||
strftime(timestr, sizeof (timestr), "%F %T", &tt);
|
||||
|
||||
// Write header
|
||||
*this << "(CIF file written " << (const char *)timestr << " by KLayout);" << endl;
|
||||
*this << "(CIF file written " << (const char *)timestr << " by KLayout);" << m_endl;
|
||||
|
||||
// TODO: this can be done more intelligently ..
|
||||
int tl_scale_divider;
|
||||
|
|
@ -136,8 +136,8 @@ CIFWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa
|
|||
|
||||
double sf = 1.0;
|
||||
|
||||
*this << "DS " << cell_index << " " << tl_scale_denom << " " << tl_scale_divider << ";" << endl;
|
||||
*this << "9 " << tl::to_word_or_quoted_string (layout.cell_name (*cell)) << ";" << endl;
|
||||
*this << "DS " << cell_index << " " << tl_scale_denom << " " << tl_scale_divider << ";" << m_endl;
|
||||
*this << "9 " << tl::to_word_or_quoted_string (layout.cell_name (*cell)) << ";" << m_endl;
|
||||
|
||||
// instances
|
||||
for (db::Cell::const_iterator inst = cref.begin (); ! inst.at_end (); ++inst) {
|
||||
|
|
@ -195,7 +195,7 @@ CIFWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa
|
|||
|
||||
*this << " T" << d.x() << xy_sep () << d.y();
|
||||
|
||||
*this << ";" << endl;
|
||||
*this << ";" << m_endl;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ CIFWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa
|
|||
}
|
||||
|
||||
// end of cell
|
||||
*this << "DF;" << endl;
|
||||
*this << "DF;" << m_endl;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -232,7 +232,7 @@ CIFWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa
|
|||
|
||||
std::map<db::cell_index_type, int>::const_iterator cif_index = db_to_cif_index_map.find (*cell);
|
||||
tl_assert(cif_index != db_to_cif_index_map.end ());
|
||||
*this << "C" << cif_index->second << ";" << endl;
|
||||
*this << "C" << cif_index->second << ";" << m_endl;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -241,7 +241,7 @@ CIFWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa
|
|||
}
|
||||
|
||||
// end of file
|
||||
*this << "E" << endl;
|
||||
*this << "E" << m_endl;
|
||||
|
||||
m_progress.set (mp_stream->pos ());
|
||||
|
||||
|
|
@ -252,7 +252,7 @@ CIFWriter::emit_layer()
|
|||
{
|
||||
if (m_needs_emit) {
|
||||
m_needs_emit = false;
|
||||
*this << "L " << tl::to_word_or_quoted_string(m_layer.name, "0123456789_.$") << ";" << endl;
|
||||
*this << "L " << tl::to_word_or_quoted_string(m_layer.name, "0123456789_.$") << ";" << m_endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -271,7 +271,7 @@ CIFWriter::write_texts (const db::Layout &layout, const db::Cell &cell, unsigned
|
|||
double h = shape->text_size () * layout.dbu ();
|
||||
|
||||
db::Vector p (shape->text_trans ().disp () * sf);
|
||||
*this << " " << p.x() << xy_sep () << p.y () << " " << h << ";" << endl;
|
||||
*this << " " << p.x() << xy_sep () << p.y () << " " << h << ";" << m_endl;
|
||||
|
||||
++shape;
|
||||
|
||||
|
|
@ -324,7 +324,7 @@ CIFWriter::write_polygon (const db::Polygon &polygon, double sf)
|
|||
db::Point pp (*p * sf);
|
||||
*this << " " << pp.x () << xy_sep () << pp.y ();
|
||||
}
|
||||
*this << ";" << endl;
|
||||
*this << ";" << m_endl;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -338,7 +338,7 @@ CIFWriter::write_boxes (const db::Layout & /*layout*/, const db::Cell &cell, uns
|
|||
emit_layer ();
|
||||
|
||||
db::Box b (shape->bbox () * sf);
|
||||
*this << "B " << b.width () << " " << b.height () << " " << b.center ().x () << xy_sep () << b.center ().y () << ";" << endl;
|
||||
*this << "B " << b.width () << " " << b.height () << " " << b.center ().x () << xy_sep () << b.center ().y () << ";" << m_endl;
|
||||
|
||||
++shape;
|
||||
|
||||
|
|
@ -411,13 +411,13 @@ CIFWriter::write_paths (const db::Layout & /*layout*/, const db::Cell &cell, uns
|
|||
db::Point pp (*shape->begin_point () * sf);
|
||||
*this << " " << pp.x () << xy_sep () << pp.y ();
|
||||
|
||||
*this << ";" << endl;
|
||||
*this << ";" << m_endl;
|
||||
|
||||
} else if (path_type >= 0 && npts > 1) {
|
||||
|
||||
emit_layer ();
|
||||
|
||||
*this << "98 " << path_type << ";" << endl;
|
||||
*this << "98 " << path_type << ";" << m_endl;
|
||||
|
||||
*this << "W " << long (floor (0.5 + sf * shape->path_width ()));
|
||||
|
||||
|
|
@ -426,7 +426,7 @@ CIFWriter::write_paths (const db::Layout & /*layout*/, const db::Cell &cell, uns
|
|||
*this << " " << pp.x () << xy_sep () << pp.y ();
|
||||
}
|
||||
|
||||
*this << ";" << endl;
|
||||
*this << ";" << m_endl;
|
||||
|
||||
} else {
|
||||
db::Polygon poly;
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ private:
|
|||
tl::OutputStream *mp_stream;
|
||||
CIFWriterOptions m_options;
|
||||
tl::AbsoluteProgress m_progress;
|
||||
endl_tag endl;
|
||||
endl_tag m_endl;
|
||||
db::LayerProperties m_layer;
|
||||
bool m_needs_emit;
|
||||
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ static bool get_cif_blank_separator (const db::SaveLayoutOptions *options)
|
|||
return options->get_options<db::CIFWriterOptions> ().blank_separator;
|
||||
}
|
||||
|
||||
// extend lay::SaveLayoutOptions with the GDS2 options
|
||||
// extend lay::SaveLayoutOptions with the CIF options
|
||||
static
|
||||
gsi::ClassExt<db::SaveLayoutOptions> cif_writer_options (
|
||||
gsi::method_ext ("cif_dummy_calls=", &set_cif_dummy_calls,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ public:
|
|||
|
||||
virtual tl::XMLElementBase *xml_reader_options_element () const
|
||||
{
|
||||
return new db::ReaderOptionsXMLElement<db::MAGReaderOptions> ("cif",
|
||||
return new db::ReaderOptionsXMLElement<db::MAGReaderOptions> ("mag",
|
||||
tl::make_member (&db::MAGReaderOptions::lambda, "lambda") +
|
||||
tl::make_member (&db::MAGReaderOptions::dbu, "dbu") +
|
||||
tl::make_member (&db::MAGReaderOptions::layer_map, "layer-map") +
|
||||
|
|
@ -98,12 +98,9 @@ public:
|
|||
|
||||
virtual tl::XMLElementBase *xml_writer_options_element () const
|
||||
{
|
||||
// @@@
|
||||
return new db::WriterOptionsXMLElement<db::MAGWriterOptions> ("cif",
|
||||
tl::make_member (&db::MAGWriterOptions::dummy_calls, "dummy-calls") +
|
||||
tl::make_member (&db::MAGWriterOptions::blank_separator, "blank-separator")
|
||||
return new db::WriterOptionsXMLElement<db::MAGWriterOptions> ("mag",
|
||||
tl::make_member (&db::MAGWriterOptions::lambda, "lambda")
|
||||
);
|
||||
// @@@
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -146,24 +146,19 @@ public:
|
|||
* @brief The constructor
|
||||
*/
|
||||
MAGWriterOptions ()
|
||||
: dummy_calls (false), blank_separator (false)
|
||||
: lambda (0.0)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A flag indicating whether dummy calls shall be written
|
||||
* If this flag is true, the writer will produce dummy cell calls on global
|
||||
* level for all top cells.
|
||||
* @brief Specifies the lambda value for writing
|
||||
*
|
||||
* The lambda value is the basic scaling parameter.
|
||||
* If this value is set to 0 or negative, the lambda value stored in the layout
|
||||
* is used (meta data "lambda").
|
||||
*/
|
||||
bool dummy_calls;
|
||||
|
||||
/**
|
||||
* @brief A flag indicating whether to use blanks as x/y separators
|
||||
* If this flag is true, blank characters will be used to separate x and y values.
|
||||
* Otherwise comma characters will be used.
|
||||
*/
|
||||
bool blank_separator;
|
||||
double lambda;
|
||||
|
||||
/**
|
||||
* @brief Implementation of FormatSpecificWriterOptions
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ MAGReader::do_read_part (db::Layout &layout, db::cell_index_type cell_index, tl:
|
|||
error (tl::to_string (tr ("Could not find 'magic' header line - is this a MAGIC file?")));
|
||||
}
|
||||
|
||||
layout.add_meta_info (db::MetaInfo ("magic_lambda", "MAGIC lambda value", tl::to_string (m_lambda)));
|
||||
layout.add_meta_info (db::MetaInfo ("lambda", "lambda value (tech scaling)", tl::to_string (m_lambda)));
|
||||
|
||||
bool valid_layer = false;
|
||||
unsigned int current_layer = 0;
|
||||
|
|
|
|||
|
|
@ -37,50 +37,19 @@ namespace db
|
|||
|
||||
MAGWriter::MAGWriter ()
|
||||
: mp_stream (0),
|
||||
m_progress (tl::to_string (tr ("Writing MAG file")), 10000),
|
||||
m_needs_emit (false)
|
||||
m_progress (tl::to_string (tr ("Writing Magic file")), 10000)
|
||||
{
|
||||
m_progress.set_format (tl::to_string (tr ("%.0f MB")));
|
||||
m_progress.set_unit (1024 * 1024);
|
||||
}
|
||||
|
||||
MAGWriter &
|
||||
MAGWriter::operator<<(const char *s)
|
||||
{
|
||||
mp_stream->put(s, strlen(s));
|
||||
return *this;
|
||||
}
|
||||
|
||||
MAGWriter &
|
||||
MAGWriter::operator<<(const std::string &s)
|
||||
{
|
||||
mp_stream->put(s.c_str(), s.size());
|
||||
return *this;
|
||||
}
|
||||
|
||||
MAGWriter &
|
||||
MAGWriter::operator<<(endl_tag)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
*this << "\r\n";
|
||||
#else
|
||||
*this << "\n";
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
const char *
|
||||
MAGWriter::xy_sep () const
|
||||
{
|
||||
return m_options.blank_separator ? " " : ",";
|
||||
}
|
||||
|
||||
void
|
||||
MAGWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLayoutOptions &options)
|
||||
{
|
||||
m_options = options.get_options<MAGWriterOptions> ();
|
||||
mp_stream = &stream;
|
||||
|
||||
#if 0 // @@@
|
||||
// compute the scale factor to get to the 10 nm basic database unit of MAG
|
||||
double tl_scale = options.scale_factor () * layout.dbu () / 0.01;
|
||||
|
||||
|
|
@ -242,11 +211,12 @@ MAGWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa
|
|||
|
||||
// end of file
|
||||
*this << "E" << endl;
|
||||
#endif
|
||||
|
||||
m_progress.set (mp_stream->pos ());
|
||||
|
||||
}
|
||||
|
||||
#if 0 // @@@
|
||||
void
|
||||
MAGWriter::emit_layer()
|
||||
{
|
||||
|
|
@ -440,6 +410,7 @@ MAGWriter::write_paths (const db::Layout & /*layout*/, const db::Cell &cell, uns
|
|||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,28 +66,6 @@ private:
|
|||
tl::OutputStream *mp_stream;
|
||||
MAGWriterOptions m_options;
|
||||
tl::AbsoluteProgress m_progress;
|
||||
endl_tag endl;
|
||||
db::LayerProperties m_layer;
|
||||
bool m_needs_emit;
|
||||
|
||||
MAGWriter &operator<<(const char *s);
|
||||
MAGWriter &operator<<(const std::string &s);
|
||||
MAGWriter &operator<<(endl_tag);
|
||||
|
||||
template<class X> MAGWriter &operator<<(const X &x)
|
||||
{
|
||||
return (*this << tl::to_string(x));
|
||||
}
|
||||
|
||||
void write_texts (const db::Layout &layout, const db::Cell &cell, unsigned int layer, double tl_scale);
|
||||
void write_polygons (const db::Layout &layout, const db::Cell &cell, unsigned int layer, double tl_scale);
|
||||
void write_polygon (const db::Polygon &polygon, double tl_scale);
|
||||
void write_boxes (const db::Layout &layout, const db::Cell &cell, unsigned int layer, double tl_scale);
|
||||
void write_paths (const db::Layout &layout, const db::Cell &cell, unsigned int layer, double tl_scale);
|
||||
void write_edges (const db::Layout &layout, const db::Cell &cell, unsigned int layer, double tl_scale);
|
||||
const char *xy_sep () const;
|
||||
|
||||
void emit_layer();
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
|
|
|
|||
|
|
@ -236,53 +236,32 @@ gsi::ClassExt<db::LoadLayoutOptions> mag_reader_options (
|
|||
// ---------------------------------------------------------------
|
||||
// gsi Implementation of specific methods
|
||||
|
||||
static void set_mag_dummy_calls (db::SaveLayoutOptions *options, bool f)
|
||||
static void set_mag_lambda_w (db::SaveLayoutOptions *options, double f)
|
||||
{
|
||||
options->get_options<db::MAGWriterOptions> ().dummy_calls = f;
|
||||
options->get_options<db::MAGWriterOptions> ().lambda = f;
|
||||
}
|
||||
|
||||
static bool get_mag_dummy_calls (const db::SaveLayoutOptions *options)
|
||||
static double get_mag_lambda_w (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::MAGWriterOptions> ().dummy_calls;
|
||||
return options->get_options<db::MAGWriterOptions> ().lambda;
|
||||
}
|
||||
|
||||
static void set_mag_blank_separator (db::SaveLayoutOptions *options, bool f)
|
||||
{
|
||||
options->get_options<db::MAGWriterOptions> ().blank_separator = f;
|
||||
}
|
||||
|
||||
static bool get_mag_blank_separator (const db::SaveLayoutOptions *options)
|
||||
{
|
||||
return options->get_options<db::MAGWriterOptions> ().blank_separator;
|
||||
}
|
||||
|
||||
// extend lay::SaveLayoutOptions with the GDS2 options
|
||||
// extend lay::SaveLayoutOptions with the MAG options
|
||||
static
|
||||
gsi::ClassExt<db::SaveLayoutOptions> mag_writer_options (
|
||||
gsi::method_ext ("mag_dummy_calls=", &set_mag_dummy_calls,
|
||||
"@brief Sets a flag indicating whether dummy calls shall be written\n"
|
||||
"If this property is set to true, dummy calls will be written in the top level entity "
|
||||
"of the MAG file calling every top cell.\n"
|
||||
"This option is useful for enhanced compatibility with other tools.\n"
|
||||
"\nThis property has been added in version 0.23.10.\n"
|
||||
gsi::method_ext ("mag_lambda=", &set_mag_lambda_w, gsi::arg ("lambda"),
|
||||
"@brief Specifies the lambda value to used for writing\n"
|
||||
"\n"
|
||||
"The lamdba value is the basic unit of the layout.\n"
|
||||
"The layout is brought to units of this value. If the layout is not on-grid on this unit, snapping will happen. "
|
||||
"If the value is less or equal to zero, KLayout will use the lambda value stored inside the layout (set by a previous read operation "
|
||||
"of a MAGIC file).\n"
|
||||
"\nThis property has been added in version 0.26.2.\n"
|
||||
) +
|
||||
gsi::method_ext ("mag_dummy_calls?|#mag_dummy_calls", &get_mag_dummy_calls,
|
||||
"@brief Gets a flag indicating whether dummy calls shall be written\n"
|
||||
"See \\mag_dummy_calls= method for a description of that property."
|
||||
"\nThis property has been added in version 0.23.10.\n"
|
||||
"\nThe predicate version (mag_blank_separator?) has been added in version 0.25.1.\n"
|
||||
) +
|
||||
gsi::method_ext ("mag_blank_separator=", &set_mag_blank_separator,
|
||||
"@brief Sets a flag indicating whether blanks shall be used as x/y separator characters\n"
|
||||
"If this property is set to true, the x and y coordinates are separated with blank characters "
|
||||
"rather than comma characters."
|
||||
"\nThis property has been added in version 0.23.10.\n"
|
||||
) +
|
||||
gsi::method_ext ("mag_blank_separator?|#mag_blank_separator", &get_mag_blank_separator,
|
||||
"@brief Gets a flag indicating whether blanks shall be used as x/y separator characters\n"
|
||||
"See \\mag_blank_separator= method for a description of that property."
|
||||
"\nThis property has been added in version 0.23.10.\n"
|
||||
"\nThe predicate version (mag_blank_separator?) has been added in version 0.25.1.\n"
|
||||
gsi::method_ext ("mag_lambda", &get_mag_lambda_w,
|
||||
"@brief Get the lambda value\n"
|
||||
"See \\mag_lambda= method for a description of this attribute."
|
||||
"\nThis property has been added in version 0.26.2.\n"
|
||||
),
|
||||
""
|
||||
);
|
||||
|
|
|
|||
|
|
@ -35,50 +35,27 @@
|
|||
<string>CIF Writer Options</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="blank_separator_cbx">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<widget class="QLineEdit" name="lambda_le"/>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>If checked, a blank character is used as x/y coordinate
|
||||
separator. Otherweise a comma is used.</string>
|
||||
<string>Micron</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Lambda value</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Blank as x/y separator</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Dummy cell calls</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="dummy_calls_cbx">
|
||||
<property name="text">
|
||||
<string>If checked, dummy cell calls are added on global level</string>
|
||||
<string>Leave this value empty to take the lambda value stored in the layout</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
|
|
@ -55,8 +55,11 @@ MAGWriterOptionPage::setup (const db::FormatSpecificWriterOptions *o, const db::
|
|||
{
|
||||
const db::MAGWriterOptions *options = dynamic_cast<const db::MAGWriterOptions *> (o);
|
||||
if (options) {
|
||||
mp_ui->dummy_calls_cbx->setChecked (options->dummy_calls);
|
||||
mp_ui->blank_separator_cbx->setChecked (options->blank_separator);
|
||||
if (options->lambda <= 0.0) {
|
||||
mp_ui->lambda_le->setText (QString ());
|
||||
} else {
|
||||
mp_ui->lambda_le->setText (tl::to_qstring (tl::to_string (options->lambda)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -65,8 +68,11 @@ MAGWriterOptionPage::commit (db::FormatSpecificWriterOptions *o, const db::Techn
|
|||
{
|
||||
db::MAGWriterOptions *options = dynamic_cast<db::MAGWriterOptions *> (o);
|
||||
if (options) {
|
||||
options->dummy_calls = mp_ui->dummy_calls_cbx->isChecked ();
|
||||
options->blank_separator = mp_ui->blank_separator_cbx->isChecked ();
|
||||
QString l = mp_ui->lambda_le->text ().trimmed ();
|
||||
options->lambda = 0.0;
|
||||
if (! l.isEmpty ()) {
|
||||
tl::from_string (tl::to_string (l), options->lambda);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,8 +97,7 @@ static void run_test (tl::TestBase *_this, const std::string &base, const char *
|
|||
tl::OutputStream stream (tmp_cif_file);
|
||||
|
||||
db::MAGWriterOptions *opt = new db::MAGWriterOptions();
|
||||
opt->dummy_calls = dummy_calls;
|
||||
opt->blank_separator = blank_sep;
|
||||
opt->lambda = 0.5;
|
||||
|
||||
db::MAGWriter writer;
|
||||
db::SaveLayoutOptions options;
|
||||
|
|
|
|||
Loading…
Reference in New Issue