mirror of https://github.com/KLayout/klayout.git
The solution is to separate the meaning of "," and "+" layout
file combination operators in strm2x tools:
* "+" does "blending"
* "," does merge
"+" has priority over "," ('a+b,c' acts as '(a+b),c').
NOTE: LEF caching only happens across "+".
This commit is contained in:
parent
0ba6064507
commit
d382629e8e
|
|
@ -43,8 +43,13 @@ int converter_main (int argc, char *argv[], const std::string &format)
|
|||
generic_reader_options.add_options (cmd);
|
||||
|
||||
cmd << tl::arg ("input", &infile, "The input file (any format, may be gzip compressed)",
|
||||
"You can use '+' or ',' to supply multiple files which will be read after each other into the same layout. "
|
||||
"This provides some cheap, but risky way of merging files. Beware of cell name conflicts.")
|
||||
"Multiple files can be combined using '+' or ','. '+' will combine the files in 'blending' mode. "
|
||||
"In this mode it is possible to combine identically named cells into one cell for example. This mode "
|
||||
"needs to be used with care and there some constraints - e.g. the database unit of the involved "
|
||||
"layouts needs to be the same. When using ',' as a separator, blending is not used, but the layouts "
|
||||
"are merged by first creating two layouts and then combining them into one. This mode is more robust "
|
||||
"but does not allow cell merging. '+' combination has higher priority than ',' - i.e. 'a+b,c' is "
|
||||
"understood as '(a+b),c'.")
|
||||
<< tl::arg ("output", &outfile, tl::sprintf ("The output file (%s format)", format))
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
#include "bdReaderOptions.h"
|
||||
#include "dbLoadLayoutOptions.h"
|
||||
#include "dbLayerMapping.h"
|
||||
#include "dbCellMapping.h"
|
||||
#include "tlCommandLineParser.h"
|
||||
|
||||
#include "tlStream.h"
|
||||
|
|
@ -831,15 +833,28 @@ static std::string::size_type find_file_sep (const std::string &s, std::string::
|
|||
}
|
||||
}
|
||||
|
||||
static std::vector<std::string> split_file_list (const std::string &infile)
|
||||
static std::vector<std::vector<std::string> > split_file_list (const std::string &infile)
|
||||
{
|
||||
std::vector<std::string> files;
|
||||
std::vector<std::vector<std::string> > files;
|
||||
files.push_back (std::vector<std::string> ());
|
||||
|
||||
size_t p = 0;
|
||||
for (size_t pp = 0; (pp = find_file_sep (infile, p)) != std::string::npos; p = pp + 1) {
|
||||
files.push_back (std::string (infile, p, pp - p));
|
||||
while (true) {
|
||||
|
||||
size_t sep = find_file_sep (infile, p);
|
||||
if (sep == std::string::npos) {
|
||||
files.back ().push_back (std::string (infile, p));
|
||||
return files;
|
||||
}
|
||||
|
||||
files.back ().push_back (std::string (infile, p, sep - p));
|
||||
if (infile [sep] == ',') {
|
||||
files.push_back (std::vector<std::string> ());
|
||||
}
|
||||
|
||||
p = sep + 1;
|
||||
|
||||
}
|
||||
files.push_back (std::string (infile, p));
|
||||
|
||||
return files;
|
||||
}
|
||||
|
|
@ -850,16 +865,47 @@ void read_files (db::Layout &layout, const std::string &infile, const db::LoadLa
|
|||
// db::LayoutLocker locker (&layout);
|
||||
// but there are yet unknown side effects
|
||||
|
||||
// enter a LEF caching context for chaining multiple DEF with the same LEF
|
||||
db::LoadLayoutOptions local_options (options);
|
||||
local_options.set_option_by_name ("lefdef_config.lef_context_enabled", true);
|
||||
std::vector<std::vector<std::string> > files = split_file_list (infile);
|
||||
|
||||
std::vector<std::string> files = split_file_list (infile);
|
||||
for (auto ff = files.begin (); ff != files.end (); ++ff) {
|
||||
|
||||
// enter a LEF caching context for chaining multiple DEF with the same LEF
|
||||
db::LoadLayoutOptions local_options (options);
|
||||
local_options.set_option_by_name ("lefdef_config.lef_context_enabled", true);
|
||||
|
||||
db::Layout tmp;
|
||||
db::Layout *ly = (ff == files.begin () ? &layout : &tmp);
|
||||
|
||||
for (auto f = ff->begin (); f != ff->end (); ++f) {
|
||||
tl::InputStream stream (*f);
|
||||
db::Reader reader (stream);
|
||||
if (f != ff->begin ()) {
|
||||
reader.set_expected_dbu (ly->dbu ());
|
||||
}
|
||||
reader.read (*ly, local_options);
|
||||
}
|
||||
|
||||
if (ly != &layout) {
|
||||
|
||||
// Move over cells from read layout to destination ("," separated blocks).
|
||||
// This path does not imply limitations in terms of DBU compatibility etc.
|
||||
|
||||
std::vector<db::cell_index_type> cells_target;
|
||||
std::vector<db::cell_index_type> cells_source;
|
||||
for (auto c = tmp.begin_top_down (); c != tmp.end_top_cells (); ++c) {
|
||||
cells_source.push_back (*c);
|
||||
cells_target.push_back (layout.add_cell (tmp.cell_name (*c)));
|
||||
}
|
||||
|
||||
db::LayerMapping lm;
|
||||
lm.create_full (layout, tmp);
|
||||
db::CellMapping cm;
|
||||
cm.create_multi_mapping_full (layout, cells_target, tmp, cells_source);
|
||||
|
||||
layout.move_tree_shapes (tmp, cm, lm);
|
||||
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::const_iterator f = files.begin (); f != files.end (); ++f) {
|
||||
tl::InputStream stream (*f);
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout, local_options);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -483,7 +483,7 @@ TEST(10)
|
|||
std::string input;
|
||||
for (size_t i = 0; i < sizeof (def_files) / sizeof (def_files[0]); ++i) {
|
||||
if (i > 0) {
|
||||
input += ",";
|
||||
input += "+";
|
||||
}
|
||||
input += def_dir + "/" + def_files[i];
|
||||
}
|
||||
|
|
@ -510,3 +510,85 @@ TEST(10)
|
|||
|
||||
db::compare_layouts (this, layout, input_au, db::WriteOAS);
|
||||
}
|
||||
|
||||
// Merging with +
|
||||
TEST(11_1)
|
||||
{
|
||||
std::string input_dir = tl::testdata ();
|
||||
input_dir += "/bd";
|
||||
|
||||
std::string input_au = input_dir + "/strm2oas_au_1.oas";
|
||||
std::string input = input_dir + "/strm2oas_1.oas+" + input_dir + "/strm2oas_2.oas";
|
||||
|
||||
std::string output = this->tmp_file ("strm2oas_1.oas");
|
||||
const char *argv[] = { "x",
|
||||
"--blend-mode=0",
|
||||
input.c_str (),
|
||||
output.c_str ()
|
||||
};
|
||||
|
||||
EXPECT_EQ (bd::converter_main (sizeof (argv) / sizeof (argv[0]), (char **) argv, bd::GenericWriterOptions::oasis_format_name), 0);
|
||||
|
||||
db::Layout layout;
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::LoadLayoutOptions options;
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout, options);
|
||||
}
|
||||
|
||||
db::compare_layouts (this, layout, input_au, db::WriteOAS);
|
||||
}
|
||||
|
||||
// Merging with + not allowed on different DBUs
|
||||
TEST(11_2)
|
||||
{
|
||||
std::string input_dir = tl::testdata ();
|
||||
input_dir += "/bd";
|
||||
|
||||
std::string input_au = input_dir + "/strm2oas_au_1.oas";
|
||||
std::string input = input_dir + "/strm2oas_1.oas+" + input_dir + "/strm2oas_2_10nm.oas";
|
||||
|
||||
std::string output = this->tmp_file ("strm2oas_1.oas");
|
||||
const char *argv[] = { "x",
|
||||
"--blend-mode=0",
|
||||
input.c_str (),
|
||||
output.c_str ()
|
||||
};
|
||||
|
||||
try {
|
||||
bd::converter_main (sizeof (argv) / sizeof (argv[0]), (char **) argv, bd::GenericWriterOptions::oasis_format_name);
|
||||
EXPECT_EQ (1, 0);
|
||||
} catch (tl::Exception &ex) {
|
||||
EXPECT_EQ (ex.msg (), "Former and present database units are not compatible: 0.001 (former) vs. 0.01 (present)");
|
||||
}
|
||||
}
|
||||
|
||||
// Merging with + not allowed on different DBUs
|
||||
TEST(11_3)
|
||||
{
|
||||
std::string input_dir = tl::testdata ();
|
||||
input_dir += "/bd";
|
||||
|
||||
std::string input_au = input_dir + "/strm2oas_au_3.oas";
|
||||
std::string input = input_dir + "/strm2oas_1.oas," + input_dir + "/strm2oas_2_10nm.oas";
|
||||
|
||||
std::string output = this->tmp_file ("strm2oas_3.oas");
|
||||
const char *argv[] = { "x",
|
||||
"--blend-mode=0",
|
||||
input.c_str (),
|
||||
output.c_str ()
|
||||
};
|
||||
|
||||
EXPECT_EQ (bd::converter_main (sizeof (argv) / sizeof (argv[0]), (char **) argv, bd::GenericWriterOptions::oasis_format_name), 0);
|
||||
|
||||
db::Layout layout;
|
||||
{
|
||||
tl::InputStream stream (output);
|
||||
db::LoadLayoutOptions options;
|
||||
db::Reader reader (stream);
|
||||
reader.read (layout, options);
|
||||
}
|
||||
|
||||
db::compare_layouts (this, layout, input_au, db::WriteOAS);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ ReaderBase::init (const db::LoadLayoutOptions &options)
|
|||
m_last_warning.clear ();
|
||||
m_warn_count_for_same_message = 0;
|
||||
m_first_warning = true;
|
||||
m_expected_dbu = 0.0;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -259,6 +259,22 @@ public:
|
|||
return mp_actual_reader->warnings_as_errors ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the expected database unit (see ReaderBase)
|
||||
*/
|
||||
void set_expected_dbu (double dbu)
|
||||
{
|
||||
return mp_actual_reader->set_expected_dbu (dbu);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the expected database unit
|
||||
*/
|
||||
double expected_dbu () const
|
||||
{
|
||||
return mp_actual_reader->expected_dbu ();
|
||||
}
|
||||
|
||||
private:
|
||||
ReaderBase *mp_actual_reader;
|
||||
tl::InputStream &m_stream;
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue