Some refactoring of buddy bodies and first strmcmp implementation

* Missing: functionaliy for strmcmp
This commit is contained in:
Matthias Koefferlein 2017-08-18 09:46:28 +02:00
parent bd5c7decce
commit b4a1143588
12 changed files with 279 additions and 215 deletions

View File

@ -24,6 +24,7 @@
#define HDR_bdInit
#include "bdCommon.h"
#include "tlLog.h" // because of BD_MAIN
namespace bd
{
@ -34,6 +35,44 @@ namespace bd
*/
void BD_PUBLIC init ();
/**
* @brief Provides a main () implementation
*
* Use this macro like this:
*
* @code
* #include "bdInit.h"
*
* BD_MAIN_FUNC
* {
* .. your code. Use argc and argv for the arguments.
* }
*
* BD_MAIN
*/
#define BD_MAIN \
int main (int argc, char *argv []) \
{ \
try { \
bd::init (); \
return main_func (argc, argv); \
} catch (tl::CancelException & /*ex*/) { \
return 1; \
} catch (std::exception &ex) { \
tl::error << ex.what (); \
return 1; \
} catch (tl::Exception &ex) { \
tl::error << ex.msg (); \
return 1; \
} catch (...) { \
tl::error << "unspecific error"; \
} \
}
#define BD_MAIN_FUNC \
int main_func (int argc, char *argv [])
}
#endif

View File

@ -28,7 +28,7 @@ namespace bd
{
GenericReaderOptions::GenericReaderOptions ()
: m_create_other_layers (true)
: m_prefix ("i"), m_group_prefix ("Input"), m_create_other_layers (true)
{
// .. nothing yet ..
}
@ -37,16 +37,16 @@ void
GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
{
{
std::string group ("[Input options - General]");
std::string group ("[" + m_group_prefix + " options - General]");
cmd << tl::arg (group +
"!-is|--skip-unknown-layers", &m_create_other_layers, "Skips unknown layers",
"!-" + m_prefix + "s|--" + m_long_prefix + "skip-unknown-layers", &m_create_other_layers, "Skips unknown layers",
"This option is effective with the the --layer-map option. If combined with "
"--skip-unknown-layers, layers not listed in the layer map will not be read. "
"By default, corresponding entries are created also for unknown layers."
)
<< tl::arg (group +
"-im|--layer-map=map", this, &GenericReaderOptions::set_layer_map, "Specifies the layer mapping for the input",
"-" + m_prefix + "m|--" + m_long_prefix + "layer-map=map", this, &GenericReaderOptions::set_layer_map, "Specifies the layer mapping for the input",
"This option specifies a layer selection or mapping. The selection or mapping is a sequence of source and optional "
"target specifications. The specifications are separated by blanks or double-slash sequences (//).\n"
"\n"
@ -76,37 +76,37 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
}
{
std::string group ("[Input options - GDS2 and OASIS]");
std::string group ("[" + m_group_prefix + " options - GDS2 and OASIS specific]");
cmd << tl::arg (group +
"#!--disable-texts", &m_common_reader_options.enable_text_objects, "Skips text objects",
"#!--" + m_long_prefix + "disable-texts", &m_common_reader_options.enable_text_objects, "Skips text objects",
"With this option set, text objects won't be read."
)
<< tl::arg (group +
"#!--disable-properties", &m_common_reader_options.enable_properties, "Skips properties",
"#!--" + m_long_prefix + "disable-properties", &m_common_reader_options.enable_properties, "Skips properties",
"With this option set, properties won't be read."
)
;
}
{
std::string group ("[Input options - GDS2]");
std::string group ("[" + m_group_prefix + " options - GDS2 specific]");
cmd << tl::arg (group +
"#!--no-multi-xy-records", &m_gds2_reader_options.allow_multi_xy_records, "Gives an error on multi-XY records",
"#!--" + m_long_prefix + "no-multi-xy-records", &m_gds2_reader_options.allow_multi_xy_records, "Gives an error on multi-XY records",
"This option disables an advanced interpretation of GDS2 which allows unlimited polygon and path "
"complexity. For compatibility with other readers, this option restores the standard behavior and "
"disables this feature."
)
<< tl::arg (group +
"#!--no-big-records", &m_gds2_reader_options.allow_big_records, "Gives an error on big (>32767 bytes) records",
"#!--" + m_long_prefix + "no-big-records", &m_gds2_reader_options.allow_big_records, "Gives an error on big (>32767 bytes) records",
"The GDS2 specification claims the record length to be a signed 16 bit value. So a record "
"can be 32767 bytes max. To allow bigger records (i.e. bigger polygons), the usual approach "
"is to take the length as a unsigned 16 bit value, so the length is up to 65535 bytes. "
"This option restores the original behavior and reports big (>32767 bytes) records are errors."
)
<< tl::arg (group +
"-ib|--box-mode=mode", &m_gds2_reader_options.box_mode, "Specifies how BOX records are read",
"-" + m_prefix + "b|--" + m_long_prefix + "box-mode=mode", &m_gds2_reader_options.box_mode, "Specifies how BOX records are read",
"This an option provided for compatibility with other readers. The mode value specifies how "
"BOX records are read:\n"
"\n"
@ -119,10 +119,10 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
}
{
std::string group ("[Input options - OASIS]");
std::string group ("[" + m_group_prefix + " options - OASIS specific]");
cmd << tl::arg (group +
"#--expect-strict-mode=mode", &m_oasis_reader_options.expect_strict_mode, "Makes the reader expect strict or non-strict mode",
"#--" + m_long_prefix + "expect-strict-mode=mode", &m_oasis_reader_options.expect_strict_mode, "Makes the reader expect strict or non-strict mode",
"With this option, the OASIS reader will expect strict mode (mode is 1) or expect non-strict mode "
"(mode is 0). By default, both modes are allowed. This is a diagnostic feature and does not "
"have any other effect than checking the mode."
@ -131,10 +131,10 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
}
{
std::string group ("[Input options - CIF and DXF]");
std::string group ("[" + m_group_prefix + " options - CIF and DXF specific]");
cmd << tl::arg (group +
"-id|--dbu-in=dbu", this, &GenericReaderOptions::set_dbu, "Specifies the database unit to use",
"-" + m_prefix + "d|--" + m_long_prefix + "dbu-in=dbu", this, &GenericReaderOptions::set_dbu, "Specifies the database unit to use",
"This option specifies the database unit the resulting layer will have. "
"The value is given in micrometer units. The default value is 1nm (0.001)."
)
@ -142,10 +142,10 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
}
{
std::string group ("[Input options - CIF]");
std::string group ("[" + m_group_prefix + " options - CIF specific]");
cmd << tl::arg (group +
"-iw|--wire-mode=mode", &m_cif_reader_options.wire_mode, "Specifies how wires (W) are read",
"-" + m_prefix + "w|--" + m_long_prefix + "wire-mode=mode", &m_cif_reader_options.wire_mode, "Specifies how wires (W) are read",
"This option specifies how wire objects (W) are read:\n"
"\n"
"* 0: as square ended paths (the default)\n"
@ -156,22 +156,22 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
}
{
std::string group ("[Input options - DXF]");
std::string group ("[" + m_group_prefix + " options - DXF specific]");
cmd << tl::arg (group +
"-iu|--dxf-unit=unit", &m_dxf_reader_options.unit, "Specifies the DXF drawing units",
"-" + m_prefix + "u|--" + m_long_prefix + "dxf-unit=unit", &m_dxf_reader_options.unit, "Specifies the DXF drawing units",
"Since DXF is unitless, this value needs to be given to specify the drawing units. "
"By default, a drawing unit of micrometers is assumed."
)
<< tl::arg (group +
"#--dxf-text-scaling=factor", &m_dxf_reader_options.text_scaling, "Specifies text scaling",
"#--" + m_long_prefix + "dxf-text-scaling=factor", &m_dxf_reader_options.text_scaling, "Specifies text scaling",
"This value specifies text scaling in percent. A value of 100 roughly means that the letter "
"pitch of the font will be 92% of the specified text height. That value applies for ROMANS fonts. "
"When generating GDS texts, a value of 100 generates TEXT objects with "
"the specified size. Smaller values generate smaller sizes."
)
<< tl::arg (group +
"#--dxf-polyline-mode=mode", &m_dxf_reader_options.polyline_mode, "Specifies how POLYLINE records are handled",
"#--" + m_long_prefix + "dxf-polyline-mode=mode", &m_dxf_reader_options.polyline_mode, "Specifies how POLYLINE records are handled",
"This value specifies how POLYLINE records are handled:\n"
"\n"
"* 0: automatic mode\n"
@ -181,11 +181,11 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
"* 4: as 3 and auto-close contours"
)
<< tl::arg (group +
"#--dxf-circle-points=points", &m_dxf_reader_options.circle_points, "Specifies the number of points for a full circle for arc interpolation",
"See --dxf-circle-accuracy for another way of specifying the number of points per circle."
"#--" + m_long_prefix + "dxf-circle-points=points", &m_dxf_reader_options.circle_points, "Specifies the number of points for a full circle for arc interpolation",
"See --" + m_long_prefix + "dxf-circle-accuracy for another way of specifying the number of points per circle."
)
<< tl::arg (group +
"#--dxf-circle-accuracy=value", &m_dxf_reader_options.circle_accuracy, "Specifies the accuracy of circle approximation",
"#--" + m_long_prefix + "dxf-circle-accuracy=value", &m_dxf_reader_options.circle_accuracy, "Specifies the accuracy of circle approximation",
"This value specifies the approximation accuracy of the circle and other\n"
"\"round\" structures. If this value is a positive number bigger than the\n"
"database unit (see dbu), it will control the number of points the\n"
@ -198,11 +198,11 @@ GenericReaderOptions::add_options (tl::CommandLineOptions &cmd)
"The value is given in the units of the DXF file."
)
<< tl::arg (group +
"#--dxf-render-texts-as-polygons", &m_dxf_reader_options.render_texts_as_polygons, "Renders texts as polygons",
"#--" + m_long_prefix + "dxf-render-texts-as-polygons", &m_dxf_reader_options.render_texts_as_polygons, "Renders texts as polygons",
"If this option is used, texts are converted to polygons instead of being converted to labels."
)
<< tl::arg (group +
"#--dxf-keep-other-cells", &m_dxf_reader_options.keep_other_cells, "Keeps cells which are not instantiated by the top cell",
"#--" + m_long_prefix + "dxf-keep-other-cells", &m_dxf_reader_options.keep_other_cells, "Keeps cells which are not instantiated by the top cell",
"With this option, all cells not found to be instantiated are kept as additional top cells. "
"By default, such cells are removed."
)

View File

@ -67,7 +67,38 @@ public:
*/
void configure (db::LoadLayoutOptions &load_options);
/**
* @brief Sets the option prefix for the short option name
* By default, the prefix is set to "i", so the short options are
* called "-is", "-id" etc.
*/
void set_prefix (const std::string &s)
{
m_prefix = s;
}
/**
* @brief Sets the option prefix for the long option name
* The prefix is prepended to the name, so with "a-", the long names
* are "--a-unit" etc. By default, this prefix is empty.
*/
void set_long_prefix (const std::string &s)
{
m_long_prefix = s;
}
/**
* @brief Sets the group name prefix
* By default, this prefix is "Input", so the group names are
* "Input options - GDS2" for example.
*/
void set_group_prefix (const std::string &s)
{
m_group_prefix = s;
}
private:
std::string m_prefix, m_long_prefix, m_group_prefix;
db::LayerMap m_layer_map;
bool m_create_other_layers;
db::CommonReaderOptions m_common_reader_options;

View File

@ -28,11 +28,8 @@
#include "dbCIFWriter.h"
#include "tlCommandLineParser.h"
int
main_func (int argc, char *argv [])
BD_MAIN_FUNC
{
bd::init ();
bd::GenericWriterOptions generic_writer_options;
bd::GenericReaderOptions generic_reader_options;
std::string infile, outfile;
@ -49,9 +46,7 @@ main_func (int argc, char *argv [])
cmd.parse (argc, argv);
db::Manager m;
db::Layout layout (&m);
db::LayerMap map;
db::Layout layout;
{
db::LoadLayoutOptions load_options;
@ -59,7 +54,7 @@ main_func (int argc, char *argv [])
tl::InputStream stream (infile);
db::Reader reader (stream);
map = reader.read (layout, load_options);
reader.read (layout, load_options);
}
{
@ -74,20 +69,4 @@ main_func (int argc, char *argv [])
return 0;
}
int
main (int argc, char *argv [])
{
try {
return main_func (argc, argv);
} catch (tl::CancelException & /*ex*/) {
return 1;
} catch (std::exception &ex) {
tl::error << ex.what ();
return 1;
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
return 1;
} catch (...) {
tl::error << "ERROR: unspecific error";
}
}
BD_MAIN

View File

@ -28,11 +28,8 @@
#include "dbDXFWriter.h"
#include "tlCommandLineParser.h"
int
main_func (int argc, char *argv [])
BD_MAIN_FUNC
{
bd::init ();
bd::GenericWriterOptions generic_writer_options;
bd::GenericReaderOptions generic_reader_options;
std::string infile, outfile;
@ -49,9 +46,7 @@ main_func (int argc, char *argv [])
cmd.parse (argc, argv);
db::Manager m;
db::Layout layout (&m);
db::LayerMap map;
db::Layout layout;
{
db::LoadLayoutOptions load_options;
@ -59,7 +54,7 @@ main_func (int argc, char *argv [])
tl::InputStream stream (infile);
db::Reader reader (stream);
map = reader.read (layout, load_options);
reader.read (layout, load_options);
}
{
@ -74,20 +69,4 @@ main_func (int argc, char *argv [])
return 0;
}
int
main (int argc, char *argv [])
{
try {
return main_func (argc, argv);
} catch (tl::CancelException & /*ex*/) {
return 1;
} catch (std::exception &ex) {
tl::error << ex.what ();
return 1;
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
return 1;
} catch (...) {
tl::error << "ERROR: unspecific error";
}
}
BD_MAIN

View File

@ -28,11 +28,8 @@
#include "dbGDS2Writer.h"
#include "tlCommandLineParser.h"
int
main_func (int argc, char *argv [])
BD_MAIN_FUNC
{
bd::init ();
bd::GenericWriterOptions generic_writer_options;
bd::GenericReaderOptions generic_reader_options;
std::string infile, outfile;
@ -49,9 +46,7 @@ main_func (int argc, char *argv [])
cmd.parse (argc, argv);
db::Manager m;
db::Layout layout (&m);
db::LayerMap map;
db::Layout layout;
{
db::LoadLayoutOptions load_options;
@ -59,7 +54,7 @@ main_func (int argc, char *argv [])
tl::InputStream stream (infile);
db::Reader reader (stream);
map = reader.read (layout, load_options);
reader.read (layout, load_options);
}
{
@ -74,20 +69,4 @@ main_func (int argc, char *argv [])
return 0;
}
int
main (int argc, char *argv [])
{
try {
return main_func (argc, argv);
} catch (tl::CancelException & /*ex*/) {
return 1;
} catch (std::exception &ex) {
tl::error << ex.what ();
return 1;
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
return 1;
} catch (...) {
tl::error << "ERROR: unspecific error";
}
}
BD_MAIN

View File

@ -28,11 +28,8 @@
#include "contrib/dbGDS2TextWriter.h"
#include "tlCommandLineParser.h"
int
main_func (int argc, char *argv [])
BD_MAIN_FUNC
{
bd::init ();
bd::GenericWriterOptions generic_writer_options;
bd::GenericReaderOptions generic_reader_options;
std::string infile, outfile;
@ -49,9 +46,7 @@ main_func (int argc, char *argv [])
cmd.parse (argc, argv);
db::Manager m;
db::Layout layout (&m);
db::LayerMap map;
db::Layout layout;
{
db::LoadLayoutOptions load_options;
@ -59,7 +54,7 @@ main_func (int argc, char *argv [])
tl::InputStream stream (infile);
db::Reader reader (stream);
map = reader.read (layout, load_options);
reader.read (layout, load_options);
}
{
@ -74,20 +69,4 @@ main_func (int argc, char *argv [])
return 0;
}
int
main (int argc, char *argv [])
{
try {
return main_func (argc, argv);
} catch (tl::CancelException & /*ex*/) {
return 1;
} catch (std::exception &ex) {
tl::error << ex.what ();
return 1;
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
return 1;
} catch (...) {
tl::error << "ERROR: unspecific error";
}
}
BD_MAIN

View File

@ -28,11 +28,8 @@
#include "dbOASISWriter.h"
#include "tlCommandLineParser.h"
int
main_func (int argc, char *argv [])
BD_MAIN_FUNC
{
bd::init ();
bd::GenericWriterOptions generic_writer_options;
bd::GenericReaderOptions generic_reader_options;
std::string infile, outfile;
@ -49,9 +46,7 @@ main_func (int argc, char *argv [])
cmd.parse (argc, argv);
db::Manager m;
db::Layout layout (&m);
db::LayerMap map;
db::Layout layout;
{
db::LoadLayoutOptions load_options;
@ -59,7 +54,7 @@ main_func (int argc, char *argv [])
tl::InputStream stream (infile);
db::Reader reader (stream);
map = reader.read (layout, load_options);
reader.read (layout, load_options);
}
{
@ -74,20 +69,4 @@ main_func (int argc, char *argv [])
return 0;
}
int
main (int argc, char *argv [])
{
try {
return main_func (argc, argv);
} catch (tl::CancelException & /*ex*/) {
return 1;
} catch (std::exception &ex) {
tl::error << ex.what ();
return 1;
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
return 1;
} catch (...) {
tl::error << "ERROR: unspecific error";
}
}
BD_MAIN

View File

@ -27,11 +27,8 @@
#include "dbTextWriter.h"
#include "tlCommandLineParser.h"
int
main_func (int argc, char *argv [])
BD_MAIN_FUNC
{
bd::init ();
bd::GenericReaderOptions generic_reader_options;
std::string infile, outfile;
@ -46,9 +43,7 @@ main_func (int argc, char *argv [])
cmd.parse (argc, argv);
db::Manager m;
db::Layout layout (&m);
db::LayerMap map;
db::Layout layout;
{
db::LoadLayoutOptions load_options;
@ -56,7 +51,7 @@ main_func (int argc, char *argv [])
tl::InputStream stream (infile);
db::Reader reader (stream);
map = reader.read (layout, load_options);
reader.read (layout, load_options);
}
{
@ -68,20 +63,4 @@ main_func (int argc, char *argv [])
return 0;
}
int
main (int argc, char *argv [])
{
try {
return main_func (argc, argv);
} catch (tl::CancelException & /*ex*/) {
return 1;
} catch (std::exception &ex) {
tl::error << ex.what ();
return 1;
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
return 1;
} catch (...) {
tl::error << "ERROR: unspecific error";
}
}
BD_MAIN

View File

@ -21,55 +21,147 @@
*/
#include "bdInit.h"
#include "bdReaderOptions.h"
#include "dbLayout.h"
#include "dbLayoutDiff.h"
#include "dbReader.h"
#include "tlCommandLineParser.h"
int
main (int argc, char *argv [])
BD_MAIN_FUNC
{
if (argc != 3) {
printf ("Syntax: strmcmp <infile-a> <infile-b>\n");
return 1;
bd::init ();
bd::GenericReaderOptions generic_reader_options_a;
generic_reader_options_a.set_prefix ("a");
generic_reader_options_a.set_long_prefix ("a-");
generic_reader_options_a.set_group_prefix ("Input A");
bd::GenericReaderOptions generic_reader_options_b;
generic_reader_options_a.set_prefix ("b");
generic_reader_options_a.set_long_prefix ("b-");
generic_reader_options_a.set_group_prefix ("Input B");
std::string infile_a, infile_b;
std::string top_a, top_b;
bool silent = false;
bool no_text_orientation = true;
bool no_text_details = true;
bool no_properties = false;
bool no_layer_names = false;
bool verbose = true;
bool as_polygons = false;
bool boxes_as_polygons = false;
bool flatten_array_insts = false;
bool smart_cell_mapping = false;
bool paths_as_polygons = false;
bool dont_summarize_missing_layers = false;
double tolerance = 0.0;
int max_count = 0;
bool print_properties = false;
tl::CommandLineOptions cmd;
generic_reader_options_a.add_options (cmd);
generic_reader_options_b.add_options (cmd);
cmd << tl::arg ("input_a", &infile_a, "The first input file (any format, may be gzip compressed)")
<< tl::arg ("input_b", &infile_b, "The second input file (any format, may be gzip compressed)")
<< tl::arg ("-ta|--top-a=name", &top_a, "Specifies the cell to take as top cell from the first layout",
"Use this option to take a specific cell as the top cell from the first layout. All "
"cells not called directly or indirectly from this cell are ignored. If you use this option, "
"--top-b must be specified too and can be different from the first layout's top cell."
)
<< tl::arg ("-tb|--top-b=name", &top_b, "Specifies the cell to take as top cell from the second layout",
"See --top-a for details."
)
<< tl::arg ("-s|--silent", &silent, "Enables silent mode",
"In silent mode, no differences are printed, but the exit code indicates whether "
"the layout are the same (0) or differences exist (> 0)."
)
<< tl::arg ("#!--with-text-orientation", &no_text_orientation, "Compares orientations for texts",
"With this option, text orientation is compared too. The position of the "
"text is always compared, but the rotation angle is compared only when this option "
"is present."
)
<< tl::arg ("#!--with-text-details", &no_text_details, "Compares font and alignment for texts",
"With this option, text font and alignment is compared too."
)
<< tl::arg ("-np|--without-properties", &no_properties, "Ignores properties",
"With this option, shape, cell and file properties are not compared."
)
<< tl::arg ("-nl|--without-layer-names", &no_layer_names, "Ignores layer names",
"With this option, layer names are not compared."
)
<< tl::arg ("!-u|--terse", &verbose, "Skips too many details",
"With this option, no details about differences are printed."
)
<< tl::arg ("-r|--print-properties", &print_properties, "Prints shape properties too",
"This option, shape properties are printed too."
)
<< tl::arg ("-p|--as-polygons", &as_polygons, "Compares shapes are polygons",
"This option is equivalent to using --boxes-as-polygons and --paths-as-polygons."
)
<< tl::arg ("--boxes-as-polygons", &boxes_as_polygons, "Turns boxes into polygons before compare",
"With this option, boxes and equivalent polygons are treated identical."
)
<< tl::arg ("--paths-as-polygons", &paths_as_polygons, "Turns paths into polygons before compare",
"With this option, paths and equivalent polygons are treated identical."
)
<< tl::arg ("--expand-arrays", &flatten_array_insts, "Expands array instances before compare",
"With this option, arrays are equivalent single instances are treated identical."
)
<< tl::arg ("-l|--layer-details", &dont_summarize_missing_layers, "Prints details about differences for missing layers",
"With this option, missing layers are treated as \"empty\" and details about differences to "
"other, non-empty layers are printed. Essentially the content of the non-empty counterpart "
"is printed. Without this option, missing layers are treated as a single difference of type "
"\"missing layer\"."
)
<< tl::arg ("-c|--cell-mapping", &smart_cell_mapping, "Attempts to identify cells by their properties",
"If this option is given, the algorithm will try to identify identical cells by their "
"geometrical properties (placement, size etc.) instead of their name. This way, cell renaming can "
"be detected"
)
<< tl::arg ("-t|--tolerance=value", &tolerance, "Specifies a tolerance for geometry compare",
"If this value is given, shape comparison allows for this tolerance when comparing "
"coordinates. The tolerance value is given in micrometer units."
)
<< tl::arg ("-m|--max-count=value", &max_count, "Specifies the maximum number of differences to report",
"If the value is 1, only a warning saying that the log has been abbreviated is printed. "
"If the value is >1, max-count-1 differences plus one warning about abbreviation is printed. "
"A value of 0 means \"no limitation\". To suppress all output, use --silent."
)
;
cmd.brief ("This program will compare two layout files on a per-object basis");
cmd.parse (argc, argv);
db::Layout layout_a;
db::Layout layout_b;
{
db::LoadLayoutOptions load_options;
generic_reader_options_a.configure (load_options);
tl::InputStream stream (infile_a);
db::Reader reader (stream);
reader.read (layout_a, load_options);
}
std::string infile_a (argv[1]);
std::string infile_b (argv[2]);
{
db::LoadLayoutOptions load_options;
generic_reader_options_b.configure (load_options);
try {
tl::InputStream stream (infile_a);
db::Reader reader (stream);
reader.read (layout_b, load_options);
}
db::Manager m;
db::Layout layout_a (false, &m);
db::Layout layout_b (false, &m);
{
tl::InputStream stream (infile_a);
db::Reader reader (stream);
reader.read (layout_a);
}
{
tl::InputStream stream (infile_b);
db::Reader reader (stream);
reader.read (layout_b);
}
if (! db::compare_layouts (layout_a, layout_b, db::layout_diff::f_boxes_as_polygons | db::layout_diff::f_no_text_orientation | db::layout_diff::f_verbose, 0 /*exact match*/)) {
throw tl::Exception ("layouts differ");
}
} catch (std::exception &ex) {
tl::error << ex.what ();
return 1;
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
return 1;
} catch (...) {
tl::error << "unspecific error";
return 1;
// @@@
if (! db::compare_layouts (layout_a, layout_b, db::layout_diff::f_boxes_as_polygons | db::layout_diff::f_no_text_orientation | db::layout_diff::f_verbose, 0 /*exact match*/)) {
throw tl::Exception ("layouts differ");
}
return 0;
}
BD_MAIN

View File

@ -1580,5 +1580,14 @@ compare_layouts (const db::Layout &a, const db::Layout &b, unsigned int flags, d
return compare_layouts (a, b, flags, tolerance, r);
}
bool
compare_layouts (const db::Layout &a, db::cell_index_type top_a, const db::Layout &b, db::cell_index_type top_b, unsigned int flags, db::Coord tolerance, size_t max_count, bool print_properties)
{
PrintingDifferenceReceiver r;
r.set_max_count (max_count);
r.set_print_properties (print_properties);
return compare_layouts (a, top_a, b, top_b, flags, tolerance, r);
}
}

View File

@ -130,9 +130,9 @@ public:
* @brief Compare two layout objects
*
* Compare layer definitions, cells, instances and shapes and properties.
* Cells are identified by name.
* Only layers with valid layer and datatype are compared.
* Several flags can be specified as a bitwise or combination of the layout_diff::f_xxx constants.
* The results are printed to the info channel.
*
* @param a The first input layout
* @param b The second input layout
@ -148,6 +148,25 @@ public:
*/
bool DB_PUBLIC compare_layouts (const db::Layout &a, const db::Layout &b, unsigned int flags, db::Coord tolerance, size_t max_count = 0, bool print_properties = false);
/**
* @brief Compare two layout objects
*
* This is an extended version that allows specification of two top cells to compare.
* It will print the results to the info channel.
*
* @param a The first input layout
* @param top_a The first top cell's index
* @param b The second input layout
* @param top_b The second top cell's index
* @param flags Flags to use for the comparison
* @param tolerance A coordinate tolerance to apply (0: exact match, 1: one DBU tolerance is allowed ...)
* @param max_count The maximum number of lines printed to the logger - the compare result will reflect all differences however
* @param print_properties If true, property differences are printed as well
*
* @return True, if the layouts are identical
*/
bool DB_PUBLIC compare_layouts (const db::Layout &a, db::cell_index_type top_a, const db::Layout &b, db::cell_index_type top_b, unsigned int flags, db::Coord tolerance, size_t max_count = 0, bool print_properties = false);
/**
* @brief Compare two layout objects with a custom receiver for the differences
*