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::string basename = tl::basename (src.path ());
|
||||||
std::pair<bool, db::cell_index_type> ci = layout.cell_by_name (basename.c_str ());
|
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 ()) {
|
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> ();
|
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;
|
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) {
|
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);
|
tl::OutputStream os (filename_for_cell (*c, layout), tl::OutputStream::OM_Auto, true);
|
||||||
write_cell (*c, layers, layout, os);
|
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 ();
|
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
|
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)
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ private:
|
||||||
|
|
||||||
std::string filename_for_cell (db::cell_index_type ci, db::Layout &layout);
|
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_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 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_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);
|
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 ()
|
OutputStream::~OutputStream ()
|
||||||
|
{
|
||||||
|
close ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
OutputStream::close ()
|
||||||
{
|
{
|
||||||
flush ();
|
flush ();
|
||||||
|
|
||||||
|
|
@ -759,7 +765,7 @@ inline void fast_copy (char *t, const char *s, size_t n)
|
||||||
void
|
void
|
||||||
OutputStream::flush ()
|
OutputStream::flush ()
|
||||||
{
|
{
|
||||||
if (m_buffer_pos > 0) {
|
if (m_buffer_pos > 0 && mp_delegate) {
|
||||||
mp_delegate->write (mp_buffer, m_buffer_pos);
|
mp_delegate->write (mp_buffer, m_buffer_pos);
|
||||||
m_buffer_pos = 0;
|
m_buffer_pos = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -768,6 +774,10 @@ OutputStream::flush ()
|
||||||
void
|
void
|
||||||
OutputStream::put (const char *b, size_t n)
|
OutputStream::put (const char *b, size_t n)
|
||||||
{
|
{
|
||||||
|
if (! mp_delegate) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_as_text) {
|
if (m_as_text) {
|
||||||
// skip CR, but replace LF by CRLF -> this will normalize the line terminators to CRLF
|
// skip CR, but replace LF by CRLF -> this will normalize the line terminators to CRLF
|
||||||
while (n > 0) {
|
while (n > 0) {
|
||||||
|
|
@ -825,7 +835,9 @@ OutputStream::seek (size_t pos)
|
||||||
{
|
{
|
||||||
flush ();
|
flush ();
|
||||||
|
|
||||||
|
if (mp_delegate) {
|
||||||
mp_delegate->seek (pos);
|
mp_delegate->seek (pos);
|
||||||
|
}
|
||||||
m_pos = pos;
|
m_pos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1033,6 +1033,11 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual ~OutputStream ();
|
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
|
* @brief This is the outer write method to call
|
||||||
*
|
*
|
||||||
|
|
@ -1108,7 +1113,7 @@ public:
|
||||||
*/
|
*/
|
||||||
bool supports_seek () const
|
bool supports_seek () const
|
||||||
{
|
{
|
||||||
return mp_delegate->supports_seek ();
|
return mp_delegate != 0 && mp_delegate->supports_seek ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue