mirror of https://github.com/KLayout/klayout.git
Bugfix: MINWIDTH ... WRONGDIRECTION wasn't considering DIRECTION VERTICAL
Added/updated some tests, some refactoring.
This commit is contained in:
parent
4a24b727d5
commit
f11a3a0dd5
|
|
@ -139,15 +139,17 @@ struct Group
|
||||||
std::pair<db::Coord, db::Coord>
|
std::pair<db::Coord, db::Coord>
|
||||||
DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::string &ln, double dbu)
|
DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::string &ln, double dbu)
|
||||||
{
|
{
|
||||||
db::Coord w = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_width (ln, rulename, 0.0) / dbu);
|
std::pair<double, double> wxy = m_lef_importer.layer_width (ln, rulename);
|
||||||
|
db::Coord wx = db::coord_traits<db::Coord>::rounded (wxy.first / dbu);
|
||||||
|
db::Coord wy = db::coord_traits<db::Coord>::rounded (wxy.second / dbu);
|
||||||
|
|
||||||
// try to find local nondefault rule
|
// try to find local nondefault rule
|
||||||
if (! rulename.empty ()) {
|
if (! rulename.empty ()) {
|
||||||
std::map<std::string, std::map<std::string, double> >::const_iterator nd = m_nondefault_widths.find (rulename);
|
std::map<std::string, std::map<std::string, db::Coord> >::const_iterator nd = m_nondefault_widths.find (rulename);
|
||||||
if (nd != m_nondefault_widths.end ()) {
|
if (nd != m_nondefault_widths.end ()) {
|
||||||
std::map<std::string, double>::const_iterator ld = nd->second.find (ln);
|
std::map<std::string, db::Coord>::const_iterator ld = nd->second.find (ln);
|
||||||
if (ld != nd->second.end ()) {
|
if (ld != nd->second.end ()) {
|
||||||
w = ld->second;
|
wx = wy = ld->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -156,30 +158,87 @@ DEFImporter::get_wire_width_for_rule (const std::string &rulename, const std::st
|
||||||
db::Coord min_wx = db::coord_traits<db::Coord>::rounded (min_wxy.first / dbu);
|
db::Coord min_wx = db::coord_traits<db::Coord>::rounded (min_wxy.first / dbu);
|
||||||
db::Coord min_wy = db::coord_traits<db::Coord>::rounded (min_wxy.second / dbu);
|
db::Coord min_wy = db::coord_traits<db::Coord>::rounded (min_wxy.second / dbu);
|
||||||
|
|
||||||
return std::make_pair (std::max (w, min_wx), std::max (w, min_wy));
|
return std::make_pair (std::max (wx, min_wx), std::max (wy, min_wy));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<db::Coord, db::Coord>
|
std::pair<db::Coord, db::Coord>
|
||||||
DEFImporter::get_def_ext (const std::string &ln, const std::pair<db::Coord, db::Coord> &wxy, double dbu)
|
DEFImporter::get_def_ext (const std::string &ln, const std::pair<db::Coord, db::Coord> &wxy, double dbu)
|
||||||
{
|
{
|
||||||
if (wxy.first == wxy.second) {
|
// This implementation assumes the "preferred width" is controlling the default extension and it is
|
||||||
db::Coord de = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, wxy.first * 0.5 * dbu) / dbu);
|
// identical to the minimum effective width. This is true if "LEF58_MINWIDTH" with "WRONGDIRECTION" is
|
||||||
return std::make_pair (de, de);
|
// used in the proposed way. Which is to specify a larger width for the "wrong" direction.
|
||||||
} else {
|
db::Coord de = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, std::min (wxy.first, wxy.second) * 0.5 * dbu) / dbu);
|
||||||
#if 0
|
return std::make_pair (de, de);
|
||||||
// This implementation picks the default extension according to the real width
|
}
|
||||||
// NOTE: the swapping of x and y for the default extension is intended. For horizontal lines, the
|
|
||||||
// extension is in x direction but corresponds to a wire width of a vertical wire and vice versa.
|
void
|
||||||
db::Coord dex = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, wxy.second * 0.5 * dbu) / dbu);
|
DEFImporter::read_diearea (db::Layout &layout, db::Cell &design, double scale)
|
||||||
db::Coord dey = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, wxy.first * 0.5 * dbu) / dbu);
|
{
|
||||||
return std::make_pair (dex, dey);
|
std::vector<db::DPoint> points;
|
||||||
#else
|
|
||||||
// This implementation picks the default extension according to the specified wire width (which is the minimum
|
while (! test (";")) {
|
||||||
// of wx and wy)
|
test ("(");
|
||||||
db::Coord de = db::coord_traits<db::Coord>::rounded (m_lef_importer.layer_ext (ln, std::min (wxy.first, wxy.second) * 0.5 * dbu) / dbu);
|
double x = get_double ();
|
||||||
return std::make_pair (de, de);
|
double y = get_double ();
|
||||||
#endif
|
points.push_back (db::DPoint (x * scale, y * scale));
|
||||||
|
test (")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (points.size () >= 2) {
|
||||||
|
|
||||||
|
// create outline shape
|
||||||
|
std::pair <bool, unsigned int> dl = open_layer (layout, std::string (), Outline);
|
||||||
|
if (dl.first) {
|
||||||
|
if (points.size () == 2) {
|
||||||
|
design.shapes (dl.second).insert (db::Box (db::DBox (points [0], points [1])));
|
||||||
|
} else {
|
||||||
|
db::DPolygon p;
|
||||||
|
p.assign_hull (points.begin (), points.end ());
|
||||||
|
design.shapes (dl.second).insert (db::Polygon (p));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DEFImporter::read_nondefaultrules (double scale)
|
||||||
|
{
|
||||||
|
// read NONDEFAULTRULES sections
|
||||||
|
get_long ();
|
||||||
|
expect (";");
|
||||||
|
|
||||||
|
while (test ("-")) {
|
||||||
|
|
||||||
|
std::string n = get ();
|
||||||
|
|
||||||
|
while (test ("+")) {
|
||||||
|
|
||||||
|
if (test ("LAYER")) {
|
||||||
|
|
||||||
|
std::string l = get ();
|
||||||
|
|
||||||
|
// read the width for the layer
|
||||||
|
if (test ("WIDTH")) {
|
||||||
|
double w = get_double () * scale;
|
||||||
|
m_nondefault_widths[n][l] = db::coord_traits<db::Coord>::rounded (w);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse over the rest
|
||||||
|
while (! peek ("+") && ! peek ("-") && ! peek (";")) {
|
||||||
|
take ();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
test (";");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
test ("END");
|
||||||
|
test ("NONDEFAULTRULES");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -231,31 +290,7 @@ DEFImporter::do_read (db::Layout &layout)
|
||||||
|
|
||||||
} else if (test ("DIEAREA")) {
|
} else if (test ("DIEAREA")) {
|
||||||
|
|
||||||
std::vector<db::DPoint> points;
|
read_diearea (layout, design, scale);
|
||||||
|
|
||||||
while (! test (";")) {
|
|
||||||
test ("(");
|
|
||||||
double x = get_double ();
|
|
||||||
double y = get_double ();
|
|
||||||
points.push_back (db::DPoint (x * scale, y * scale));
|
|
||||||
test (")");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (points.size () >= 2) {
|
|
||||||
|
|
||||||
// create outline shape
|
|
||||||
std::pair <bool, unsigned int> dl = open_layer (layout, std::string (), Outline);
|
|
||||||
if (dl.first) {
|
|
||||||
if (points.size () == 2) {
|
|
||||||
design.shapes (dl.second).insert (db::Box (db::DBox (points [0], points [1])));
|
|
||||||
} else {
|
|
||||||
db::DPolygon p;
|
|
||||||
p.assign_hull (points.begin (), points.end ());
|
|
||||||
design.shapes (dl.second).insert (db::Polygon (p));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (test ("PROPERTYDEFINITIONS")) {
|
} else if (test ("PROPERTYDEFINITIONS")) {
|
||||||
// read over PROPERTYDEFINITIONS sections
|
// read over PROPERTYDEFINITIONS sections
|
||||||
|
|
@ -265,41 +300,7 @@ DEFImporter::do_read (db::Layout &layout)
|
||||||
|
|
||||||
} else if (test ("NONDEFAULTRULES")) {
|
} else if (test ("NONDEFAULTRULES")) {
|
||||||
|
|
||||||
// read NONDEFAULTRULES sections
|
read_nondefaultrules (scale);
|
||||||
get_long ();
|
|
||||||
expect (";");
|
|
||||||
|
|
||||||
while (test ("-")) {
|
|
||||||
|
|
||||||
std::string n = get ();
|
|
||||||
|
|
||||||
while (test ("+")) {
|
|
||||||
|
|
||||||
if (test ("LAYER")) {
|
|
||||||
|
|
||||||
std::string l = get ();
|
|
||||||
|
|
||||||
// read the width for the layer
|
|
||||||
if (test ("WIDTH")) {
|
|
||||||
double w = get_double () * scale;
|
|
||||||
m_nondefault_widths[n][l] = w;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse over the rest
|
|
||||||
while (! peek ("+") && ! peek ("-") && ! peek (";")) {
|
|
||||||
take ();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
test (";");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
test ("END");
|
|
||||||
test ("NONDEFAULTRULES");
|
|
||||||
|
|
||||||
} else if (test ("REGIONS")) {
|
} else if (test ("REGIONS")) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,13 +61,15 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LEFImporter m_lef_importer;
|
LEFImporter m_lef_importer;
|
||||||
std::map<std::string, std::map<std::string, double> > m_nondefault_widths;
|
std::map<std::string, std::map<std::string, db::Coord> > m_nondefault_widths;
|
||||||
|
|
||||||
db::FTrans get_orient (bool optional);
|
db::FTrans get_orient (bool optional);
|
||||||
void read_polygon (db::Polygon &poly, double scale);
|
void read_polygon (db::Polygon &poly, double scale);
|
||||||
void read_rect (db::Polygon &poly, double scale);
|
void read_rect (db::Polygon &poly, double scale);
|
||||||
std::pair<Coord, Coord> get_wire_width_for_rule(const std::string &rule, const std::string &ln, double dbu);
|
std::pair<Coord, Coord> get_wire_width_for_rule(const std::string &rule, const std::string &ln, double dbu);
|
||||||
std::pair<db::Coord, db::Coord> get_def_ext (const std::string &ln, const std::pair<db::Coord, db::Coord> &wxy, double dbu);
|
std::pair<db::Coord, db::Coord> get_def_ext (const std::string &ln, const std::pair<db::Coord, db::Coord> &wxy, double dbu);
|
||||||
|
void read_diearea (db::Layout &layout, db::Cell &design, double scale);
|
||||||
|
void read_nondefaultrules (double scale);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,12 +76,12 @@ LEFImporter::min_layer_width (const std::string &layer) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
std::pair<double, double>
|
||||||
LEFImporter::layer_width (const std::string &layer, const std::string &nondefaultrule, double def_width) const
|
LEFImporter::layer_width (const std::string &layer, const std::string &nondefaultrule, const std::pair<double, double> &def_width) const
|
||||||
{
|
{
|
||||||
std::map<std::string, std::map<std::string, double> >::const_iterator nd = m_nondefault_widths.find (nondefaultrule);
|
std::map<std::string, std::map<std::string, std::pair<double, double> > >::const_iterator nd = m_nondefault_widths.find (nondefaultrule);
|
||||||
|
|
||||||
std::map<std::string, double>::const_iterator l;
|
std::map<std::string, std::pair<double, double> >::const_iterator l;
|
||||||
bool has_width = false;
|
bool has_width = false;
|
||||||
|
|
||||||
if (! nondefaultrule.empty () && nd != m_nondefault_widths.end ()) {
|
if (! nondefaultrule.empty () && nd != m_nondefault_widths.end ()) {
|
||||||
|
|
@ -185,9 +185,9 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
||||||
}
|
}
|
||||||
|
|
||||||
w = 0.0;
|
w = 0.0;
|
||||||
std::map<std::string, double>::const_iterator dw = m_default_widths.find (layer_name);
|
std::map<std::string, std::pair<double, double> >::const_iterator dw = m_default_widths.find (layer_name);
|
||||||
if (dw != m_default_widths.end ()) {
|
if (dw != m_default_widths.end ()) {
|
||||||
w = dw->second;
|
w = dw->second.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (! test (";")) {
|
while (! test (";")) {
|
||||||
|
|
@ -388,7 +388,7 @@ LEFImporter::read_nondefaultrule (db::Layout & /*layout*/)
|
||||||
if (test ("WIDTH")) {
|
if (test ("WIDTH")) {
|
||||||
double w = get_double ();
|
double w = get_double ();
|
||||||
test (";");
|
test (";");
|
||||||
m_nondefault_widths[n][l] = w;
|
m_nondefault_widths[n][l] = std::make_pair (w, w);
|
||||||
} else {
|
} else {
|
||||||
while (! test (";")) {
|
while (! test (";")) {
|
||||||
take ();
|
take ();
|
||||||
|
|
@ -590,7 +590,8 @@ LEFImporter::read_layer (Layout & /*layout*/)
|
||||||
{
|
{
|
||||||
std::string ln = get ();
|
std::string ln = get ();
|
||||||
double wmin = 0.0, wmin_wrongdir = 0.0;
|
double wmin = 0.0, wmin_wrongdir = 0.0;
|
||||||
bool is_horizontal = true;
|
double w = 0.0, w_wrongdir = 0.0;
|
||||||
|
bool is_horizontal = false;
|
||||||
|
|
||||||
register_layer (ln);
|
register_layer (ln);
|
||||||
|
|
||||||
|
|
@ -615,8 +616,12 @@ LEFImporter::read_layer (Layout & /*layout*/)
|
||||||
|
|
||||||
} else if (test ("WIDTH")) {
|
} else if (test ("WIDTH")) {
|
||||||
|
|
||||||
double w = get_double ();
|
w = get_double ();
|
||||||
m_default_widths.insert (std::make_pair (ln, w));
|
expect (";");
|
||||||
|
|
||||||
|
} else if (test ("MINWIDTH")) {
|
||||||
|
|
||||||
|
wmin = get_double ();
|
||||||
expect (";");
|
expect (";");
|
||||||
|
|
||||||
} else if (test ("DIRECTION")) {
|
} else if (test ("DIRECTION")) {
|
||||||
|
|
@ -629,8 +634,8 @@ LEFImporter::read_layer (Layout & /*layout*/)
|
||||||
|
|
||||||
} else if (test ("WIREEXTENSION")) {
|
} else if (test ("WIREEXTENSION")) {
|
||||||
|
|
||||||
double w = get_double ();
|
double v = get_double ();
|
||||||
m_default_ext.insert (std::make_pair (ln, w));
|
m_default_ext.insert (std::make_pair (ln, v));
|
||||||
expect (";");
|
expect (";");
|
||||||
|
|
||||||
} else if (test ("ACCURRENTDENSITY")) {
|
} else if (test ("ACCURRENTDENSITY")) {
|
||||||
|
|
@ -656,17 +661,32 @@ LEFImporter::read_layer (Layout & /*layout*/)
|
||||||
|
|
||||||
// Cadence extension
|
// Cadence extension
|
||||||
tl::Extractor ex (value.to_string ());
|
tl::Extractor ex (value.to_string ());
|
||||||
double mw = 0.0;
|
double v = 0.0;
|
||||||
if (ex.test ("MINWIDTH") && ex.try_read (mw)) {
|
if (ex.test ("MINWIDTH") && ex.try_read (v)) {
|
||||||
if (ex.test ("WRONGDIRECTION")) {
|
if (ex.test ("WRONGDIRECTION")) {
|
||||||
wmin_wrongdir = mw;
|
wmin_wrongdir = v;
|
||||||
} else {
|
} else {
|
||||||
wmin = mw;
|
wmin = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (name == "LEF58_WIDTH") {
|
||||||
|
|
||||||
|
// Cadence extension
|
||||||
|
tl::Extractor ex (value.to_string ());
|
||||||
|
double v = 0.0;
|
||||||
|
if (ex.test ("WIDTH") && ex.try_read (v)) {
|
||||||
|
if (ex.test ("WRONGDIRECTION")) {
|
||||||
|
w_wrongdir = v;
|
||||||
|
} else {
|
||||||
|
w = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expect (";");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
while (! test (";")) {
|
while (! test (";")) {
|
||||||
|
|
@ -676,9 +696,23 @@ LEFImporter::read_layer (Layout & /*layout*/)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (w > 0.0 || w_wrongdir > 0.0) {
|
||||||
|
|
||||||
|
if (w_wrongdir == 0.0) {
|
||||||
|
w_wrongdir = w;
|
||||||
|
} else if (! is_horizontal) {
|
||||||
|
std::swap (w, w_wrongdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_default_widths.insert (std::make_pair (ln, std::make_pair (w, w_wrongdir)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (wmin > 0.0 || wmin_wrongdir > 0.0) {
|
if (wmin > 0.0 || wmin_wrongdir > 0.0) {
|
||||||
|
|
||||||
if (! is_horizontal) {
|
if (wmin_wrongdir == 0.0) {
|
||||||
|
wmin_wrongdir = wmin;
|
||||||
|
} else if (! is_horizontal) {
|
||||||
std::swap (wmin, wmin_wrongdir);
|
std::swap (wmin, wmin_wrongdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ public:
|
||||||
* The nondefaultrule name gives the name of the nondefaultrule or an empty string if
|
* The nondefaultrule name gives the name of the nondefaultrule or an empty string if
|
||||||
* none is requested.
|
* none is requested.
|
||||||
*/
|
*/
|
||||||
double layer_width (const std::string &layer, const std::string &nondefaultrule, double def_width = 0.0) const;
|
std::pair<double, double> layer_width (const std::string &layer, const std::string &nondefaultrule, const std::pair<double, double> &def_width = std::make_pair (0.0, 0.0)) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the extension for a layer with the given name
|
* @brief Get the extension for a layer with the given name
|
||||||
|
|
@ -121,8 +121,8 @@ protected:
|
||||||
void do_read (db::Layout &layout);
|
void do_read (db::Layout &layout);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, std::map<std::string, double> > m_nondefault_widths;
|
std::map<std::string, std::map<std::string, std::pair<double, double> > > m_nondefault_widths;
|
||||||
std::map<std::string, double> m_default_widths;
|
std::map<std::string, std::pair<double, double> > m_default_widths;
|
||||||
std::map<std::string, double> m_default_ext;
|
std::map<std::string, double> m_default_ext;
|
||||||
std::map<std::string, std::pair<double, double> > m_min_widths;
|
std::map<std::string, std::pair<double, double> > m_min_widths;
|
||||||
std::map<std::string, db::Cell *> m_macros_by_name;
|
std::map<std::string, db::Cell *> m_macros_by_name;
|
||||||
|
|
|
||||||
|
|
@ -284,3 +284,14 @@ TEST(106_wrongdirection)
|
||||||
{
|
{
|
||||||
run_test (_this, "wrongdirection", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
|
run_test (_this, "wrongdirection", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(107_specialwidths)
|
||||||
|
{
|
||||||
|
run_test (_this, "specialwidths", "lef:test.lef+def:test.def", "au.oas.gz", default_options (), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(108_scanchain)
|
||||||
|
{
|
||||||
|
run_test (_this, "scanchain", "def:test.def", "au.oas.gz", default_options (), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,32 @@
|
||||||
|
VERSION 5.8 ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DESIGN chip_top ;
|
||||||
|
UNITS DISTANCE MICRONS 1000 ;
|
||||||
|
DIEAREA ( 0 0 ) ( 8729280 8199360 ) ;
|
||||||
|
SCANCHAINS 9992 ;
|
||||||
|
- chain1
|
||||||
|
+ PARTITION part/Y_45_45_0.720000
|
||||||
|
+ START whereever/anchor_buf_8 Y
|
||||||
|
+ FLOATING
|
||||||
|
dumdidum/_reg_1_reg_2_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_2_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_7_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_8_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_5_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_9_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_6_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_4_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_7_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_1_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_3_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_1_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_0_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_4_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_0_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_6_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_3_ ( IN SI ) ( OUT Q )
|
||||||
|
dumdidum/_reg_1_reg_5_ ( IN SI ) ( OUT Q )
|
||||||
|
+ STOP somewhere/LOCKUP D ;
|
||||||
|
END SCANCHAINS
|
||||||
|
END DESIGN
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,19 @@
|
||||||
|
VERSION 5.8 ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DESIGN test ;
|
||||||
|
UNITS DISTANCE MICRONS 1000 ;
|
||||||
|
DIEAREA ( 0 0 ) ( 10000 10000 ) ;
|
||||||
|
NONDEFAULTRULES 1 ;
|
||||||
|
- ndr
|
||||||
|
+ HARDSPACING
|
||||||
|
+ LAYER M3 WIDTH 500 SPACING 500
|
||||||
|
;
|
||||||
|
END NONDEFAULTRULES
|
||||||
|
NETS 1 ;
|
||||||
|
- net_b
|
||||||
|
+ NONDEFAULTRULE ndr
|
||||||
|
+ ROUTED M3 ( 0 2000 ) ( 0 0 ) ( 2000 0 ) via34 ( * 2000 ) ( 4000 * ) ( * 4000 )
|
||||||
|
;
|
||||||
|
END NETS
|
||||||
|
END DESIGN
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
VERSION 5.8 ;
|
||||||
|
BUSBITCHARS "[]" ;
|
||||||
|
DIVIDERCHAR "/" ;
|
||||||
|
|
||||||
|
UNITS
|
||||||
|
DATABASE MICRONS 1000 ;
|
||||||
|
END UNITS
|
||||||
|
|
||||||
|
MANUFACTURINGGRID 0.001 ;
|
||||||
|
|
||||||
|
PROPERTYDEFINITIONS
|
||||||
|
LAYER LEF58_MINWIDTH STRING ;
|
||||||
|
END PROPERTYDEFINITIONS
|
||||||
|
|
||||||
|
LAYER M3
|
||||||
|
TYPE ROUTING ;
|
||||||
|
DIRECTION VERTICAL ;
|
||||||
|
WIDTH 0.4 ;
|
||||||
|
PROPERTY LEF58_MINWIDTH "MINWIDTH 0.5 ; " ;
|
||||||
|
PROPERTY LEF58_MINWIDTH "MINWIDTH 0.8 WRONGDIRECTION ; " ;
|
||||||
|
END M3
|
||||||
|
|
||||||
|
LAYER VIA3
|
||||||
|
TYPE CUT ;
|
||||||
|
END VIA3
|
||||||
|
|
||||||
|
LAYER M4
|
||||||
|
TYPE ROUTING ;
|
||||||
|
DIRECTION HORIZONTAL ;
|
||||||
|
PROPERTY LEF58_WIDTH "WIDTH 0.6 ; " ;
|
||||||
|
PROPERTY LEF58_WIDTH "WIDTH 1.0 WRONGDIRECTION ; " ;
|
||||||
|
END M4
|
||||||
|
|
||||||
|
VIA via34
|
||||||
|
LAYER M3 ;
|
||||||
|
RECT -0.4 -0.3 0.4 0.3 ;
|
||||||
|
LAYER VIA3 ;
|
||||||
|
RECT -0.3 -0.25 0.3 0.25 ;
|
||||||
|
LAYER M4 ;
|
||||||
|
RECT -1.00 -0.5 1.00 0.5 ;
|
||||||
|
END via34
|
||||||
|
|
||||||
|
END LIBRARY
|
||||||
Loading…
Reference in New Issue