Basic implementation of 'resolve skew aref' feature

This commit is contained in:
Matthias Koefferlein 2021-05-21 00:08:02 +02:00
parent 6496a71b5b
commit eb26b6ed34
12 changed files with 127 additions and 57 deletions

View File

@ -74,6 +74,7 @@ class GDS2FormatDeclaration
tl::make_member (&db::GDS2WriterOptions::write_file_properties, "write-file-properties") +
tl::make_member (&db::GDS2WriterOptions::no_zero_length_paths, "no-zero-length-paths") +
tl::make_member (&db::GDS2WriterOptions::multi_xy_records, "multi-xy-records") +
tl::make_member (&db::GDS2WriterOptions::resolve_skew_arrays, "resolve-skew-arrays") +
tl::make_member (&db::GDS2WriterOptions::max_vertex_count, "max-vertex-count") +
tl::make_member (&db::GDS2WriterOptions::max_cellname_length, "max-cellname-length") +
tl::make_member (&db::GDS2WriterOptions::libname, "libname")

View File

@ -109,6 +109,7 @@ public:
: max_vertex_count (8000),
no_zero_length_paths (false),
multi_xy_records (false),
resolve_skew_arrays (false),
max_cellname_length (32000),
libname ("LIB"),
user_units (1.0),
@ -146,6 +147,13 @@ public:
*/
bool multi_xy_records;
/**
* @brief Resolve skew arrays into single instances
*
* Setting this property to true will resolve skew (non-orthogonal) arrays into single instances.
*/
bool resolve_skew_arrays;
/**
* @brief Maximum length of cell names
*

View File

@ -130,6 +130,7 @@ GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::S
size_t max_cellname_length = std::max (gds2_options.max_cellname_length, (unsigned int)8);
size_t max_vertex_count = std::max (gds2_options.max_vertex_count, (unsigned int)4);
bool no_zero_length_paths = gds2_options.no_zero_length_paths;
bool resolve_skew_arrays = gds2_options.resolve_skew_arrays;
m_cell_name_map = db::WriterCellNameMap (max_cellname_length);
m_cell_name_map.replacement ('$');
@ -281,7 +282,7 @@ GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::S
if (options.keep_instances () || cell_set.find (inst->cell_index ()) != cell_set.end ()) {
progress_checkpoint ();
write_inst (sf, *inst, true /*normalize*/, layout, inst->prop_id ());
write_inst (sf, *inst, true /*normalize*/, resolve_skew_arrays, layout, inst->prop_id ());
}
@ -346,14 +347,24 @@ GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::S
progress_checkpoint ();
}
static bool is_orthogonal (const db::Vector &rv, const db::Vector &cv)
{
return (rv.x () == 0 && cv.y () == 0) || (rv.y () == 0 && cv.x () == 0);
}
void
GDS2WriterBase::write_inst (double sf, const db::Instance &instance, bool normalize, const db::Layout &layout, db::properties_id_type prop_id)
GDS2WriterBase::write_inst (double sf, const db::Instance &instance, bool normalize, bool resolve_skew_arrays, const db::Layout &layout, db::properties_id_type prop_id)
{
db::Vector a, b;
unsigned long amax, bmax;
bool is_reg = instance.is_regular_array (a, b, amax, bmax);
// skew arrays are resolved if required
if (is_reg && ! is_orthogonal (a, b) != 0 && resolve_skew_arrays) {
is_reg = false;
}
for (db::CellInstArray::iterator ii = instance.begin (); ! ii.at_end (); ++ii) {
db::Trans t = *ii;

View File

@ -122,7 +122,7 @@ protected:
/**
* @brief Write an instance
*/
void write_inst (double sf, const db::Instance &instance, bool normalize, const db::Layout &layout, db::properties_id_type prop_id);
void write_inst (double sf, const db::Instance &instance, bool normalize, bool resolve_skew_arrays, const db::Layout &layout, db::properties_id_type prop_id);
/**
* @brief Write a shape as box

View File

@ -65,6 +65,16 @@ static bool get_gds2_multi_xy_records (const db::SaveLayoutOptions *options)
return options->get_options<db::GDS2WriterOptions> ().multi_xy_records;
}
static void set_gds2_resolve_skew_arrays (db::SaveLayoutOptions *options, bool n)
{
options->get_options<db::GDS2WriterOptions> ().resolve_skew_arrays = n;
}
static bool get_gds2_resolve_skew_arrays (const db::SaveLayoutOptions *options)
{
return options->get_options<db::GDS2WriterOptions> ().resolve_skew_arrays;
}
static void set_gds2_write_file_properties (db::SaveLayoutOptions *options, bool n)
{
options->get_options<db::GDS2WriterOptions> ().write_file_properties = n;
@ -129,7 +139,7 @@ static double get_gds2_user_units (const db::SaveLayoutOptions *options)
static
gsi::ClassExt<db::SaveLayoutOptions> gds2_writer_options (
gsi::method_ext ("gds2_max_vertex_count=", &set_gds2_max_vertex_count, gsi::arg ("count"),
"@brief Set the maximum number of vertices for polygons to write\n"
"@brief Sets the maximum number of vertices for polygons to write\n"
"This property describes the maximum number of point for polygons in GDS2 files.\n"
"Polygons with more points will be split.\n"
"The minimum value for this property is 4. The maximum allowed value is about 4000 or 8000, depending on the\n"
@ -138,24 +148,37 @@ gsi::ClassExt<db::SaveLayoutOptions> gds2_writer_options (
"\nThis property has been added in version 0.18.\n"
) +
gsi::method_ext ("gds2_max_vertex_count", &get_gds2_max_vertex_count,
"@brief Get the maximum number of vertices for polygons to write\n"
"@brief Gets the maximum number of vertices for polygons to write\n"
"See \\gds2_max_vertex_count= method for a description of the maximum vertex count."
"\nThis property has been added in version 0.18.\n"
) +
gsi::method_ext ("gds2_multi_xy_records=", &set_gds2_multi_xy_records, gsi::arg ("flag"),
"@brief Use multiple XY records in BOUNDARY elements for unlimited large polygons\n"
"@brief Uses multiple XY records in BOUNDARY elements for unlimited large polygons\n"
"\n"
"Setting this property to true allows producing polygons with an unlimited number of points \n"
"at the cost of incompatible formats. Setting it to true disables the \\gds2_max_vertex_count setting.\n"
"\nThis property has been added in version 0.18.\n"
) +
gsi::method_ext ("gds2_multi_xy_records?", &get_gds2_multi_xy_records,
"@brief Get the property enabling multiple XY records for BOUNDARY elements\n"
"@brief Gets the property enabling multiple XY records for BOUNDARY elements\n"
"See \\gds2_multi_xy_records= method for a description of this property."
"\nThis property has been added in version 0.18.\n"
) +
gsi::method_ext ("gds2_resolve_skew_arrays=", &set_gds2_resolve_skew_arrays, gsi::arg ("flag"),
"@brief Resolves skew arrays into single instances\n"
"\n"
"Setting this property to true will make skew (non-orthongonal) arrays being resolved into single instances.\n"
"Skew arrays happen if either the row or column vector isn't paralell to x or y axis. Such arrays can cause problems with "
"some legacy software and can be disabled with this option.\n"
"\nThis property has been added in version 0.27.1.\n"
) +
gsi::method_ext ("gds2_resolve_skew_arrays?", &get_gds2_resolve_skew_arrays,
"@brief Gets a value indicating whether to resolve skew arrays into single instances\n"
"See \\gds2_resolve_skew_arrays= method for a description of this property."
"\nThis property has been added in version 0.27.1.\n"
) +
gsi::method_ext ("gds2_write_timestamps=", &set_gds2_write_timestamps, gsi::arg ("flag"),
"@brief Write the current time into the GDS2 timestamps if set to true\n"
"@brief Writes the current time into the GDS2 timestamps if set to true\n"
"\n"
"If this property is set to false, the time fields will all be zero. This somewhat simplifies compare and diff "
"applications.\n"

View File

@ -50,58 +50,13 @@
<property name="spacing">
<number>6</number>
</property>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Max. vertices</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="3">
<item row="7" column="0" colspan="3">
<widget class="QCheckBox" name="write_timestamps">
<property name="text">
<string>Write current time to time stamps (BGNLIB, BGNSTR)</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="max_vertex_le"/>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>(&lt;4000 recommended, absolute limit 8191)</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="libname_le"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>(keep empty for unspecified limit)</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="3">
<widget class="QCheckBox" name="multi_xy_cbx">
<property name="text">
<string>Multi-XY record mode for boundaries
(enables infinitely large polygons/paths at the cost of compatibility)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="cell_name_length_le"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Library name</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
@ -109,13 +64,16 @@
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QCheckBox" name="no_zero_length_paths">
<item row="2" column="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Eliminate zero-length paths (convert to BOUNDARY)</string>
<string>(&lt;4000 recommended, absolute limit 8191)</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="cell_name_length_le"/>
</item>
<item row="4" column="0" colspan="3">
<widget class="QFrame" name="frame">
<property name="frameShape">
@ -181,6 +139,55 @@
</layout>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="max_vertex_le"/>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>(keep empty for unspecified limit)</string>
</property>
</widget>
</item>
<item row="3" column="1" colspan="3">
<widget class="QCheckBox" name="multi_xy_cbx">
<property name="text">
<string>Multi-XY record mode for boundaries
(enables infinitely large polygons/paths at the cost of compatibility)</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Library name</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Max. vertices</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QLineEdit" name="libname_le"/>
</item>
<item row="6" column="0" colspan="3">
<widget class="QCheckBox" name="no_zero_length_paths">
<property name="text">
<string>Eliminate zero-length paths (convert to BOUNDARY)</string>
</property>
</widget>
</item>
<item row="5" column="0" colspan="3">
<widget class="QCheckBox" name="resolve_skew_arrays_cbx">
<property name="text">
<string>Resolve skew (non-orthogonal) arrays into single instances</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>

View File

@ -61,6 +61,7 @@ GDS2WriterOptionPage::setup (const db::FormatSpecificWriterOptions *o, const db:
mp_ui->write_file_properties->setChecked (options->write_file_properties);
mp_ui->no_zero_length_paths->setChecked (options->no_zero_length_paths);
mp_ui->multi_xy_cbx->setChecked (options->multi_xy_records);
mp_ui->resolve_skew_arrays_cbx->setChecked (options->resolve_skew_arrays);
mp_ui->max_vertex_le->setEnabled (! options->multi_xy_records);
mp_ui->max_vertex_le->setText (tl::to_qstring (tl::to_string (options->max_vertex_count)));
mp_ui->cell_name_length_le->setText (tl::to_qstring (tl::to_string (options->max_cellname_length)));
@ -76,6 +77,7 @@ GDS2WriterOptionPage::commit (db::FormatSpecificWriterOptions *o, const db::Tech
unsigned int n;
options->multi_xy_records = mp_ui->multi_xy_cbx->isChecked ();
options->resolve_skew_arrays = mp_ui->resolve_skew_arrays_cbx->isChecked ();
options->write_timestamps = mp_ui->write_timestamps->isChecked ();
options->write_cell_properties = mp_ui->write_cell_properties->isChecked ();
options->write_file_properties = mp_ui->write_file_properties->isChecked ();

View File

@ -83,6 +83,19 @@ TEST(1)
run_test (_this, "arefs.gds", "arefs_ref.gds");
}
TEST(1a)
{
db::GDS2WriterOptions opt;
run_test (_this, "arefs_skew.gds", "arefs_skew1.gds", false, opt);
}
TEST(1b)
{
db::GDS2WriterOptions opt;
opt.resolve_skew_arrays = true;
run_test (_this, "arefs_skew.gds", "arefs_skew2.gds", false, opt);
}
TEST(2)
{
db::Manager m (false);

BIN
testdata/gds/arefs_skew.gds vendored Normal file

Binary file not shown.

BIN
testdata/gds/arefs_skew1.gds vendored Normal file

Binary file not shown.

BIN
testdata/gds/arefs_skew2.gds vendored Normal file

Binary file not shown.

View File

@ -64,6 +64,11 @@ class DBReadersTests(unittest.TestCase):
opt.gds2_allow_multi_xy_records = False
self.assertEqual(opt.gds2_allow_multi_xy_records, False)
opt.gds2_resolve_skew_arrays = True
self.assertEqual(opt.gds2_resolve_skew_arrays, True)
opt.gds2_resolve_skew_arrays = False
self.assertEqual(opt.gds2_resolve_skew_arrays, False)
opt.gds2_allow_big_records = True
self.assertEqual(opt.gds2_allow_big_records, True)
opt.gds2_allow_big_records = False