mirror of https://github.com/KLayout/klayout.git
Added VIA size selectors for LEF/DEF .map files.
This commit is contained in:
parent
898dbf07e9
commit
eda1992a7d
|
|
@ -893,8 +893,16 @@ DEFImporter::read_nets (db::Layout &layout, db::Cell &design, double scale, bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Shape>
|
||||||
|
static db::DVector
|
||||||
|
via_size (double dbu, const Shape &shape)
|
||||||
|
{
|
||||||
|
db::Box box = db::box_convert<Shape> () (shape);
|
||||||
|
return db::DVector (box.width () * dbu, box.height () * dbu);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DEFImporter::read_vias (db::Layout & /*layout*/, db::Cell & /*design*/, double scale)
|
DEFImporter::read_vias (db::Layout &layout, db::Cell & /*design*/, double scale)
|
||||||
{
|
{
|
||||||
while (test ("-")) {
|
while (test ("-")) {
|
||||||
|
|
||||||
|
|
@ -1036,13 +1044,13 @@ DEFImporter::read_vias (db::Layout & /*layout*/, db::Cell & /*design*/, double s
|
||||||
|
|
||||||
db::Polygon poly;
|
db::Polygon poly;
|
||||||
read_polygon (poly, scale);
|
read_polygon (poly, scale);
|
||||||
geo_based_vg->add_polygon (ln, ViaGeometry, poly, mask, 0);
|
geo_based_vg->add_polygon (ln, ViaGeometry, poly, mask, 0, via_size (layout.dbu (), poly));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
db::Polygon poly;
|
db::Polygon poly;
|
||||||
read_rect (poly, scale);
|
read_rect (poly, scale);
|
||||||
geo_based_vg->add_polygon (ln, ViaGeometry, poly, mask, 0);
|
geo_based_vg->add_polygon (ln, ViaGeometry, poly, mask, 0, via_size (layout.dbu (), poly));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,66 @@ static unsigned int mask (const std::vector<unsigned int> &masks, unsigned int i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string purpose_to_name (LayerPurpose purpose)
|
||||||
|
{
|
||||||
|
switch (purpose) {
|
||||||
|
case Outline:
|
||||||
|
return "OUTLINE";
|
||||||
|
case Regions:
|
||||||
|
return "REGION";
|
||||||
|
case PlacementBlockage:
|
||||||
|
return "BLOCKAGE";
|
||||||
|
case Routing:
|
||||||
|
return "NET";
|
||||||
|
case SpecialRouting:
|
||||||
|
return "SPNET";
|
||||||
|
case ViaGeometry:
|
||||||
|
return "VIA";
|
||||||
|
case Label:
|
||||||
|
return "LABEL";
|
||||||
|
case Pins:
|
||||||
|
return "PIN";
|
||||||
|
case Fills:
|
||||||
|
return "FILL";
|
||||||
|
case FillsOPC:
|
||||||
|
return "FILLOPC";
|
||||||
|
case LEFPins:
|
||||||
|
return "LEFPIN";
|
||||||
|
case Obstructions:
|
||||||
|
return "LEFOBS";
|
||||||
|
case Blockage:
|
||||||
|
return "BLK";
|
||||||
|
case All:
|
||||||
|
return "ALL";
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::string ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string
|
||||||
|
layer_spec_to_name (const std::string &layer_name, LayerPurpose purpose, unsigned int mask, const db::DVector &via_size)
|
||||||
|
{
|
||||||
|
std::string ps = purpose_to_name (purpose);
|
||||||
|
|
||||||
|
std::string n = layer_name;
|
||||||
|
if (! n.empty ()) {
|
||||||
|
n += ".";
|
||||||
|
}
|
||||||
|
n += ps;
|
||||||
|
|
||||||
|
if (mask > 0) {
|
||||||
|
n += ":";
|
||||||
|
n += tl::to_string (mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (via_size != db::DVector ()) {
|
||||||
|
n += ":SIZE";
|
||||||
|
n += tl::sprintf ("%.12gX%.12g", via_size.x (), via_size.y ());
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
// RuleBasedViaGenerator implementation
|
// RuleBasedViaGenerator implementation
|
||||||
|
|
||||||
|
|
@ -144,12 +204,12 @@ RuleBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, d
|
||||||
|
|
||||||
std::set <unsigned int> dl;
|
std::set <unsigned int> dl;
|
||||||
|
|
||||||
dl = reader.open_layer (layout, m_bottom_layer, ViaGeometry, mask_bottom);
|
dl = reader.open_layer (layout, m_bottom_layer, ViaGeometry, mask_bottom, via_box.enlarged (m_be));
|
||||||
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
|
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
|
||||||
cell.shapes (*l).insert (db::Polygon (via_box.enlarged (m_be).moved (m_bo)));
|
cell.shapes (*l).insert (db::Polygon (via_box.enlarged (m_be).moved (m_bo)));
|
||||||
}
|
}
|
||||||
|
|
||||||
dl = reader.open_layer (layout, m_top_layer, ViaGeometry, mask_top);
|
dl = reader.open_layer (layout, m_top_layer, ViaGeometry, mask_top, via_box.enlarged (m_te));
|
||||||
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
|
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
|
||||||
cell.shapes (*l).insert (db::Polygon (via_box.enlarged (m_te).moved (m_bo)));
|
cell.shapes (*l).insert (db::Polygon (via_box.enlarged (m_te).moved (m_bo)));
|
||||||
}
|
}
|
||||||
|
|
@ -248,7 +308,7 @@ RuleBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, d
|
||||||
cm = (mask_cut + r + c - 1) % num_cut_masks + 1;
|
cm = (mask_cut + r + c - 1) % num_cut_masks + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dl = reader.open_layer (layout, m_cut_layer, ViaGeometry, cm);
|
dl = reader.open_layer (layout, m_cut_layer, ViaGeometry, cm, vb);
|
||||||
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
|
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
|
||||||
cell.shapes (*l).insert (db::Polygon (vb));
|
cell.shapes (*l).insert (db::Polygon (vb));
|
||||||
}
|
}
|
||||||
|
|
@ -313,12 +373,12 @@ GeometryBasedLayoutGenerator::combine_maskshifts (const std::string &ln, unsigne
|
||||||
void
|
void
|
||||||
GeometryBasedLayoutGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector<std::string> *ext_msl, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm)
|
GeometryBasedLayoutGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector<std::string> *ext_msl, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm)
|
||||||
{
|
{
|
||||||
for (std::map <std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, db::Shapes>::const_iterator g = m_shapes.begin (); g != m_shapes.end (); ++g) {
|
for (std::map <std::pair<std::string, LayerDetailsKey>, db::Shapes>::const_iterator g = m_shapes.begin (); g != m_shapes.end (); ++g) {
|
||||||
|
|
||||||
unsigned int mshift = get_maskshift (g->first.first, ext_msl, masks);
|
unsigned int mshift = get_maskshift (g->first.first, ext_msl, masks);
|
||||||
unsigned int mask = mask_for (g->first.first, g->first.second.second, mshift, nm);
|
unsigned int mask = mask_for (g->first.first, g->first.second.mask, mshift, nm);
|
||||||
|
|
||||||
std::set <unsigned int> dl = reader.open_layer (layout, g->first.first, g->first.second.first, mask);
|
std::set <unsigned int> dl = reader.open_layer (layout, g->first.first, g->first.second.purpose, mask, g->first.second.via_size);
|
||||||
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
|
for (std::set<unsigned int>::const_iterator l = dl.begin (); l != dl.end (); ++l) {
|
||||||
cell.shapes (*l).insert (g->second);
|
cell.shapes (*l).insert (g->second);
|
||||||
}
|
}
|
||||||
|
|
@ -363,27 +423,27 @@ static db::Shape insert_shape (db::Shapes &shapes, const Shape &shape, db::prope
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GeometryBasedLayoutGenerator::add_polygon (const std::string &ln, LayerPurpose purpose, const db::Polygon &poly, unsigned int mask, db::properties_id_type prop_id)
|
GeometryBasedLayoutGenerator::add_polygon (const std::string &ln, LayerPurpose purpose, const db::Polygon &poly, unsigned int mask, db::properties_id_type prop_id, const db::DVector &via_size)
|
||||||
{
|
{
|
||||||
insert_shape (m_shapes [std::make_pair (ln, std::make_pair (purpose, mask))], poly, prop_id);
|
insert_shape (m_shapes [std::make_pair (ln, LayerDetailsKey (purpose, mask, via_size))], poly, prop_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GeometryBasedLayoutGenerator::add_box (const std::string &ln, LayerPurpose purpose, const db::Box &box, unsigned int mask, db::properties_id_type prop_id)
|
GeometryBasedLayoutGenerator::add_box (const std::string &ln, LayerPurpose purpose, const db::Box &box, unsigned int mask, db::properties_id_type prop_id, const db::DVector &via_size)
|
||||||
{
|
{
|
||||||
insert_shape (m_shapes [std::make_pair (ln, std::make_pair (purpose, mask))], box, prop_id);
|
insert_shape (m_shapes [std::make_pair (ln, LayerDetailsKey (purpose, mask, via_size))], box, prop_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GeometryBasedLayoutGenerator::add_path (const std::string &ln, LayerPurpose purpose, const db::Path &path, unsigned int mask, db::properties_id_type prop_id)
|
GeometryBasedLayoutGenerator::add_path (const std::string &ln, LayerPurpose purpose, const db::Path &path, unsigned int mask, db::properties_id_type prop_id, const db::DVector &via_size)
|
||||||
{
|
{
|
||||||
insert_shape (m_shapes [std::make_pair (ln, std::make_pair (purpose, mask))], path, prop_id);
|
insert_shape (m_shapes [std::make_pair (ln, LayerDetailsKey (purpose, mask, via_size))], path, prop_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GeometryBasedLayoutGenerator::add_text (const std::string &ln, LayerPurpose purpose, const db::Text &text, unsigned int mask, db::properties_id_type prop_id)
|
GeometryBasedLayoutGenerator::add_text (const std::string &ln, LayerPurpose purpose, const db::Text &text, unsigned int mask, db::properties_id_type prop_id)
|
||||||
{
|
{
|
||||||
insert_shape (m_shapes [std::make_pair (ln, std::make_pair (purpose, mask))], text, prop_id);
|
insert_shape (m_shapes [std::make_pair (ln, LayerDetailsKey (purpose, mask))], text, prop_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -876,12 +936,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
purpose_translation ["BLOCKAGE"] = Blockage;
|
purpose_translation ["BLOCKAGE"] = Blockage;
|
||||||
purpose_translation ["ALL"] = All;
|
purpose_translation ["ALL"] = All;
|
||||||
|
|
||||||
std::map<LayerPurpose, std::string> purpose_translation_rev;
|
std::map<std::pair<std::string, LayerDetailsKey>, std::vector<db::LayerProperties> > layer_map;
|
||||||
for (std::map<std::string, LayerPurpose>::const_iterator i = purpose_translation.begin (); i != purpose_translation.end (); ++i) {
|
|
||||||
purpose_translation_rev.insert (std::make_pair (i->second, i->first));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::map<std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, std::vector<db::LayerProperties> > layer_map;
|
|
||||||
|
|
||||||
while (! ts.at_end ()) {
|
while (! ts.at_end ()) {
|
||||||
|
|
||||||
|
|
@ -896,7 +951,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
|
|
||||||
std::string w1, w2;
|
std::string w1, w2;
|
||||||
std::vector<int> layers, datatypes;
|
std::vector<int> layers, datatypes;
|
||||||
size_t max_purpose_str = 10;
|
size_t max_purpose_str = 15;
|
||||||
|
|
||||||
if (! ex.try_read_word (w1) || ! ex.try_read_word (w2, "._$,/:") || ! try_read_layers (ex, layers) || ! try_read_layers (ex, datatypes)) {
|
if (! ex.try_read_word (w1) || ! ex.try_read_word (w2, "._$,/:") || ! try_read_layers (ex, layers) || ! try_read_layers (ex, datatypes)) {
|
||||||
tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d not understood - skipped")), path, ts.line_number ());
|
tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d not understood - skipped")), path, ts.line_number ());
|
||||||
|
|
@ -907,7 +962,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
|
|
||||||
for (std::vector<int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
for (std::vector<int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
||||||
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
|
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
|
||||||
layer_map [std::make_pair (std::string (), std::make_pair (Outline, (unsigned int) 0))].push_back (db::LayerProperties (*l, *d, "OUTLINE"));
|
layer_map [std::make_pair (std::string (), LayerDetailsKey (Outline))].push_back (db::LayerProperties (*l, *d, "OUTLINE"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -915,7 +970,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
|
|
||||||
for (std::vector<int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
for (std::vector<int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
||||||
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
|
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
|
||||||
layer_map [std::make_pair (std::string (), std::make_pair (Regions, (unsigned int) 0))].push_back (db::LayerProperties (*l, *d, "REGIONS"));
|
layer_map [std::make_pair (std::string (), LayerDetailsKey (Regions))].push_back (db::LayerProperties (*l, *d, "REGIONS"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -923,7 +978,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
|
|
||||||
for (std::vector<int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
for (std::vector<int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
||||||
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
|
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
|
||||||
layer_map [std::make_pair (std::string (), std::make_pair (PlacementBlockage, (unsigned int) 0))].push_back (db::LayerProperties (*l, *d, "PLACEMENT_BLK"));
|
layer_map [std::make_pair (std::string (), LayerDetailsKey (PlacementBlockage))].push_back (db::LayerProperties (*l, *d, "PLACEMENT_BLK"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -949,7 +1004,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
for (std::vector<std::string>::const_iterator ln = layer_names.begin (); ln != layer_names.end (); ++ln) {
|
for (std::vector<std::string>::const_iterator ln = layer_names.begin (); ln != layer_names.end (); ++ln) {
|
||||||
for (std::vector<int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
for (std::vector<int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
||||||
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
|
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
|
||||||
layer_map [std::make_pair (*ln, std::make_pair (Label, (unsigned int) 0))].push_back (db::LayerProperties (*l, *d, final_name));
|
layer_map [std::make_pair (*ln, LayerDetailsKey (Label))].push_back (db::LayerProperties (*l, *d, final_name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -968,7 +1023,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
// "(M1,PINS): M1.NET/PINS"
|
// "(M1,PINS): M1.NET/PINS"
|
||||||
// (separating, translating and recombing the purposes)
|
// (separating, translating and recombing the purposes)
|
||||||
|
|
||||||
std::set<std::pair<LayerPurpose, unsigned int> > translated_purposes;
|
std::set<LayerDetailsKey> translated_purposes;
|
||||||
|
|
||||||
std::vector<std::string> purposes = tl::split (w2, ",");
|
std::vector<std::string> purposes = tl::split (w2, ",");
|
||||||
std::reverse (purposes.begin (), purposes.end ());
|
std::reverse (purposes.begin (), purposes.end ());
|
||||||
|
|
@ -982,6 +1037,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
|
|
||||||
std::string ps;
|
std::string ps;
|
||||||
ex.read_word_or_quoted (ps);
|
ex.read_word_or_quoted (ps);
|
||||||
|
db::DVector via_size;
|
||||||
|
|
||||||
std::map<std::string, LayerPurpose>::const_iterator i = purpose_translation.find (ps);
|
std::map<std::string, LayerPurpose>::const_iterator i = purpose_translation.find (ps);
|
||||||
if (i != purpose_translation.end ()) {
|
if (i != purpose_translation.end ()) {
|
||||||
|
|
@ -997,9 +1053,11 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
} else if (i->second == ViaGeometry) {
|
} else if (i->second == ViaGeometry) {
|
||||||
|
|
||||||
if (ex.test (":SIZE:")) {
|
if (ex.test (":SIZE:")) {
|
||||||
std::string sz;
|
double sx = 0.0, sy = 0.0;
|
||||||
ex.read_word (sz);
|
ex.read (sx);
|
||||||
tl::warn << tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: VIA size constraint ignored for layer %s")), path, ts.line_number (), w1);
|
ex.test("X");
|
||||||
|
ex.read (sy);
|
||||||
|
via_size = db::DVector (sx, sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1018,13 +1076,13 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
|
|
||||||
for (std::map<std::string, LayerPurpose>::const_iterator p = purpose_translation.begin (); p != purpose_translation.end (); ++p) {
|
for (std::map<std::string, LayerPurpose>::const_iterator p = purpose_translation.begin (); p != purpose_translation.end (); ++p) {
|
||||||
if (p->second != All) {
|
if (p->second != All) {
|
||||||
translated_purposes.insert (std::make_pair (p->second, mask));
|
translated_purposes.insert (LayerDetailsKey (p->second, mask, via_size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
translated_purposes.insert (std::make_pair (i->second, mask));
|
translated_purposes.insert (LayerDetailsKey (i->second, mask, via_size));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1033,19 +1091,15 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
// create a visual description string for the combined purposes
|
// create a visual description string for the combined purposes
|
||||||
std::string purpose_str;
|
std::string purpose_str;
|
||||||
|
|
||||||
for (std::set<std::pair<LayerPurpose, unsigned int> >::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) {
|
for (std::set<LayerDetailsKey>::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) {
|
||||||
|
|
||||||
if (p != translated_purposes.begin ()) {
|
if (p != translated_purposes.begin ()) {
|
||||||
purpose_str += "/";
|
purpose_str += "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ps = purpose_translation_rev [p->first];
|
std::string ps = layer_spec_to_name (std::string (), p->purpose, p->mask, p->via_size);
|
||||||
if (p->second > 0) {
|
|
||||||
ps += ":";
|
|
||||||
ps += tl::to_string (p->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((purpose_str + ps).size () > max_purpose_str) {
|
if (p != translated_purposes.begin () && (purpose_str + ps).size () > max_purpose_str) {
|
||||||
purpose_str += "...";
|
purpose_str += "...";
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1056,7 +1110,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
|
|
||||||
std::string final_name = w1 + "." + purpose_str;
|
std::string final_name = w1 + "." + purpose_str;
|
||||||
|
|
||||||
for (std::set<std::pair<LayerPurpose, unsigned int> >::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) {
|
for (std::set<LayerDetailsKey>::const_iterator p = translated_purposes.begin (); p != translated_purposes.end (); ++p) {
|
||||||
for (std::vector<int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
for (std::vector<int>::const_iterator l = layers.begin (); l != layers.end (); ++l) {
|
||||||
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
|
for (std::vector<int>::const_iterator d = datatypes.begin (); d != datatypes.end (); ++d) {
|
||||||
layer_map [std::make_pair (w1, *p)].push_back (db::LayerProperties (*l, *d, final_name));
|
layer_map [std::make_pair (w1, *p)].push_back (db::LayerProperties (*l, *d, final_name));
|
||||||
|
|
@ -1077,7 +1131,7 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
m_layer_map.clear ();
|
m_layer_map.clear ();
|
||||||
|
|
||||||
db::DirectLayerMapping lm (&layout);
|
db::DirectLayerMapping lm (&layout);
|
||||||
for (std::map<std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, std::vector<db::LayerProperties> >::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) {
|
for (std::map<std::pair<std::string, LayerDetailsKey>, std::vector<db::LayerProperties> >::const_iterator i = layer_map.begin (); i != layer_map.end (); ++i) {
|
||||||
for (std::vector<db::LayerProperties>::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
|
for (std::vector<db::LayerProperties>::const_iterator j = i->second.begin (); j != i->second.end (); ++j) {
|
||||||
unsigned int layer = lm.map_layer (*j).second;
|
unsigned int layer = lm.map_layer (*j).second;
|
||||||
m_layers [i->first].insert (layer);
|
m_layers [i->first].insert (layer);
|
||||||
|
|
@ -1087,9 +1141,13 @@ LEFDEFReaderState::read_map_file (const std::string &path, db::Layout &layout)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set <unsigned int>
|
std::set <unsigned int>
|
||||||
LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPurpose purpose, unsigned int mask)
|
LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPurpose purpose, unsigned int mask, const db::DVector &via_size)
|
||||||
{
|
{
|
||||||
std::map <std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, std::set<unsigned int> >::const_iterator nl = m_layers.find (std::make_pair (n, std::make_pair (purpose, mask)));
|
std::map <std::pair<std::string, LayerDetailsKey>, std::set<unsigned int> >::const_iterator nl;
|
||||||
|
nl = m_layers.find (std::make_pair (n, LayerDetailsKey (purpose, mask, via_size)));
|
||||||
|
if (nl == m_layers.end ()) {
|
||||||
|
nl = m_layers.find (std::make_pair (n, LayerDetailsKey (purpose, mask)));
|
||||||
|
}
|
||||||
if (nl == m_layers.end ()) {
|
if (nl == m_layers.end ()) {
|
||||||
|
|
||||||
std::set <unsigned int> ll;
|
std::set <unsigned int> ll;
|
||||||
|
|
@ -1098,7 +1156,7 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu
|
||||||
ll = open_layer_uncached (layout, n, purpose, mask);
|
ll = open_layer_uncached (layout, n, purpose, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_layers.insert (std::make_pair (std::make_pair (n, std::make_pair (purpose, mask)), ll));
|
m_layers.insert (std::make_pair (std::make_pair (n, LayerDetailsKey (purpose, mask)), ll));
|
||||||
return ll;
|
return ll;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1106,42 +1164,6 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string purpose_to_name (LayerPurpose purpose)
|
|
||||||
{
|
|
||||||
switch (purpose) {
|
|
||||||
case Outline:
|
|
||||||
return "OUTLINE";
|
|
||||||
case Regions:
|
|
||||||
return "REGION";
|
|
||||||
case PlacementBlockage:
|
|
||||||
return "BLOCKAGE";
|
|
||||||
case Routing:
|
|
||||||
return "NET";
|
|
||||||
case SpecialRouting:
|
|
||||||
return "SPNET";
|
|
||||||
case ViaGeometry:
|
|
||||||
return "VIA";
|
|
||||||
case Label:
|
|
||||||
return "LABEL";
|
|
||||||
case Pins:
|
|
||||||
return "PIN";
|
|
||||||
case Fills:
|
|
||||||
return "FILL";
|
|
||||||
case FillsOPC:
|
|
||||||
return "FILLOPC";
|
|
||||||
case LEFPins:
|
|
||||||
return "LEFPIN";
|
|
||||||
case Obstructions:
|
|
||||||
return "LEFOBS";
|
|
||||||
case Blockage:
|
|
||||||
return "BLK";
|
|
||||||
case All:
|
|
||||||
return "ALL";
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::string ();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implements implicit layer mapping
|
* @brief Implements implicit layer mapping
|
||||||
*
|
*
|
||||||
|
|
@ -1467,24 +1489,13 @@ LEFDEFReaderState::finish (db::Layout &layout)
|
||||||
|
|
||||||
db::LayerMap lm;
|
db::LayerMap lm;
|
||||||
|
|
||||||
for (std::map <std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, std::set<unsigned int> >::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
|
for (std::map <std::pair<std::string, LayerDetailsKey>, std::set<unsigned int> >::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
|
||||||
|
|
||||||
if (l->second.empty ()) {
|
if (l->second.empty ()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ps = purpose_to_name (l->first.second.first);
|
std::string n = layer_spec_to_name (l->first.first, l->first.second.purpose, l->first.second.mask, l->first.second.via_size);
|
||||||
|
|
||||||
std::string n = l->first.first;
|
|
||||||
if (! n.empty ()) {
|
|
||||||
n += ".";
|
|
||||||
}
|
|
||||||
n += ps;
|
|
||||||
|
|
||||||
if (l->first.second.second > 0) {
|
|
||||||
n += ":";
|
|
||||||
n += tl::to_string (l->first.second.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (std::set<unsigned int>::const_iterator li = l->second.begin (); li != l->second.end (); ++li) {
|
for (std::set<unsigned int>::const_iterator li = l->second.begin (); li != l->second.end (); ++li) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -962,6 +962,46 @@ enum LayerPurpose
|
||||||
All // from DEF only
|
All // from DEF only
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A structure holding the layer details like purpose, mask and via size
|
||||||
|
*/
|
||||||
|
struct LayerDetailsKey
|
||||||
|
{
|
||||||
|
LayerDetailsKey ()
|
||||||
|
: purpose (Routing), mask (0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
LayerDetailsKey (LayerPurpose _purpose, unsigned int _mask = 0, const db::DVector &_via_size = db::DVector ())
|
||||||
|
: purpose (_purpose), mask (_mask), via_size (_via_size)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool operator< (const LayerDetailsKey &other) const
|
||||||
|
{
|
||||||
|
if (purpose != other.purpose) {
|
||||||
|
return purpose < other.purpose;
|
||||||
|
}
|
||||||
|
if (mask != other.mask) {
|
||||||
|
return mask < other.mask;
|
||||||
|
}
|
||||||
|
return via_size.less (other.via_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator== (const LayerDetailsKey &other) const
|
||||||
|
{
|
||||||
|
if (purpose != other.purpose) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mask != other.mask) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return via_size.equal (other.via_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerPurpose purpose;
|
||||||
|
unsigned int mask;
|
||||||
|
db::DVector via_size;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief An interface for resolving the number of masks from a layer name
|
* @brief An interface for resolving the number of masks from a layer name
|
||||||
*/
|
*/
|
||||||
|
|
@ -1054,9 +1094,9 @@ public:
|
||||||
virtual std::vector<std::string> maskshift_layers () const { return m_maskshift_layers; }
|
virtual std::vector<std::string> maskshift_layers () const { return m_maskshift_layers; }
|
||||||
virtual bool is_fixedmask () const { return m_fixedmask; }
|
virtual bool is_fixedmask () const { return m_fixedmask; }
|
||||||
|
|
||||||
void add_polygon (const std::string &ln, LayerPurpose purpose, const db::Polygon &poly, unsigned int mask, properties_id_type prop_id);
|
void add_polygon (const std::string &ln, LayerPurpose purpose, const db::Polygon &poly, unsigned int mask, properties_id_type prop_id, const DVector &via_size = db::DVector ());
|
||||||
void add_box (const std::string &ln, LayerPurpose purpose, const db::Box &box, unsigned int mask, properties_id_type prop_id);
|
void add_box (const std::string &ln, LayerPurpose purpose, const db::Box &box, unsigned int mask, properties_id_type prop_id, const DVector &via_size = db::DVector ());
|
||||||
void add_path (const std::string &ln, LayerPurpose purpose, const db::Path &path, unsigned int mask, properties_id_type prop_id);
|
void add_path (const std::string &ln, LayerPurpose purpose, const db::Path &path, unsigned int mask, properties_id_type prop_id, const DVector &via_size = db::DVector ());
|
||||||
void add_via (const std::string &vn, const db::Trans &trans, unsigned int bottom_mask, unsigned int cut_mask, unsigned int top_mask);
|
void add_via (const std::string &vn, const db::Trans &trans, unsigned int bottom_mask, unsigned int cut_mask, unsigned int top_mask);
|
||||||
void add_text (const std::string &ln, LayerPurpose purpose, const db::Text &text, unsigned int mask, db::properties_id_type prop_id);
|
void add_text (const std::string &ln, LayerPurpose purpose, const db::Text &text, unsigned int mask, db::properties_id_type prop_id);
|
||||||
|
|
||||||
|
|
@ -1083,7 +1123,7 @@ private:
|
||||||
db::Trans trans;
|
db::Trans trans;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map <std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, db::Shapes> m_shapes;
|
std::map <std::pair<std::string, LayerDetailsKey>, db::Shapes> m_shapes;
|
||||||
std::list<Via> m_vias;
|
std::list<Via> m_vias;
|
||||||
std::vector<std::string> m_maskshift_layers;
|
std::vector<std::string> m_maskshift_layers;
|
||||||
bool m_fixedmask;
|
bool m_fixedmask;
|
||||||
|
|
@ -1129,7 +1169,17 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Create a new layer or return the index of the given layer
|
* @brief Create a new layer or return the index of the given layer
|
||||||
*/
|
*/
|
||||||
std::set<unsigned int> open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
|
std::set<unsigned int> open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask, const DVector &via_size = db::DVector ());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create a new layer or return the index of the given layer
|
||||||
|
*/
|
||||||
|
template <class Shape>
|
||||||
|
std::set<unsigned int> open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask, const Shape &via_shape)
|
||||||
|
{
|
||||||
|
db::Box via_box = db::box_convert<Shape> () (via_shape);
|
||||||
|
return open_layer (layout, name, purpose, mask, db::DVector (via_box.width () * layout.dbu (), via_box.height () * layout.dbu ()));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Registers a layer (assign a new default layer number)
|
* @brief Registers a layer (assign a new default layer number)
|
||||||
|
|
@ -1263,7 +1313,7 @@ private:
|
||||||
LEFDEFReaderState (const LEFDEFReaderState &);
|
LEFDEFReaderState (const LEFDEFReaderState &);
|
||||||
LEFDEFReaderState &operator= (const LEFDEFReaderState &);
|
LEFDEFReaderState &operator= (const LEFDEFReaderState &);
|
||||||
|
|
||||||
std::map <std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, std::set<unsigned int> > m_layers;
|
std::map <std::pair<std::string, LayerDetailsKey>, std::set<unsigned int> > m_layers;
|
||||||
db::LayerMap m_layer_map;
|
db::LayerMap m_layer_map;
|
||||||
bool m_create_layers;
|
bool m_create_layers;
|
||||||
bool m_has_explicit_layer_mapping;
|
bool m_has_explicit_layer_mapping;
|
||||||
|
|
@ -1438,9 +1488,9 @@ protected:
|
||||||
/**
|
/**
|
||||||
* @brief Create a new layer or return the index of the given layer
|
* @brief Create a new layer or return the index of the given layer
|
||||||
*/
|
*/
|
||||||
std::set<unsigned int> open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask)
|
std::set<unsigned int> open_layer (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask, const db::DVector &via_size = db::DVector ())
|
||||||
{
|
{
|
||||||
return mp_reader_state->open_layer (layout, name, purpose, mask);
|
return mp_reader_state->open_layer (layout, name, purpose, mask, via_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -517,6 +517,14 @@ LEFImporter::read_viadef_by_rule (RuleBasedViaGenerator *vg, ViaDesc &via_desc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Shape>
|
||||||
|
static db::DVector
|
||||||
|
via_size (double dbu, const Shape &shape)
|
||||||
|
{
|
||||||
|
db::Box box = db::box_convert<Shape> () (shape);
|
||||||
|
return db::DVector (box.width () * dbu, box.height () * dbu);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc &via_desc, const std::string &n, double dbu)
|
LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc &via_desc, const std::string &n, double dbu)
|
||||||
{
|
{
|
||||||
|
|
@ -577,7 +585,7 @@ LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc
|
||||||
db::Polygon p;
|
db::Polygon p;
|
||||||
p.assign_hull (points.begin (), points.end ());
|
p.assign_hull (points.begin (), points.end ());
|
||||||
|
|
||||||
lg->add_polygon (layer_name, ViaGeometry, p, mask, 0);
|
lg->add_polygon (layer_name, ViaGeometry, p, mask, 0, via_size (dbu, p));
|
||||||
|
|
||||||
expect (";");
|
expect (";");
|
||||||
|
|
||||||
|
|
@ -599,7 +607,7 @@ LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Box b (points [0], points [1]);
|
db::Box b (points [0], points [1]);
|
||||||
lg->add_box (layer_name, ViaGeometry, b, mask, 0);
|
lg->add_box (layer_name, ViaGeometry, b, mask, 0, via_size (dbu, b));
|
||||||
|
|
||||||
expect (";");
|
expect (";");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -762,6 +762,11 @@ TEST(121_fillwithmask)
|
||||||
run_test (_this, "fill", "map:with_mask.map+lef:with_mask.lef+def:with_mask.def", "with_mask_au.oas.gz", default_options (), false);
|
run_test (_this, "fill", "map:with_mask.map+lef:with_mask.lef+def:with_mask.def", "with_mask_au.oas.gz", default_options (), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(130_viasize)
|
||||||
|
{
|
||||||
|
run_test (_this, "viasize", "map:test.map+lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(200_lefdef_plugin)
|
TEST(200_lefdef_plugin)
|
||||||
{
|
{
|
||||||
db::Layout ly;
|
db::Layout ly;
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
VERSION 5.8 ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DESIGN chip_top ;
|
||||||
|
UNITS DISTANCE MICRONS 1000 ;
|
||||||
|
DIEAREA ( 0 0 ) ( 300 300 ) ;
|
||||||
|
STYLES 2 ;
|
||||||
|
- STYLE 1 ( 30 10 ) ( 10 30 ) ( -10 30 ) ( -30 10 ) ( -30 -10 ) ( -10 -30 ) ( 10 -30 ) ( 30 -10 ) ;
|
||||||
|
END STYLES
|
||||||
|
VIAS 1 ;
|
||||||
|
- VIA1_small
|
||||||
|
+ RECT M1 ( -20 -15 ) ( 20 15 )
|
||||||
|
+ RECT VIA1 ( -10 -10 ) ( 10 10 )
|
||||||
|
+ RECT VIA1 ( -13 -13 ) ( 13 13 )
|
||||||
|
+ RECT M2 ( -25 -25 ) ( 25 25 ) ;
|
||||||
|
- VIA1_large
|
||||||
|
+ RECT M1 ( -20 -15 ) ( 20 15 )
|
||||||
|
+ RECT VIA1 ( -12 -12 ) ( 12 12 )
|
||||||
|
+ RECT VIA1 ( -13 -13 ) ( 13 13 )
|
||||||
|
+ RECT M2 ( -25 -25 ) ( 25 25 ) ;
|
||||||
|
END VIAS
|
||||||
|
SPECIALNETS 1 ;
|
||||||
|
- dummy
|
||||||
|
+ ROUTED + RECT M2 ( 350 0 ) ( 250 100 )
|
||||||
|
+ POLYGON M1 ( 300 0 ) ( 300 50 ) ( 350 50 ) ( 400 100 ) ( 400 0 )
|
||||||
|
+ ROUTED + POLYGON M2 ( 300 150 ) ( 300 200 ) ( 350 200 ) ( 400 250 ) ( 400 150 )
|
||||||
|
+ RECT M1 ( 0 0 ) ( 100 200 )
|
||||||
|
+ ROUTED M1 30 + MASK 2 ( 0 0 15 ) ( 100 0 0 ) VIA1_small ( 100 100 10 )
|
||||||
|
+ ROUTED M2 50 + SHAPE RING + STYLE 1 ( 0 100 ) ( 100 200 ) ( 200 200 )
|
||||||
|
+ ROUTED + MASK 2 + RECT M2 ( 250 0 ) ( 150 100 )
|
||||||
|
+ ROUTED + SHAPE RING + MASK 1 + VIA VIA1_large E ( 200 200 )
|
||||||
|
;
|
||||||
|
END SPECIALNETS
|
||||||
|
END DESIGN
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
VERSION 5.8 ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
|
||||||
|
UNITS
|
||||||
|
DATABASE MICRONS 1000 ;
|
||||||
|
END UNITS
|
||||||
|
|
||||||
|
MANUFACTURINGGRID 0.001 ;
|
||||||
|
|
||||||
|
LAYER M1
|
||||||
|
TYPE ROUTING ;
|
||||||
|
END M1
|
||||||
|
|
||||||
|
LAYER VIA1
|
||||||
|
TYPE CUT ;
|
||||||
|
END VIA1
|
||||||
|
|
||||||
|
LAYER M2
|
||||||
|
TYPE ROUTING ;
|
||||||
|
WIDTH 0.05 ;
|
||||||
|
END M2
|
||||||
|
|
||||||
|
END LIBRARY
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
# some variations of map file entries
|
||||||
|
DIEAREA ALL 1 0
|
||||||
|
COMP ALL 2 0
|
||||||
|
M1 NET,SPNET 7 0
|
||||||
|
M2 NET,SPNET 9 0
|
||||||
|
VIA1 VIA 8 0
|
||||||
|
VIA1 VIA:SIZE:0.02x0.02 8 1
|
||||||
|
VIA1 VIA:SIZE:0.024x0.024 8 2
|
||||||
Loading…
Reference in New Issue