mirror of https://github.com/KLayout/klayout.git
WIP: first test case for mask support - needs testing.
This commit is contained in:
parent
5c7862d8cd
commit
d069dde98e
|
|
@ -142,7 +142,7 @@ DEFImporter::read_diearea (db::Layout &layout, db::Cell &design, double scale)
|
|||
{
|
||||
std::vector<db::Point> points;
|
||||
|
||||
while (! test (";")) {
|
||||
while (! at_end () && ! test (";")) {
|
||||
test ("(");
|
||||
points.push_back (get_point (scale));
|
||||
test (")");
|
||||
|
|
@ -276,7 +276,7 @@ DEFImporter::read_blockages (db::Layout &layout, db::Cell &design, double scale)
|
|||
|
||||
std::string layer;
|
||||
|
||||
while (! test (";")) {
|
||||
while (! at_end () && ! test (";")) {
|
||||
|
||||
if (test ("PLACEMENT")) {
|
||||
|
||||
|
|
@ -570,24 +570,26 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C
|
|||
|
||||
} else if (peek ("(")) {
|
||||
|
||||
unsigned int new_mask = mask;
|
||||
|
||||
while (peek ("(") || peek ("MASK")) {
|
||||
|
||||
new_mask = 0;
|
||||
if (test ("MASK")) {
|
||||
unsigned int m = get_mask (get_long ());
|
||||
if (m != mask) {
|
||||
// stop here with the segments and use the mask value for the next iteration
|
||||
mask = m;
|
||||
|
||||
new_mask = get_mask (get_long ());
|
||||
read_mask = false;
|
||||
|
||||
if (! peek ("(")) {
|
||||
break;
|
||||
} else if (new_mask != mask) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! test ("(")) {
|
||||
// We have a via here. MASK is already read, but the value did not change.
|
||||
read_mask = false;
|
||||
break;
|
||||
}
|
||||
|
||||
test ("(");
|
||||
|
||||
if (! test ("*")) {
|
||||
x = get_double ();
|
||||
}
|
||||
|
|
@ -613,6 +615,13 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C
|
|||
}
|
||||
}
|
||||
|
||||
// continue a segment with the current point and the new mask
|
||||
if (pts.size () > 1) {
|
||||
pts.erase (pts.begin (), pts.end () - 1);
|
||||
}
|
||||
|
||||
mask = new_mask;
|
||||
|
||||
} else if (! peek ("NEW") && ! peek ("+") && ! peek ("-") && ! peek (";")) {
|
||||
|
||||
// indicates a via
|
||||
|
|
@ -661,10 +670,16 @@ DEFImporter::read_single_net (std::string &nondefaultrule, Layout &layout, db::C
|
|||
|
||||
if (ln == vd->second.m1) {
|
||||
ln = vd->second.m2;
|
||||
mask = mask_top;
|
||||
} else if (ln == vd->second.m2) {
|
||||
ln = vd->second.m1;
|
||||
mask = mask_bottom;
|
||||
} else {
|
||||
mask = 0;
|
||||
}
|
||||
|
||||
read_mask = false;
|
||||
|
||||
}
|
||||
|
||||
if (! specialnets) {
|
||||
|
|
@ -890,6 +905,8 @@ DEFImporter::read_vias (db::Layout & /*layout*/, db::Cell & /*design*/, double s
|
|||
|
||||
while (test ("+")) {
|
||||
|
||||
bool is_polygon = false;
|
||||
|
||||
if (test ("VIARULE")) {
|
||||
|
||||
if (! rule_based_vg.get ()) {
|
||||
|
|
@ -974,7 +991,7 @@ DEFImporter::read_vias (db::Layout & /*layout*/, db::Cell & /*design*/, double s
|
|||
vd.m1 = bn;
|
||||
vd.m2 = tn;
|
||||
|
||||
} else if (test ("POLYGON")) {
|
||||
} else if ((is_polygon = test ("POLYGON")) || test ("RECT")) {
|
||||
|
||||
if (! geo_based_vg.get ()) {
|
||||
geo_based_vg.reset (new GeometryBasedViaGenerator ());
|
||||
|
|
@ -982,37 +999,37 @@ DEFImporter::read_vias (db::Layout & /*layout*/, db::Cell & /*design*/, double s
|
|||
|
||||
std::string ln = get ();
|
||||
|
||||
if (m_lef_importer.is_routing_layer (ln) && seen_layers.find (ln) == seen_layers.end ()) {
|
||||
if (m_lef_importer.is_routing_layer (ln)) {
|
||||
|
||||
if (routing_layers.size () == 0) {
|
||||
geo_based_vg->set_bottom_layer (ln);
|
||||
} else if (routing_layers.size () == 1) {
|
||||
geo_based_vg->set_top_layer (ln);
|
||||
}
|
||||
|
||||
if (seen_layers.find (ln) == seen_layers.end ()) {
|
||||
seen_layers.insert (ln);
|
||||
routing_layers.push_back (ln);
|
||||
}
|
||||
|
||||
} else if (m_lef_importer.is_cut_layer (ln)) {
|
||||
|
||||
geo_based_vg->set_cut_layer (ln);
|
||||
|
||||
}
|
||||
|
||||
if (test ("+")) {
|
||||
expect ("MASK");
|
||||
mask = get_mask (get_long ());
|
||||
}
|
||||
|
||||
if (is_polygon) {
|
||||
|
||||
db::Polygon poly;
|
||||
read_polygon (poly, scale);
|
||||
geo_based_vg->add_polygon (ln, poly, mask);
|
||||
|
||||
} else if (test ("RECT")) {
|
||||
|
||||
if (! geo_based_vg.get ()) {
|
||||
geo_based_vg.reset (new GeometryBasedViaGenerator ());
|
||||
}
|
||||
|
||||
std::string ln = get ();
|
||||
|
||||
if (m_lef_importer.is_routing_layer (ln) && seen_layers.find (ln) == seen_layers.end ()) {
|
||||
seen_layers.insert (ln);
|
||||
routing_layers.push_back (ln);
|
||||
}
|
||||
|
||||
if (test ("+")) {
|
||||
expect ("MASK");
|
||||
mask = get_mask (get_long ());
|
||||
}
|
||||
} else {
|
||||
|
||||
db::Polygon poly;
|
||||
read_rect (poly, scale);
|
||||
|
|
@ -1022,6 +1039,8 @@ DEFImporter::read_vias (db::Layout & /*layout*/, db::Cell & /*design*/, double s
|
|||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (vd.m1.empty () && vd.m2.empty ()) {
|
||||
|
||||
// analyze the layers to find the metals
|
||||
|
|
@ -1058,9 +1077,8 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale)
|
|||
|
||||
std::string net;
|
||||
std::string dir;
|
||||
std::map <std::string, std::vector <db::Polygon> > geometry;
|
||||
std::map <std::pair<std::string, unsigned int>, std::vector <db::Polygon> > geometry;
|
||||
db::Trans trans;
|
||||
unsigned int mask = 0;
|
||||
|
||||
while (test ("+")) {
|
||||
|
||||
|
|
@ -1074,6 +1092,11 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale)
|
|||
|
||||
std::string ln = get ();
|
||||
|
||||
unsigned int mask = 0;
|
||||
if (test ("MASK")) {
|
||||
mask = get_mask (get_long ());
|
||||
}
|
||||
|
||||
while (test ("DESIGNRULEWIDTH") || test ("SPACING")) {
|
||||
take ();
|
||||
}
|
||||
|
|
@ -1086,12 +1109,17 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale)
|
|||
db::Point pt2 = get_point (scale);
|
||||
test (")");
|
||||
|
||||
geometry.insert (std::make_pair (ln, std::vector<db::Polygon> ())).first->second.push_back (db::Polygon (db::Box (pt1, pt2)));
|
||||
geometry.insert (std::make_pair (std::make_pair (ln, mask), std::vector<db::Polygon> ())).first->second.push_back (db::Polygon (db::Box (pt1, pt2)));
|
||||
|
||||
} else if (test ("POLYGON")) {
|
||||
|
||||
std::string ln = get ();
|
||||
|
||||
unsigned int mask = 0;
|
||||
if (test ("MASK")) {
|
||||
mask = get_mask (get_long ());
|
||||
}
|
||||
|
||||
while (test ("DESIGNRULEWIDTH") || test ("SPACING")) {
|
||||
take ();
|
||||
}
|
||||
|
|
@ -1100,7 +1128,7 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale)
|
|||
|
||||
double x = 0.0, y = 0.0;
|
||||
|
||||
while (! test ("+") && ! test (";")) {
|
||||
while (! at_end () && ! test ("+") && ! test (";")) {
|
||||
|
||||
test ("(");
|
||||
if (! test ("*")) {
|
||||
|
|
@ -1114,7 +1142,7 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale)
|
|||
|
||||
}
|
||||
|
||||
std::vector<db::Polygon> &polygons = geometry.insert (std::make_pair (ln, std::vector<db::Polygon> ())).first->second;
|
||||
std::vector<db::Polygon> &polygons = geometry.insert (std::make_pair (std::make_pair (ln, mask), std::vector<db::Polygon> ())).first->second;
|
||||
polygons.push_back (db::Polygon ());
|
||||
polygons.back ().assign_hull (points.begin (), points.end ());
|
||||
|
||||
|
|
@ -1131,6 +1159,11 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale)
|
|||
|
||||
flush = true;
|
||||
|
||||
} else if (test ("VIA")) {
|
||||
|
||||
// TODO: implement
|
||||
error (tl::to_string (tr ("VIA not supported on pins currently")));
|
||||
|
||||
} else {
|
||||
while (! peek ("+") && ! peek ("-") && ! peek (";")) {
|
||||
take ();
|
||||
|
|
@ -1149,9 +1182,9 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale)
|
|||
*/
|
||||
|
||||
// Produce geometry collected so far
|
||||
for (std::map<std::string, std::vector<db::Polygon> >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) {
|
||||
for (std::map<std::pair<std::string, unsigned int>, std::vector<db::Polygon> >::const_iterator g = geometry.begin (); g != geometry.end (); ++g) {
|
||||
|
||||
std::pair <bool, unsigned int> dl = open_layer (layout, g->first, Pins, mask);
|
||||
std::pair <bool, unsigned int> dl = open_layer (layout, g->first.first, Pins, g->first.second);
|
||||
if (dl.first) {
|
||||
|
||||
db::properties_id_type prop_id = 0;
|
||||
|
|
@ -1172,7 +1205,7 @@ DEFImporter::read_pins (db::Layout &layout, db::Cell &design, double scale)
|
|||
|
||||
}
|
||||
|
||||
dl = open_layer (layout, g->first, Label, 0);
|
||||
dl = open_layer (layout, g->first.first, Label, 0);
|
||||
if (dl.first) {
|
||||
db::Box bbox;
|
||||
if (! g->second.empty ()) {
|
||||
|
|
@ -1208,7 +1241,7 @@ DEFImporter::read_styles (double scale)
|
|||
|
||||
double x = 0.0, y = 0.0;
|
||||
|
||||
while (! test (";")) {
|
||||
while (! at_end () && ! test (";")) {
|
||||
|
||||
test ("(");
|
||||
if (! test ("*")) {
|
||||
|
|
@ -1433,6 +1466,13 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
expect ("END");
|
||||
expect ("STYLES");
|
||||
|
||||
} else if (test ("COMPONENTMASKSHIFT")) {
|
||||
|
||||
warn (tl::to_string (tr ("Component mask shift not supported currently")));
|
||||
while (! at_end () && ! test (";")) {
|
||||
take ();
|
||||
}
|
||||
|
||||
} else if (test ("COMPONENTS")) {
|
||||
|
||||
get_long ();
|
||||
|
|
@ -1454,7 +1494,7 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
expect ("PINS");
|
||||
|
||||
} else {
|
||||
while (! test (";")) {
|
||||
while (! at_end () && ! test (";")) {
|
||||
take ();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -242,37 +242,41 @@ GeometryBasedViaGenerator::GeometryBasedViaGenerator ()
|
|||
: LEFDEFViaGenerator ()
|
||||
{ }
|
||||
|
||||
unsigned int
|
||||
GeometryBasedViaGenerator::mask_for (const std::string &ln, unsigned int m, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top) const
|
||||
{
|
||||
if (m == 0) {
|
||||
if (ln == m_bottom_layer) {
|
||||
return (mask_bottom);
|
||||
} else if (ln == m_cut_layer) {
|
||||
return (mask_cut);
|
||||
} else if (ln == m_top_layer) {
|
||||
return (mask_top);
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
void
|
||||
GeometryBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, unsigned int /*mask_bottom*/, unsigned int /*mask_cut*/, unsigned int /*mask_top*/, const LEFDEFNumberOfMasks * /*nm*/)
|
||||
GeometryBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks * /*nm*/)
|
||||
{
|
||||
for (std::map <std::string, std::list<std::pair<unsigned int, db::Polygon> > >::const_iterator g = m_polygons.begin (); g != m_polygons.end (); ++g) {
|
||||
|
||||
for (std::list<std::pair<unsigned int, db::Polygon> >::const_iterator i = g->second.begin (); i != g->second.end (); ++i) {
|
||||
|
||||
std::pair <bool, unsigned int> dl (false, 0);
|
||||
|
||||
dl = reader.open_layer (layout, g->first, ViaGeometry, i->first);
|
||||
std::pair <bool, unsigned int> dl = reader.open_layer (layout, g->first, ViaGeometry, mask_for (g->first, i->first, mask_bottom, mask_cut, mask_top));
|
||||
if (dl.first) {
|
||||
cell.shapes (dl.second).insert (i->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (std::map <std::string, std::list<std::pair<unsigned int, db::Box> > >::const_iterator g = m_boxes.begin (); g != m_boxes.end (); ++g) {
|
||||
|
||||
for (std::list<std::pair<unsigned int, db::Box> >::const_iterator i = g->second.begin (); i != g->second.end (); ++i) {
|
||||
|
||||
std::pair <bool, unsigned int> dl (false, 0);
|
||||
|
||||
dl = reader.open_layer (layout, g->first, ViaGeometry, i->first);
|
||||
std::pair <bool, unsigned int> dl = reader.open_layer (layout, g->first, ViaGeometry, mask_for (g->first, i->first, mask_bottom, mask_cut, mask_top));
|
||||
if (dl.first) {
|
||||
cell.shapes (dl.second).insert (i->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -433,7 +437,7 @@ static void set_datatypes (db::LEFDEFReaderOptions *data, void (db::LEFDEFReader
|
|||
if (ex.try_read (mask) && ex.test (":")) {
|
||||
int dt = 0;
|
||||
ex.read (dt);
|
||||
(data->*set_datatype_per_mask) (std::max ((unsigned int) 1, mask) - 1, dt);
|
||||
(data->*set_datatype_per_mask) (std::max ((unsigned int) 1, mask), dt);
|
||||
} else {
|
||||
ex = ex_saved;
|
||||
int dt = 0;
|
||||
|
|
@ -464,7 +468,7 @@ static void set_suffixes (db::LEFDEFReaderOptions *data, void (db::LEFDEFReaderO
|
|||
if (ex.try_read (mask) && ex.test (":")) {
|
||||
std::string sfx;
|
||||
ex.read_word_or_quoted (sfx);
|
||||
(data->*set_suffix_per_mask) (std::max ((unsigned int) 1, mask) - 1, sfx);
|
||||
(data->*set_suffix_per_mask) (std::max ((unsigned int) 1, mask), sfx);
|
||||
} else {
|
||||
ex = ex_saved;
|
||||
std::string sfx;
|
||||
|
|
@ -495,7 +499,7 @@ static std::string get_datatypes (const db::LEFDEFReaderOptions *data, int (db::
|
|||
if (! res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += tl::to_string (i + 1);
|
||||
res += tl::to_string (i);
|
||||
res += ":";
|
||||
res += tl::to_string (dt);
|
||||
}
|
||||
|
|
@ -518,7 +522,7 @@ static std::string get_suffixes (const db::LEFDEFReaderOptions *data, const std:
|
|||
if (! res.empty ()) {
|
||||
res += ",";
|
||||
}
|
||||
res += tl::to_string (i + 1);
|
||||
res += tl::to_string (i);
|
||||
res += ":";
|
||||
res += tl::to_word_or_quoted_string (sfx);
|
||||
}
|
||||
|
|
@ -936,47 +940,53 @@ LEFDEFReaderState::open_layer_uncached (db::Layout &layout, const std::string &n
|
|||
|
||||
// Note: "name" is the decorated name as provided by the tech component's
|
||||
// x_suffix specifications.
|
||||
std::string name (n);
|
||||
std::string name_suffix;
|
||||
int dt = 0;
|
||||
|
||||
if (mp_tech_comp) {
|
||||
switch (purpose) {
|
||||
case Routing:
|
||||
default:
|
||||
name += mp_tech_comp->routing_suffix_per_mask (mask);
|
||||
dt += mp_tech_comp->routing_datatype_per_mask (mask);
|
||||
name_suffix = mp_tech_comp->routing_suffix_per_mask (mask);
|
||||
dt = mp_tech_comp->routing_datatype_per_mask (mask);
|
||||
break;
|
||||
case SpecialRouting:
|
||||
name += mp_tech_comp->special_routing_suffix_per_mask (mask);
|
||||
dt += mp_tech_comp->special_routing_datatype_per_mask (mask);
|
||||
name_suffix = mp_tech_comp->special_routing_suffix_per_mask (mask);
|
||||
dt = mp_tech_comp->special_routing_datatype_per_mask (mask);
|
||||
break;
|
||||
case ViaGeometry:
|
||||
name += mp_tech_comp->via_geometry_suffix_per_mask (mask);
|
||||
dt += mp_tech_comp->via_geometry_datatype_per_mask (mask);
|
||||
name_suffix = mp_tech_comp->via_geometry_suffix_per_mask (mask);
|
||||
dt = mp_tech_comp->via_geometry_datatype_per_mask (mask);
|
||||
break;
|
||||
case Label:
|
||||
name += mp_tech_comp->labels_suffix ();
|
||||
dt += mp_tech_comp->labels_datatype ();
|
||||
name_suffix = mp_tech_comp->labels_suffix ();
|
||||
dt = mp_tech_comp->labels_datatype ();
|
||||
break;
|
||||
case Pins:
|
||||
name += mp_tech_comp->pins_suffix_per_mask (mask);
|
||||
dt += mp_tech_comp->pins_datatype_per_mask (mask);
|
||||
name_suffix = mp_tech_comp->pins_suffix_per_mask (mask);
|
||||
dt = mp_tech_comp->pins_datatype_per_mask (mask);
|
||||
break;
|
||||
case LEFPins:
|
||||
name += mp_tech_comp->lef_pins_suffix_per_mask (mask);
|
||||
dt += mp_tech_comp->lef_pins_datatype_per_mask (mask);
|
||||
name_suffix = mp_tech_comp->lef_pins_suffix_per_mask (mask);
|
||||
dt = mp_tech_comp->lef_pins_datatype_per_mask (mask);
|
||||
break;
|
||||
case Obstructions:
|
||||
name += mp_tech_comp->obstructions_suffix ();
|
||||
dt += mp_tech_comp->obstructions_datatype ();
|
||||
name_suffix = mp_tech_comp->obstructions_suffix ();
|
||||
dt = mp_tech_comp->obstructions_datatype ();
|
||||
break;
|
||||
case Blockage:
|
||||
name += mp_tech_comp->blockages_suffix ();
|
||||
dt += mp_tech_comp->blockages_datatype ();
|
||||
name_suffix = mp_tech_comp->blockages_suffix ();
|
||||
dt = mp_tech_comp->blockages_datatype ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dt > 0 && name_suffix.empty ()) {
|
||||
name_suffix = "#" + tl::to_string (dt);
|
||||
}
|
||||
|
||||
std::string name = n + name_suffix;
|
||||
|
||||
std::pair<bool, unsigned int> ll = m_layer_map.logical (name, layout);
|
||||
|
||||
if (ll.first) {
|
||||
|
|
@ -1120,7 +1130,7 @@ LEFDEFReaderState::via_cell (const std::string &vn, db::Layout &layout, unsigned
|
|||
std::string cn = mp_tech_comp->via_cellname_prefix () + vn + mask_suffix;
|
||||
cell = &layout.cell (layout.add_cell (cn.c_str ()));
|
||||
|
||||
vg->create_cell (*this, layout, *cell, mask_bottom, mask_cut, mask_bottom, nm);
|
||||
vg->create_cell (*this, layout, *cell, mask_bottom, mask_cut, mask_top, nm);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -926,10 +926,16 @@ public:
|
|||
|
||||
void add_polygon (const std::string &ln, const db::Polygon &poly, unsigned int mask);
|
||||
void add_box (const std::string &ln, const db::Box &box, unsigned int mask);
|
||||
void set_bottom_layer (const std::string &ln) { m_bottom_layer = ln; }
|
||||
void set_cut_layer (const std::string &ln) { m_cut_layer = ln; }
|
||||
void set_top_layer (const std::string &ln) { m_top_layer = ln; }
|
||||
|
||||
private:
|
||||
std::map <std::string, std::list<std::pair<unsigned int, db::Polygon> > > m_polygons;
|
||||
std::map <std::string, std::list<std::pair<unsigned int, db::Box> > > m_boxes;
|
||||
std::string m_bottom_layer, m_cut_layer, m_top_layer;
|
||||
|
||||
unsigned int mask_for (const std::string &ln, unsigned int m, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -556,11 +556,23 @@ LEFImporter::read_viadef_by_geometry (GeometryBasedViaGenerator *vg, ViaDesc &vi
|
|||
|
||||
layer_name = get ();
|
||||
|
||||
if (m_routing_layers.find (layer_name) != m_routing_layers.end () && seen_layers.find (layer_name) == seen_layers.end ()) {
|
||||
if (m_routing_layers.find (layer_name) != m_routing_layers.end ()) {
|
||||
|
||||
if (routing_layers.size () == 0) {
|
||||
vg->set_bottom_layer (layer_name);
|
||||
} else if (routing_layers.size () == 1) {
|
||||
vg->set_top_layer (layer_name);
|
||||
}
|
||||
|
||||
if (seen_layers.find (layer_name) == seen_layers.end ()) {
|
||||
seen_layers.insert (layer_name);
|
||||
routing_layers.push_back (layer_name);
|
||||
}
|
||||
|
||||
} else {
|
||||
vg->set_cut_layer (layer_name);
|
||||
}
|
||||
|
||||
while (! at_end () && ! test (";")) {
|
||||
take ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -395,3 +395,22 @@ TEST(112_via_properties)
|
|||
run_test (_this, "via_properties", "lef:in.lef+def:in.def", "au.oas.gz", default_options (), false);
|
||||
}
|
||||
|
||||
TEST(113_masks_1)
|
||||
{
|
||||
db::LEFDEFReaderOptions options = default_options ();
|
||||
options.set_routing_suffix ("");
|
||||
options.set_routing_datatype_per_mask (1, 100);
|
||||
options.set_routing_datatype_per_mask (2, 200);
|
||||
options.set_special_routing_suffix ("");
|
||||
options.set_special_routing_datatype_per_mask (1, 101);
|
||||
options.set_special_routing_datatype_per_mask (2, 201);
|
||||
options.set_via_geometry_suffix ("");
|
||||
options.set_via_geometry_datatype_per_mask (1, 102);
|
||||
options.set_via_geometry_datatype_per_mask (2, 202);
|
||||
options.set_pins_suffix ("");
|
||||
options.set_pins_datatype_per_mask (1, 110);
|
||||
options.set_pins_datatype_per_mask (2, 210);
|
||||
|
||||
run_test (_this, "masks-1", "lef:in_tech.lef+def:in.def", "au.oas.gz", options, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,323 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2020 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "dbLEFDEFImporter.h"
|
||||
|
||||
#include "tlUnitTest.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
TEST(1)
|
||||
{
|
||||
db::LEFDEFReaderOptions options;
|
||||
EXPECT_EQ (options.max_mask_number (), (unsigned int) 0);
|
||||
|
||||
options.set_dbu (1.5);
|
||||
EXPECT_EQ (options.dbu (), 1.5);
|
||||
|
||||
options.set_produce_net_names (true);
|
||||
EXPECT_EQ (options.produce_net_names (), true);
|
||||
options.set_produce_net_names (false);
|
||||
EXPECT_EQ (options.produce_net_names (), false);
|
||||
|
||||
options.set_net_property_name (tl::Variant (12));
|
||||
EXPECT_EQ (options.net_property_name ().to_string (), "12");
|
||||
|
||||
options.set_produce_inst_names (true);
|
||||
EXPECT_EQ (options.produce_inst_names (), true);
|
||||
options.set_produce_inst_names (false);
|
||||
EXPECT_EQ (options.produce_inst_names (), false);
|
||||
|
||||
options.set_inst_property_name (tl::Variant (12));
|
||||
EXPECT_EQ (options.inst_property_name ().to_string (), "12");
|
||||
|
||||
options.set_produce_pin_names (true);
|
||||
EXPECT_EQ (options.produce_pin_names (), true);
|
||||
options.set_produce_pin_names (false);
|
||||
EXPECT_EQ (options.produce_pin_names (), false);
|
||||
|
||||
options.set_pin_property_name (tl::Variant (12));
|
||||
EXPECT_EQ (options.pin_property_name ().to_string (), "12");
|
||||
|
||||
options.set_produce_cell_outlines (true);
|
||||
EXPECT_EQ (options.produce_cell_outlines (), true);
|
||||
options.set_produce_cell_outlines (false);
|
||||
EXPECT_EQ (options.produce_cell_outlines (), false);
|
||||
|
||||
options.set_cell_outline_layer ("OL");
|
||||
EXPECT_EQ (options.cell_outline_layer (), "OL");
|
||||
|
||||
options.set_produce_placement_blockages (true);
|
||||
EXPECT_EQ (options.produce_placement_blockages (), true);
|
||||
options.set_produce_placement_blockages (false);
|
||||
EXPECT_EQ (options.produce_placement_blockages (), false);
|
||||
|
||||
options.set_placement_blockage_layer ("B");
|
||||
EXPECT_EQ (options.placement_blockage_layer (), "B");
|
||||
|
||||
options.set_produce_regions (true);
|
||||
EXPECT_EQ (options.produce_regions (), true);
|
||||
options.set_produce_regions (false);
|
||||
EXPECT_EQ (options.produce_regions (), false);
|
||||
|
||||
options.set_region_layer ("R");
|
||||
EXPECT_EQ (options.region_layer (), "R");
|
||||
|
||||
|
||||
options.set_via_cellname_prefix ("VIACELL");
|
||||
EXPECT_EQ (options.via_cellname_prefix (), "VIACELL");
|
||||
|
||||
options.set_produce_via_geometry (true);
|
||||
EXPECT_EQ (options.produce_via_geometry (), true);
|
||||
options.set_produce_via_geometry (false);
|
||||
EXPECT_EQ (options.produce_via_geometry (), false);
|
||||
|
||||
options.set_via_geometry_suffix ("VIAG");
|
||||
EXPECT_EQ (options.via_geometry_suffix (), "VIAG");
|
||||
|
||||
options.set_via_geometry_datatype (17);
|
||||
EXPECT_EQ (options.via_geometry_datatype (), 17);
|
||||
|
||||
options.set_via_geometry_suffix_str ("VIAG, 2: VIAGM2, 1: VIAGM1");
|
||||
EXPECT_EQ (options.via_geometry_suffix_str (), "VIAG,1:VIAGM1,2:VIAGM2");
|
||||
EXPECT_EQ (options.via_geometry_suffix_per_mask (0), "VIAG");
|
||||
EXPECT_EQ (options.via_geometry_suffix_per_mask (1), "VIAGM1");
|
||||
EXPECT_EQ (options.via_geometry_suffix_per_mask (2), "VIAGM2");
|
||||
EXPECT_EQ (options.via_geometry_suffix_per_mask (3), "VIAG");
|
||||
options.set_via_geometry_suffix_per_mask (2, "AB");
|
||||
EXPECT_EQ (options.via_geometry_suffix_per_mask (2), "AB");
|
||||
EXPECT_EQ (options.max_mask_number (), (unsigned int) 2);
|
||||
|
||||
options.set_via_geometry_datatype_str ("17, 2:217, 1: 117");
|
||||
EXPECT_EQ (options.via_geometry_datatype_str (), "17,1:117,2:217");
|
||||
EXPECT_EQ (options.via_geometry_datatype_per_mask (0), 17);
|
||||
EXPECT_EQ (options.via_geometry_datatype_per_mask (1), 117);
|
||||
EXPECT_EQ (options.via_geometry_datatype_per_mask (2), 217);
|
||||
EXPECT_EQ (options.via_geometry_datatype_per_mask (3), 17);
|
||||
options.set_via_geometry_datatype_per_mask (2, 42);
|
||||
EXPECT_EQ (options.via_geometry_datatype_per_mask (2), 42);
|
||||
|
||||
options.clear_via_geometry_suffixes_per_mask ();
|
||||
EXPECT_EQ (options.via_geometry_suffix_str (), "VIAG");
|
||||
|
||||
options.clear_via_geometry_datatypes_per_mask ();
|
||||
EXPECT_EQ (options.via_geometry_datatype_str (), "17");
|
||||
|
||||
|
||||
options.set_produce_pins (true);
|
||||
EXPECT_EQ (options.produce_pins (), true);
|
||||
options.set_produce_pins (false);
|
||||
EXPECT_EQ (options.produce_pins (), false);
|
||||
|
||||
options.set_pins_suffix ("PIN");
|
||||
EXPECT_EQ (options.pins_suffix (), "PIN");
|
||||
|
||||
options.set_pins_datatype (42);
|
||||
EXPECT_EQ (options.pins_datatype (), 42);
|
||||
|
||||
options.set_pins_suffix_str ("PIN, 2: PINM2, 1: PINM1");
|
||||
EXPECT_EQ (options.pins_suffix_str (), "PIN,1:PINM1,2:PINM2");
|
||||
EXPECT_EQ (options.pins_suffix_per_mask (0), "PIN");
|
||||
EXPECT_EQ (options.pins_suffix_per_mask (1), "PINM1");
|
||||
EXPECT_EQ (options.pins_suffix_per_mask (2), "PINM2");
|
||||
EXPECT_EQ (options.pins_suffix_per_mask (3), "PIN");
|
||||
options.set_pins_suffix_per_mask (2, "AB");
|
||||
EXPECT_EQ (options.pins_suffix_per_mask (2), "AB");
|
||||
|
||||
options.set_pins_datatype_str ("42, 2:242, 1: 142");
|
||||
EXPECT_EQ (options.pins_datatype_str (), "42,1:142,2:242");
|
||||
EXPECT_EQ (options.pins_datatype_per_mask (0), 42);
|
||||
EXPECT_EQ (options.pins_datatype_per_mask (1), 142);
|
||||
EXPECT_EQ (options.pins_datatype_per_mask (2), 242);
|
||||
EXPECT_EQ (options.pins_datatype_per_mask (3), 42);
|
||||
options.set_pins_datatype_per_mask (2, 42);
|
||||
EXPECT_EQ (options.pins_datatype_per_mask (2), 42);
|
||||
|
||||
options.clear_pins_suffixes_per_mask ();
|
||||
EXPECT_EQ (options.pins_suffix_str (), "PIN");
|
||||
|
||||
options.clear_pins_datatypes_per_mask ();
|
||||
EXPECT_EQ (options.pins_datatype_str (), "42");
|
||||
|
||||
|
||||
options.set_produce_lef_pins (true);
|
||||
EXPECT_EQ (options.produce_lef_pins (), true);
|
||||
options.set_produce_lef_pins (false);
|
||||
EXPECT_EQ (options.produce_lef_pins (), false);
|
||||
|
||||
options.set_lef_pins_suffix ("LEFPIN");
|
||||
EXPECT_EQ (options.lef_pins_suffix (), "LEFPIN");
|
||||
|
||||
options.set_lef_pins_datatype (41);
|
||||
EXPECT_EQ (options.lef_pins_datatype (), 41);
|
||||
|
||||
options.set_lef_pins_suffix_str ("LEFPIN, 2: LEFPINM2, 1: LEFPINM1");
|
||||
EXPECT_EQ (options.lef_pins_suffix_str (), "LEFPIN,1:LEFPINM1,2:LEFPINM2");
|
||||
EXPECT_EQ (options.lef_pins_suffix_per_mask (0), "LEFPIN");
|
||||
EXPECT_EQ (options.lef_pins_suffix_per_mask (1), "LEFPINM1");
|
||||
EXPECT_EQ (options.lef_pins_suffix_per_mask (2), "LEFPINM2");
|
||||
EXPECT_EQ (options.lef_pins_suffix_per_mask (3), "LEFPIN");
|
||||
options.set_lef_pins_suffix_per_mask (2, "AB");
|
||||
EXPECT_EQ (options.lef_pins_suffix_per_mask (2), "AB");
|
||||
|
||||
options.set_lef_pins_datatype_str ("41, 2:241, 1: 141");
|
||||
EXPECT_EQ (options.lef_pins_datatype_str (), "41,1:141,2:241");
|
||||
EXPECT_EQ (options.lef_pins_datatype_per_mask (0), 41);
|
||||
EXPECT_EQ (options.lef_pins_datatype_per_mask (1), 141);
|
||||
EXPECT_EQ (options.lef_pins_datatype_per_mask (2), 241);
|
||||
EXPECT_EQ (options.lef_pins_datatype_per_mask (3), 41);
|
||||
options.set_lef_pins_datatype_per_mask (2, 41);
|
||||
EXPECT_EQ (options.lef_pins_datatype_per_mask (2), 41);
|
||||
|
||||
options.clear_lef_pins_suffixes_per_mask ();
|
||||
EXPECT_EQ (options.lef_pins_suffix_str (), "LEFPIN");
|
||||
|
||||
options.clear_lef_pins_datatypes_per_mask ();
|
||||
EXPECT_EQ (options.lef_pins_datatype_str (), "41");
|
||||
|
||||
options.set_produce_obstructions (true);
|
||||
EXPECT_EQ (options.produce_obstructions (), true);
|
||||
options.set_produce_obstructions (false);
|
||||
EXPECT_EQ (options.produce_obstructions (), false);
|
||||
|
||||
options.set_obstructions_suffix ("OBS");
|
||||
EXPECT_EQ (options.obstructions_suffix (), "OBS");
|
||||
|
||||
options.set_obstructions_datatype (31);
|
||||
EXPECT_EQ (options.obstructions_datatype (), 31);
|
||||
|
||||
options.set_produce_blockages (true);
|
||||
EXPECT_EQ (options.produce_blockages (), true);
|
||||
options.set_produce_blockages (false);
|
||||
EXPECT_EQ (options.produce_blockages (), false);
|
||||
|
||||
options.set_blockages_suffix ("BLK");
|
||||
EXPECT_EQ (options.blockages_suffix (), "BLK");
|
||||
|
||||
options.set_blockages_datatype (41);
|
||||
EXPECT_EQ (options.blockages_datatype (), 41);
|
||||
|
||||
options.set_produce_labels (true);
|
||||
EXPECT_EQ (options.produce_labels (), true);
|
||||
options.set_produce_labels (false);
|
||||
EXPECT_EQ (options.produce_labels (), false);
|
||||
|
||||
options.set_labels_suffix ("LBL");
|
||||
EXPECT_EQ (options.labels_suffix (), "LBL");
|
||||
|
||||
options.set_labels_datatype (51);
|
||||
EXPECT_EQ (options.labels_datatype (), 51);
|
||||
|
||||
|
||||
options.set_produce_routing (true);
|
||||
EXPECT_EQ (options.produce_routing (), true);
|
||||
options.set_produce_routing (false);
|
||||
EXPECT_EQ (options.produce_routing (), false);
|
||||
|
||||
options.set_routing_suffix ("ROUTING");
|
||||
EXPECT_EQ (options.routing_suffix (), "ROUTING");
|
||||
|
||||
options.set_routing_datatype (40);
|
||||
EXPECT_EQ (options.routing_datatype (), 40);
|
||||
|
||||
options.set_routing_suffix_str ("ROUTING, 2: ROUTINGM2, 1: ROUTINGM1");
|
||||
EXPECT_EQ (options.routing_suffix_str (), "ROUTING,1:ROUTINGM1,2:ROUTINGM2");
|
||||
EXPECT_EQ (options.routing_suffix_per_mask (0), "ROUTING");
|
||||
EXPECT_EQ (options.routing_suffix_per_mask (1), "ROUTINGM1");
|
||||
EXPECT_EQ (options.routing_suffix_per_mask (2), "ROUTINGM2");
|
||||
EXPECT_EQ (options.routing_suffix_per_mask (3), "ROUTING");
|
||||
options.set_routing_suffix_per_mask (2, "AB");
|
||||
EXPECT_EQ (options.routing_suffix_per_mask (2), "AB");
|
||||
|
||||
options.set_routing_datatype_str ("40, 2:240, 1: 140");
|
||||
EXPECT_EQ (options.routing_datatype_str (), "40,1:140,2:240");
|
||||
EXPECT_EQ (options.routing_datatype_per_mask (0), 40);
|
||||
EXPECT_EQ (options.routing_datatype_per_mask (1), 140);
|
||||
EXPECT_EQ (options.routing_datatype_per_mask (2), 240);
|
||||
EXPECT_EQ (options.routing_datatype_per_mask (3), 40);
|
||||
options.set_routing_datatype_per_mask (2, 40);
|
||||
EXPECT_EQ (options.routing_datatype_per_mask (2), 40);
|
||||
|
||||
options.clear_routing_suffixes_per_mask ();
|
||||
EXPECT_EQ (options.routing_suffix_str (), "ROUTING");
|
||||
|
||||
options.clear_routing_datatypes_per_mask ();
|
||||
EXPECT_EQ (options.routing_datatype_str (), "40");
|
||||
|
||||
|
||||
options.set_produce_special_routing (true);
|
||||
EXPECT_EQ (options.produce_special_routing (), true);
|
||||
options.set_produce_special_routing (false);
|
||||
EXPECT_EQ (options.produce_special_routing (), false);
|
||||
|
||||
options.set_special_routing_suffix ("SPECIALROUTING");
|
||||
EXPECT_EQ (options.special_routing_suffix (), "SPECIALROUTING");
|
||||
|
||||
options.set_special_routing_datatype (44);
|
||||
EXPECT_EQ (options.special_routing_datatype (), 44);
|
||||
|
||||
options.set_special_routing_suffix_str ("SPECIALROUTING, 2: SPECIALROUTINGM2, 1: SPECIALROUTINGM1");
|
||||
EXPECT_EQ (options.special_routing_suffix_str (), "SPECIALROUTING,1:SPECIALROUTINGM1,2:SPECIALROUTINGM2");
|
||||
EXPECT_EQ (options.special_routing_suffix_per_mask (0), "SPECIALROUTING");
|
||||
EXPECT_EQ (options.special_routing_suffix_per_mask (1), "SPECIALROUTINGM1");
|
||||
EXPECT_EQ (options.special_routing_suffix_per_mask (2), "SPECIALROUTINGM2");
|
||||
EXPECT_EQ (options.special_routing_suffix_per_mask (3), "SPECIALROUTING");
|
||||
options.set_special_routing_suffix_per_mask (2, "AB");
|
||||
EXPECT_EQ (options.special_routing_suffix_per_mask (2), "AB");
|
||||
|
||||
options.set_special_routing_datatype_str ("44, 2:244, 1: 144");
|
||||
EXPECT_EQ (options.special_routing_datatype_str (), "44,1:144,2:244");
|
||||
EXPECT_EQ (options.special_routing_datatype_per_mask (0), 44);
|
||||
EXPECT_EQ (options.special_routing_datatype_per_mask (1), 144);
|
||||
EXPECT_EQ (options.special_routing_datatype_per_mask (2), 244);
|
||||
EXPECT_EQ (options.special_routing_datatype_per_mask (3), 44);
|
||||
options.set_special_routing_datatype_per_mask (2, 44);
|
||||
EXPECT_EQ (options.special_routing_datatype_per_mask (2), 44);
|
||||
|
||||
options.clear_special_routing_suffixes_per_mask ();
|
||||
EXPECT_EQ (options.special_routing_suffix_str (), "SPECIALROUTING");
|
||||
|
||||
options.clear_special_routing_datatypes_per_mask ();
|
||||
EXPECT_EQ (options.special_routing_datatype_str (), "44");
|
||||
|
||||
EXPECT_EQ (options.begin_lef_files () == options.end_lef_files (), true);
|
||||
options.push_lef_file ("ABC.lef");
|
||||
EXPECT_EQ (options.begin_lef_files () == options.end_lef_files (), false);
|
||||
EXPECT_EQ (options.lef_files ().size (), size_t (1));
|
||||
EXPECT_EQ (*options.begin_lef_files (), "ABC.lef");
|
||||
std::vector<std::string> lf = options.lef_files ();
|
||||
options.clear_lef_files ();
|
||||
EXPECT_EQ (options.begin_lef_files () == options.end_lef_files (), true);
|
||||
EXPECT_EQ (options.lef_files ().size (), size_t (0));
|
||||
options.set_lef_files (lf);
|
||||
EXPECT_EQ (options.lef_files ().size (), size_t (1));
|
||||
EXPECT_EQ (*options.begin_lef_files (), "ABC.lef");
|
||||
|
||||
|
||||
options.set_map_file ("ABC.map");
|
||||
EXPECT_EQ (options.map_file (), "ABC.map");
|
||||
|
||||
|
||||
options.set_macro_resolution_mode (2);
|
||||
EXPECT_EQ (options.macro_resolution_mode (), (unsigned int) 2);
|
||||
}
|
||||
|
||||
|
|
@ -6,7 +6,8 @@ TARGET = lefdef_tests
|
|||
include($$PWD/../../../../lib_ut.pri)
|
||||
|
||||
SOURCES = \
|
||||
dbLEFDEFImportTests.cc
|
||||
dbLEFDEFImportTests.cc \
|
||||
dbLEFDEFReaderOptionsTests.cc
|
||||
|
||||
INCLUDEPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
||||
DEPENDPATH += $$LAY_INC $$TL_INC $$DB_INC $$GSI_INC $$PWD/../db_plugin $$PWD/../../../common
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
VERSION 5.8 ;
|
||||
DIVIDERCHAR "/" ;
|
||||
BUSBITCHARS "[]" ;
|
||||
DESIGN mapfile ;
|
||||
UNITS DISTANCE MICRONS 1000 ;
|
||||
|
||||
DIEAREA ( 0 0 ) ( 1000 3000 ) ;
|
||||
|
||||
SPECIALNETS 1 ;
|
||||
- VDD ( * VDD )
|
||||
+ ROUTED + MASK 1 + RECT M0PO ( 0 1000 ) ( 500 1500 )
|
||||
+ ROUTED + MASK 2 + POLYGON M1 ( 0 1600 ) ( 0 2100 ) ( 500 2100 ) ( 500 1600 )
|
||||
+ ROUTED M1 50 + SHAPE STRIPE ( 500 0 ) MASK 1 ( 500 500 30 ) MASK 112 square ( 0 500 )
|
||||
+ USE POWER ;
|
||||
END SPECIALNETS
|
||||
|
||||
PINS 1 ;
|
||||
- VDD + NET VDD + SPECIAL + DIRECTION INOUT + USE POWER
|
||||
+ LAYER M1 MASK 1 ( 0 0 ) ( 50 70 )
|
||||
+ LAYER M0PO ( 0 100 ) ( 50 170 )
|
||||
+ LAYER M0PO MASK 2 ( 100 100 ) ( 150 170 )
|
||||
;
|
||||
END PINS
|
||||
|
||||
NETS 1 ;
|
||||
- TOP
|
||||
+ ROUTED M1 ( 100 700 ) MASK 1 ( 500 * ) MASK 2 ( 1000 * ) MASK 221 square ( * 800 ) ;
|
||||
END NETS
|
||||
|
||||
END DESIGN
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
LAYER M0PO
|
||||
TYPE MASTERSLICE ;
|
||||
WIDTH 0.02 ;
|
||||
MASKS 2 ;
|
||||
END M0PO
|
||||
LAYER VIA0
|
||||
TYPE CUT ;
|
||||
MASKS 2 ;
|
||||
END VIA0
|
||||
LAYER M1
|
||||
TYPE MASTERSLICE ;
|
||||
WIDTH 0.025 ;
|
||||
MASKS 2 ;
|
||||
END M1
|
||||
LAYER VIA1
|
||||
TYPE CUT ;
|
||||
MASKS 2 ;
|
||||
END VIA1
|
||||
LAYER M2
|
||||
TYPE MASTERSLICE ;
|
||||
WIDTH 0.03 ;
|
||||
MASKS 2 ;
|
||||
END M2
|
||||
|
||||
VIA square
|
||||
LAYER M0PO ;
|
||||
RECT -0.06 -0.06 0.06 0.06 ;
|
||||
LAYER VIA0 ;
|
||||
RECT -0.06 -0.06 0.06 0.06 ;
|
||||
LAYER M1 ;
|
||||
RECT -0.06 -0.06 0.06 0.06 ;
|
||||
END square
|
||||
Loading…
Reference in New Issue