Next steps - persistency of meta info

This commit is contained in:
Matthias Koefferlein
2023-04-18 21:24:26 +02:00
parent b14c630ce9
commit 78da3effa2
9 changed files with 368 additions and 107 deletions
@@ -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