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
+53 -27
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;
+2
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);
+53 -38
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 {
+2
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 ();
+46
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
-1
View File
@@ -89,4 +89,3 @@ TEST(1)
}
}
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
File diff suppressed because one or more lines are too long