mirror of https://github.com/KLayout/klayout.git
Merge pull request #1889 from KLayout/issue-1877
Fixed issue #1877 (rounding introduces DRC error in LEF/DEF via)
This commit is contained in:
commit
6b906b9582
|
|
@ -223,8 +223,13 @@ RuleBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, d
|
||||||
|
|
||||||
// NOTE: missing cuts due to pattern holes don't change mask assignment
|
// NOTE: missing cuts due to pattern holes don't change mask assignment
|
||||||
|
|
||||||
db::Vector vs ((m_cutsize.x () * m_columns + m_cutspacing.x () * (m_columns - 1)) / 2, (m_cutsize.y () * m_rows + m_cutspacing.y () * (m_rows - 1)) / 2);
|
// special rounding to ensure the dimensions are correct for non-even width or height (issue #1877)
|
||||||
db::Box via_box (m_offset - vs, m_offset + vs);
|
db::Vector vs ((m_cutsize.x () * m_columns + m_cutspacing.x () * (m_columns - 1)), (m_cutsize.y () * m_rows + m_cutspacing.y () * (m_rows - 1)));
|
||||||
|
if (vs.x () % 2 != 0 || vs.y () % 2 != 0) {
|
||||||
|
reader.warn (tl::sprintf (tl::to_string (tr ("Via has odd width or height (x,y dimension of cut array is %s database units) - this may lead to inaccurate positioning of the via")), vs.to_string ()));
|
||||||
|
}
|
||||||
|
db::Point via_ll = m_offset - db::Vector (vs.x () / 2, vs.y () / 2);
|
||||||
|
db::Box via_box (via_ll, via_ll + vs);
|
||||||
|
|
||||||
std::set <unsigned int> dl;
|
std::set <unsigned int> dl;
|
||||||
|
|
||||||
|
|
@ -975,7 +980,7 @@ LEFDEFReaderState::~LEFDEFReaderState ()
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LEFDEFReaderState::common_reader_error (const std::string &msg)
|
LEFDEFReaderState::error (const std::string &msg)
|
||||||
{
|
{
|
||||||
if (mp_importer) {
|
if (mp_importer) {
|
||||||
mp_importer->error (msg);
|
mp_importer->error (msg);
|
||||||
|
|
@ -983,7 +988,7 @@ LEFDEFReaderState::common_reader_error (const std::string &msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LEFDEFReaderState::common_reader_warn (const std::string &msg, int warn_level)
|
LEFDEFReaderState::warn (const std::string &msg, int warn_level)
|
||||||
{
|
{
|
||||||
if (mp_importer) {
|
if (mp_importer) {
|
||||||
mp_importer->warn (msg, warn_level);
|
mp_importer->warn (msg, warn_level);
|
||||||
|
|
@ -1117,7 +1122,7 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::
|
||||||
size_t max_purpose_str = 15;
|
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)) {
|
||||||
common_reader_warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d not understood - skipped")), path, ts.line_number ()));
|
warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d not understood - skipped")), path, ts.line_number ()));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1143,7 +1148,7 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::
|
||||||
name = "REGIONS_NONE";
|
name = "REGIONS_NONE";
|
||||||
lp = RegionsNone;
|
lp = RegionsNone;
|
||||||
} else if (w2 != "ALL") {
|
} else if (w2 != "ALL") {
|
||||||
common_reader_warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d - ignoring unknowns REGION purpose %s (use FENCE, GUIDE or ALL)")), path, ts.line_number (), w2));
|
warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d - ignoring unknowns REGION purpose %s (use FENCE, GUIDE or ALL)")), path, ts.line_number (), w2));
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
@ -1176,7 +1181,7 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::
|
||||||
|
|
||||||
if (*p == "DIEAREA" || *p == "ALL" || *p == "COMP") {
|
if (*p == "DIEAREA" || *p == "ALL" || *p == "COMP") {
|
||||||
|
|
||||||
common_reader_warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: NAME record ignored for entity: %s")), path, ts.line_number (), *p));
|
warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: NAME record ignored for entity: %s")), path, ts.line_number (), *p));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
@ -1193,7 +1198,7 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::
|
||||||
if (label_purpose == Pins || label_purpose == LEFPins) {
|
if (label_purpose == Pins || label_purpose == LEFPins) {
|
||||||
layer_defs.push_back (std::make_pair (lp.front (), label_purpose == Pins ? Label : LEFLabel));
|
layer_defs.push_back (std::make_pair (lp.front (), label_purpose == Pins ? Label : LEFLabel));
|
||||||
} else {
|
} else {
|
||||||
common_reader_warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: NAME record ignored for purpose: %s")), path, ts.line_number (), purpose_to_name (label_purpose)));
|
warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: NAME record ignored for purpose: %s")), path, ts.line_number (), purpose_to_name (label_purpose)));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1226,7 +1231,7 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::
|
||||||
} else if (w1 == "COMP") {
|
} else if (w1 == "COMP") {
|
||||||
|
|
||||||
// ignore "COMP (ALL) ..."
|
// ignore "COMP (ALL) ..."
|
||||||
common_reader_warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: COMP entry ignored")), path, ts.line_number ()));
|
warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: COMP entry ignored")), path, ts.line_number ()));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
@ -1261,7 +1266,7 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::
|
||||||
if (ex.test (":VOLTAGE:")) {
|
if (ex.test (":VOLTAGE:")) {
|
||||||
double f = 0.0;
|
double f = 0.0;
|
||||||
ex.read (f);
|
ex.read (f);
|
||||||
common_reader_warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: NET voltage constraint ignored for layer %s")), path, ts.line_number (), w1));
|
warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: NET voltage constraint ignored for layer %s")), path, ts.line_number (), w1));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (i->second == ViaGeometry) {
|
} else if (i->second == ViaGeometry) {
|
||||||
|
|
@ -1284,7 +1289,7 @@ LEFDEFReaderState::read_single_map_file (const std::string &path, std::map<std::
|
||||||
|
|
||||||
if (i == purpose_translation.end ()) {
|
if (i == purpose_translation.end ()) {
|
||||||
|
|
||||||
common_reader_warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: purpose %s ignored for layer %s")), path, ts.line_number (), ps, w1));
|
warn (tl::sprintf (tl::to_string (tr ("Reading layer map file %s, line %d: purpose %s ignored for layer %s")), path, ts.line_number (), ps, w1));
|
||||||
|
|
||||||
} else if (i->second == All) {
|
} else if (i->second == All) {
|
||||||
|
|
||||||
|
|
@ -1379,7 +1384,7 @@ LEFDEFReaderState::open_layer (db::Layout &layout, const std::string &n, LayerPu
|
||||||
msg += tl::to_string (tr (" Via size ")) + via_size.to_string ();
|
msg += tl::to_string (tr (" Via size ")) + via_size.to_string ();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
common_reader_warn (msg + tl::to_string (tr (" - layer is ignored")));
|
warn (msg + tl::to_string (tr (" - layer is ignored")));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ll;
|
return ll;
|
||||||
|
|
|
||||||
|
|
@ -1354,9 +1354,19 @@ public:
|
||||||
return m_foreign_cells;
|
return m_foreign_cells;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Issues an error
|
||||||
|
*/
|
||||||
|
void error (const std::string &msg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Issues a warning
|
||||||
|
*/
|
||||||
|
void warn (const std::string &msg, int warn_level = 1);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void common_reader_error (const std::string &msg);
|
virtual void common_reader_error (const std::string &msg) { error (msg); }
|
||||||
virtual void common_reader_warn (const std::string &msg, int warn_level = 1);
|
virtual void common_reader_warn (const std::string &msg, int warn_level) { warn (msg, warn_level); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1077,3 +1077,26 @@ TEST(213_no_duplicate_LEF)
|
||||||
db::compare_layouts (_this, ly, fn_path + "au.oas", db::WriteOAS);
|
db::compare_layouts (_this, ly, fn_path + "au.oas", db::WriteOAS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// issue-1877 (VIA placement rounding)
|
||||||
|
TEST(214_issue1877)
|
||||||
|
{
|
||||||
|
db::Layout ly;
|
||||||
|
|
||||||
|
std::string fn_path (tl::testdata ());
|
||||||
|
fn_path += "/lefdef/issue-1877/";
|
||||||
|
|
||||||
|
db::LEFDEFReaderOptions lefdef_opt = default_options ();
|
||||||
|
lefdef_opt.set_map_file ("tech.map");
|
||||||
|
lefdef_opt.set_read_lef_with_def (true);
|
||||||
|
db::LoadLayoutOptions opt;
|
||||||
|
opt.set_options (lefdef_opt);
|
||||||
|
|
||||||
|
{
|
||||||
|
tl::InputStream is (fn_path + "test.def");
|
||||||
|
db::Reader reader (is);
|
||||||
|
reader.read (ly, opt);
|
||||||
|
}
|
||||||
|
|
||||||
|
db::compare_layouts (_this, ly, fn_path + "au.oas", db::WriteOAS);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,27 @@
|
||||||
|
VERSION 5.6 ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
|
||||||
|
UNITS
|
||||||
|
DATABASE MICRONS 1000 ;
|
||||||
|
END UNITS
|
||||||
|
MANUFACTURINGGRID 0.001 ;
|
||||||
|
|
||||||
|
LAYER METAL_1
|
||||||
|
TYPE ROUTING ;
|
||||||
|
DIRECTION HORIZONTAL ;
|
||||||
|
WIDTH 0.6 ;
|
||||||
|
END METAL_1
|
||||||
|
|
||||||
|
LAYER VIA_1
|
||||||
|
TYPE CUT ;
|
||||||
|
END VIA_1
|
||||||
|
|
||||||
|
LAYER METAL_2
|
||||||
|
TYPE ROUTING ;
|
||||||
|
DIRECTION VERTICAL ;
|
||||||
|
WIDTH 0.6 ;
|
||||||
|
END METAL_2
|
||||||
|
|
||||||
|
END LIBRARY
|
||||||
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
DIEAREA ALL 1 0
|
||||||
|
METAL_1 ALL 2 0
|
||||||
|
VIA_1 ALL 3 0
|
||||||
|
METAL_2 ALL 4 0
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
VERSION 5.8 ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DESIGN dummy_design ;
|
||||||
|
UNITS DISTANCE MICRONS 1000 ;
|
||||||
|
|
||||||
|
DIEAREA ( 21500 7000 ) ( 26000 9000 ) ;
|
||||||
|
|
||||||
|
VIAS 1 ;
|
||||||
|
- via1_2_XXXX_XXX_X_X_XXX_XXX + VIARULE MYVIA1_ARRAY + CUTSIZE 246 246 + LAYERS METAL_1 VIA_1 METAL_2 + CUTSPACING 231 231 + ENCLOSURE 62 137 8 61 + ROWCOL 1 8 ;
|
||||||
|
END VIAS
|
||||||
|
|
||||||
|
|
||||||
|
SPECIALNETS 1 ;
|
||||||
|
- VDD
|
||||||
|
# ( PIN VDD ) ( * vdd )
|
||||||
|
+ USE POWER
|
||||||
|
+ ROUTED METAL_1 0 + SHAPE STRIPE ( 23620 7840 ) via1_2_XXXX_XXX_X_X_XXX_XXX ;
|
||||||
|
END SPECIALNETS
|
||||||
|
|
||||||
|
END DESIGN
|
||||||
Loading…
Reference in New Issue