2017-02-12 13:21:08 +01:00
/*
KLayout Layout Viewer
2018-01-01 21:08:06 +01:00
Copyright ( C ) 2006 - 2018 Matthias Koefferlein
2017-02-12 13:21:08 +01:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
2018-06-17 09:43:25 +02:00
# include "layDiffToolDialog.h"
2017-02-12 13:21:08 +01:00
# include "rdb.h"
# include "dbLayoutDiff.h"
# include "dbRecursiveShapeIterator.h"
# include "dbShapeProcessor.h"
# include "tlTimer.h"
# include "tlProgress.h"
# include "layCellView.h"
# include "layLayoutView.h"
# include "tlExceptions.h"
# include "ui_DiffToolDialog.h"
# include <stdio.h>
2018-06-17 09:43:25 +02:00
namespace lay
2017-02-12 13:21:08 +01:00
{
std : : string cfg_diff_run_xor ( " diff-run-xor " ) ;
std : : string cfg_diff_detailed ( " diff-detailed " ) ;
std : : string cfg_diff_smart ( " diff-smart " ) ;
std : : string cfg_diff_summarize ( " diff-summarize " ) ;
std : : string cfg_diff_expand_cell_arrays ( " diff-expand-cell-arrays " ) ;
std : : string cfg_diff_exact ( " diff-exact " ) ;
// ------------------------------------------------------------------------------
// RdbDifferenceReceiver definition
class RdbDifferenceReceiver
: public db : : DifferenceReceiver
{
public :
RdbDifferenceReceiver ( const db : : Layout & la , const db : : Layout & lb , rdb : : Database * rdb , bool detailed , bool with_properties , bool run_xor ) ;
void dbu_differs ( double dbu_a , double dbu_b ) ;
void layer_in_a_only ( const db : : LayerProperties & la ) ;
void layer_in_b_only ( const db : : LayerProperties & lb ) ;
void layer_name_differs ( const db : : LayerProperties & la , const db : : LayerProperties & lb ) ;
void cell_in_a_only ( const std : : string & cellname , db : : cell_index_type ci ) ;
void cell_in_b_only ( const std : : string & cellname , db : : cell_index_type ci ) ;
void cell_name_differs ( const std : : string & cellname_a , db : : cell_index_type cia , const std : : string & cellname_b , db : : cell_index_type cib ) ;
void bbox_differs ( const db : : Box & ba , const db : : Box & bb ) ;
void begin_cell ( const std : : string & cellname , db : : cell_index_type cia , db : : cell_index_type cib ) ;
void begin_inst_differences ( ) ;
void instances_in_a ( const std : : vector < db : : CellInstArrayWithProperties > & insts_a , const std : : vector < std : : string > & cell_names , const db : : PropertiesRepository & props ) ;
void instances_in_b ( const std : : vector < db : : CellInstArrayWithProperties > & insts_b , const std : : vector < std : : string > & cell_names , const db : : PropertiesRepository & props ) ;
void instances_in_a_only ( const std : : vector < db : : CellInstArrayWithProperties > & anotb , const db : : Layout & a ) ;
void instances_in_b_only ( const std : : vector < db : : CellInstArrayWithProperties > & bnota , const db : : Layout & b ) ;
void begin_layer ( const db : : LayerProperties & layer , unsigned int layer_index_a , bool is_valid_a , unsigned int layer_index_b , bool is_valid_b ) ;
void end_layer ( ) ;
void per_layer_bbox_differs ( const db : : Box & ba , const db : : Box & bb ) ;
void begin_polygon_differences ( ) ;
void detailed_diff ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < db : : Polygon , db : : properties_id_type > > & a , const std : : vector < std : : pair < db : : Polygon , db : : properties_id_type > > & b ) ;
void begin_path_differences ( ) ;
void detailed_diff ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < db : : Path , db : : properties_id_type > > & a , const std : : vector < std : : pair < db : : Path , db : : properties_id_type > > & b ) ;
void begin_box_differences ( ) ;
void detailed_diff ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < db : : Box , db : : properties_id_type > > & a , const std : : vector < std : : pair < db : : Box , db : : properties_id_type > > & b ) ;
void begin_edge_differences ( ) ;
void detailed_diff ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < db : : Edge , db : : properties_id_type > > & a , const std : : vector < std : : pair < db : : Edge , db : : properties_id_type > > & b ) ;
void begin_text_differences ( ) ;
void detailed_diff ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < db : : Text , db : : properties_id_type > > & a , const std : : vector < std : : pair < db : : Text , db : : properties_id_type > > & b ) ;
private :
const db : : Layout * mp_layout_a ;
const db : : Layout * mp_layout_b ;
rdb : : Database * mp_rdb ;
rdb : : Cell * mp_cell ;
rdb : : Cell * mp_topcell ;
rdb : : Category * mp_general_cat ;
rdb : : Category * mp_a_only_cat ;
rdb : : Category * mp_b_only_cat ;
std : : vector < rdb : : Category * > mp_a_only_per_layer_cat ;
std : : vector < rdb : : Category * > mp_b_only_per_layer_cat ;
std : : map < std : : pair < int , int > , rdb : : Category * > mp_xor_cat ;
std : : vector < db : : CellInstArrayWithProperties > m_insts_a , m_insts_b ;
std : : string m_cellname ;
db : : LayerProperties m_layer ;
unsigned int m_layer_index_a , m_layer_index_b ;
bool m_is_valid_layer_index_a , m_is_valid_layer_index_b ;
bool m_diffs_reported ;
bool m_with_properties ;
bool m_detailed ;
bool m_run_xor ;
db : : ShapeProcessor m_ep ;
size_t m_obj_index ;
void produce_cell_inst ( const db : : CellInstArrayWithProperties & ci , const db : : Layout * layout , const rdb : : Category * cat ) ;
template < class SH > void produce_diffs_for_xor ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < SH , db : : properties_id_type > > & a , const std : : vector < std : : pair < SH , db : : properties_id_type > > & b , double dbu_a , db : : Shapes & shapes ) ;
template < class SH > void produce_diffs ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < SH , db : : properties_id_type > > & a , const std : : vector < std : : pair < SH , db : : properties_id_type > > & b , double dbu_a , const rdb : : Category * cat ) ;
template < class SH > void shape_diffs ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < SH , db : : properties_id_type > > & a , const std : : vector < std : : pair < SH , db : : properties_id_type > > & b ) ;
void shape_diffs_found ( ) ;
} ;
RdbDifferenceReceiver : : RdbDifferenceReceiver ( const db : : Layout & layout_a , const db : : Layout & layout_b , rdb : : Database * rdb , bool detailed , bool with_properties , bool run_xor )
: mp_layout_a ( & layout_a ) ,
mp_layout_b ( & layout_b ) ,
mp_rdb ( rdb ) ,
mp_cell ( 0 ) ,
m_cellname ( ) ,
m_layer ( ) ,
m_layer_index_a ( 0 ) ,
m_layer_index_b ( 0 ) ,
m_is_valid_layer_index_a ( false ) ,
m_is_valid_layer_index_b ( false ) ,
m_diffs_reported ( false ) ,
m_with_properties ( with_properties ) ,
m_detailed ( detailed ) ,
m_run_xor ( run_xor )
{
mp_topcell = rdb - > create_cell ( " " /*dummy*/ ) ;
mp_general_cat = rdb - > create_category ( " Summary " ) ;
mp_general_cat - > set_description ( tl : : to_string ( QObject : : tr ( " Summary of Differences " ) ) ) ;
m_obj_index = 0 ;
std : : map < db : : LayerProperties , std : : pair < int , int > , db : : LPLogicalLessFunc > layers ;
for ( db : : Layout : : layer_iterator l = layout_a . begin_layers ( ) ; l ! = layout_a . end_layers ( ) ; + + l ) {
layers . insert ( std : : make_pair ( * ( * l ) . second , std : : make_pair ( - 1 , - 1 ) ) ) . first - > second . first = ( * l ) . first ;
}
for ( db : : Layout : : layer_iterator l = layout_b . begin_layers ( ) ; l ! = layout_b . end_layers ( ) ; + + l ) {
layers . insert ( std : : make_pair ( * ( * l ) . second , std : : make_pair ( - 1 , - 1 ) ) ) . first - > second . second = ( * l ) . first ;
}
if ( detailed ) {
rdb : : Category * instances_cat = rdb - > create_category ( " Instances " ) ;
instances_cat - > set_description ( tl : : to_string ( QObject : : tr ( " Differences in instances " ) ) ) ;
mp_a_only_cat = rdb - > create_category ( instances_cat , " A " ) ;
mp_a_only_cat - > set_description ( tl : : to_string ( QObject : : tr ( " Instances in A but not in B " ) ) ) ;
mp_b_only_cat = rdb - > create_category ( instances_cat , " B " ) ;
mp_b_only_cat - > set_description ( tl : : to_string ( QObject : : tr ( " Instances in B but not in A " ) ) ) ;
for ( std : : map < db : : LayerProperties , std : : pair < int , int > , db : : LPLogicalLessFunc > : : const_iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; + + l ) {
while ( ( int ) mp_a_only_per_layer_cat . size ( ) < = l - > second . first ) {
mp_a_only_per_layer_cat . push_back ( 0 ) ;
}
while ( ( int ) mp_b_only_per_layer_cat . size ( ) < = l - > second . second ) {
mp_b_only_per_layer_cat . push_back ( 0 ) ;
}
rdb : : Category * layer_cat = rdb - > create_category ( l - > first . to_string ( ) ) ;
layer_cat - > set_description ( tl : : to_string ( QObject : : tr ( " Differences in layer " ) ) + " " + l - > first . to_string ( ) ) ;
if ( l - > second . first > = 0 ) {
mp_a_only_per_layer_cat [ ( unsigned int ) l - > second . first ] = rdb - > create_category ( layer_cat , " A " ) ;
mp_a_only_per_layer_cat [ ( unsigned int ) l - > second . first ] - > set_description ( tl : : to_string ( QObject : : tr ( " Shapes in A but not in B, on Layer " ) ) + l - > first . to_string ( ) ) ;
}
if ( l - > second . second > = 0 ) {
mp_b_only_per_layer_cat [ ( unsigned int ) l - > second . second ] = rdb - > create_category ( layer_cat , " B " ) ;
mp_b_only_per_layer_cat [ ( unsigned int ) l - > second . second ] - > set_description ( tl : : to_string ( QObject : : tr ( " Shapes in B but not in A, on Layer " ) ) + l - > first . to_string ( ) ) ;
}
}
} else {
mp_a_only_cat = 0 ;
mp_b_only_cat = 0 ;
}
if ( run_xor ) {
for ( std : : map < db : : LayerProperties , std : : pair < int , int > , db : : LPLogicalLessFunc > : : const_iterator l = layers . begin ( ) ; l ! = layers . end ( ) ; + + l ) {
rdb : : Category * cat = rdb - > create_category ( std : : string ( " XOR " ) + l - > first . to_string ( ) ) ;
cat - > set_description ( tl : : to_string ( QObject : : tr ( " Geometrical differences on layer " ) ) + " " + l - > first . to_string ( ) ) ;
mp_xor_cat [ l - > second ] = cat ;
}
}
}
static void
add_property_text ( rdb : : Item * item , const db : : PropertiesRepository & pr , db : : properties_id_type prop_id )
{
if ( prop_id ! = 0 ) {
const db : : PropertiesRepository : : properties_set & p = pr . properties ( prop_id ) ;
for ( db : : PropertiesRepository : : properties_set : : const_iterator pp = p . begin ( ) ; pp ! = p . end ( ) ; + + pp ) {
const tl : : Variant & name = pr . prop_name ( pp - > first ) ;
std : : string r = std : : string ( " property: " ) + name . to_string ( ) + " = " + pp - > second . to_string ( ) ;
item - > add_value ( r ) ;
}
}
}
void
RdbDifferenceReceiver : : produce_cell_inst ( const db : : CellInstArrayWithProperties & ci , const db : : Layout * layout , const rdb : : Category * cat )
{
db : : box_convert < db : : CellInstArrayWithProperties > bc ( * layout ) ;
rdb : : Item * item = mp_rdb - > create_item ( mp_cell - > id ( ) , cat - > id ( ) ) ;
std : : string r = " item: " + tl : : sprintf ( tl : : to_string ( QObject : : tr ( " instance: (%s) %s " ) ) , layout - > cell_name ( ci . object ( ) . cell_index ( ) ) , ci . complex_trans ( ) . to_string ( ) ) ;
db : : Vector a , b ;
unsigned long amax , bmax ;
if ( ci . is_regular_array ( a , b , amax , bmax ) ) {
r + = tl : : sprintf ( " [a=%s, b=%s, na=%ld, nb=%ld] " , a . to_string ( ) , b . to_string ( ) , amax , bmax ) ;
}
item - > add_value ( r ) ;
db : : Box box = bc ( ci ) ;
item - > add_value ( box * layout - > dbu ( ) ) ;
if ( m_with_properties ) {
add_property_text ( item , layout - > properties_repository ( ) , ci . properties_id ( ) ) ;
}
}
void
RdbDifferenceReceiver : : dbu_differs ( double dbu_a , double dbu_b )
{
rdb : : Item * item = mp_rdb - > create_item ( mp_topcell - > id ( ) , mp_general_cat - > id ( ) ) ;
item - > add_value ( tl : : sprintf ( tl : : to_string ( QObject : : tr ( " Database units differ %g vs. %g " ) ) , dbu_a , dbu_b ) ) ;
}
void
RdbDifferenceReceiver : : layer_in_a_only ( const db : : LayerProperties & la )
{
rdb : : Item * item = mp_rdb - > create_item ( mp_topcell - > id ( ) , mp_general_cat - > id ( ) ) ;
item - > add_value ( tl : : sprintf ( tl : : to_string ( QObject : : tr ( " Layer %s is not present in layout B, but in A " ) ) , la . to_string ( ) ) ) ;
}
void
RdbDifferenceReceiver : : layer_in_b_only ( const db : : LayerProperties & lb )
{
rdb : : Item * item = mp_rdb - > create_item ( mp_topcell - > id ( ) , mp_general_cat - > id ( ) ) ;
item - > add_value ( tl : : sprintf ( tl : : to_string ( QObject : : tr ( " Layer %s is not present in layout A, but in B " ) ) , lb . to_string ( ) ) ) ;
}
void
RdbDifferenceReceiver : : layer_name_differs ( const db : : LayerProperties & la , const db : : LayerProperties & lb )
{
rdb : : Item * item = mp_rdb - > create_item ( mp_topcell - > id ( ) , mp_general_cat - > id ( ) ) ;
item - > add_value ( tl : : sprintf ( tl : : to_string ( QObject : : tr ( " Layer names differ between layout A and B for layer %d/%d: %s vs. %s " ) ) , la . layer , la . datatype , la . name , lb . name ) ) ;
}
void
RdbDifferenceReceiver : : cell_in_a_only ( const std : : string & cellname , db : : cell_index_type /*ci*/ )
{
rdb : : Item * item = mp_rdb - > create_item ( mp_topcell - > id ( ) , mp_general_cat - > id ( ) ) ;
item - > add_value ( tl : : sprintf ( tl : : to_string ( QObject : : tr ( " Cell %s is not present in layout B, but in A " ) ) , cellname ) ) ;
}
void
RdbDifferenceReceiver : : cell_in_b_only ( const std : : string & cellname , db : : cell_index_type /*ci*/ )
{
rdb : : Item * item = mp_rdb - > create_item ( mp_topcell - > id ( ) , mp_general_cat - > id ( ) ) ;
item - > add_value ( tl : : sprintf ( tl : : to_string ( QObject : : tr ( " Cell %s is not present in layout A, but in B " ) ) , cellname ) ) ;
}
void
RdbDifferenceReceiver : : cell_name_differs ( const std : : string & cellname_a , db : : cell_index_type /*cia*/ , const std : : string & cellname_b , db : : cell_index_type /*cib*/ )
{
rdb : : Item * item = mp_rdb - > create_item ( mp_topcell - > id ( ) , mp_general_cat - > id ( ) ) ;
item - > add_value ( tl : : sprintf ( tl : : to_string ( QObject : : tr ( " Cell %s in A is renamed to %s in B " ) ) , cellname_a , cellname_b ) ) ;
}
void
RdbDifferenceReceiver : : begin_cell ( const std : : string & cellname , db : : cell_index_type /*cia*/ , db : : cell_index_type /*cib*/ )
{
mp_cell = mp_rdb - > create_cell ( cellname ) ;
m_diffs_reported = false ;
m_insts_a . clear ( ) ;
m_insts_b . clear ( ) ;
}
void
RdbDifferenceReceiver : : bbox_differs ( const db : : Box & ba , const db : : Box & bb )
{
rdb : : Item * item = mp_rdb - > create_item ( mp_cell - > id ( ) , mp_general_cat - > id ( ) ) ;
item - > add_value ( tl : : sprintf ( tl : : to_string ( QObject : : tr ( " Bounding boxes differ: %s (A) vs. %s (B) " ) ) , ba . to_string ( ) , bb . to_string ( ) ) ) ;
}
void
RdbDifferenceReceiver : : begin_inst_differences ( )
{
rdb : : Item * item = mp_rdb - > create_item ( mp_cell - > id ( ) , mp_general_cat - > id ( ) ) ;
item - > add_value ( tl : : to_string ( QObject : : tr ( " Instances differ " ) ) ) ;
}
void
RdbDifferenceReceiver : : instances_in_a ( const std : : vector < db : : CellInstArrayWithProperties > & /*insts_a*/ , const std : : vector < std : : string > & /*cell_names*/ , const db : : PropertiesRepository & /*props*/ )
{
// .. nothing ..
}
void
RdbDifferenceReceiver : : instances_in_b ( const std : : vector < db : : CellInstArrayWithProperties > & /*insts_b*/ , const std : : vector < std : : string > & /*cell_names*/ , const db : : PropertiesRepository & /*props*/ )
{
// .. nothing ..
}
void
RdbDifferenceReceiver : : instances_in_a_only ( const std : : vector < db : : CellInstArrayWithProperties > & anotb , const db : : Layout & /*a*/ )
{
if ( m_detailed ) {
for ( std : : vector < db : : CellInstArrayWithProperties > : : const_iterator s = anotb . begin ( ) ; s ! = anotb . end ( ) ; + + s ) {
produce_cell_inst ( * s , mp_layout_a , mp_a_only_cat ) ;
}
}
if ( m_run_xor ) {
m_insts_a . insert ( m_insts_a . end ( ) , anotb . begin ( ) , anotb . end ( ) ) ;
}
}
void
RdbDifferenceReceiver : : instances_in_b_only ( const std : : vector < db : : CellInstArrayWithProperties > & bnota , const db : : Layout & /*b*/ )
{
if ( m_detailed ) {
for ( std : : vector < db : : CellInstArrayWithProperties > : : const_iterator s = bnota . begin ( ) ; s ! = bnota . end ( ) ; + + s ) {
produce_cell_inst ( * s , mp_layout_b , mp_b_only_cat ) ;
}
}
if ( m_run_xor ) {
m_insts_b . insert ( m_insts_b . end ( ) , bnota . begin ( ) , bnota . end ( ) ) ;
}
}
void
RdbDifferenceReceiver : : begin_layer ( const db : : LayerProperties & layer , unsigned int layer_index_a , bool is_valid_a , unsigned int layer_index_b , bool is_valid_b )
{
m_layer = layer ;
m_diffs_reported = false ;
m_layer_index_a = layer_index_a ;
m_is_valid_layer_index_a = is_valid_a ;
m_layer_index_b = layer_index_b ;
m_is_valid_layer_index_b = is_valid_b ;
if ( m_run_xor ) {
m_obj_index = 0 ;
if ( is_valid_a ) {
for ( std : : vector < db : : CellInstArrayWithProperties > : : const_iterator i = m_insts_a . begin ( ) ; i ! = m_insts_a . end ( ) ; + + i ) {
for ( db : : RecursiveShapeIterator shapes ( * mp_layout_a , mp_layout_a - > cell ( i - > object ( ) . cell_index ( ) ) , m_layer_index_a ) ; ! shapes . at_end ( ) ; + + shapes ) {
for ( db : : CellInstArray : : iterator a = i - > begin ( ) ; ! a . at_end ( ) ; + + a ) {
m_ep . insert ( shapes . shape ( ) , i - > complex_trans ( * a ) * shapes . trans ( ) , m_obj_index * 2 ) ;
+ + m_obj_index ;
}
}
}
}
if ( is_valid_b ) {
for ( std : : vector < db : : CellInstArrayWithProperties > : : const_iterator i = m_insts_b . begin ( ) ; i ! = m_insts_b . end ( ) ; + + i ) {
for ( db : : RecursiveShapeIterator shapes ( * mp_layout_b , mp_layout_b - > cell ( i - > object ( ) . cell_index ( ) ) , m_layer_index_b ) ; ! shapes . at_end ( ) ; + + shapes ) {
for ( db : : CellInstArray : : iterator a = i - > begin ( ) ; ! a . at_end ( ) ; + + a ) {
m_ep . insert ( shapes . shape ( ) , i - > complex_trans ( * a ) * shapes . trans ( ) , m_obj_index * 2 + 1 ) ;
+ + m_obj_index ;
}
}
}
}
}
}
void
RdbDifferenceReceiver : : end_layer ( )
{
if ( m_run_xor ) {
std : : vector < db : : Polygon > out_polygons ;
db : : BooleanOp op ( db : : BooleanOp : : Xor ) ;
db : : PolygonContainer pc ( out_polygons ) ;
db : : PolygonGenerator out ( pc , false /*don't resolve holes*/ , true /*min coherence*/ ) ;
m_ep . process ( out , op ) ;
db : : CplxTrans t ( mp_layout_a - > dbu ( ) ) ;
rdb : : Category * cat = mp_xor_cat [ std : : make_pair ( m_is_valid_layer_index_a ? m_layer_index_a : - 1 , m_is_valid_layer_index_b ? m_layer_index_b : - 1 ) ] ;
if ( cat ) {
for ( std : : vector < db : : Polygon > : : const_iterator x = out_polygons . begin ( ) ; x ! = out_polygons . end ( ) ; + + x ) {
rdb : : Item * item = mp_rdb - > create_item ( mp_cell - > id ( ) , cat - > id ( ) ) ;
item - > add_value ( t * * x ) ;
}
}
m_ep . clear ( ) ;
}
}
void
RdbDifferenceReceiver : : per_layer_bbox_differs ( const db : : Box & ba , const db : : Box & bb )
{
rdb : : Item * item = mp_rdb - > create_item ( mp_cell - > id ( ) , mp_general_cat - > id ( ) ) ;
item - > add_value ( tl : : sprintf ( tl : : to_string ( QObject : : tr ( " Per-layer bounding boxes differ (layer %s): %s (A) vs. %s (B) " ) ) , m_layer . to_string ( ) , ba . to_string ( ) , bb . to_string ( ) ) ) ;
}
void
RdbDifferenceReceiver : : shape_diffs_found ( )
{
if ( ! m_diffs_reported ) {
rdb : : Item * item = mp_rdb - > create_item ( mp_cell - > id ( ) , mp_general_cat - > id ( ) ) ;
item - > add_value ( tl : : sprintf ( tl : : to_string ( QObject : : tr ( " Shapes differ on layer %s " ) ) , m_layer . to_string ( ) ) ) ;
m_diffs_reported = true ;
}
}
void
RdbDifferenceReceiver : : begin_polygon_differences ( )
{
shape_diffs_found ( ) ;
}
inline std : : string shape_type ( const db : : Polygon & )
{
return " polygon " ;
}
inline std : : string shape_type ( const db : : Path & )
{
return " path " ;
}
inline std : : string shape_type ( const db : : Edge & )
{
return " edge " ;
}
inline std : : string shape_type ( const db : : Text & )
{
return " text " ;
}
inline std : : string shape_type ( const db : : Box & )
{
return " box " ;
}
template < class SH >
void
RdbDifferenceReceiver : : produce_diffs_for_xor ( const db : : PropertiesRepository & /*pr*/ , const std : : vector < std : : pair < SH , db : : properties_id_type > > & a , const std : : vector < std : : pair < SH , db : : properties_id_type > > & b , double dbu_a , db : : Shapes & shapes )
{
db : : CplxTrans t ( dbu_a ) ;
std : : vector < std : : pair < SH , db : : properties_id_type > > anotb ;
std : : set_difference ( a . begin ( ) , a . end ( ) , b . begin ( ) , b . end ( ) , std : : back_inserter ( anotb ) ) ;
for ( typename std : : vector < std : : pair < SH , db : : properties_id_type > > : : const_iterator s = anotb . begin ( ) ; s ! = anotb . end ( ) ; + + s ) {
shapes . insert ( s - > first ) ;
}
}
template < class SH >
void
RdbDifferenceReceiver : : produce_diffs ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < SH , db : : properties_id_type > > & a , const std : : vector < std : : pair < SH , db : : properties_id_type > > & b , double dbu_a , const rdb : : Category * cat )
{
db : : CplxTrans t ( dbu_a ) ;
std : : vector < std : : pair < SH , db : : properties_id_type > > anotb ;
std : : set_difference ( a . begin ( ) , a . end ( ) , b . begin ( ) , b . end ( ) , std : : back_inserter ( anotb ) ) ;
for ( typename std : : vector < std : : pair < SH , db : : properties_id_type > > : : const_iterator s = anotb . begin ( ) ; s ! = anotb . end ( ) ; + + s ) {
rdb : : Item * item = mp_rdb - > create_item ( mp_cell - > id ( ) , cat - > id ( ) ) ;
if ( s - > second & & m_with_properties ) {
item - > add_value ( " item: " + shape_type ( s - > first ) + " " + tl : : to_string ( QObject : : tr ( " with properties " ) ) ) ;
} else {
item - > add_value ( " item: " + shape_type ( s - > first ) ) ;
}
item - > add_value ( t * s - > first ) ;
if ( s - > second & & m_with_properties ) {
add_property_text ( item , pr , s - > second ) ;
}
}
}
template < class SH >
void
RdbDifferenceReceiver : : shape_diffs ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < SH , db : : properties_id_type > > & a , const std : : vector < std : : pair < SH , db : : properties_id_type > > & b )
{
if ( m_detailed & & m_is_valid_layer_index_a & & mp_a_only_per_layer_cat [ m_layer_index_a ] ! = 0 ) {
produce_diffs ( pr , a , b , mp_layout_a - > dbu ( ) , mp_a_only_per_layer_cat [ m_layer_index_a ] ) ;
}
if ( m_run_xor & & m_is_valid_layer_index_a ) {
db : : Shapes shapes ;
produce_diffs_for_xor ( pr , a , b , mp_layout_a - > dbu ( ) , shapes ) ;
for ( db : : Shapes : : shape_iterator s = shapes . begin ( db : : Shapes : : shape_iterator : : All ) ; ! s . at_end ( ) ; + + s ) {
m_ep . insert ( * s , m_obj_index * 2 ) ;
+ + m_obj_index ;
}
}
if ( m_detailed & & m_is_valid_layer_index_b & & mp_b_only_per_layer_cat [ m_layer_index_b ] ! = 0 ) {
produce_diffs ( pr , b , a , mp_layout_b - > dbu ( ) , mp_b_only_per_layer_cat [ m_layer_index_b ] ) ;
}
if ( m_run_xor & & m_is_valid_layer_index_b ) {
db : : Shapes shapes ;
produce_diffs_for_xor ( pr , b , a , mp_layout_b - > dbu ( ) , shapes ) ;
for ( db : : Shapes : : shape_iterator s = shapes . begin ( db : : Shapes : : shape_iterator : : All ) ; ! s . at_end ( ) ; + + s ) {
m_ep . insert ( * s , m_obj_index * 2 + 1 ) ;
+ + m_obj_index ;
}
}
}
void
RdbDifferenceReceiver : : detailed_diff ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < db : : Polygon , db : : properties_id_type > > & a , const std : : vector < std : : pair < db : : Polygon , db : : properties_id_type > > & b )
{
shape_diffs ( pr , a , b ) ;
}
void
RdbDifferenceReceiver : : begin_path_differences ( )
{
shape_diffs_found ( ) ;
}
void
RdbDifferenceReceiver : : detailed_diff ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < db : : Path , db : : properties_id_type > > & a , const std : : vector < std : : pair < db : : Path , db : : properties_id_type > > & b )
{
shape_diffs ( pr , a , b ) ;
}
void
RdbDifferenceReceiver : : begin_box_differences ( )
{
shape_diffs_found ( ) ;
}
void
RdbDifferenceReceiver : : detailed_diff ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < db : : Box , db : : properties_id_type > > & a , const std : : vector < std : : pair < db : : Box , db : : properties_id_type > > & b )
{
shape_diffs ( pr , a , b ) ;
}
void
RdbDifferenceReceiver : : begin_edge_differences ( )
{
shape_diffs_found ( ) ;
}
void
RdbDifferenceReceiver : : detailed_diff ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < db : : Edge , db : : properties_id_type > > & a , const std : : vector < std : : pair < db : : Edge , db : : properties_id_type > > & b )
{
shape_diffs ( pr , a , b ) ;
}
void
RdbDifferenceReceiver : : begin_text_differences ( )
{
shape_diffs_found ( ) ;
}
void
RdbDifferenceReceiver : : detailed_diff ( const db : : PropertiesRepository & pr , const std : : vector < std : : pair < db : : Text , db : : properties_id_type > > & a , const std : : vector < std : : pair < db : : Text , db : : properties_id_type > > & b )
{
shape_diffs ( pr , a , b ) ;
}
// ------------------------------------------------------------------------------
// DiffToolDialog definition
DiffToolDialog : : DiffToolDialog ( QWidget * parent )
: QDialog ( parent ) , mp_view ( 0 )
{
mp_ui = new Ui : : DiffToolDialog ( ) ;
mp_ui - > setupUi ( this ) ;
connect ( mp_ui - > xor_cbx , SIGNAL ( clicked ( ) ) , this , SLOT ( xor_changed ( ) ) ) ;
}
DiffToolDialog : : ~ DiffToolDialog ( )
{
delete mp_ui ;
mp_ui = 0 ;
}
int
DiffToolDialog : : exec_dialog ( lay : : LayoutView * view )
{
mp_view = view ;
if ( view ! = mp_ui - > layouta - > layout_view ( ) | | view ! = mp_ui - > layoutb - > layout_view ( ) ) {
mp_ui - > layouta - > set_layout_view ( view ) ;
mp_ui - > layoutb - > set_layout_view ( view ) ;
if ( view - > cellviews ( ) > = 2 ) {
mp_ui - > layouta - > set_current_cv_index ( 0 ) ;
mp_ui - > layoutb - > set_current_cv_index ( 1 ) ;
}
} else {
// force update of the layer list
// TODO: the controls should register a listener for the view so this activity is not necessary:
mp_ui - > layouta - > set_layout_view ( view ) ;
mp_ui - > layoutb - > set_layout_view ( view ) ;
}
lay : : PluginRoot * config_root = lay : : PluginRoot : : instance ( ) ;
bool f = false ;
if ( config_root - > config_get ( cfg_diff_run_xor , f ) ) {
mp_ui - > xor_cbx - > setChecked ( f ) ;
}
if ( config_root - > config_get ( cfg_diff_detailed , f ) ) {
mp_ui - > detailed_cbx - > setChecked ( f ) ;
}
if ( config_root - > config_get ( cfg_diff_smart , f ) ) {
mp_ui - > smart_cbx - > setChecked ( f ) ;
}
if ( config_root - > config_get ( cfg_diff_summarize , f ) ) {
mp_ui - > summarize_cbx - > setChecked ( f ) ;
}
if ( config_root - > config_get ( cfg_diff_expand_cell_arrays , f ) ) {
mp_ui - > expand_cell_arrays_cbx - > setChecked ( f ) ;
}
if ( config_root - > config_get ( cfg_diff_exact , f ) ) {
mp_ui - > exact_cbx - > setChecked ( f ) ;
}
update ( ) ;
int ret = QDialog : : exec ( ) ;
if ( ret ) {
run_diff ( ) ;
}
mp_view = 0 ;
return ret ;
}
void
DiffToolDialog : : accept ( )
{
BEGIN_PROTECTED
int cv_index_a = mp_ui - > layouta - > current_cv_index ( ) ;
int cv_index_b = mp_ui - > layoutb - > current_cv_index ( ) ;
const lay : : CellView & cva = mp_view - > cellview ( cv_index_a ) ;
const lay : : CellView & cvb = mp_view - > cellview ( cv_index_b ) ;
if ( & cva - > layout ( ) = = & cvb - > layout ( ) & & cva . cell_index ( ) = = cvb . cell_index ( ) ) {
throw tl : : Exception ( tl : : to_string ( QObject : : tr ( " Trying to perform an Diff between identical layouts " ) ) ) ;
}
lay : : PluginRoot * config_root = lay : : PluginRoot : : instance ( ) ;
config_root - > config_set ( cfg_diff_run_xor , mp_ui - > xor_cbx - > isChecked ( ) ) ;
config_root - > config_set ( cfg_diff_detailed , mp_ui - > detailed_cbx - > isChecked ( ) ) ;
config_root - > config_set ( cfg_diff_smart , mp_ui - > smart_cbx - > isChecked ( ) ) ;
config_root - > config_set ( cfg_diff_summarize , mp_ui - > summarize_cbx - > isChecked ( ) ) ;
config_root - > config_set ( cfg_diff_expand_cell_arrays , mp_ui - > expand_cell_arrays_cbx - > isChecked ( ) ) ;
config_root - > config_set ( cfg_diff_exact , mp_ui - > exact_cbx - > isChecked ( ) ) ;
config_root - > config_end ( ) ;
QDialog : : accept ( ) ;
END_PROTECTED
}
void
DiffToolDialog : : update ( )
{
bool xor_mode = mp_ui - > xor_cbx - > isChecked ( ) ;
mp_ui - > summarize_cbx - > setEnabled ( ! xor_mode ) ;
mp_ui - > detailed_cbx - > setEnabled ( ! xor_mode ) ;
mp_ui - > expand_cell_arrays_cbx - > setEnabled ( ! xor_mode ) ;
mp_ui - > exact_cbx - > setEnabled ( ! xor_mode ) ;
}
void
DiffToolDialog : : run_diff ( )
{
bool smart = mp_ui - > smart_cbx - > isChecked ( ) ;
bool run_xor = mp_ui - > xor_cbx - > isChecked ( ) ;
bool detailed = ! run_xor & & mp_ui - > detailed_cbx - > isChecked ( ) ;
bool summarize = ! run_xor & & mp_ui - > summarize_cbx - > isChecked ( ) ;
bool expand_cell_arrays = ! run_xor & & mp_ui - > expand_cell_arrays_cbx - > isChecked ( ) ;
bool exact = ! run_xor & & mp_ui - > exact_cbx - > isChecked ( ) ;
int cv_index_a = mp_ui - > layouta - > current_cv_index ( ) ;
int cv_index_b = mp_ui - > layoutb - > current_cv_index ( ) ;
lay : : CellView cva = mp_view - > cellview ( cv_index_a ) ;
lay : : CellView cvb = mp_view - > cellview ( cv_index_b ) ;
unsigned int flags = 0 ;
if ( detailed | | run_xor ) {
flags | = db : : layout_diff : : f_verbose ;
}
if ( ! exact ) {
flags | = db : : layout_diff : : f_no_text_details ;
flags | = db : : layout_diff : : f_no_layer_names ;
flags | = db : : layout_diff : : f_no_text_orientation ;
flags | = db : : layout_diff : : f_no_properties ;
flags | = db : : layout_diff : : f_boxes_as_polygons ;
flags | = db : : layout_diff : : f_paths_as_polygons ;
}
if ( expand_cell_arrays ) {
flags | = db : : layout_diff : : f_flatten_array_insts ;
}
if ( ! summarize ) {
flags | = db : : layout_diff : : f_dont_summarize_missing_layers ;
}
if ( smart ) {
flags | = db : : layout_diff : : f_smart_cell_mapping ;
}
// TODO: make an parameter
db : : Coord tolerance = 0 ;
// Create the report database or identify the output layout
rdb : : Database * rdb = 0 ;
int rdb_index = 0 ;
rdb = new rdb : : Database ( ) ;
rdb - > set_name ( " Diff " + cva - > name ( ) + " / " + cvb - > name ( ) ) ;
rdb - > set_top_cell_name ( cva - > layout ( ) . cell_name ( cva . cell_index ( ) ) ) ;
rdb_index = mp_view - > add_rdb ( rdb ) ;
std : : string srca = cva - > name ( ) + " , Cell " + cva - > layout ( ) . cell_name ( cva . cell_index ( ) ) ;
std : : string srcb = cvb - > name ( ) + " , Cell " + cvb - > layout ( ) . cell_name ( cvb . cell_index ( ) ) ;
rdb - > set_description ( " Diff of ' " + srca + " ' vs. ' " + srcb + " ' " ) ;
RdbDifferenceReceiver r ( cva - > layout ( ) , cvb - > layout ( ) , rdb , detailed , exact , run_xor ) ;
db : : compare_layouts ( cva - > layout ( ) , cva . cell_index ( ) , cvb - > layout ( ) , cvb . cell_index ( ) , flags , tolerance , r ) ;
mp_view - > open_rdb_browser ( rdb_index , cv_index_a ) ;
mp_view - > update_content ( ) ;
}
}