diff --git a/src/plugins/streamers/magic/db_plugin/dbMAGWriter.cc b/src/plugins/streamers/magic/db_plugin/dbMAGWriter.cc index c349a0bbf..aea13efbc 100644 --- a/src/plugins/streamers/magic/db_plugin/dbMAGWriter.cc +++ b/src/plugins/streamers/magic/db_plugin/dbMAGWriter.cc @@ -63,7 +63,7 @@ MAGWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa std::string basename = tl::basename (src.path ()); std::pair ci = layout.cell_by_name (basename.c_str ()); if (! ci.first || cell_set.find (ci.second) == cell_set.end ()) { - tl::warn << tl::to_string (tr ("Magic file names should be valid cell names - otherwise no such file is written. This is not a valid name: ")) << basename; + tl::warn << tl::to_string (tr ("The output file is not corresponding to an existing cell name. The content of this cell will not be a real layout: ")) << basename; } m_options = options.get_options (); @@ -91,6 +91,11 @@ MAGWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa m_sf = layout.dbu () / lambda; + // As a favor, write a dummy top level file before closing the stream. If the file name corresponds to a real cell, + // this file is overwritten by the true cell. + write_dummmy_top (cell_set, layout, stream); + stream.close (); + for (std::set::const_iterator c = cell_set.begin (); c != cell_set.end (); ++c) { tl::OutputStream os (filename_for_cell (*c, layout), tl::OutputStream::OM_Auto, true); write_cell (*c, layers, layout, os); @@ -109,6 +114,50 @@ MAGWriter::filename_for_cell (db::cell_index_type ci, db::Layout &layout) return uri.to_string (); } +void +MAGWriter::write_dummmy_top (const std::set &cell_set, const db::Layout &layout, tl::OutputStream &os) +{ + os.set_as_text (true); + os << "magic\n"; + + std::string tech = m_options.tech; + if (tech.empty ()) { + tech = layout.meta_info_value ("technology"); + } + if (! tech.empty ()) { + os << "tech " << make_string (tl::to_lower_case (tech)) << "\n"; + } + + os << "timestamp " << m_timestamp << "\n"; + + std::map cells_by_name; + for (std::set::const_iterator c = cell_set.begin (); c != cell_set.end (); ++c) { + cells_by_name.insert (std::make_pair (std::string (layout.cell_name (*c)), *c)); + } + + db::Coord y = 0; + db::Coord w = 0; + std::vector cell_instances; + cell_instances.reserve (cells_by_name.size ()); + for (std::map::const_iterator c = cells_by_name.begin (); c != cells_by_name.end (); ++c) { + // instances are arrayed as stack + db::Box bx = layout.cell (c->second).bbox (); + cell_instances.push_back (db::CellInstArray (db::CellInst (c->second), db::Trans (db::Vector (0, y) + (db::Point () - bx.p1 ())))); + y += bx.height (); + w = std::max (w, db::Coord (bx.width ())); + } + + os << "<< checkpaint >>\n"; + write_polygon (db::Polygon (db::Box (0, 0, w, y)), layout, os); + + m_cell_id.clear (); + for (std::vector::const_iterator i = cell_instances.begin (); i != cell_instances.end (); ++i) { + write_instance (*i, layout, os); + } + + os << "<< end >>\n"; +} + void MAGWriter::write_cell (db::cell_index_type ci, const std::vector > &layers, db::Layout &layout, tl::OutputStream &os) { @@ -403,6 +452,4 @@ MAGWriter::make_string (const std::string &s) return res; } - } - diff --git a/src/plugins/streamers/magic/db_plugin/dbMAGWriter.h b/src/plugins/streamers/magic/db_plugin/dbMAGWriter.h index d562b1d57..d3ca4671e 100644 --- a/src/plugins/streamers/magic/db_plugin/dbMAGWriter.h +++ b/src/plugins/streamers/magic/db_plugin/dbMAGWriter.h @@ -99,6 +99,7 @@ private: std::string filename_for_cell (db::cell_index_type ci, db::Layout &layout); void write_cell (db::cell_index_type ci, const std::vector > &layers, db::Layout &layout, tl::OutputStream &os); + void write_dummmy_top (const std::set &cell_set, const db::Layout &layout, tl::OutputStream &os); void do_write_cell (db::cell_index_type ci, const std::vector > &layers, db::Layout &layout, tl::OutputStream &os); void write_polygon (const db::Polygon &poly, const db::Layout &layout, tl::OutputStream &os); void write_label (const std::string &layer, const db::Text &text, const Layout &layout, tl::OutputStream &os); diff --git a/src/tl/tl/tlStream.cc b/src/tl/tl/tlStream.cc index 69594712f..7b1724bf8 100644 --- a/src/tl/tl/tlStream.cc +++ b/src/tl/tl/tlStream.cc @@ -715,6 +715,12 @@ OutputStream::OutputStream (const std::string &abstract_path, OutputStreamMode o } OutputStream::~OutputStream () +{ + close (); +} + +void +OutputStream::close () { flush (); @@ -759,7 +765,7 @@ inline void fast_copy (char *t, const char *s, size_t n) void OutputStream::flush () { - if (m_buffer_pos > 0) { + if (m_buffer_pos > 0 && mp_delegate) { mp_delegate->write (mp_buffer, m_buffer_pos); m_buffer_pos = 0; } @@ -768,6 +774,10 @@ OutputStream::flush () void OutputStream::put (const char *b, size_t n) { + if (! mp_delegate) { + return; + } + if (m_as_text) { // skip CR, but replace LF by CRLF -> this will normalize the line terminators to CRLF while (n > 0) { @@ -825,7 +835,9 @@ OutputStream::seek (size_t pos) { flush (); - mp_delegate->seek (pos); + if (mp_delegate) { + mp_delegate->seek (pos); + } m_pos = pos; } diff --git a/src/tl/tl/tlStream.h b/src/tl/tl/tlStream.h index 19c854690..c300c551d 100644 --- a/src/tl/tl/tlStream.h +++ b/src/tl/tl/tlStream.h @@ -1033,6 +1033,11 @@ public: */ virtual ~OutputStream (); + /** + * @brief Closes the stream - after closing, the stream can't be accessed anymore + */ + void close (); + /** * @brief This is the outer write method to call * @@ -1108,7 +1113,7 @@ public: */ bool supports_seek () const { - return mp_delegate->supports_seek (); + return mp_delegate != 0 && mp_delegate->supports_seek (); } /**