mirror of https://github.com/KLayout/klayout.git
Next steps - persistency of meta info
This commit is contained in:
parent
b14c630ce9
commit
78da3effa2
|
|
@ -49,8 +49,8 @@ ColdProxy::cold_proxies_per_lib_name (const std::string &libname)
|
|||
}
|
||||
}
|
||||
|
||||
ColdProxy::ColdProxy (db::cell_index_type ci, db::Layout &layout, const ProxyContextInfo &info)
|
||||
: Cell (ci, layout), mp_context_info (new ProxyContextInfo (info))
|
||||
ColdProxy::ColdProxy (db::cell_index_type ci, db::Layout &layout, const LayoutOrCellContextInfo &info)
|
||||
: Cell (ci, layout), mp_context_info (new LayoutOrCellContextInfo (info))
|
||||
{
|
||||
if (! info.lib_name.empty ()) {
|
||||
tl::MutexLocker locker (&s_map_mutex);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
struct ProxyContextInfo;
|
||||
struct LayoutOrCellContextInfo;
|
||||
|
||||
/**
|
||||
* @brief A cell specialization: a cold proxy representing a library or PCell which has gone out of scope
|
||||
|
|
@ -53,7 +53,7 @@ public:
|
|||
*
|
||||
* Creates a cold proxy represented by the ProxyContextInfo data.
|
||||
*/
|
||||
ColdProxy (db::cell_index_type ci, db::Layout &layout, const ProxyContextInfo &info);
|
||||
ColdProxy (db::cell_index_type ci, db::Layout &layout, const LayoutOrCellContextInfo &info);
|
||||
|
||||
/**
|
||||
* @brief The destructor
|
||||
|
|
@ -68,7 +68,7 @@ public:
|
|||
/**
|
||||
* @brief Get the library id
|
||||
*/
|
||||
const ProxyContextInfo &context_info () const
|
||||
const LayoutOrCellContextInfo &context_info () const
|
||||
{
|
||||
return *mp_context_info;
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ public:
|
|||
virtual std::string get_qualified_name () const;
|
||||
|
||||
private:
|
||||
ProxyContextInfo *mp_context_info;
|
||||
LayoutOrCellContextInfo *mp_context_info;
|
||||
|
||||
ColdProxy (const ColdProxy &d);
|
||||
ColdProxy &operator= (const ColdProxy &d);
|
||||
|
|
|
|||
|
|
@ -258,12 +258,12 @@ private:
|
|||
// -----------------------------------------------------------------
|
||||
// Implementation of the ProxyContextInfo class
|
||||
|
||||
ProxyContextInfo
|
||||
ProxyContextInfo::deserialize (std::vector<std::string>::const_iterator from, std::vector<std::string>::const_iterator to)
|
||||
LayoutOrCellContextInfo
|
||||
LayoutOrCellContextInfo::deserialize (std::vector<std::string>::const_iterator from, std::vector<std::string>::const_iterator to)
|
||||
{
|
||||
ProxyContextInfo info;
|
||||
LayoutOrCellContextInfo info;
|
||||
|
||||
for (std::vector<std::string>::const_iterator i = from; i != to; ++i) {
|
||||
for (auto i = from; i != to; ++i) {
|
||||
|
||||
tl::Extractor ex (i->c_str ());
|
||||
|
||||
|
|
@ -290,6 +290,20 @@ ProxyContextInfo::deserialize (std::vector<std::string>::const_iterator from, st
|
|||
|
||||
info.cell_name = ex.skip ();
|
||||
|
||||
} else if (ex.test ("META(")) {
|
||||
|
||||
std::pair<std::string, std::pair<tl::Variant, std::string> > vv;
|
||||
|
||||
ex.read_word_or_quoted (vv.first);
|
||||
if (ex.test (",")) {
|
||||
ex.read_word_or_quoted (vv.second.second);
|
||||
}
|
||||
ex.test (")");
|
||||
ex.test ("=");
|
||||
ex.read (vv.second.first);
|
||||
|
||||
info.meta_info.insert(vv);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -298,12 +312,12 @@ ProxyContextInfo::deserialize (std::vector<std::string>::const_iterator from, st
|
|||
}
|
||||
|
||||
void
|
||||
ProxyContextInfo::serialize (std::vector<std::string> &strings)
|
||||
LayoutOrCellContextInfo::serialize (std::vector<std::string> &strings)
|
||||
{
|
||||
if (! lib_name.empty ()) {
|
||||
strings.push_back ("LIB=" + lib_name);
|
||||
}
|
||||
for (std::map<std::string, tl::Variant> ::const_iterator p = pcell_parameters.begin (); p != pcell_parameters.end (); ++p) {
|
||||
for (auto p = pcell_parameters.begin (); p != pcell_parameters.end (); ++p) {
|
||||
strings.push_back ("P(" + tl::to_word_or_quoted_string (p->first) + ")=" + p->second.to_parsable_string ());
|
||||
}
|
||||
if (! pcell_name.empty ()) {
|
||||
|
|
@ -312,6 +326,20 @@ ProxyContextInfo::serialize (std::vector<std::string> &strings)
|
|||
if (! cell_name.empty ()) {
|
||||
strings.push_back ("CELL=" + cell_name);
|
||||
}
|
||||
|
||||
std::string mv;
|
||||
for (auto m = meta_info.begin (); m != meta_info.end (); ++m) {
|
||||
mv.clear ();
|
||||
mv += "META(";
|
||||
mv += tl::to_word_or_quoted_string (m->first);
|
||||
if (! m->second.second.empty ()) {
|
||||
mv += ",";
|
||||
mv += tl::to_word_or_quoted_string (m->second.second);
|
||||
}
|
||||
mv += ")=";
|
||||
mv += m->second.first.to_parsable_string ();
|
||||
strings.push_back (mv);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
|
@ -593,7 +621,7 @@ Layout::set_technology_name (const std::string &tech)
|
|||
if (! pn.first) {
|
||||
|
||||
// substitute by a cold proxy
|
||||
db::ProxyContextInfo info;
|
||||
db::LayoutOrCellContextInfo info;
|
||||
get_context_info (ci, info);
|
||||
create_cold_proxy_as (info, ci);
|
||||
|
||||
|
|
@ -606,7 +634,7 @@ Layout::set_technology_name (const std::string &tech)
|
|||
if (! old_pcell_decl || ! new_pcell_decl) {
|
||||
|
||||
// substitute by a cold proxy
|
||||
db::ProxyContextInfo info;
|
||||
db::LayoutOrCellContextInfo info;
|
||||
get_context_info (ci, info);
|
||||
create_cold_proxy_as (info, ci);
|
||||
|
||||
|
|
@ -633,7 +661,7 @@ Layout::set_technology_name (const std::string &tech)
|
|||
if (! cn.first) {
|
||||
|
||||
// unlink this proxy: substitute by a cold proxy
|
||||
db::ProxyContextInfo info;
|
||||
db::LayoutOrCellContextInfo info;
|
||||
get_context_info (ci, info);
|
||||
create_cold_proxy_as (info, ci);
|
||||
|
||||
|
|
@ -650,7 +678,7 @@ Layout::set_technology_name (const std::string &tech)
|
|||
db::cell_index_type ci = (*lp)->Cell::cell_index ();
|
||||
|
||||
// substitute by a cold proxy
|
||||
db::ProxyContextInfo info;
|
||||
db::LayoutOrCellContextInfo info;
|
||||
get_context_info (ci, info);
|
||||
create_cold_proxy_as (info, ci);
|
||||
|
||||
|
|
@ -2446,10 +2474,85 @@ Layout::get_pcell_variant_cell (cell_index_type cell_index, const std::vector<tl
|
|||
|
||||
}
|
||||
|
||||
bool
|
||||
Layout::has_context_info () const
|
||||
{
|
||||
for (auto i = m_meta_info.begin (); i != m_meta_info.end (); ++i) {
|
||||
if (i->second.persisted) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
Layout::has_context_info (cell_index_type cell_index) const
|
||||
{
|
||||
auto c = m_meta_info_by_cell.find (cell_index);
|
||||
if (c != m_meta_info_by_cell.end ()) {
|
||||
for (auto i = c->second.begin (); i != c->second.end (); ++i) {
|
||||
if (i->second.persisted) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const db::Cell &cref = cell (cell_index);
|
||||
if (cref.is_proxy () && ! cref.is_top ()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Layout::get_context_info (std::vector <std::string> &strings) const
|
||||
{
|
||||
LayoutOrCellContextInfo info;
|
||||
if (! get_context_info (info)) {
|
||||
return false;
|
||||
} else {
|
||||
info.serialize (strings);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Layout::get_context_info (LayoutOrCellContextInfo &info) const
|
||||
{
|
||||
for (auto i = m_meta_info.begin (); i != m_meta_info.end (); ++i) {
|
||||
if (i->second.persisted) {
|
||||
std::pair<tl::Variant, std::string> &mi = info.meta_info [m_meta_info_names [i->first] ];
|
||||
mi.first = i->second.value;
|
||||
mi.second = i->second.description;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Layout::fill_meta_info_from_context (std::vector <std::string>::const_iterator from, std::vector <std::string>::const_iterator to)
|
||||
{
|
||||
fill_meta_info_from_context (LayoutOrCellContextInfo::deserialize (from, to));
|
||||
}
|
||||
|
||||
void
|
||||
Layout::fill_meta_info_from_context (const LayoutOrCellContextInfo &context_info)
|
||||
{
|
||||
if (! context_info.meta_info.empty ()) {
|
||||
for (auto i = context_info.meta_info.begin (); i != context_info.meta_info.end (); ++i) {
|
||||
meta_info_name_id_type name_id = meta_info_name_id (i->first);
|
||||
m_meta_info [name_id] = MetaInfo (i->second.second, i->second.first, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Layout::get_context_info (cell_index_type cell_index, std::vector <std::string> &strings) const
|
||||
{
|
||||
ProxyContextInfo info;
|
||||
LayoutOrCellContextInfo info;
|
||||
if (! get_context_info (cell_index, info)) {
|
||||
return false;
|
||||
} else {
|
||||
|
|
@ -2459,8 +2562,19 @@ Layout::get_context_info (cell_index_type cell_index, std::vector <std::string>
|
|||
}
|
||||
|
||||
bool
|
||||
Layout::get_context_info (cell_index_type cell_index, ProxyContextInfo &info) const
|
||||
Layout::get_context_info (cell_index_type cell_index, LayoutOrCellContextInfo &info) const
|
||||
{
|
||||
auto cmi = m_meta_info_by_cell.find (cell_index);
|
||||
if (cmi != m_meta_info_by_cell.end ()) {
|
||||
for (auto i = cmi->second.begin (); i != cmi->second.end (); ++i) {
|
||||
if (i->second.persisted) {
|
||||
std::pair<tl::Variant, std::string> &mi = info.meta_info [m_meta_info_names [i->first] ];
|
||||
mi.first = i->second.value;
|
||||
mi.second = i->second.description;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const db::Cell *cptr = &cell (cell_index);
|
||||
|
||||
const db::ColdProxy *cold_proxy = dynamic_cast <const db::ColdProxy *> (cptr);
|
||||
|
|
@ -2509,6 +2623,27 @@ Layout::get_context_info (cell_index_type cell_index, ProxyContextInfo &info) co
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Layout::fill_meta_info_from_context (cell_index_type cell_index, std::vector <std::string>::const_iterator from, std::vector <std::string>::const_iterator to)
|
||||
{
|
||||
fill_meta_info_from_context (cell_index, LayoutOrCellContextInfo::deserialize (from, to));
|
||||
}
|
||||
|
||||
void
|
||||
Layout::fill_meta_info_from_context (cell_index_type cell_index, const LayoutOrCellContextInfo &context_info)
|
||||
{
|
||||
if (! context_info.meta_info.empty ()) {
|
||||
|
||||
meta_info_map &mi = m_meta_info_by_cell [cell_index];
|
||||
|
||||
for (auto i = context_info.meta_info.begin (); i != context_info.meta_info.end (); ++i) {
|
||||
meta_info_name_id_type name_id = meta_info_name_id (i->first);
|
||||
mi [name_id] = MetaInfo (i->second.second, i->second.first, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Layout::restore_proxies (ImportLayerMapping *layer_mapping)
|
||||
{
|
||||
|
|
@ -2540,11 +2675,11 @@ Layout::recover_proxy_as (cell_index_type cell_index, std::vector <std::string>:
|
|||
return false;
|
||||
}
|
||||
|
||||
return recover_proxy_as (cell_index, ProxyContextInfo::deserialize (from, to), layer_mapping);
|
||||
return recover_proxy_as (cell_index, LayoutOrCellContextInfo::deserialize (from, to), layer_mapping);
|
||||
}
|
||||
|
||||
bool
|
||||
Layout::recover_proxy_as (cell_index_type cell_index, const ProxyContextInfo &info, ImportLayerMapping *layer_mapping)
|
||||
Layout::recover_proxy_as (cell_index_type cell_index, const LayoutOrCellContextInfo &info, ImportLayerMapping *layer_mapping)
|
||||
{
|
||||
if (! info.lib_name.empty ()) {
|
||||
|
||||
|
|
@ -2594,11 +2729,11 @@ Layout::recover_proxy (std::vector <std::string>::const_iterator from, std::vect
|
|||
return 0;
|
||||
}
|
||||
|
||||
return recover_proxy (ProxyContextInfo::deserialize (from, to));
|
||||
return recover_proxy (LayoutOrCellContextInfo::deserialize (from, to));
|
||||
}
|
||||
|
||||
db::Cell *
|
||||
Layout::recover_proxy (const ProxyContextInfo &info)
|
||||
Layout::recover_proxy (const LayoutOrCellContextInfo &info)
|
||||
{
|
||||
if (! info.lib_name.empty ()) {
|
||||
|
||||
|
|
@ -2626,7 +2761,7 @@ Layout::recover_proxy (const ProxyContextInfo &info)
|
|||
}
|
||||
|
||||
db::Cell *
|
||||
Layout::recover_proxy_no_lib (const ProxyContextInfo &info)
|
||||
Layout::recover_proxy_no_lib (const LayoutOrCellContextInfo &info)
|
||||
{
|
||||
if (! info.pcell_name.empty ()) {
|
||||
|
||||
|
|
@ -2723,7 +2858,7 @@ Layout::get_lib_proxy (Library *lib, cell_index_type cell_index)
|
|||
}
|
||||
|
||||
cell_index_type
|
||||
Layout::create_cold_proxy (const db::ProxyContextInfo &info)
|
||||
Layout::create_cold_proxy (const db::LayoutOrCellContextInfo &info)
|
||||
{
|
||||
// create a new unique name
|
||||
std::string b;
|
||||
|
|
@ -2754,7 +2889,7 @@ Layout::create_cold_proxy (const db::ProxyContextInfo &info)
|
|||
}
|
||||
|
||||
void
|
||||
Layout::create_cold_proxy_as (const db::ProxyContextInfo &info, cell_index_type target_cell_index)
|
||||
Layout::create_cold_proxy_as (const db::LayoutOrCellContextInfo &info, cell_index_type target_cell_index)
|
||||
{
|
||||
tl_assert (m_cell_ptrs [target_cell_index] != 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -417,14 +417,15 @@ public:
|
|||
/**
|
||||
* @brief A binary object representing context information for regenerating library proxies and PCells
|
||||
*/
|
||||
struct DB_PUBLIC ProxyContextInfo
|
||||
struct DB_PUBLIC LayoutOrCellContextInfo
|
||||
{
|
||||
std::string lib_name;
|
||||
std::string cell_name;
|
||||
std::string pcell_name;
|
||||
std::map<std::string, tl::Variant> pcell_parameters;
|
||||
std::map<std::string, std::pair<tl::Variant, std::string> > meta_info;
|
||||
|
||||
static ProxyContextInfo deserialize (std::vector<std::string>::const_iterator from, std::vector<std::string>::const_iterator to);
|
||||
static LayoutOrCellContextInfo deserialize (std::vector<std::string>::const_iterator from, std::vector<std::string>::const_iterator to);
|
||||
void serialize (std::vector<std::string> &strings);
|
||||
};
|
||||
|
||||
|
|
@ -1015,27 +1016,69 @@ public:
|
|||
/**
|
||||
* @brief Creates a cold proxy representing the given context information
|
||||
*/
|
||||
cell_index_type create_cold_proxy (const db::ProxyContextInfo &info);
|
||||
cell_index_type create_cold_proxy (const db::LayoutOrCellContextInfo &info);
|
||||
|
||||
/**
|
||||
* @brief Subsitutes the given cell by a cold proxy representing the given context information
|
||||
*/
|
||||
void create_cold_proxy_as (const db::ProxyContextInfo &info, cell_index_type cell_index);
|
||||
void create_cold_proxy_as (const db::LayoutOrCellContextInfo &info, cell_index_type cell_index);
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether layout context info is provided / needed
|
||||
*/
|
||||
bool has_context_info() const;
|
||||
|
||||
/**
|
||||
* @brief Gets a value indicating whether layout context info is provided / needed
|
||||
*/
|
||||
bool has_context_info(cell_index_type cell_index) const;
|
||||
|
||||
/**
|
||||
* @brief Get the context information for the layout (for writing into a file)
|
||||
*
|
||||
* The context information is a sequence of strings which is pushed onto the given
|
||||
* vector. It can be used to fill meta information with fill_meta_info_from_context.
|
||||
*/
|
||||
bool get_context_info (std::vector <std::string> &strings) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the context information as a binary object
|
||||
*/
|
||||
bool get_context_info (LayoutOrCellContextInfo &context_info) const;
|
||||
|
||||
/**
|
||||
* @brief Fills the layout's meta information from the context
|
||||
*/
|
||||
void fill_meta_info_from_context (std::vector <std::string>::const_iterator from, std::vector <std::string>::const_iterator to);
|
||||
|
||||
/**
|
||||
* @brief Fills the layout's meta information from the binary context
|
||||
*/
|
||||
void fill_meta_info_from_context (const LayoutOrCellContextInfo &context_info);
|
||||
|
||||
/**
|
||||
* @brief Get the context information for a given cell (for writing into a file)
|
||||
*
|
||||
* The context information is a sequence of strings which is pushed onto the given
|
||||
* vector. It can be used to recover a respective proxy cell with the recover_proxy method.
|
||||
* If the given cell is not a valid proxy or library references are missing, the method
|
||||
* will return false.
|
||||
* vector. It can be used to recover a respective proxy cell with the recover_proxy method
|
||||
* or to fill meta information using fill_meta_info_from_context.
|
||||
*/
|
||||
bool get_context_info (cell_index_type cell_index, std::vector <std::string> &context_info) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the context information as a binary object
|
||||
*/
|
||||
bool get_context_info (cell_index_type cell_index, ProxyContextInfo &context_info) const;
|
||||
bool get_context_info (cell_index_type cell_index, LayoutOrCellContextInfo &context_info) const;
|
||||
|
||||
/**
|
||||
* @brief Fills the layout's meta information from the context
|
||||
*/
|
||||
void fill_meta_info_from_context (cell_index_type cell_index, std::vector <std::string>::const_iterator from, std::vector <std::string>::const_iterator to);
|
||||
|
||||
/**
|
||||
* @brief Fills the layout's meta information from the binary context
|
||||
*/
|
||||
void fill_meta_info_from_context (cell_index_type cell_index, const LayoutOrCellContextInfo &context_info);
|
||||
|
||||
/**
|
||||
* @brief Recover a proxy cell from the given context info.
|
||||
|
|
@ -1051,7 +1094,7 @@ public:
|
|||
/**
|
||||
* @brief Recover a proxy cell from the given binary context info object.
|
||||
*/
|
||||
db::Cell *recover_proxy (const ProxyContextInfo &context_info);
|
||||
db::Cell *recover_proxy (const LayoutOrCellContextInfo &context_info);
|
||||
|
||||
/**
|
||||
* @brief Recover a proxy cell from the given context info.
|
||||
|
|
@ -1073,7 +1116,7 @@ public:
|
|||
*
|
||||
* See the string-based version of "recover_proxy_as" for details.
|
||||
*/
|
||||
bool recover_proxy_as (cell_index_type cell_index, const ProxyContextInfo &context_info, ImportLayerMapping *layer_mapping = 0);
|
||||
bool recover_proxy_as (cell_index_type cell_index, const LayoutOrCellContextInfo &context_info, ImportLayerMapping *layer_mapping = 0);
|
||||
|
||||
/**
|
||||
* @brief Restores proxies as far as possible
|
||||
|
|
@ -2026,7 +2069,7 @@ private:
|
|||
/**
|
||||
* @brief Recovers a proxy without considering the library from context_info
|
||||
*/
|
||||
db::Cell *recover_proxy_no_lib (const ProxyContextInfo &context_info);
|
||||
db::Cell *recover_proxy_no_lib (const LayoutOrCellContextInfo &context_info);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ Library::remap_to (db::Library *other)
|
|||
if (! pn.first) {
|
||||
|
||||
// substitute by a cold proxy
|
||||
db::ProxyContextInfo info;
|
||||
db::LayoutOrCellContextInfo info;
|
||||
r->first->get_context_info (ci, info);
|
||||
r->first->create_cold_proxy_as (info, ci);
|
||||
|
||||
|
|
@ -216,7 +216,7 @@ Library::remap_to (db::Library *other)
|
|||
if (! old_pcell_decl || ! new_pcell_decl) {
|
||||
|
||||
// substitute by a cold proxy
|
||||
db::ProxyContextInfo info;
|
||||
db::LayoutOrCellContextInfo info;
|
||||
r->first->get_context_info (ci, info);
|
||||
r->first->create_cold_proxy_as (info, ci);
|
||||
|
||||
|
|
@ -254,7 +254,7 @@ Library::remap_to (db::Library *other)
|
|||
if (! cn.first) {
|
||||
|
||||
// substitute by a cold proxy
|
||||
db::ProxyContextInfo info;
|
||||
db::LayoutOrCellContextInfo info;
|
||||
r->first->get_context_info (ci, info);
|
||||
r->first->create_cold_proxy_as (info, ci);
|
||||
|
||||
|
|
|
|||
|
|
@ -543,7 +543,7 @@ TEST(5)
|
|||
db::Layout l (&m);
|
||||
EXPECT_EQ (l.technology_name (), "");
|
||||
|
||||
db::ProxyContextInfo info;
|
||||
db::LayoutOrCellContextInfo info;
|
||||
info.lib_name = "LIB";
|
||||
info.cell_name = "LIBCELL";
|
||||
|
||||
|
|
@ -624,7 +624,7 @@ TEST(6)
|
|||
|
||||
EXPECT_EQ (l.technology_name (), "");
|
||||
|
||||
db::ProxyContextInfo info;
|
||||
db::LayoutOrCellContextInfo info;
|
||||
info.lib_name = "Basic";
|
||||
info.pcell_name = "CIRCLE";
|
||||
info.pcell_parameters ["actual_radius"] = tl::Variant (10.0);
|
||||
|
|
@ -644,7 +644,7 @@ TEST(6)
|
|||
|
||||
EXPECT_EQ (l2s (l), "begin_lib 0.001\nbegin_cell {CIRCLE}\nboundary 1 0 {-4142 -10000} {-10000 -4142} {-10000 4142} {-4142 10000} {4142 10000} {10000 4142} {10000 -4142} {4142 -10000} {-4142 -10000}\nend_cell\nend_lib\n");
|
||||
|
||||
db::ProxyContextInfo info2;
|
||||
db::LayoutOrCellContextInfo info2;
|
||||
l.get_context_info (cell->cell_index (), info2);
|
||||
info2.pcell_parameters ["actual_radius"] = tl::Variant (5.0);
|
||||
|
||||
|
|
|
|||
|
|
@ -289,13 +289,19 @@ GDS2ReaderBase::do_read (db::Layout &layout)
|
|||
db::cell_index_type cell_index = make_cell (layout, m_cellname);
|
||||
|
||||
bool ignore_cell = false;
|
||||
std::map <tl::string, std::vector <std::string> >::const_iterator ctx = m_context_info.find (m_cellname);
|
||||
auto ctx = m_context_info.find (m_cellname);
|
||||
if (ctx != m_context_info.end ()) {
|
||||
|
||||
CommonReaderLayerMapping layer_mapping (this, &layout);
|
||||
if (layout.recover_proxy_as (cell_index, ctx->second.begin (), ctx->second.end (), &layer_mapping)) {
|
||||
LayoutOrCellContextInfo ci = LayoutOrCellContextInfo::deserialize (ctx->second.begin (), ctx->second.end ());
|
||||
|
||||
if (layout.recover_proxy_as (cell_index, ci, &layer_mapping)) {
|
||||
// ignore everything in that cell since it is created by the import:
|
||||
ignore_cell = true;
|
||||
}
|
||||
|
||||
layout.fill_meta_info_from_context (cell_index, ci);
|
||||
|
||||
}
|
||||
|
||||
db::Cell *cell = 0;
|
||||
|
|
@ -386,6 +392,13 @@ GDS2ReaderBase::do_read (db::Layout &layout)
|
|||
|
||||
}
|
||||
|
||||
// deserialize global context information
|
||||
auto ctx = m_context_info.find (std::string ());
|
||||
if (ctx != m_context_info.end ()) {
|
||||
LayoutOrCellContextInfo ci = LayoutOrCellContextInfo::deserialize (ctx->second.begin (), ctx->second.end ());
|
||||
layout.fill_meta_info_from_context (ci);
|
||||
}
|
||||
|
||||
// check, if the last record is a ENDLIB
|
||||
if (rec_id != sENDLIB) {
|
||||
error (tl::to_string (tr ("ENDLIB record expected")));
|
||||
|
|
@ -396,12 +409,16 @@ void
|
|||
GDS2ReaderBase::read_context_info_cell ()
|
||||
{
|
||||
short rec_id = 0;
|
||||
std::string cn;
|
||||
|
||||
// read cell content
|
||||
while ((rec_id = get_record ()) != sENDSTR) {
|
||||
|
||||
progress_checkpoint ();
|
||||
|
||||
bool valid_hook = false;
|
||||
cn.clear ();
|
||||
|
||||
if (rec_id == sSREF) {
|
||||
|
||||
do {
|
||||
|
|
@ -411,7 +428,7 @@ GDS2ReaderBase::read_context_info_cell ()
|
|||
error (tl::to_string (tr ("SNAME record expected")));
|
||||
}
|
||||
|
||||
std::string cn = get_string ();
|
||||
cn = get_string ();
|
||||
|
||||
rec_id = get_record ();
|
||||
while (rec_id == sSTRANS || rec_id == sANGLE || rec_id == sMAG) {
|
||||
|
|
@ -421,6 +438,24 @@ GDS2ReaderBase::read_context_info_cell ()
|
|||
error (tl::to_string (tr ("XY record expected")));
|
||||
}
|
||||
|
||||
valid_hook = true;
|
||||
|
||||
} else if (rec_id == sBOUNDARY) {
|
||||
|
||||
rec_id = get_record ();
|
||||
while (rec_id == sLAYER || rec_id == sDATATYPE) {
|
||||
rec_id = get_record ();
|
||||
}
|
||||
if (rec_id != sXY) {
|
||||
error (tl::to_string (tr ("XY record expected")));
|
||||
}
|
||||
|
||||
valid_hook = true;
|
||||
|
||||
}
|
||||
|
||||
if (valid_hook) {
|
||||
|
||||
std::vector <std::string> &strings = m_context_info.insert (std::make_pair (cn, std::vector <std::string> ())).first->second;
|
||||
|
||||
size_t attr = 0;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,109 @@ inline int scale (double sf, int value)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
GDS2WriterBase::write_context_cell (db::Layout &layout, const short *time_data, const std::vector<db::cell_index_type> &cells)
|
||||
{
|
||||
write_record_size (4 + 12 * 2);
|
||||
write_record (sBGNSTR);
|
||||
write_time (time_data);
|
||||
write_time (time_data);
|
||||
|
||||
write_string_record (sSTRNAME, "$$$CONTEXT_INFO$$$");
|
||||
|
||||
std::vector <std::string> context_prop_strings;
|
||||
|
||||
if (layout.has_context_info ()) {
|
||||
|
||||
// Use a dummy BOUNDARY element to attach the global context
|
||||
|
||||
write_record_size (4);
|
||||
write_record (sBOUNDARY);
|
||||
|
||||
write_record_size (6);
|
||||
write_record (sLAYER);
|
||||
write_short (0);
|
||||
|
||||
write_record_size (6);
|
||||
write_record (sDATATYPE);
|
||||
write_short (0);
|
||||
|
||||
write_record_size (4 + 5 * 2 * 4);
|
||||
write_record (sXY);
|
||||
for (unsigned int i = 0; i < 10; ++i) {
|
||||
write_int (0);
|
||||
}
|
||||
|
||||
context_prop_strings.clear ();
|
||||
|
||||
if (layout.get_context_info (context_prop_strings)) {
|
||||
|
||||
// Hint: write in the reverse order since this way, the reader is more efficient (it knows how many strings
|
||||
// will arrive)
|
||||
for (std::vector <std::string>::const_iterator s = context_prop_strings.end (); s != context_prop_strings.begin (); ) {
|
||||
|
||||
--s;
|
||||
|
||||
write_record_size (6);
|
||||
write_record (sPROPATTR);
|
||||
write_short (short (std::distance (std::vector <std::string>::const_iterator (context_prop_strings.begin ()), s))); // = user string
|
||||
|
||||
write_string_record (sPROPVALUE, *s);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
write_record_size (4);
|
||||
write_record (sENDEL);
|
||||
|
||||
}
|
||||
|
||||
for (std::vector<db::cell_index_type>::const_iterator cell = cells.begin (); cell != cells.end (); ++cell) {
|
||||
|
||||
if (layout.has_context_info (*cell)) {
|
||||
|
||||
write_record_size (4);
|
||||
write_record (sSREF);
|
||||
|
||||
write_string_record (sSNAME, m_cell_name_map.cell_name (*cell));
|
||||
|
||||
write_record_size (12);
|
||||
write_record (sXY);
|
||||
write_int (0);
|
||||
write_int (0);
|
||||
|
||||
context_prop_strings.clear ();
|
||||
|
||||
if (layout.get_context_info (*cell, context_prop_strings)) {
|
||||
|
||||
// Hint: write in the reverse order since this way, the reader is more efficient (it knows how many strings
|
||||
// will arrive)
|
||||
for (std::vector <std::string>::const_iterator s = context_prop_strings.end (); s != context_prop_strings.begin (); ) {
|
||||
|
||||
--s;
|
||||
|
||||
write_record_size (6);
|
||||
write_record (sPROPATTR);
|
||||
write_short (short (std::distance (std::vector <std::string>::const_iterator (context_prop_strings.begin ()), s))); // = user string
|
||||
|
||||
write_string_record (sPROPVALUE, *s);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
write_record_size (4);
|
||||
write_record (sENDEL);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
write_record_size (4);
|
||||
write_record (sENDSTR);
|
||||
}
|
||||
|
||||
void
|
||||
GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLayoutOptions &options)
|
||||
{
|
||||
|
|
@ -178,73 +281,17 @@ GDS2WriterBase::write (db::Layout &layout, tl::OutputStream &stream, const db::S
|
|||
|
||||
// write context info
|
||||
|
||||
bool any_proxy = false;
|
||||
bool has_context = false;
|
||||
|
||||
if (options.write_context_info ()) {
|
||||
for (std::vector<db::cell_index_type>::const_iterator cell = cells.begin (); cell != cells.end () && !any_proxy; ++cell) {
|
||||
const db::Cell &cref = layout.cell (*cell);
|
||||
if (cref.is_proxy () && ! cref.is_top ()) {
|
||||
any_proxy = true;
|
||||
}
|
||||
has_context = layout.has_context_info ();
|
||||
for (std::vector<db::cell_index_type>::const_iterator cell = cells.begin (); cell != cells.end () && !has_context; ++cell) {
|
||||
has_context = layout.has_context_info (*cell);
|
||||
}
|
||||
}
|
||||
|
||||
if (any_proxy) {
|
||||
|
||||
write_record_size (4 + 12 * 2);
|
||||
write_record (sBGNSTR);
|
||||
write_time (time_data);
|
||||
write_time (time_data);
|
||||
|
||||
write_string_record (sSTRNAME, "$$$CONTEXT_INFO$$$");
|
||||
|
||||
std::vector <std::string> context_prop_strings;
|
||||
|
||||
for (std::vector<db::cell_index_type>::const_iterator cell = cells.begin (); cell != cells.end (); ++cell) {
|
||||
|
||||
const db::Cell &cref = layout.cell (*cell);
|
||||
if (cref.is_proxy () && ! cref.is_top ()) {
|
||||
|
||||
write_record_size (4);
|
||||
write_record (sSREF);
|
||||
|
||||
write_string_record (sSNAME, m_cell_name_map.cell_name (*cell));
|
||||
|
||||
write_record_size (12);
|
||||
write_record (sXY);
|
||||
write_int (0);
|
||||
write_int (0);
|
||||
|
||||
context_prop_strings.clear ();
|
||||
|
||||
if (layout.get_context_info (*cell, context_prop_strings)) {
|
||||
|
||||
// Hint: write in the reverse order since this way, the reader is more efficient (it knows how many strings
|
||||
// will arrive)
|
||||
for (std::vector <std::string>::const_iterator s = context_prop_strings.end (); s != context_prop_strings.begin (); ) {
|
||||
|
||||
--s;
|
||||
|
||||
write_record_size (6);
|
||||
write_record (sPROPATTR);
|
||||
write_short (short (std::distance (std::vector <std::string>::const_iterator (context_prop_strings.begin ()), s))); // = user string
|
||||
|
||||
write_string_record (sPROPVALUE, *s);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
write_record_size (4);
|
||||
write_record (sENDEL);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
write_record_size (4);
|
||||
write_record (sENDSTR);
|
||||
|
||||
if (has_context) {
|
||||
write_context_cell (layout, time_data, cells);
|
||||
}
|
||||
|
||||
// body
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ private:
|
|||
db::WriterCellNameMap m_cell_name_map;
|
||||
|
||||
void write_properties (const db::Layout &layout, db::properties_id_type prop_id);
|
||||
void write_context_cell (db::Layout &layout, const short *time_data, const std::vector<cell_index_type> &cells);
|
||||
};
|
||||
|
||||
} // namespace db
|
||||
|
|
|
|||
Loading…
Reference in New Issue