mirror of https://github.com/KLayout/klayout.git
Implemented a dummy arrangement of cells when the MAG output file isn't corresponding to a existing cell - useful for obtaining a cell overview
This commit is contained in:
parent
c49bc17e6a
commit
152dc87682
|
|
@ -63,7 +63,7 @@ MAGWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa
|
|||
std::string basename = tl::basename (src.path ());
|
||||
std::pair<bool, db::cell_index_type> 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<MAGWriterOptions> ();
|
||||
|
|
@ -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<db::cell_index_type>::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<db::cell_index_type> &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<std::string, db::cell_index_type> cells_by_name;
|
||||
for (std::set<db::cell_index_type>::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<db::CellInstArray> cell_instances;
|
||||
cell_instances.reserve (cells_by_name.size ());
|
||||
for (std::map<std::string, db::cell_index_type>::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<db::CellInstArray>::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 <std::pair <unsigned int, db::LayerProperties> > &layers, db::Layout &layout, tl::OutputStream &os)
|
||||
{
|
||||
|
|
@ -403,6 +452,4 @@ MAGWriter::make_string (const std::string &s)
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <std::pair <unsigned int, db::LayerProperties> > &layers, db::Layout &layout, tl::OutputStream &os);
|
||||
void write_dummmy_top (const std::set<db::cell_index_type> &cell_set, const db::Layout &layout, tl::OutputStream &os);
|
||||
void do_write_cell (db::cell_index_type ci, const std::vector <std::pair <unsigned int, db::LayerProperties> > &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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue