Fixed bug #121 (reopening of PCell's in GDS and - partially - in OASIS)

This commit is contained in:
Matthias Koefferlein 2018-05-17 22:24:32 +02:00
parent 887bcb3e04
commit f74f2d3416
18 changed files with 211 additions and 77 deletions

View File

@ -237,6 +237,7 @@ GDS2ReaderBase::do_read (db::Layout &layout)
m_cellname = "";
m_libname = "";
m_mapped_cellnames.clear ();
// read header
if (get_record () != sHEADER) {
@ -350,17 +351,7 @@ GDS2ReaderBase::do_read (db::Layout &layout)
} else {
db::cell_index_type cell_index;
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (m_cellname.c_str ());
if (c.first) {
// cell already there: just add shapes (cell might have been created through forward reference)
cell_index = c.second;
// remove "ghost cell" state
layout.cell (cell_index).set_ghost_cell (false);
} else {
cell_index = layout.add_cell (m_cellname.c_str ());
}
db::cell_index_type cell_index = make_cell (layout, m_cellname.c_str (), false);
db::Cell *cell = &layout.cell (cell_index);
@ -370,6 +361,8 @@ GDS2ReaderBase::do_read (db::Layout &layout)
if (layout.recover_proxy_as (cell_index, ctx->second.begin (), ctx->second.end (), &layer_mapping)) {
// ignore everything in that cell since it is created by the import:
cell = 0;
// marks the cell for begin addressed by REF's despite being a proxy:
m_mapped_cellnames.insert (std::make_pair (m_cellname, m_cellname));
}
}
@ -982,6 +975,54 @@ GDS2ReaderBase::read_box (db::Layout &layout, db::Cell &cell)
}
}
db::cell_index_type
GDS2ReaderBase::make_cell (db::Layout &layout, const char *cn, bool for_instance)
{
db::cell_index_type ci = 0;
// map to the real name which maybe a different one due to localization
// of proxy cells (they are not to be reopened)
bool is_mapped = false;
if (! m_mapped_cellnames.empty ()) {
std::map<tl::string, tl::string>::const_iterator n = m_mapped_cellnames.find (cn);
if (n != m_mapped_cellnames.end ()) {
cn = n->second.c_str ();
is_mapped = true;
}
}
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (cn);
if (c.first && (is_mapped || ! layout.cell (c.second).is_proxy ())) {
// cell already there: just add instance (cell might have been created through forward reference)
// NOTE: we don't address "reopened" proxies as proxies are always local to a layout
ci = c.second;
// mark the cell as read
if (! for_instance) {
layout.cell (ci).set_ghost_cell (false);
}
} else {
ci = layout.add_cell (cn);
if (for_instance) {
// mark this cell a "ghost cell" until it's actually read
layout.cell (ci).set_ghost_cell (true);
}
if (c.first) {
// this cell has been given a new name: remember this name for localization
m_mapped_cellnames.insert (std::make_pair (cn, layout.cell_name (ci)));
}
}
return ci;
}
void
GDS2ReaderBase::read_ref (db::Layout &layout, db::Cell & /*cell*/, bool array, tl::vector<db::CellInstArray> &instances, tl::vector<db::CellInstArrayWithProperties> &instances_with_props)
{
@ -994,22 +1035,7 @@ GDS2ReaderBase::read_ref (db::Layout &layout, db::Cell & /*cell*/, bool array, t
error (tl::to_string (QObject::tr ("SNAME record expected")));
}
db::cell_index_type ci;
{
// obtain cell or create new: "cn" is not valid beyond the
// scope of the get_string() call
const char *cn = get_string ();
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (cn);
if (c.first) {
// cell already there: just add shapes (cell might have been created through forward reference)
ci = c.second;
} else {
ci = layout.add_cell (cn);
// mark this cell a "ghost cell" until it's actually read
layout.cell (ci).set_ghost_cell (true);
}
}
db::cell_index_type ci = make_cell (layout, get_string (), true);
bool mirror = false;
int angle = 0;

View File

@ -109,6 +109,7 @@ private:
unsigned int m_box_mode;
std::map <tl::string, std::vector<std::string> > m_context_info;
std::vector <db::Point> m_all_points;
std::map <tl::string, tl::string> m_mapped_cellnames;
void read_context_info_cell ();
void read_boundary (db::Layout &layout, db::Cell &cell, bool from_box_record);
@ -116,6 +117,7 @@ private:
void read_text (db::Layout &layout, db::Cell &cell);
void read_box (db::Layout &layout, db::Cell &cell);
void read_ref (db::Layout &layout, db::Cell &cell, bool array, tl::vector<db::CellInstArray> &instances, tl::vector<db::CellInstArrayWithProperties> &insts_wp);
db::cell_index_type make_cell (db::Layout &layout, const char *cn, bool for_instance);
void do_read (db::Layout &layout);

View File

@ -770,6 +770,7 @@ OASISReader::do_read (db::Layout &layout)
m_cells_by_name.clear ();
m_defined_cells_by_id.clear ();
m_defined_cells_by_name.clear ();
m_mapped_cellnames.clear ();
m_instances.clear ();
m_instances_with_props.clear ();
@ -1174,14 +1175,7 @@ OASISReader::do_read (db::Layout &layout)
} else {
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (name->second.c_str ());
if (c.first) {
cell_index = c.second;
layout.cell (cell_index).set_ghost_cell (false);
} else {
cell_index = layout.add_cell (name->second.c_str ());
}
cell_index = make_cell (layout, name->second.c_str (), false);
m_cells_by_name.insert (std::make_pair (name->second, cell_index));
}
@ -1209,14 +1203,7 @@ OASISReader::do_read (db::Layout &layout)
} else {
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (name.c_str ());
if (c.first) {
cell_index = c.second;
layout.cell (cell_index).set_ghost_cell (false);
} else {
cell_index = layout.add_cell (name.c_str ());
}
cell_index = make_cell (layout, name.c_str (), false);
m_cells_by_name.insert (std::make_pair (name, cell_index));
}
@ -1859,6 +1846,54 @@ OASISReader::read_repetition ()
return mm_repetition.get ().size () > 1;
}
db::cell_index_type
OASISReader::make_cell (db::Layout &layout, const char *cn, bool for_instance)
{
db::cell_index_type ci = 0;
// map to the real name which maybe a different one due to localization
// of proxy cells (they are not to be reopened)
bool is_mapped = false;
if (! m_mapped_cellnames.empty ()) {
std::map<tl::string, tl::string>::const_iterator n = m_mapped_cellnames.find (cn);
if (n != m_mapped_cellnames.end ()) {
cn = n->second.c_str ();
is_mapped = true;
}
}
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (cn);
if (c.first && (is_mapped || ! layout.cell (c.second).is_proxy ())) {
// cell already there: just add instance (cell might have been created through forward reference)
// NOTE: we don't address "reopened" proxies as proxies are always local to a layout
ci = c.second;
// mark the cell as read
if (! for_instance) {
layout.cell (ci).set_ghost_cell (false);
}
} else {
ci = layout.add_cell (cn);
if (for_instance) {
// mark this cell a "ghost cell" until it's actually read
layout.cell (ci).set_ghost_cell (true);
}
if (c.first) {
// this cell has been given a new name: remember this name for localization
m_mapped_cellnames.insert (std::make_pair (cn, layout.cell_name (ci)));
}
}
return ci;
}
void
OASISReader::do_read_placement (unsigned char r,
bool xy_absolute,
@ -1891,17 +1926,7 @@ OASISReader::do_read_placement (unsigned char r,
} else {
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (name->second.c_str ());
if (c.first) {
// take existing cell
mm_placement_cell = c.second;
} else {
// create the cell
mm_placement_cell = layout.add_cell (name->second.c_str ());
// temporarily mark as "ghost cell"
layout.cell (mm_placement_cell.get ()).set_ghost_cell (true);
}
mm_placement_cell = make_cell (layout, name->second.c_str (), true);
m_cells_by_name.insert (std::make_pair (name->second, mm_placement_cell.get ()));
}
@ -1921,17 +1946,7 @@ OASISReader::do_read_placement (unsigned char r,
std::map <std::string, db::cell_index_type>::const_iterator cid = m_cells_by_name.find (name);
if (cid == m_cells_by_name.end ()) {
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (name.c_str ());
if (c.first) {
// take existing cell
mm_placement_cell = c.second;
} else {
// create the cell
mm_placement_cell = layout.add_cell (name.c_str ());
// temporarily mark as "ghost cell"
layout.cell (mm_placement_cell.get ()).set_ghost_cell (true);
}
mm_placement_cell = make_cell (layout, name.c_str (), true);
m_cells_by_name.insert (std::make_pair (name, mm_placement_cell.get ()));
} else {

View File

@ -269,6 +269,7 @@ private:
std::set <unsigned long> m_defined_cells_by_id;
std::set <std::string> m_defined_cells_by_name;
std::map <tl::string, tl::string> m_mapped_cellnames;
std::map <unsigned long, db::property_names_id_type> m_propname_forward_references;
std::map <unsigned long, std::string> m_propvalue_forward_references;
@ -291,6 +292,7 @@ private:
void do_read_trapezoid (unsigned char r, bool xy_absolute,db::cell_index_type cell_index, db::Layout &layout);
void do_read_ctrapezoid (bool xy_absolute,db::cell_index_type cell_index, db::Layout &layout);
void do_read_circle (bool xy_absolute,db::cell_index_type cell_index, db::Layout &layout);
db::cell_index_type make_cell (db::Layout &layout, const char *cn, bool for_instance);
void reset_modal_variables ();

View File

@ -24,7 +24,9 @@
#include "dbGDS2Reader.h"
#include "dbLayoutDiff.h"
#include "dbTestSupport.h"
#include "tlUnitTest.h"
#include "tlStream.h"
#include <iostream>
@ -347,3 +349,47 @@ TEST(2)
}
}
// Ability to merge GDS files with PCells
TEST(Bug_121_1)
{
db::Manager m;
db::Layout layout (&m);
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/bug_121a.gds");
db::GDS2Reader reader (file);
reader.read (layout);
}
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/bug_121b.gds");
db::GDS2Reader reader (file);
reader.read (layout);
}
std::string fn_au (tl::testsrc () + "/testdata/gds/bug_121_au1.gds");
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
}
TEST(Bug_121_2)
{
db::Manager m;
db::Layout layout (&m);
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/bug_121a.gds");
db::GDS2Reader reader (file);
reader.read (layout);
}
{
tl::InputStream file (tl::testsrc () + "/testdata/gds/bug_121c.gds");
db::GDS2Reader reader (file);
reader.read (layout);
}
std::string fn_au (tl::testsrc () + "/testdata/gds/bug_121_au2.gds");
db::compare_layouts (_this, layout, fn_au, db::WriteGDS2, 1);
}

File diff suppressed because one or more lines are too long

View File

@ -89,4 +89,3 @@ TEST(1)
}
}

BIN
testdata/gds/bug_121_au1.gds vendored Normal file

Binary file not shown.

BIN
testdata/gds/bug_121_au2.gds vendored Normal file

Binary file not shown.

BIN
testdata/gds/bug_121a.gds vendored Normal file

Binary file not shown.

BIN
testdata/gds/bug_121b.gds vendored Normal file

Binary file not shown.

BIN
testdata/gds/bug_121c.gds vendored Normal file

Binary file not shown.

BIN
testdata/oasis/bug_121_au1.gds vendored Normal file

Binary file not shown.

BIN
testdata/oasis/bug_121_au2.gds vendored Normal file

Binary file not shown.

BIN
testdata/oasis/bug_121a.oas vendored Normal file

Binary file not shown.

BIN
testdata/oasis/bug_121b.oas vendored Normal file

Binary file not shown.

BIN
testdata/oasis/bug_121c.oas vendored Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long