Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 94 additions & 21 deletions src/plugins/streamers/magic/db_plugin/dbMAGReader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "tlClassRegistry.h"
#include "tlFileUtils.h"
#include "tlUri.h"
#include "tlEnv.h"

#include <cctype>
#include <string>
Expand Down Expand Up @@ -183,7 +184,7 @@ MAGReader::cell_from_path (const std::string &path, db::Layout &layout)
std::string cell_file;
if (! resolve_path (path, layout, cell_file)) {
// skip with a warning if the file can't be opened (TODO: better to raise an error?)
tl::warn << tl::to_string (tr ("Unable to find a layout file for cell - skipping this cell: ")) << path;
warn (tl::sprintf (tl::to_string (tr ("Unable to find a layout file for cell %s - skipping this file: %s")), cellname, path));
layout.cell (ci).set_ghost_cell (true);
} else {
m_cells_to_read.insert (std::make_pair (cellname, std::make_pair (cell_file, ci)));
Expand Down Expand Up @@ -249,12 +250,49 @@ static bool find_and_normalize_file (const tl::URI &uri, std::string &path)
return false;
}

namespace
{

// TODO: this may be useful somewhere else
class EnvInterpolator
: public tl::Eval
{
public:
EnvInterpolator ()
: tl::Eval (0, 0, false) // safe mode
{
// .. nothing yet ..
}

void resolve_name (const std::string &name, const tl::EvalFunction *&function, const tl::Variant *&value, tl::Variant *&var)
{
tl::Eval::resolve_name (name, function, value, var);

if (! value && ! function && ! var) {
auto i = m_values.find (name);
if (i != m_values.end ()) {
value = &i->second;
} else {
std::string v = tl::get_env (name);
tl::Variant *vv = &m_values[name];
*vv = v;
value = vv;
}
}
}

private:
std::map<std::string, tl::Variant> m_values;
};

}

bool
MAGReader::resolve_path (const std::string &path, const db::Layout & /*layout*/, std::string &real_path)
{
tl::Eval expr;
EnvInterpolator expr;

// the variables supported for evaluation are
// the variables supported for lib path evaluation are
// "tech_name": the name of the KLayout technology this file is loaded for (this may be the Magic technology name)
// "tech_dir": the path to KLayout's technology folder for "tech_name" or the default technology's folder path
// "magic_tech": the technology name from the Magic file currently read
Expand All @@ -268,11 +306,20 @@ MAGReader::resolve_path (const std::string &path, const db::Layout & /*layout*/,
}
expr.set_var ("magic_tech", m_tech);

tl::URI path_uri (path);
tl::URI path_uri (expr.interpolate (path));

// absolute URIs are kept - we just try to figure out the suffix
if (tl::is_absolute (path_uri.path ())) {
return find_and_normalize_file (path_uri, real_path);

if (! find_and_normalize_file (path_uri, real_path)) {
if (tl::verbosity () >= 20) {
tl::log << "Unable to locate file with expanded path: " << path_uri.to_string ();
}
return false;
} else {
return true;
}

}

tl::URI source_uri (mp_current_stream->source ());
Expand All @@ -291,6 +338,10 @@ MAGReader::resolve_path (const std::string &path, const db::Layout & /*layout*/,
}
}

if (tl::verbosity () >= 20) {
tl::log << "Unable to locate file with expanded path: " << path_uri.to_string ();
}

return false;
}

Expand Down Expand Up @@ -330,6 +381,7 @@ MAGReader::do_read_part (db::Layout &layout, db::cell_index_type cell_index, tl:
bool valid_layer = false;
unsigned int current_layer = 0;
bool in_labels = false;
double scale = m_lambda;

while (! stream.at_end ()) {

Expand Down Expand Up @@ -359,6 +411,22 @@ MAGReader::do_read_part (db::Layout &layout, db::cell_index_type cell_index, tl:

ex.expect_end ();

} else if (ex.test ("magscale")) {

int n = 1, d = 1;
ex.read (n);
ex.read (d);

if (d <= 0) {
error (tl::to_string (tr ("'magscale' denominator must not be negative or zero")));
}
if (n <= 0) {
error (tl::to_string (tr ("'magscale' nominator must not be negative or zero")));
}
scale = m_lambda * double (n) / double (d);

ex.expect_end ();

} else if (ex.test ("timestamp")) {

size_t ts = 0;
Expand All @@ -385,6 +453,10 @@ MAGReader::do_read_part (db::Layout &layout, db::cell_index_type cell_index, tl:
// ignore "checkpaint" internal layer
in_labels = false;
valid_layer = false;
} else if (lname == "properties") {
// ignore "properties" section as of now
in_labels = false;
valid_layer = false;
} else {
in_labels = false;
std::pair<bool, unsigned int> ll = open_layer (layout, lname);
Expand All @@ -400,28 +472,28 @@ MAGReader::do_read_part (db::Layout &layout, db::cell_index_type cell_index, tl:
if (in_labels) {
error (tl::to_string (tr ("'rect' statement inside labels section")));
} else if (valid_layer) {
read_rect (ex, layout, cell_index, current_layer);
read_rect (ex, layout, cell_index, current_layer, scale);
}

} else if (ex.test ("tri")) {

if (in_labels) {
error (tl::to_string (tr ("'rect' statement inside labels section")));
} else if (valid_layer) {
read_tri (ex, layout, cell_index, current_layer);
read_tri (ex, layout, cell_index, current_layer, scale);
}

} else if (ex.test ("rlabel")) {

if (! in_labels) {
error (tl::to_string (tr ("'rlabel' statement outside labels section")));
} else {
read_rlabel (ex, layout, cell_index);
read_rlabel (ex, layout, cell_index, scale);
}

} else if (ex.test ("use")) {

read_cell_instance (ex, stream, layout, cell_index);
read_cell_instance (ex, stream, layout, cell_index, scale);

}

Expand Down Expand Up @@ -467,7 +539,7 @@ MAGReader::do_merge_part (Layout &layout, cell_index_type cell_index)
}

void
MAGReader::read_rect (tl::Extractor &ex, Layout &layout, cell_index_type cell_index, unsigned int layer)
MAGReader::read_rect (tl::Extractor &ex, Layout &layout, cell_index_type cell_index, unsigned int layer, double scale)
{
double l, b, r, t;
ex.read (l);
Expand All @@ -477,29 +549,30 @@ MAGReader::read_rect (tl::Extractor &ex, Layout &layout, cell_index_type cell_in
ex.expect_end ();

db::DBox box (l, b, r, t);
layout.cell (cell_index).shapes (layer).insert ((box * m_lambda).transformed (m_dbu_trans_inv));
layout.cell (cell_index).shapes (layer).insert ((box * scale).transformed (m_dbu_trans_inv));
}

void
MAGReader::read_tri (tl::Extractor &ex, Layout &layout, cell_index_type cell_index, unsigned int layer)
MAGReader::read_tri (tl::Extractor &ex, Layout &layout, cell_index_type cell_index, unsigned int layer, double scale)
{
double l, b, r, t;
ex.read (l);
ex.read (b);
ex.read (r);
ex.read (t);

// NOTE: that scheme is compatible with MAGIC's reader code (as of version 8.3) -
// we just skip unknown characters
bool s = false, e = false;
while (! ex.at_end ()) {
if (ex.test ("s")) {
s = true;
} else if (ex.test ("e")) {
e = true;
} else {
break;
++ex;
}
}
ex.expect_end ();

std::vector<db::Point> pts;

Expand All @@ -523,11 +596,11 @@ MAGReader::read_tri (tl::Extractor &ex, Layout &layout, cell_index_type cell_ind

db::SimplePolygon poly;
poly.assign_hull (pts.begin (), pts.end ());
layout.cell (cell_index).shapes (layer).insert ((poly * m_lambda).transformed (m_dbu_trans_inv));
layout.cell (cell_index).shapes (layer).insert ((poly * scale).transformed (m_dbu_trans_inv));
}

void
MAGReader::read_rlabel (tl::Extractor &ex, Layout &layout, cell_index_type cell_index)
MAGReader::read_rlabel (tl::Extractor &ex, Layout &layout, cell_index_type cell_index, double scale)
{
std::string lname;
ex.read (lname);
Expand Down Expand Up @@ -573,13 +646,13 @@ MAGReader::read_rlabel (tl::Extractor &ex, Layout &layout, cell_index_type cell_
if (true || lname != "space") { // really? "space"? ignore it?
std::pair<bool, unsigned int> ll = open_layer (layout, lname);
if (ll.first) {
layout.cell (cell_index).shapes (ll.second).insert ((text * m_lambda).transformed (m_dbu_trans_inv));
layout.cell (cell_index).shapes (ll.second).insert ((text * scale).transformed (m_dbu_trans_inv));
}
}
}

void
MAGReader::read_cell_instance (tl::Extractor &ex, tl::TextInputStream &stream, Layout &layout, cell_index_type cell_index)
MAGReader::read_cell_instance (tl::Extractor &ex, tl::TextInputStream &stream, Layout &layout, cell_index_type cell_index, double scale)
{
const char *include_chars_in_files = "$_,.-$+#:;[]()<>|/\\";

Expand Down Expand Up @@ -637,9 +710,9 @@ MAGReader::read_cell_instance (tl::Extractor &ex, tl::TextInputStream &stream, L
ex2.read (ysep);

na = (unsigned long) std::max (0, xhi - xlo + 1);
a = db::DVector (xsep, 0) * m_lambda;
a = db::DVector (xsep, 0) * scale;
nb = (unsigned long) std::max (0, yhi - ylo + 1);
b = db::DVector (0, ysep) * m_lambda;
b = db::DVector (0, ysep) * scale;

} else if (ex2.test ("timestamp")) {
// ignored
Expand All @@ -655,7 +728,7 @@ MAGReader::read_cell_instance (tl::Extractor &ex, tl::TextInputStream &stream, L
ex2.read (m22);
ex2.read (dy);

trans = db::DCplxTrans (db::Matrix2d (m11, m12, m21, m22), db::DVector (dx, dy) * m_lambda);
trans = db::DCplxTrans (db::Matrix2d (m11, m12, m21, m22), db::DVector (dx, dy) * scale);

} else if (ex2.test ("box")) {
// ignored
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/streamers/magic/db_plugin/dbMAGReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,10 @@ class DB_PLUGIN_PUBLIC MAGReader
bool resolve_path(const std::string &path, const Layout &layout, std::string &real_path);
std::string cell_name_from_path (const std::string &path);
db::cell_index_type cell_from_path (const std::string &path, Layout &layout);
void read_rect (tl::Extractor &ex, Layout &layout, cell_index_type cell_index, unsigned int layer);
void read_tri (tl::Extractor &ex, Layout &layout, cell_index_type cell_index, unsigned int layer);
void read_rlabel (tl::Extractor &ex, Layout &layout, cell_index_type cell_index);
void read_cell_instance (tl::Extractor &ex, tl::TextInputStream &stream, Layout &layout, cell_index_type cell_index);
void read_rect (tl::Extractor &ex, Layout &layout, cell_index_type cell_index, unsigned int layer, double scale);
void read_tri (tl::Extractor &ex, Layout &layout, cell_index_type cell_index, unsigned int layer, double scale);
void read_rlabel (tl::Extractor &ex, Layout &layout, cell_index_type cell_index, double scale);
void read_cell_instance (tl::Extractor &ex, tl::TextInputStream &stream, Layout &layout, cell_index_type cell_index, double scale);
};

}
Expand Down
37 changes: 26 additions & 11 deletions src/plugins/streamers/magic/db_plugin/dbMAGWriter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ namespace db
// ---------------------------------------------------------------------------------
// MAGWriter implementation

// A function to produce a zero-area box instead of an empty one
static db::Box safe_box (const db::Box &bx)
{
return bx.empty () ? db::Box (0, 0, 0, 0) : bx;
}

MAGWriter::MAGWriter ()
: mp_stream (0),
m_progress (tl::to_string (tr ("Writing Magic file")), 10000)
Expand Down Expand Up @@ -120,6 +126,8 @@ MAGWriter::filename_for_cell (db::cell_index_type ci, db::Layout &layout)
void
MAGWriter::write_dummy_top (const std::set<db::cell_index_type> &cell_set, const db::Layout &layout, tl::OutputStream &os)
{
m_cellname = "<TOP>";

os.set_as_text (true);
os << "magic\n";

Expand All @@ -144,7 +152,7 @@ MAGWriter::write_dummy_top (const std::set<db::cell_index_type> &cell_set, const
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 ();
db::Box bx = safe_box (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 ()));
Expand Down Expand Up @@ -191,7 +199,7 @@ MAGWriter::do_write_cell (db::cell_index_type ci, const std::vector <std::pair <
db::Cell &cell = layout.cell (ci);

os << "<< checkpaint >>\n";
write_polygon (db::Polygon (cell.bbox ()), layout, os);
write_polygon (db::Polygon (safe_box (cell.bbox ())), layout, os);

bool any;

Expand Down Expand Up @@ -292,18 +300,25 @@ namespace {
void
MAGWriter::write_polygon (const db::Polygon &poly, const db::Layout & /*layout*/, tl::OutputStream &os)
{
db::EdgeProcessor ep;
ep.insert (scaled (poly));
db::MergeOp op;
TrapezoidWriter writer (os);
db::TrapezoidGenerator tpgen (writer);
ep.process (tpgen, op);

if (poly.is_empty ()) {
// ignore empty polygons
} else if (poly.is_box ()) {
writer.put (db::SimplePolygon (scaled (poly.box ())));
} else {
db::EdgeProcessor ep;
ep.insert (scaled (poly));
db::MergeOp op;
db::TrapezoidGenerator tpgen (writer);
ep.process (tpgen, op);
}
}

void
MAGWriter::write_label (const std::string &layer, const db::Text &text, const db::Layout & /*layout*/, tl::OutputStream &os)
{
db::DVector v = db::DVector (text.trans ().disp ()) * m_sf;
db::Vector v = scaled (text.trans ().disp ());

std::string s = text.string ();
if (s.find ("\n") != std::string::npos) {
Expand Down Expand Up @@ -372,7 +387,7 @@ MAGWriter::write_single_instance (db::cell_index_type ci, db::ICplxTrans trans,
db::Vector d = scaled (trans.disp ());
os << "transform " << m.m11 () << " " << m.m12 () << " " << d.x () << " " << m.m21 () << " " << m.m22 () << " " << d.y () << "\n";

db::Box bx = scaled (layout.cell (ci).bbox ());
db::Box bx = scaled (safe_box (layout.cell (ci).bbox ()));
os << "box " << bx.left () << " " << bx.bottom () << " " << bx.right () << " " << bx.top () << "\n";
}

Expand Down Expand Up @@ -410,7 +425,7 @@ MAGWriter::scaled (const db::Vector &v) const
{
db::Vector res (db::DVector (v) * m_sf);
if (! db::DVector (res).equal (db::DVector (v) * m_sf)) {
tl::warn << tl::sprintf (tl::to_string (tr ("Vector rounding occurred at %s in cell %s - not a multiple of lambda (%.12g)")), v.to_string (), m_cellname, m_options.lambda);
tl::warn << tl::sprintf (tl::to_string (tr ("Vector rounding occurred at %s in cell %s - not a multiple of lambda (%.12g)")), (db::DVector (v) * m_sf).to_string (), m_cellname, m_options.lambda);
}
return res;
}
Expand All @@ -420,7 +435,7 @@ MAGWriter::scaled (const db::Point &p) const
{
db::Point res (db::DPoint (p) * m_sf);
if (! db::DPoint (res).equal (db::DPoint (p) * m_sf)) {
tl::warn << tl::sprintf (tl::to_string (tr ("Coordinate rounding occurred at %s in cell %s - not a multiple of lambda (%.12g)")), p.to_string (), m_cellname, m_options.lambda);
tl::warn << tl::sprintf (tl::to_string (tr ("Coordinate rounding occurred at %s in cell %s - not a multiple of lambda (%.12g)")), (db::DPoint (p) * m_sf).to_string (), m_cellname, m_options.lambda);
}
return res;
}
Expand Down
Loading
Loading