Allowing to explicity specify a format

Most tools and functions now allow to explicitly
specify a format for input and output. On input,
the format is usually detected, but for some
cases, this is not possible (e.g. DEF). So you can
specify the format attached to the file name in
square brackets:

e.g. file.defok[def]

"def" is the intended suffix, "defok" is the given one.

On output, the same is possible, specifically in strmxor
and strmclip:

strmxor a.gds b.gds out.xor[oas]
This commit is contained in:
Matthias Koefferlein
2026-03-20 16:30:28 +01:00
parent 00c826688f
commit 2dfcc9293e
26 changed files with 425 additions and 76 deletions
@@ -46,38 +46,8 @@ namespace db
*/
static bool is_lef_format (const std::string &fn)
{
static const char *suffixes[] = { ".lef", ".LEF", ".lef.gz", ".LEF.gz" };
// NOTE: there is no reliable way of (easily) detecting the format. Hence we use the file
// name's suffix for the format hint.
for (size_t i = 0; i < sizeof (suffixes) / sizeof (suffixes[0]); ++i) {
std::string suffix = suffixes [i];
if (fn.size () > suffix.size () && fn.find (suffix) == fn.size () - suffix.size ()) {
return true;
}
}
return false;
}
/**
* @brief Determines the format of the given stream
* Returns true, if the stream has DEF format
*/
static bool is_def_format (const std::string &fn)
{
static const char *suffixes[] = { ".def", ".DEF", ".def.gz", ".DEF.gz" };
// NOTE: there is no reliable way of (easily) detecting the format. Hence we use the file
// name's suffix for the format hint.
for (size_t i = 0; i < sizeof (suffixes) / sizeof (suffixes[0]); ++i) {
std::string suffix = suffixes [i];
if (fn.size () > suffix.size () && fn.find (suffix) == fn.size () - suffix.size ()) {
return true;
}
}
return false;
static std::string lef_format ("LEF files (*.lef *.LEF *.lef.gz *.LEF.gz)");
return tl::match_filename_to_format (fn, lef_format);
}
// ---------------------------------------------------------------
@@ -92,13 +62,13 @@ LEFDEFReader::LEFDEFReader (tl::InputStream &s)
const db::LayerMap &
LEFDEFReader::read (db::Layout &layout, const db::LoadLayoutOptions &options)
{
return read_lefdef (layout, options, is_lef_format (m_stream.filename ()));
return read_lefdef (layout, options, is_lef_format ("." + m_stream.suffix ()));
}
const db::LayerMap &
LEFDEFReader::read (db::Layout &layout)
{
return read_lefdef (layout, db::LoadLayoutOptions (), is_lef_format (m_stream.filename ()));
return read_lefdef (layout, db::LoadLayoutOptions (), is_lef_format ("." + m_stream.suffix ()));
}
const char *
@@ -287,7 +257,7 @@ class LEFDEFFormatDeclaration
virtual bool detect (tl::InputStream &stream) const
{
return is_lef_format (stream.filename ()) || is_def_format (stream.filename ());
return tl::match_filename_to_format (stream.filename (), file_format ());
}
virtual db::ReaderBase *create_reader (tl::InputStream &s) const
@@ -467,15 +467,27 @@ TEST(100)
run_test (_this, "issue-172", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false);
}
TEST(101)
TEST(101a)
{
db::LEFDEFReaderOptions opt = default_options ();
opt.set_produce_pin_names (true);
opt.set_pin_property_name (2);
opt.set_cell_outline_layer ("OUTLINE (13/0)");
run_test (_this, "issue-489", "lef:in.lef+def:in.def", "au.oas", opt, false);
}
TEST(101b)
{
db::LEFDEFReaderOptions opt = default_options ();
opt.set_produce_pin_names (true);
opt.set_pin_property_name (2);
opt.set_cell_outline_layer ("OUTLINE (13/0)");
// also with fake suffix
run_test (_this, "issue-489", "lef:'in.l[lef]'+def:'in.d[def]'", "au.oas", opt, false);
}
TEST(102)
{
db::LEFDEFReaderOptions opt = default_options ();