Merge branch 'master' into lefdef-enhancments

This commit is contained in:
Matthias Koefferlein 2020-06-05 14:05:13 +02:00
commit 5992a9b509
33 changed files with 786 additions and 278 deletions

View File

@ -1180,7 +1180,7 @@ db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Poin
}
}
db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_perimeter_factor, const db::Region &metal, double metal_perimeter_factor, double ratio, const std::vector<std::pair<const db::Region *, double> > &diodes)
db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_area_factor, double gate_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector<std::pair<const db::Region *, double> > &diodes)
{
// TODO: that's basically too much .. we only need the clusters
if (! m_netlist_extracted) {
@ -1210,12 +1210,18 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_p
deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (gate), db::ICplxTrans (), rgate, 0);
deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (metal), db::ICplxTrans (), rmetal, 0);
double agate = rgate.area () * dbu * dbu;
double agate = 0.0;
if (fabs (gate_area_factor) > 1e-6) {
agate += rgate.area () * dbu * dbu * gate_area_factor;
}
if (fabs (gate_perimeter_factor) > 1e-6) {
agate += rgate.perimeter () * dbu * gate_perimeter_factor;
}
double ametal = rmetal.area () * dbu * dbu;
double ametal = 0.0;
if (fabs (metal_area_factor) > 1e-6) {
ametal += rmetal.area () * dbu * dbu * metal_area_factor;
}
if (fabs (metal_perimeter_factor) > 1e-6) {
ametal += rmetal.perimeter () * dbu * metal_perimeter_factor;
}

View File

@ -733,9 +733,9 @@ public:
* The area computation of gate and metal happens by taking the polygon
* area (A) and perimeter (P) into account:
*
* A(antenna) = A + P * f
* A(antenna) = A + P * t
*
* where f is the perimeter factor. The unit of the area factor is
* where t is the perimeter factor. The unit of this area factor is
* micrometers.
*
* The limit ratio can be modified by the presence of connections to
@ -750,7 +750,10 @@ public:
* regardless of the diode's area.
* In other words: any diode will make the net safe against antenna discharge.
*/
db::Region antenna_check (const db::Region &gate, double gate_perimeter_factor, const db::Region &metal, double metal_perimeter_factor, double ratio, const std::vector<std::pair<const db::Region *, double> > &diodes = std::vector<std::pair<const db::Region *, double> > ());
db::Region antenna_check (const db::Region &gate, double gate_perimeter_factor, const db::Region &metal, double metal_perimeter_factor, double ratio, const std::vector<std::pair<const db::Region *, double> > &diodes = std::vector<std::pair<const db::Region *, double> > ())
{
return antenna_check (gate, 1.0, gate_perimeter_factor, metal, 1.0, metal_perimeter_factor, ratio, diodes);
}
/**
* @brief Variant of the antennna check not using the perimeter
@ -758,9 +761,21 @@ public:
*/
db::Region antenna_check (const db::Region &gate, const db::Region &metal, double ratio, const std::vector<std::pair<const db::Region *, double> > &diodes = std::vector<std::pair<const db::Region *, double> > ())
{
return antenna_check (gate, 0.0, metal, 0.0, ratio, diodes);
return antenna_check (gate, 1.0, 0.0, metal, 1.0, 0.0, ratio, diodes);
}
/**
* @brief Variant of the antenna check providing an area scale factor
*
* This version provides an additional area scale factor f, so the effective area becomes
*
* A(antenna) = A * f + P * t
*
* where f is the area scale factor and t the perimeter scale factor. This version allows to ignore the
* area contribution entirely and switch to a perimeter-based antenna check by setting f to zero.
*/
db::Region antenna_check (const db::Region &gate, double gate_area_factor, double gate_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector<std::pair<const db::Region *, double> > &diodes = std::vector<std::pair<const db::Region *, double> > ());
/**
* @brief Saves the database to the given path
*

View File

@ -46,6 +46,39 @@ Library::~Library ()
// .. nothing yet ..
}
bool
Library::is_for_technology (const std::string &name) const
{
return m_technologies.find (name) != m_technologies.end ();
}
bool
Library::for_technologies () const
{
return ! m_technologies.empty ();
}
void
Library::set_technology (const std::string &t)
{
m_technologies.clear ();
if (! t.empty ()) {
m_technologies.insert (t);
}
}
void
Library::clear_technologies ()
{
m_technologies.clear ();
}
void
Library::add_technology (const std::string &tech)
{
m_technologies.insert (tech);
}
void
Library::register_proxy (db::LibraryProxy *lib_proxy, db::Layout *ly)
{

View File

@ -31,6 +31,7 @@
#include "tlObject.h"
#include <string>
#include <set>
namespace db
{
@ -108,18 +109,38 @@ public:
* If this attribute is non-empty, the library is selected only when the given technology is
* used for the layout.
*/
const std::string &get_technology () const
const std::set<std::string> &get_technologies () const
{
return m_technology;
return m_technologies;
}
/**
* @brief Sets the technology name this library is associated with
* @brief Gets a value indicating whether this library is associated with the given technology
*/
void set_technology (const std::string &t)
{
m_technology = t;
}
bool is_for_technology (const std::string &name) const;
/**
* @brief Gets a value indicating whether the library is associated with any technology
*/
bool for_technologies () const;
/**
* @brief Sets the technology name this library is associated with
*
* This will reset the list of technologies to this one.
* If the given technology string is empty, the list of technologies will be cleared.
*/
void set_technology (const std::string &t);
/**
* @brief Clears the list of technologies this library is associated with
*/
void clear_technologies ();
/**
* @brief Additionally associate the library with the given technology
*/
void add_technology (const std::string &tech);
/**
* @brief Getter for the description property
@ -198,7 +219,7 @@ public:
private:
std::string m_name;
std::string m_description;
std::string m_technology;
std::set<std::string> m_technologies;
lib_id_type m_id;
db::Layout m_layout;
std::map<db::Layout *, int> m_referrers;

View File

@ -98,7 +98,7 @@ static std::vector<std::string> l2n_layer_names (const db::LayoutToNetlist *l2n)
return ln;
}
static db::Region antenna_check2 (db::LayoutToNetlist *l2n, const db::Region &poly, double poly_perimeter_factor, const db::Region &metal, double metal_perimeter_factor, double ratio, const std::vector<tl::Variant> &diodes)
static db::Region antenna_check3 (db::LayoutToNetlist *l2n, const db::Region &poly, double poly_area_factor, double poly_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector<tl::Variant> &diodes)
{
std::vector<std::pair<const db::Region *, double> > diode_pairs;
@ -127,12 +127,17 @@ static db::Region antenna_check2 (db::LayoutToNetlist *l2n, const db::Region &po
}
return l2n->antenna_check (poly, poly_perimeter_factor, metal, metal_perimeter_factor, ratio, diode_pairs);
return l2n->antenna_check (poly, poly_area_factor, poly_perimeter_factor, metal, metal_area_factor, metal_perimeter_factor, ratio, diode_pairs);
}
static db::Region antenna_check2 (db::LayoutToNetlist *l2n, const db::Region &poly, double poly_perimeter_factor, const db::Region &metal, double metal_perimeter_factor, double ratio, const std::vector<tl::Variant> &diodes)
{
return antenna_check3 (l2n, poly, 1, poly_perimeter_factor, metal, 1, metal_perimeter_factor, ratio, diodes);
}
static db::Region antenna_check (db::LayoutToNetlist *l2n, const db::Region &poly, const db::Region &metal, double ratio, const std::vector<tl::Variant> &diodes)
{
return antenna_check2 (l2n, poly, 0, metal, 0, ratio, diodes);
return antenna_check3 (l2n, poly, 1, 0, metal, 1, 0, ratio, diodes);
}
Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
@ -617,15 +622,32 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"The effective area is computed using:\n"
"\n"
"@code\n"
"Aeff = A + P * f\n"
"Aeff = A + P * t\n"
"@/code\n"
"\n"
"Here Aeff is the area used in the check, A is the polygon area, P the perimeter and f the perimeter factor. "
"This formula applies to gate polygon area/perimeter with 'gate_perimeter_factor' for f and metal polygon area/perimeter "
"Here Aeff is the area used in the check, A is the polygon area, P the perimeter and t the perimeter factor. "
"This formula applies to gate polygon area/perimeter with 'gate_perimeter_factor' for t and metal polygon area/perimeter "
"with 'metal_perimeter_factor'. The perimeter_factor has the dimension of micrometers and can be thought of as the width "
"of the material. Essentially the side walls of the material are taking into account for the surface area as well.\n"
"\n"
"This variant has been introduced in version 0.26.6.\n"
) +
gsi::method_ext ("antenna_check", &antenna_check3, gsi::arg ("gate"), gsi::arg ("gate_area_factor"), gsi::arg ("gate_perimeter_factor"), gsi::arg ("metal"), gsi::arg ("metal_area_factor"), gsi::arg ("metal_perimeter_factor"), gsi::arg ("ratio"), gsi::arg ("diodes", std::vector<tl::Variant> (), "[]"),
"@brief Runs an antenna check on the extracted clusters taking the perimeter into account and providing an area factor\n"
"\n"
"This (most generic) version of the \\antenna_check method allows taking the perimeter of gate or metal into account and also "
"provides a scaling factor for the area part.\n"
"The effective area is computed using:\n"
"\n"
"@code\n"
"Aeff = A * f + P * t\n"
"@/code\n"
"\n"
"Here f is the area factor and t the perimeter factor. A is the polygon area and P the polygon perimeter. "
"A use case for this variant is to set the area factor to zero. This way, only perimeter contributions are "
"considered.\n"
"\n"
"This variant has been introduced in version 0.26.6.\n"
),
"@brief A generic framework for extracting netlists from layouts\n"
"\n"

View File

@ -68,6 +68,16 @@ static void delete_lib (db::Library *lib)
db::LibraryManager::instance ().delete_lib (lib);
}
static std::string get_technology (db::Library *lib)
{
const std::set<std::string> &techs = lib->get_technologies ();
if (techs.empty ()) {
return std::string ();
} else {
return *techs.begin ();
}
}
Class<db::Library> decl_Library ("db", "Library",
gsi::constructor ("new", &new_lib,
"@brief Creates a new, empty library"
@ -111,18 +121,47 @@ Class<db::Library> decl_Library ("db", "Library",
gsi::method ("description=", &db::Library::set_description, gsi::arg ("description"),
"@brief Sets the libraries' description text\n"
) +
gsi::method ("technology", &db::Library::get_technology,
gsi::method_ext ("#technology", &get_technology,
"@brief Returns name of the technology the library is associated with\n"
"If this attribute is a non-empty string, this library is only offered for "
"selection if the current layout uses this technology.\n"
"\n"
"This attribute has been introduced in version 0.25."
"This attribute has been introduced in version 0.25. In version 0.27 this attribute is deprecated as "
"a library can now be associated with multiple technologies."
) +
gsi::method ("technology=", &db::Library::set_technology, gsi::arg ("technology"),
"@brief sets the name of the technology the library is associated with\n"
"\n"
"See \\technology for details. "
"This attribute has been introduced in version 0.25."
"This attribute has been introduced in version 0.25. In version 0.27, a library can be associated with "
"multiple technologies and this method will revert the selection to a single one. Passing an empty string "
"is equivalent to \\clear_technologies."
) +
gsi::method ("clear_technologies", &db::Library::clear_technologies,
"@brief Clears the list of technologies the library is associated with.\n"
"See also \\add_technology.\n"
"\n"
"This method has been introduced in version 0.27"
) +
gsi::method ("add_technology", &db::Library::add_technology, gsi::arg ("tech"),
"@brief Additionally associates the library with the given technology.\n"
"See also \\clear_technologies.\n"
"\n"
"This method has been introduced in version 0.27"
) +
gsi::method ("is_for_technology", &db::Library::is_for_technology, gsi::arg ("tech"),
"@brief Returns a value indicating whether the library is associated with the given technology.\n"
"This method has been introduced in version 0.27"
) +
gsi::method ("for_technologies", &db::Library::for_technologies,
"@brief Returns a value indicating whether the library is associated with any technology.\n"
"The method is equivalent to checking whether the \\technologies list is empty.\n"
"\n"
"This method has been introduced in version 0.27"
) +
gsi::method ("technologies", &db::Library::get_technologies,
"@brief Gets the list of technologies this library is associated with.\n"
"This method has been introduced in version 0.27"
) +
gsi::method ("layout_const", (const db::Layout &(db::Library::*)() const) &db::Library::layout,
"@brief The layout object where the cells reside that this library defines (const version)\n"

View File

@ -2639,8 +2639,16 @@ TEST(10_Antenna)
a5_5.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (500, 0)));
a5_15.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (501, 0)));
a5_29.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (502, 0)));
}
// with area factor
db::Region b5_5 = l2n.antenna_check (*rpoly, 2.0, 0.0, *rmetal2, 1.0, 1.0, 2.5);
db::Region b5_15 = l2n.antenna_check (*rpoly, 2.0, 0.0, *rmetal2, 1.0, 1.0, 7.5);
db::Region b5_29 = l2n.antenna_check (*rpoly, 2.0, 0.0, *rmetal2, 1.0, 1.0, 14.5);
b5_5.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (550, 0)));
b5_15.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (551, 0)));
b5_29.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (552, 0)));
}
{
db::LayoutToNetlist l2n (&dss);
@ -2672,6 +2680,15 @@ TEST(10_Antenna)
a6_3.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (600, 0)));
a6_5.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (601, 0)));
a6_9.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (602, 0)));
// with area factor
db::Region b6_3 = l2n.antenna_check (*rpoly, 1.0, 0.3, *rmetal2, 2.0, 0.0, 6);
db::Region b6_5 = l2n.antenna_check (*rpoly, 1.0, 0.3, *rmetal2, 2.0, 0.0, 10);
db::Region b6_9 = l2n.antenna_check (*rpoly, 1.0, 0.3, *rmetal2, 2.0, 0.0, 18);
b6_3.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (650, 0)));
b6_5.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (651, 0)));
b6_9.insert_into (&ly2, top2.cell_index (), ly2.insert_layer (db::LayerProperties (652, 0)));
}
std::string au = tl::testsrc ();

View File

@ -122,11 +122,15 @@ module DRC
end
def area_only(r)
DRCAreaAndPerimeter::new(r, 0.0)
DRCAreaAndPerimeter::new(r, 1.0, 0.0)
end
def perimeter_only(r, f)
DRCAreaAndPerimeter::new(r, 0.0, f)
end
def area_and_perimeter(r, f)
DRCAreaAndPerimeter::new(r, f)
DRCAreaAndPerimeter::new(r, 1.0, f)
end
# %DRC%

View File

@ -370,6 +370,18 @@ module DRC
# errors = antenna_check(gate, ...)
# @/code
#
# Finally there is also "perimeter_only". When using this
# specification with a thickness value, the area is computed
# from the perimeter alone:
#
# @code
# A(eff) = P * t
# @/code
#
# @code
# errors = antenna_check(perimeter_only(gate, 0.5), ...)
# @/code
#
# The error shapes produced by the antenna check are copies
# of the metal shapes on the metal layers of each network
# violating the antenna rule.
@ -377,11 +389,13 @@ module DRC
def antenna_check(agate, ametal, ratio, *diodes)
gate_perimeter_factor = 0.0
gate_area_factor = 1.0
if agate.is_a?(DRC::DRCLayer)
gate = agate
elsif agate.is_a?(DRC::DRCAreaAndPerimeter)
gate = agate.region
gate_perimeter_factor = agate.perimeter_factor
gate_area_factor = agate.area_factor
if ! gate.is_a?(DRC::DRCLayer)
raise("gate with area or area_and_perimeter: input argument must be a layer")
end
@ -392,11 +406,13 @@ module DRC
gate.requires_region("Netter#antenna_check (gate argument)")
metal_perimeter_factor = 0.0
metal_area_factor = 1.0
if ametal.is_a?(DRC::DRCLayer)
metal = ametal
elsif ametal.is_a?(DRC::DRCAreaAndPerimeter)
metal = ametal.region
metal_perimeter_factor = ametal.perimeter_factor
metal_area_factor = ametal.area_factor
if ! metal.is_a?(DRC::DRCLayer)
raise("metal with area or area_and_perimeter: input argument must be a layer")
end
@ -421,7 +437,7 @@ module DRC
end
end
DRC::DRCLayer::new(@engine, @engine._cmd(l2n_data, :antenna_check, gate.data, gate_perimeter_factor, metal.data, metal_perimeter_factor, ratio, dl))
DRC::DRCLayer::new(@engine, @engine._cmd(l2n_data, :antenna_check, gate.data, gate_area_factor, gate_perimeter_factor, metal.data, metal_area_factor, metal_perimeter_factor, ratio, dl))
end

View File

@ -117,10 +117,12 @@ module DRC
# optional perimeter factor
class DRCAreaAndPerimeter
attr_accessor :region
attr_accessor :area_factor
attr_accessor :perimeter_factor
def initialize(r, f)
def initialize(r, f, t)
self.region = r
self.perimeter_factor = f
self.area_factor = f
self.perimeter_factor = t
end
end

View File

@ -1,7 +1,8 @@
<ui version="4.0" >
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>EditorOptionsInst</class>
<widget class="QWidget" name="EditorOptionsInst" >
<property name="geometry" >
<widget class="QWidget" name="EditorOptionsInst">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
@ -9,52 +10,66 @@
<height>574</height>
</rect>
</property>
<property name="windowTitle" >
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QFrame" name="frame" >
<property name="frameShape" >
<widget class="QFrame" name="frame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow" >
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" >
<property name="margin" >
<number>0</number>
</property>
<property name="spacing" >
<layout class="QHBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="label_2" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text" >
<property name="text">
<string>Cell </string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="cell_le" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>0</vsizetype>
<widget class="QLineEdit" name="cell_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -62,47 +77,41 @@
</widget>
</item>
<item>
<widget class="QToolButton" name="browse_pb" >
<property name="text" >
<widget class="QToolButton" name="browse_pb">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_13" >
<property name="text" >
<widget class="QLabel" name="label_13">
<property name="text">
<string> Library </string>
</property>
</widget>
</item>
<item>
<widget class="lay::LibrarySelectionComboBox" name="lib_cbx" />
</item>
<item>
<spacer>
<property name="orientation" >
<enum>Qt::Horizontal</enum>
<widget class="lay::LibrarySelectionComboBox" name="lib_cbx">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeHint" >
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType" >
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>522</width>
<height>8</height>
@ -111,99 +120,111 @@
</spacer>
</item>
<item>
<widget class="QTabWidget" name="param_tab_widget" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>7</hsizetype>
<vsizetype>7</vsizetype>
<widget class="QTabWidget" name="param_tab_widget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="currentIndex" >
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab" >
<attribute name="title" >
<widget class="QWidget" name="tab">
<attribute name="title">
<string>Geometry</string>
</attribute>
<layout class="QVBoxLayout" >
<property name="margin" >
<number>9</number>
</property>
<property name="spacing" >
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Rotation / Scaling</string>
</property>
<layout class="QGridLayout" >
<property name="margin" >
<layout class="QGridLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="spacing" >
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="1" >
<widget class="QLineEdit" name="scale_le" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<item row="0" column="1">
<widget class="QLineEdit" name="scale_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="0" >
<widget class="QLabel" name="label_5" >
<property name="text" >
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Mirror </string>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>mirror_cbx</cstring>
</property>
</widget>
</item>
<item row="0" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Scaling factor (magnification)</string>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="QLineEdit" name="angle_le" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<item row="1" column="1">
<widget class="QLineEdit" name="angle_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="2" >
<widget class="QLabel" name="label_7" >
<property name="text" >
<item row="1" column="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string>degree</string>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Rotation angle</string>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2" >
<widget class="QCheckBox" name="mirror_cbx" >
<property name="text" >
<item row="2" column="1" colspan="2">
<widget class="QCheckBox" name="mirror_cbx">
<property name="text">
<string>(at X-axis before rotation)</string>
</property>
</widget>
@ -212,182 +233,177 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="array_grp" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>5</hsizetype>
<vsizetype>5</vsizetype>
<widget class="QGroupBox" name="array_grp">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title" >
<property name="title">
<string>Array Instance</string>
</property>
<property name="checkable" >
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QGridLayout" >
<property name="margin" >
<layout class="QGridLayout">
<property name="leftMargin">
<number>9</number>
</property>
<property name="spacing" >
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="2" column="0" >
<widget class="QLabel" name="label_16" >
<property name="text" >
<item row="2" column="0">
<widget class="QLabel" name="label_16">
<property name="text">
<string> Column vector (x,y)</string>
</property>
</widget>
</item>
<item row="2" column="2" >
<widget class="QLineEdit" name="column_x_le" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<item row="2" column="2">
<widget class="QLineEdit" name="column_x_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="QLabel" name="label_14" >
<property name="text" >
<item row="2" column="1">
<widget class="QLabel" name="label_14">
<property name="text">
<string>x =</string>
</property>
<property name="alignment" >
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="4" >
<widget class="QLineEdit" name="column_y_le" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<item row="2" column="4">
<widget class="QLineEdit" name="column_y_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="2" column="3" >
<widget class="QLabel" name="label_15" >
<property name="text" >
<item row="2" column="3">
<widget class="QLabel" name="label_15">
<property name="text">
<string>y =</string>
</property>
<property name="alignment" >
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="4" >
<widget class="QLineEdit" name="row_y_le" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<item row="1" column="4">
<widget class="QLineEdit" name="row_y_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="3" >
<widget class="QLabel" name="label_10" >
<property name="text" >
<item row="1" column="3">
<widget class="QLabel" name="label_10">
<property name="text">
<string>y =</string>
</property>
<property name="alignment" >
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="2" >
<widget class="QLineEdit" name="row_x_le" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<item row="1" column="2">
<widget class="QLineEdit" name="row_x_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="QLabel" name="label_11" >
<property name="text" >
<item row="1" column="1">
<widget class="QLabel" name="label_11">
<property name="text">
<string>x =</string>
</property>
<property name="alignment" >
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_9" >
<property name="text" >
<item row="1" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string> Row vector (x,y)</string>
</property>
</widget>
</item>
<item row="0" column="0" >
<widget class="QLabel" name="label_4" >
<property name="text" >
<item row="0" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string> Rows/Columns</string>
</property>
</widget>
</item>
<item row="0" column="3" >
<widget class="QLabel" name="label_8" >
<property name="text" >
<item row="0" column="3">
<widget class="QLabel" name="label_8">
<property name="text">
<string>columns =</string>
</property>
</widget>
</item>
<item row="0" column="4" >
<widget class="QLineEdit" name="columns_le" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<item row="0" column="4">
<widget class="QLineEdit" name="columns_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="1" >
<widget class="QLabel" name="label_6" >
<property name="text" >
<item row="0" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string>rows = </string>
</property>
</widget>
</item>
<item row="0" column="2" >
<widget class="QLineEdit" name="rows_le" >
<property name="sizePolicy" >
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<item row="0" column="2">
<widget class="QLineEdit" name="rows_le">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="0" colspan="5" >
<widget class="QLabel" name="label_12" >
<property name="text" >
<item row="3" column="0" colspan="5">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Warning: although row and column vectors can be arbitrary combination,
some design systems only accept orthogonal (rectangular) arrays.</string>
</property>
<property name="wordWrap" >
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
@ -397,10 +413,10 @@ some design systems only accept orthogonal (rectangular) arrays.</string>
</item>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
@ -410,26 +426,26 @@ some design systems only accept orthogonal (rectangular) arrays.</string>
</item>
</layout>
</widget>
<widget class="QWidget" name="pcell_tab" >
<attribute name="title" >
<widget class="QWidget" name="pcell_tab">
<attribute name="title">
<string>PCell</string>
</attribute>
</widget>
</widget>
</item>
<item>
<widget class="QCheckBox" name="place_origin_cb" >
<property name="text" >
<widget class="QCheckBox" name="place_origin_cb">
<property name="text">
<string>Place origin of cell</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation" >
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" >
<property name="sizeHint" stdset="0">
<size>
<width>50</width>
<height>8</height>
@ -462,8 +478,6 @@ some design systems only accept orthogonal (rectangular) arrays.</string>
<tabstop>column_y_le</tabstop>
<tabstop>place_origin_cb</tabstop>
</tabstops>
<resources>
<include location="layResources.qrc" />
</resources>
<resources/>
<connections/>
</ui>

View File

@ -17,7 +17,16 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
@ -32,7 +41,16 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -84,7 +102,16 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -119,20 +146,14 @@
</widget>
</item>
<item>
<widget class="lay::LibrarySelectionComboBox" name="lib_cbx"/>
</item>
<item>
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
<widget class="lay::LibrarySelectionComboBox" name="lib_cbx">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</widget>
</item>
</layout>
</widget>
@ -178,7 +199,16 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
@ -190,7 +220,16 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -265,7 +304,16 @@
<string>Position / Rotation / Scaling</string>
</property>
<layout class="QGridLayout">
<property name="margin">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<property name="spacing">
@ -393,7 +441,16 @@
<bool>true</bool>
</property>
<layout class="QGridLayout">
<property name="margin">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<property name="spacing">
@ -629,7 +686,16 @@ some design systems only accept orthogonal (rectangular) arrays.</string>
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>

View File

@ -167,6 +167,18 @@ errors = antenna_check(area_and_perimeter(gate, 0.0), ...)
errors = antenna_check(gate, ...)
</pre>
</p><p>
Finally there is also "perimeter_only". When using this
specification with a thickness value, the area is computed
from the perimeter alone:
</p><p>
<pre>
A(eff) = P * t
</pre>
</p><p>
<pre>
errors = antenna_check(perimeter_only(gate, 0.5), ...)
</pre>
</p><p>
The error shapes produced by the antenna check are copies
of the metal shapes on the metal layers of each network
violating the antenna rule.

View File

@ -205,7 +205,7 @@ LibraryController::sync_files ()
}
}
tl::log << "Registering as '" << lib->get_name () << "' for tech '" << lib->get_technology () << "'";
tl::log << "Registering as '" << lib->get_name () << "' for tech '" << p->second << "'";
new_lib_files.insert (std::make_pair (lib_path, std::make_pair (lib->get_name (), fi.lastModified ())));
db::LibraryManager::instance ().register_lib (lib.release ());

View File

@ -135,7 +135,7 @@ TechBaseEditorPage::setup ()
for (db::LibraryManager::iterator l = db::LibraryManager::instance ().begin (); l != db::LibraryManager::instance ().end (); ++l) {
const db::Library *lib = db::LibraryManager::instance ().lib (l->second);
if (lib->get_technology () == tech ()->name ()) {
if (lib->is_for_technology (tech ()->name ())) {
std::string text = lib->get_name ();
if (! lib->get_description ().empty ()) {
text += " - " + lib->get_description ();

View File

@ -213,6 +213,7 @@ HierarchyControlPanel::HierarchyControlPanel (lay::LayoutView *view, QWidget *pa
mp_selector = new QComboBox (this);
mp_selector->setObjectName (QString::fromUtf8 ("cellview_selection"));
mp_selector->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Fixed);
ly->addWidget (mp_selector);
mp_search_frame = new QFrame (this);

View File

@ -4739,6 +4739,8 @@ LayoutView::active_library_changed (int /*index*/)
void
LayoutView::cellview_changed (unsigned int index)
{
mp_hierarchy_panel->do_update_content (index);
cellview_changed_event (index);
if (m_title.empty ()) {

View File

@ -210,7 +210,8 @@ LibrariesView::LibrariesView (lay::LayoutView *view, QWidget *parent, const char
ly->setContentsMargins (0, 0, 0, 0);
mp_selector = new QComboBox (this);
mp_selector->setObjectName (QString::fromUtf8 ("cellview_selection"));
mp_selector->setObjectName (QString::fromUtf8 ("library_selection"));
mp_selector->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Fixed);
ly->addWidget (mp_selector);
mp_search_frame = new QFrame (this);
@ -771,9 +772,10 @@ LibrariesView::display_string (int n) const
if (! lib->get_description ().empty ()) {
text += " - " + lib->get_description ();
}
if (! lib->get_technology ().empty ()) {
if (lib->for_technologies ()) {
text += " ";
text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (lib->get_technology ())));
std::string tn = tl::join (std::vector<std::string> (lib->get_technologies ().begin (), lib->get_technologies ().end ()), ",");
text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (tn)));
}
return text;
}

View File

@ -600,15 +600,16 @@ LibrarySelectionComboBox::update_list ()
for (db::LibraryManager::iterator l = db::LibraryManager::instance ().begin (); l != db::LibraryManager::instance ().end (); ++l) {
db::Library *lib = db::LibraryManager::instance ().lib (l->second);
if (! m_tech_set || lib->get_technology ().empty () || m_tech == lib->get_technology ()) {
if (! m_tech_set || !lib->for_technologies ()|| lib->is_for_technology (m_tech)) {
std::string item_text = lib->get_name ();
if (! lib->get_description ().empty ()) {
item_text += " - " + lib->get_description ();
}
if (m_tech_set && !lib->get_technology ().empty ()) {
if (m_tech_set && lib->for_technologies ()) {
item_text += " ";
item_text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (lib->get_technology ())));
std::string tn = tl::join (std::vector<std::string> (lib->get_technologies ().begin (), lib->get_technologies ().end ()), ",");
item_text += tl::to_string (QObject::tr ("[Technology %1]").arg (tl::to_qstring (tn)));
}
addItem (tl::to_qstring (item_text), QVariant ((unsigned int) lib->get_id ()));

View File

@ -165,23 +165,18 @@ CIFWriter::write (db::Layout &layout, tl::OutputStream &stream, const db::SaveLa
}
double a = t.angle();
while (a < 0) {
a += 360.0;
}
double ya = 0.0, xa = 0.0;
if (a < 45 || a > 315) {
xa = 1.0;
ya = tan(a / 180.0 * M_PI);
} else if (a < 135) {
xa = 1.0 / tan(a / 180.0 * M_PI);
ya = 1.0;
} else if (a < 225) {
xa = -1.0;
ya = tan(a / 180.0 * M_PI);
double xa = cos(a / 180.0 * M_PI);
double ya = sin(a / 180.0 * M_PI);
// normalize xa or ya whichever is better
double n;
if (fabs (xa) >= M_SQRT1_2) {
n = 1.0 / fabs (xa);
} else {
xa = 1.0 / tan(a / 180.0 * M_PI);
ya = -1.0;
}
n = 1.0 / fabs (ya);
}
xa *= n;
ya *= n;
// TODO: that can be done smarter ...
for (int n = 0; n < 20 && (fabs (xa - floor (0.5 + xa)) > 1e-3 || fabs (ya - floor (0.5 + ya)) > 1e-3); ++n) {

View File

@ -200,3 +200,9 @@ TEST(rot_instances)
{
run_test (_this, tl::testsrc (), "issue_568.cif", "issue_568_au.gds");
}
// Issue #578
TEST(rot_instances2)
{
run_test (_this, tl::testsrc (), "issue_578.cif", "issue_578_au.gds");
}

View File

@ -104,6 +104,7 @@ RUBYTEST (dbGlyphs, "dbGlyphs.rb")
RUBYTEST (dbInstanceTest, "dbInstanceTest.rb")
RUBYTEST (dbInstElementTest, "dbInstElementTest.rb")
RUBYTEST (dbLayerMapping, "dbLayerMapping.rb")
RUBYTEST (dbLibrary, "dbLibrary.rb")
RUBYTEST (dbLayout, "dbLayout.rb")
RUBYTEST (dbLayoutTest, "dbLayoutTest.rb")
RUBYTEST (dbLayoutDiff, "dbLayoutDiff.rb")

View File

@ -83,7 +83,7 @@ public:
std::vector <db::DPoint> points;
std::vector <db::DEdge> edges;
ex = tl::Extractor (m_input_stream.get_line ().c_str ());
ex = tl::Extractor (get_line ().c_str ());
ex.read (s, " ");
ex.read (res);
@ -99,7 +99,7 @@ public:
std::string cat_name;
id_type waived_tag_id = db.tags ().tag ("waived").id ();
while (! m_input_stream.at_end ()) {
while (! at_end ()) {
// TODO: check if this is correct: when a new category is started the
// cell name is reset. Any shape not having a specific cell will go into the
@ -108,7 +108,7 @@ public:
// Read the category name unless we have some already (that we got when parsing the shapes).
if (cat_name.empty ()) {
ex = tl::Extractor (m_input_stream.get_line ().c_str ());
ex = tl::Extractor (get_line ().c_str ());
const char *start = ex.skip ();
if (! *start) {
break;
@ -127,11 +127,11 @@ public:
Category *cath = db.create_category (cat_name);
cat_name.clear ();
if (m_input_stream.at_end ()) {
if (at_end ()) {
error (tl::to_string (tr ("Unexpected end of file")));
}
ex = tl::Extractor (m_input_stream.get_line ().c_str ());
ex = tl::Extractor (get_line ().c_str ());
size_t n1, n2, n3;
ex.read (n1);
ex.read (n2);
@ -142,11 +142,11 @@ public:
std::string desc;
for (size_t i = 0; i < n3; ++i) {
if (m_input_stream.at_end ()) {
if (at_end ()) {
error (tl::to_string (tr ("Unexpected end of file")));
}
std::string l = m_input_stream.get_line ();
std::string l = get_line ();
if (l.size () > 3 && l[0] == 'W' && l[1] == 'E' && isdigit (l[2])) {
size_t n = 0;
@ -178,12 +178,12 @@ public:
bool waived = (w != waivers.end ());
// TODO: add waiver string somehow ...
if (m_input_stream.at_end ()) {
if (at_end ()) {
warn (tl::to_string (tr ("Unexpected end of file before the specified number of shapes was read - stopping.")));
break;
}
s = m_input_stream.get_line ();
s = get_line ();
ex = tl::Extractor (s.c_str ());
@ -221,11 +221,11 @@ public:
while (true) {
if (m_input_stream.at_end ()) {
if (at_end ()) {
error (tl::to_string (tr ("Unexpected end of file")));
}
ex = tl::Extractor (m_input_stream.get_line ().c_str ());
ex = tl::Extractor (get_line ().c_str ());
char c = *ex.skip ();
if (isalpha (c)) {
@ -340,11 +340,11 @@ public:
if (point > 0) {
if (m_input_stream.at_end ()) {
if (at_end ()) {
error (tl::to_string (tr ("Unexpected end of file")));
}
ex = tl::Extractor (m_input_stream.get_line ().c_str ());
ex = tl::Extractor (get_line ().c_str ());
}
@ -368,11 +368,11 @@ public:
if (point > 0) {
if (m_input_stream.at_end ()) {
if (at_end ()) {
error (tl::to_string (tr ("Unexpected end of file")));
}
ex = tl::Extractor (m_input_stream.get_line ().c_str ());
ex = tl::Extractor (get_line ().c_str ());
}
@ -424,6 +424,26 @@ public:
private:
tl::TextInputStream m_input_stream;
tl::AbsoluteProgress m_progress;
std::string m_line;
bool at_end ()
{
return m_input_stream.at_end ();
}
const std::string &get_line ()
{
m_line.clear ();
while (! m_input_stream.at_end ()) {
m_line = m_input_stream.get_line ();
// skip lines starting with "//" (#522)
if (m_line.size () < 2 || m_line[0] != '/' || m_line[1] != '/') {
break;
}
m_line.clear ();
}
return m_line;
}
void warn (const std::string &msg)
{

View File

@ -20,8 +20,6 @@
*/
#include "rdb.h"
#include "tlUnitTest.h"
#include "dbBox.h"

View File

@ -0,0 +1,78 @@
/*
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 "rdb.h"
#include "rdbReader.h"
#include "tlUnitTest.h"
#include "tlFileUtils.h"
#include "tlLog.h"
void run_rve_test (tl::TestBase *_this, const std::string &fn_rve, const std::string &fn_au)
{
rdb::Database db;
{
tl::InputFile input (tl::testsrc_private () + "/testdata/rve/" + fn_rve);
tl::InputStream is (input);
rdb::Reader reader (is);
reader.read (db);
}
std::string tmp = _this->tmp_file ();
db.save (tmp);
std::string au_path = tl::absolute_file_path (tl::testsrc_private () + "/testdata/rve/" + fn_au);
std::string txt, au_txt;
try {
tl::InputFile input (au_path);
tl::InputStream is (input);
tl::TextInputStream ts (is);
au_txt = ts.read_all ();
} catch (tl::Exception &ex) {
tl::error << ex.msg ();
}
{
tl::InputFile input (tmp);
tl::InputStream is (input);
tl::TextInputStream ts (is);
txt = ts.read_all ();
}
if (au_txt != txt) {
tl::error << "Golden and actual data differs:";
tl::error << " cp " << tmp << " " << au_path;
}
EXPECT_EQ (au_txt == txt, true);
}
TEST(1)
{
run_rve_test (_this, "rve1.db", "rve1_au.txt");
}
TEST(2)
{
run_rve_test (_this, "rve2.db", "rve2_au.txt");
}

View File

@ -8,6 +8,7 @@ include($$PWD/../../lib_ut.pri)
SOURCES = \
rdb.cc \
rdbRVEReaderTests.cc
INCLUDEPATH += $$RDB_INC $$TL_INC $$DB_INC $$GSI_INC
DEPENDPATH += $$RDB_INC $$TL_INC $$DB_INC $$GSI_INC

Binary file not shown.

18
testdata/cif/issue_578.cif vendored Normal file
View File

@ -0,0 +1,18 @@
(CIF file written 2020-06-04 16:17:46 by KLayout);
DS 1 1 10;
9 F;
L L1D0;
P 0,0 0,7000 4000,7000 4000,6000 1000,6000 1000,4000 2000,4000 2000,3000 1000,3000 1000,0;
DF;
DS 2 1 10;
9 ALL;
C1 R1,0 T0,0;
C1 R1,1 T0,0;
C1 R0,1 T0,0;
C1 R-1,-1 T0,0;
C1 R-1,0 T0,0;
C1 R-1,1 T0,0;
C1 R0,-1 T0,0;
C1 R1,-1 T0,0;
DF;
E

BIN
testdata/cif/issue_578_au.gds vendored Normal file

Binary file not shown.

View File

@ -52,3 +52,10 @@ antenna_check(area_and_perimeter(gate, 70.nm), area_only(metal2), 5.0, diode).ou
antenna_check(area_and_perimeter(gate, 0.07), area_only(metal2), 10.0, diode).output(410)
antenna_check(area_and_perimeter(gate, 0.07), area_only(metal2), 50.0, diode).output(450)
antenna_check(perimeter_only(gate, 0.07.um), area_only(metal2), 1.0, diode).output(501)
antenna_check(perimeter_only(gate, 0.07.um), area_only(metal2), 1.5, diode).output(502)
antenna_check(perimeter_only(gate, 0.07.um), area_only(metal2), 2.0, diode).output(503)
antenna_check(perimeter_only(gate, 70.nm), area_only(metal2), 5.0, diode).output(505)
antenna_check(perimeter_only(gate, 0.07), area_only(metal2), 10.0, diode).output(510)
antenna_check(perimeter_only(gate, 0.07), area_only(metal2), 50.0, diode).output(550)

Binary file not shown.

View File

@ -798,6 +798,15 @@ END
assert_equal((a5_15.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(501, 0)))).to_s, "")
assert_equal((a5_29.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(502, 0)))).to_s, "")
b5_5 = l2n.antenna_check(rpoly, 2.0, 0.0, rmetal2, 1.0, 1.0, 2.5)
b5_15 = l2n.antenna_check(rpoly, 2.0, 0.0, rmetal2, 1.0, 1.0, 7.5)
b5_29 = l2n.antenna_check(rpoly, 2.0, 0.0, rmetal2, 1.0, 1.0, 14.5)
# Note: flatten.merged performs some normalization
assert_equal((b5_5.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(500, 0)))).to_s, "")
assert_equal((b5_15.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(501, 0)))).to_s, "")
assert_equal((b5_29.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(502, 0)))).to_s, "")
# --- antenna check gate perimeter included
l2n._destroy
@ -830,6 +839,15 @@ END
assert_equal((a6_5.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(601, 0)))).to_s, "")
assert_equal((a6_9.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(602, 0)))).to_s, "")
b6_3 = l2n.antenna_check(rpoly, 1.0, 0.3, rmetal2, 2.0, 0.0, 6)
b6_5 = l2n.antenna_check(rpoly, 1.0, 0.3, rmetal2, 2.0, 0.0, 10)
b6_9 = l2n.antenna_check(rpoly, 1.0, 0.3, rmetal2, 2.0, 0.0, 18)
# Note: flatten.merged performs some normalization
assert_equal((b6_3.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(600, 0)))).to_s, "")
assert_equal((b6_5.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(601, 0)))).to_s, "")
assert_equal((b6_9.flatten ^ RBA::Region::new(ly_au.top_cell.begin_shapes_rec(ly_au.layer(602, 0)))).to_s, "")
end
end

93
testdata/ruby/dbLibrary.rb vendored Normal file
View File

@ -0,0 +1,93 @@
# encoding: UTF-8
# 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
if !$:.member?(File::dirname($0))
$:.push(File::dirname($0))
end
load("test_prologue.rb")
class DBLibrary_TestClass < TestBase
def test_1_registration
lib = RBA::Library::new
assert_equal(lib.name, "")
assert_equal(lib.id, 0)
lib.register("RBA-unit-test")
assert_equal(lib.name, "RBA-unit-test")
assert_equal(lib.id != 0, true)
assert_equal(RBA::Library::library_names.member?("RBA-unit-test"), true)
assert_equal(RBA::Library::library_by_name("RBA-unit-test").id, lib.id)
lib.delete
assert_equal(RBA::Library::library_by_name("RBA-unit-test"), nil)
end
def test_2_attributes
lib = RBA::Library::new
lib.description = "42 is the answer"
assert_equal(lib.description, "42 is the answer")
assert_equal(lib.is_for_technology("X"), false)
assert_equal(lib.technologies, [])
assert_equal(lib.for_technologies, false)
lib.technology = "X"
assert_equal(lib.is_for_technology("X"), true)
assert_equal(lib.technologies, ["X"])
assert_equal(lib.for_technologies, true)
lib.technology = ""
assert_equal(lib.is_for_technology("X"), false)
assert_equal(lib.technologies, [])
assert_equal(lib.for_technologies, false)
lib.add_technology("Y")
assert_equal(lib.is_for_technology("X"), false)
assert_equal(lib.is_for_technology("Y"), true)
assert_equal(lib.technologies, ["Y"])
assert_equal(lib.for_technologies, true)
lib.clear_technologies
assert_equal(lib.is_for_technology("Y"), false)
assert_equal(lib.technologies, [])
assert_equal(lib.for_technologies, false)
end
def test_3_layout
lib = RBA::Library::new
lib.layout.create_cell("X")
assert_equal(lib.layout.top_cell.name, "X")
end
end
load("test_epilogue.rb")