Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/buddies/src/bd/bdConverterMain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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))
;

Expand Down
98 changes: 85 additions & 13 deletions src/buddies/src/bd/bdReaderOptions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include "bdReaderOptions.h"
#include "dbLoadLayoutOptions.h"
#include "dbLayerMapping.h"
#include "dbCellMapping.h"
#include "tlCommandLineParser.h"

#include "tlStream.h"
Expand Down Expand Up @@ -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;
}
Expand All @@ -850,16 +865,73 @@ 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);

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);

// as a special rule, join ghost cells if the source top cell fits into
// a ghost cell of the target.
auto cell_target = layout.cell_by_name (tmp.cell_name (*c));
if (cell_target.first && layout.cell (cell_target.second).is_ghost_cell ()) {
cells_target.push_back (cell_target.second);
} else {
cells_target.push_back (layout.add_cell (tmp.cell_name (*c)));
}

}

// ghost cell joining also works the other way around: a top cell of destination
// can match a ghost cell of the source
for (auto c = tmp.end_top_cells (); c != tmp.end_top_down (); ++c) {

const db::Cell &cell_source = tmp.cell (*c);
auto cell_target = layout.cell_by_name (tmp.cell_name (*c));

if (cell_source.is_ghost_cell () && cell_target.first) {
cells_source.push_back (*c);
cells_target.push_back (cell_target.second);
}

}

db::CellMapping cm;
cm.create_multi_mapping_full (layout, cells_target, tmp, cells_source);

db::LayerMapping lm;
lm.create_full (layout, tmp);

layout.move_tree_shapes (tmp, cm, lm);

std::vector<std::string> files = split_file_list (infile);
}

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);
}
}

Expand Down
200 changes: 199 additions & 1 deletion src/buddies/unit_tests/bdConverterTests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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];
}
Expand All @@ -510,3 +510,201 @@ 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);
}

// Merging with + and , under the presence of ghost cells: test+test,top->(test)
TEST(12_1)
{
std::string input_dir = tl::testdata ();
input_dir += "/bd";

std::string input_au = input_dir + "/strm2oas_au_12_1.oas";
std::string input = input_dir + "/strm2oas_a.oas+" + input_dir + "/strm2oas_b.oas," + input_dir + "/strm2oas_c.oas";

std::string output = this->tmp_file ("strm2oas_12_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 + and , under the presence of ghost cells: top->(test),test+test
TEST(12_2)
{
std::string input_dir = tl::testdata ();
input_dir += "/bd";

std::string input_au = input_dir + "/strm2oas_au_12_2.oas";
std::string input = input_dir + "/strm2oas_c.oas," + input_dir + "/strm2oas_a.oas+" + input_dir + "/strm2oas_b.oas";

std::string output = this->tmp_file ("strm2oas_12_2.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 + and , under the presence of ghost cells: test+test,toptop->top->(test)
TEST(12_3)
{
std::string input_dir = tl::testdata ();
input_dir += "/bd";

std::string input_au = input_dir + "/strm2oas_au_12_3.oas";
std::string input = input_dir + "/strm2oas_a.oas+" + input_dir + "/strm2oas_b.oas," + input_dir + "/strm2oas_cc.oas";

std::string output = this->tmp_file ("strm2oas_12_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);
}

// Merging with + and , under the presence of ghost cells: toptop->top->(test),test+test
TEST(12_4)
{
std::string input_dir = tl::testdata ();
input_dir += "/bd";

std::string input_au = input_dir + "/strm2oas_au_12_4.oas";
std::string input = input_dir + "/strm2oas_cc.oas," + input_dir + "/strm2oas_a.oas+" + input_dir + "/strm2oas_b.oas";

std::string output = this->tmp_file ("strm2oas_12_4.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);
}
16 changes: 15 additions & 1 deletion src/db/db/dbReader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ join_layer_names (std::string &s, const std::string &n)
// ReaderBase implementation

ReaderBase::ReaderBase ()
: m_warnings_as_errors (false), m_warn_level (1), m_warn_count_for_same_message (0), m_first_warning (true)
: m_warnings_as_errors (false), m_warn_level (1), m_warn_count_for_same_message (0), m_first_warning (true), m_expected_dbu (0.0)
{
}

Expand Down Expand Up @@ -114,6 +114,20 @@ ReaderBase::compress_warning (const std::string &msg)
}
}

void
ReaderBase::set_expected_dbu (double dbu)
{
m_expected_dbu = dbu;
}

void
ReaderBase::check_dbu (double dbu) const
{
if (m_expected_dbu > db::epsilon && fabs (dbu - m_expected_dbu) > db::epsilon) {
throw ReaderException (tl::sprintf (tl::to_string (tr ("Former and present database units are not compatible: %.12g (former) vs. %.12g (present)")), m_expected_dbu, dbu));
}
}

// ---------------------------------------------------------------
// Reader implementation

Expand Down
Loading
Loading