Added "device_scaling" to LVS

Plus: added some missing files

Implementation details:
* scaling factor was introduced in DeviceExtractor::extract
* for easy implementation this is available in "sdbu"
* "sdbu" is made available in GSI
* to test this, the db::compare_netlist had to be enhanced to
  exactly check device parameters
* enhancement of LVS script framework and doc updates
This commit is contained in:
Matthias Koefferlein
2019-07-24 00:16:47 +02:00
parent 5dabd6093d
commit afb5cea576
27 changed files with 2944 additions and 59 deletions
+35
View File
@@ -97,6 +97,41 @@ EqualDeviceParameters &EqualDeviceParameters::operator+= (const EqualDeviceParam
return *this;
}
// --------------------------------------------------------------------------------
// AllDeviceParametersAreEqual class implementation
AllDeviceParametersAreEqual::AllDeviceParametersAreEqual (double relative)
: m_relative (relative)
{
// .. nothing yet ..
}
bool AllDeviceParametersAreEqual::less (const db::Device &a, const db::Device &b) const
{
const std::vector<db::DeviceParameterDefinition> &parameters = a.device_class ()->parameter_definitions ();
for (std::vector<db::DeviceParameterDefinition>::const_iterator c = parameters.begin (); c != parameters.end (); ++c) {
int cmp = compare_parameters (a.parameter_value (c->id ()), b.parameter_value (c->id ()), 0.0, m_relative);
if (cmp != 0) {
return cmp < 0;
}
}
return false;
}
bool AllDeviceParametersAreEqual::equal (const db::Device &a, const db::Device &b) const
{
const std::vector<db::DeviceParameterDefinition> &parameters = a.device_class ()->parameter_definitions ();
for (std::vector<db::DeviceParameterDefinition>::const_iterator c = parameters.begin (); c != parameters.end (); ++c) {
int cmp = compare_parameters (a.parameter_value (c->id ()), b.parameter_value (c->id ()), 0.0, m_relative);
if (cmp != 0) {
return false;
}
}
return true;
}
// --------------------------------------------------------------------------------
// DeviceClass class implementation
+16
View File
@@ -286,6 +286,22 @@ private:
std::vector<std::pair<size_t, std::pair<double, double> > > m_compare_set;
};
/**
* @brief A parameter compare delegate that compares all parameters in a relative fashion
*/
class DB_PUBLIC AllDeviceParametersAreEqual
: public DeviceParameterCompareDelegate
{
public:
AllDeviceParametersAreEqual (double relative);
virtual bool less (const db::Device &a, const db::Device &b) const;
virtual bool equal (const db::Device &a, const db::Device &b) const;
private:
double m_relative;
};
/**
* @brief A device class
*
+14 -4
View File
@@ -58,7 +58,7 @@ LayoutToNetlist::LayoutToNetlist (const db::RecursiveShapeIterator &iter)
}
LayoutToNetlist::LayoutToNetlist (db::DeepShapeStore *dss, unsigned int layout_index)
: mp_dss (dss), m_layout_index (layout_index), m_netlist_extracted (false), m_is_flat (false)
: mp_dss (dss), m_layout_index (layout_index), m_netlist_extracted (false), m_is_flat (false), m_device_scaling (1.0)
{
if (dss->is_valid_layout_index (m_layout_index)) {
m_iter = db::RecursiveShapeIterator (dss->layout (m_layout_index), dss->initial_cell (m_layout_index), std::set<unsigned int> ());
@@ -66,7 +66,7 @@ LayoutToNetlist::LayoutToNetlist (db::DeepShapeStore *dss, unsigned int layout_i
}
LayoutToNetlist::LayoutToNetlist (const std::string &topcell_name, double dbu)
: m_iter (), m_netlist_extracted (false), m_is_flat (true)
: m_iter (), m_netlist_extracted (false), m_is_flat (true), m_device_scaling (1.0)
{
mp_internal_dss.reset (new db::DeepShapeStore (topcell_name, dbu));
mp_dss.reset (mp_internal_dss.get ());
@@ -77,7 +77,7 @@ LayoutToNetlist::LayoutToNetlist (const std::string &topcell_name, double dbu)
LayoutToNetlist::LayoutToNetlist ()
: m_iter (), mp_internal_dss (new db::DeepShapeStore ()), mp_dss (mp_internal_dss.get ()), m_layout_index (0),
m_netlist_extracted (false), m_is_flat (false)
m_netlist_extracted (false), m_is_flat (false), m_device_scaling (1.0)
{
init ();
}
@@ -136,6 +136,16 @@ size_t LayoutToNetlist::max_vertex_count () const
return dss ().max_vertex_count ();
}
void LayoutToNetlist::set_device_scaling (double s)
{
m_device_scaling = s;
}
double LayoutToNetlist::device_scaling () const
{
return m_device_scaling;
}
db::Region *LayoutToNetlist::make_layer (const std::string &n)
{
db::RecursiveShapeIterator si (m_iter);
@@ -195,7 +205,7 @@ void LayoutToNetlist::extract_devices (db::NetlistDeviceExtractor &extractor, co
if (! mp_netlist.get ()) {
mp_netlist.reset (new db::Netlist ());
}
extractor.extract (dss (), m_layout_index, layers, *mp_netlist, m_net_clusters);
extractor.extract (dss (), m_layout_index, layers, *mp_netlist, m_net_clusters, m_device_scaling);
}
void LayoutToNetlist::connect (const db::Region &l)
+13
View File
@@ -220,6 +220,18 @@ public:
*/
size_t max_vertex_count () const;
/**
* @brief Sets the device scaling factor
* This factor will scale the physical properties of the extracted devices
* accordingly. The scale factor applies an isotropic shrink (<1) or expansion (>1).
*/
void set_device_scaling (double s);
/**
* @brief Gets the device scaling factor
*/
double device_scaling () const;
/**
* @brief Register a layer under the given name
* This is a formal name for the layer. Using a name or layer properties
@@ -711,6 +723,7 @@ private:
std::map<unsigned int, std::string> m_name_of_layer;
bool m_netlist_extracted;
bool m_is_flat;
double m_device_scaling;
db::DeepLayer m_dummy_layer;
struct CellReuseTableKey
+8 -6
View File
@@ -75,7 +75,7 @@ std::string NetlistDeviceExtractorError::to_string () const
// NetlistDeviceExtractor implementation
NetlistDeviceExtractor::NetlistDeviceExtractor (const std::string &name)
: mp_layout (0), m_cell_index (0), mp_circuit (0)
: mp_layout (0), m_cell_index (0), m_device_scaling (1.0), mp_circuit (0)
{
m_name = name;
m_terminal_id_propname_id = 0;
@@ -110,6 +110,7 @@ void NetlistDeviceExtractor::initialize (db::Netlist *nl)
{
m_layer_definitions.clear ();
mp_device_class = 0;
m_device_scaling = 1.0;
m_terminal_id_propname_id = 0;
m_device_id_propname_id = 0;
m_device_class_propname_id = 0;
@@ -123,7 +124,7 @@ static void insert_into_region (const db::PolygonRef &s, const db::ICplxTrans &t
region.insert (s.obj ().transformed (tr * db::ICplxTrans (s.trans ())));
}
void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, unsigned int layout_index, const NetlistDeviceExtractor::input_layers &layer_map, db::Netlist &nl, hier_clusters_type &clusters)
void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, unsigned int layout_index, const NetlistDeviceExtractor::input_layers &layer_map, db::Netlist &nl, hier_clusters_type &clusters, double device_scaling)
{
initialize (&nl);
@@ -183,13 +184,13 @@ void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, unsigned int layo
}
extract_without_initialize (dss.layout (layout_index), dss.initial_cell (layout_index), clusters, layers);
extract_without_initialize (dss.layout (layout_index), dss.initial_cell (layout_index), clusters, layers, device_scaling);
}
void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const std::vector<unsigned int> &layers, db::Netlist *nl, hier_clusters_type &clusters)
void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const std::vector<unsigned int> &layers, db::Netlist *nl, hier_clusters_type &clusters, double device_scaling)
{
initialize (nl);
extract_without_initialize (layout, cell, clusters, layers);
extract_without_initialize (layout, cell, clusters, layers, device_scaling);
}
namespace {
@@ -202,7 +203,7 @@ struct ExtractorCacheValueType {
}
void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers)
void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers, double device_scaling)
{
tl_assert (layers.size () == m_layer_definitions.size ());
@@ -212,6 +213,7 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db:
mp_layout = &layout;
m_layers = layers;
mp_clusters = &clusters;
m_device_scaling = device_scaling;
// terminal properties are kept in a property with the terminal_property_name name
m_terminal_id_propname_id = mp_layout->properties_repository ().prop_name_id (terminal_id_property_name ());
+14 -3
View File
@@ -263,7 +263,7 @@ public:
*
* NOTE: The extractor expects "PolygonRef" type layers.
*/
void extract (Layout &layout, Cell &cell, const std::vector<unsigned int> &layers, Netlist *netlist, hier_clusters_type &clusters);
void extract (Layout &layout, Cell &cell, const std::vector<unsigned int> &layers, Netlist *netlist, hier_clusters_type &clusters, double device_scaling = 1.0);
/**
* @brief Extracts the devices from a list of regions
@@ -272,7 +272,7 @@ public:
* named regions for input. These regions need to be of deep region type and
* originate from the same layout than the DeepShapeStore.
*/
void extract (DeepShapeStore &dss, unsigned int layout_index, const input_layers &layers, Netlist &netlist, hier_clusters_type &clusters);
void extract (DeepShapeStore &dss, unsigned int layout_index, const input_layers &layers, Netlist &netlist, hier_clusters_type &clusters, double device_scaling = 1.0);
/**
* @brief Gets the error iterator, begin
@@ -416,6 +416,16 @@ public:
return mp_layout->dbu ();
}
/**
* @brief Gets the scaled database unit
* Use this unit to compute device properties. It is the database unit multiplied with the
* device scaling factor.
*/
double sdbu () const
{
return m_device_scaling * mp_layout->dbu ();
}
/**
* @brief Gets the layout the shapes are taken from
* NOTE: this method is provided for testing purposes mainly.
@@ -523,6 +533,7 @@ private:
db::properties_id_type m_terminal_id_propname_id, m_device_id_propname_id, m_device_class_propname_id;
hier_clusters_type *mp_clusters;
db::cell_index_type m_cell_index;
double m_device_scaling;
db::Circuit *mp_circuit;
db::DeviceClass *mp_device_class;
std::string m_name;
@@ -542,7 +553,7 @@ private:
*/
void initialize (db::Netlist *nl);
void extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers);
void extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers, double device_scaling);
void push_new_devices (const Vector &disp_cache);
void push_cached_devices (const tl::vector<Device *> &cached_devices, const db::Vector &disp_cache, const db::Vector &new_disp);
};
+18 -18
View File
@@ -112,8 +112,8 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
device->set_trans (db::DCplxTrans ((p->box ().center () - db::Point ()) * dbu ()));
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, dbu () * edges.length () * 0.5);
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, dbu () * (p->perimeter () - edges.length ()) * 0.5);
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, sdbu () * edges.length () * 0.5);
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, sdbu () * (p->perimeter () - edges.length ()) * 0.5);
int diff_index = 0;
for (db::Region::const_iterator d = rdiff2gate.begin (); !d.at_end () && diff_index < 2; ++d, ++diff_index) {
@@ -123,8 +123,8 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
size_t n = rgates.selected_interacting (db::Region (*d)).size ();
tl_assert (n > 0);
device->set_parameter_value (diff_index == 0 ? db::DeviceClassMOS3Transistor::param_id_AS : db::DeviceClassMOS3Transistor::param_id_AD, dbu () * dbu () * d->area () / double (n));
device->set_parameter_value (diff_index == 0 ? db::DeviceClassMOS3Transistor::param_id_PS : db::DeviceClassMOS3Transistor::param_id_PD, dbu () * d->perimeter () / double (n));
device->set_parameter_value (diff_index == 0 ? db::DeviceClassMOS3Transistor::param_id_AS : db::DeviceClassMOS3Transistor::param_id_AD, sdbu () * sdbu () * d->area () / double (n));
device->set_parameter_value (diff_index == 0 ? db::DeviceClassMOS3Transistor::param_id_PS : db::DeviceClassMOS3Transistor::param_id_PD, sdbu () * d->perimeter () / double (n));
unsigned int sd_index = diff_index == 0 ? source_terminal_geometry_index : drain_terminal_geometry_index;
define_terminal (device, diff_index == 0 ? db::DeviceClassMOS3Transistor::terminal_id_S : db::DeviceClassMOS3Transistor::terminal_id_D, sd_index, *d);
@@ -262,10 +262,10 @@ void NetlistDeviceExtractorResistor::extract_devices (const std::vector<db::Regi
}
device->set_parameter_value (db::DeviceClassResistor::param_id_R, m_sheet_rho * double (length) / double (width));
device->set_parameter_value (db::DeviceClassResistor::param_id_L, dbu () * length);
device->set_parameter_value (db::DeviceClassResistor::param_id_W, dbu () * width);
device->set_parameter_value (db::DeviceClassResistor::param_id_A, dbu () * dbu () * p->area ());
device->set_parameter_value (db::DeviceClassResistor::param_id_P, dbu () * p->perimeter ());
device->set_parameter_value (db::DeviceClassResistor::param_id_L, sdbu () * length);
device->set_parameter_value (db::DeviceClassResistor::param_id_W, sdbu () * width);
device->set_parameter_value (db::DeviceClassResistor::param_id_A, sdbu () * sdbu () * p->area ());
device->set_parameter_value (db::DeviceClassResistor::param_id_P, sdbu () * p->perimeter ());
int cont_index = 0;
for (db::Region::const_iterator d = contacts_per_res.begin (); !d.at_end () && cont_index < 2; ++d, ++cont_index) {
@@ -366,11 +366,11 @@ void NetlistDeviceExtractorCapacitor::extract_devices (const std::vector<db::Reg
device->set_trans (db::DCplxTrans ((p->box ().center () - db::Point ()) * dbu ()));
double area = p->area () * dbu () * dbu ();
double area = p->area () * sdbu () * sdbu ();
device->set_parameter_value (db::DeviceClassCapacitor::param_id_C, m_area_cap * area);
device->set_parameter_value (db::DeviceClassCapacitor::param_id_A, area);
device->set_parameter_value (db::DeviceClassCapacitor::param_id_P, dbu () * p->perimeter ());
device->set_parameter_value (db::DeviceClassCapacitor::param_id_P, sdbu () * p->perimeter ());
define_terminal (device, db::DeviceClassCapacitor::terminal_id_A, a_terminal_geometry_index, *p);
define_terminal (device, db::DeviceClassCapacitor::terminal_id_B, b_terminal_geometry_index, *p);
@@ -498,11 +498,11 @@ void NetlistDeviceExtractorBJT3Transistor::extract_devices (const std::vector<db
// emitter wins over collector for the collector contact
rcollector -= remitter2base;
double ab = dbu () * dbu () * p->area ();
double pb = dbu () * p->perimeter ();
double ab = sdbu () * sdbu () * p->area ();
double pb = sdbu () * p->perimeter ();
double ac = dbu () * dbu () * rcollector2base.area ();
double pc = dbu () * rcollector2base.perimeter ();
double ac = sdbu () * sdbu () * rcollector2base.area ();
double pc = sdbu () * rcollector2base.perimeter ();
for (db::Region::const_iterator pe = remitter2base.begin_merged (); !pe.at_end (); ++pe) {
@@ -512,8 +512,8 @@ void NetlistDeviceExtractorBJT3Transistor::extract_devices (const std::vector<db
device->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_NE, 1.0);
device->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_AE, dbu () * dbu () * pe->area ());
device->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_PE, dbu () * pe->perimeter ());
device->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_AE, sdbu () * sdbu () * pe->area ());
device->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_PE, sdbu () * pe->perimeter ());
device->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_AB, ab);
device->set_parameter_value (db::DeviceClassBJT3Transistor::param_id_PB, pb);
@@ -629,10 +629,10 @@ void NetlistDeviceExtractorDiode::extract_devices (const std::vector<db::Region>
device->set_trans (db::DCplxTrans ((p->box ().center () - db::Point ()) * dbu ()));
double area = p->area () * dbu () * dbu ();
double area = p->area () * sdbu () * sdbu ();
device->set_parameter_value (db::DeviceClassDiode::param_id_A, area);
device->set_parameter_value (db::DeviceClassDiode::param_id_P, dbu () * p->perimeter ());
device->set_parameter_value (db::DeviceClassDiode::param_id_P, sdbu () * p->perimeter ());
define_terminal (device, db::DeviceClassDiode::terminal_id_A, a_terminal_geometry_index, *p);
define_terminal (device, db::DeviceClassDiode::terminal_id_C, c_terminal_geometry_index, *p);
+16 -14
View File
@@ -291,7 +291,7 @@ private:
}
};
void DB_PUBLIC compare_netlist (tl::TestBase *_this, const db::Netlist &netlist, const std::string &au_nl_string)
void DB_PUBLIC compare_netlist (tl::TestBase *_this, const db::Netlist &netlist, const std::string &au_nl_string, bool exact_parameter_match)
{
db::Netlist au_nl;
for (db::Netlist::const_device_class_iterator d = netlist.begin_device_classes (); d != netlist.end_device_classes (); ++d) {
@@ -300,27 +300,29 @@ void DB_PUBLIC compare_netlist (tl::TestBase *_this, const db::Netlist &netlist,
au_nl.from_string (au_nl_string);
db::NetlistComparer comp (0);
if (! comp.compare (&netlist, &au_nl)) {
_this->raise ("Compare failed - see log for details.\n\nActual:\n" + netlist.to_string () + "\nGolden:\n" + au_nl_string);
// Compare once again - this time with logger
CompareLogger logger;
db::NetlistComparer comp (&logger);
comp.compare (&netlist, &au_nl);
}
compare_netlist (_this, netlist, au_nl, exact_parameter_match);
}
void DB_PUBLIC compare_netlist (tl::TestBase *_this, const db::Netlist &netlist, const db::Netlist &netlist_au)
void DB_PUBLIC compare_netlist (tl::TestBase *_this, const db::Netlist &netlist, const db::Netlist &netlist_au, bool exact_parameter_match)
{
db::NetlistComparer comp (0);
if (! comp.compare (&netlist, &netlist_au)) {
_this->raise ("Compare failed - see log for details.\n\nActual:\n" + netlist.to_string () + "\nGolden:\n" + netlist_au.to_string ());
db::Netlist netlist_copy (netlist);
if (exact_parameter_match) {
// install a "all parameters are equal" device parameter comparer so we make sure the devices are compared exactly
for (db::Netlist::device_class_iterator dc = netlist_copy.begin_device_classes (); dc != netlist_copy.end_device_classes (); ++dc) {
db::DeviceClass &cls = *dc;
cls.set_parameter_compare_delegate (new db::AllDeviceParametersAreEqual (0.01));
}
}
if (! comp.compare (&netlist_copy, &netlist_au)) {
_this->raise ("Compare failed - see log for details.\n\nActual:\n" + netlist_copy.to_string () + "\nGolden:\n" + netlist_au.to_string ());
// Compare once again - this time with logger
CompareLogger logger;
db::NetlistComparer comp (&logger);
comp.compare (&netlist, &netlist_au);
comp.compare (&netlist_copy, &netlist_au);
}
}
+2 -2
View File
@@ -77,12 +77,12 @@ void DB_PUBLIC compare_layouts (tl::TestBase *_this, const db::Layout &layout, c
/**
* @brief Compares a netlist against a string
*/
void DB_PUBLIC compare_netlist (tl::TestBase *_this, const db::Netlist &netlist, const std::string &au_nl_string);
void DB_PUBLIC compare_netlist (tl::TestBase *_this, const db::Netlist &netlist, const std::string &au_nl_string, bool exact_parameter_match = false);
/**
* @brief Compares a netlist against another netlist
*/
void DB_PUBLIC compare_netlist (tl::TestBase *_this, const db::Netlist &netlist, const db::Netlist &netlist_au);
void DB_PUBLIC compare_netlist (tl::TestBase *_this, const db::Netlist &netlist, const db::Netlist &netlist_au, bool exact_parameter_match = false);
}
+9
View File
@@ -198,6 +198,15 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
gsi::method ("max_vertex_count", &db::LayoutToNetlist::max_vertex_count,
"See \\max_vertex_count= for details about this attribute."
) +
gsi::method ("device_scaling=", &db::LayoutToNetlist::set_device_scaling, gsi::arg ("f"),
"@brief Sets the device scaling factor\n"
"This factor will scale the physical properties of the extracted devices\n"
"accordingly. The scale factor applies an isotropic shrink (<1) or expansion (>1).\n"
) +
gsi::method ("device_scaling", &db::LayoutToNetlist::device_scaling,
"@brief Gets the device scaling factor\n"
"See \\device_scaling= for details about this attribute."
) +
gsi::method ("name", (const std::string &(db::LayoutToNetlist::*) () const) &db::LayoutToNetlist::name,
"@brief Gets the name of the database\n"
) +
+9
View File
@@ -283,6 +283,15 @@ Class<db::Device> decl_dbDevice ("db", "Device",
gsi::method ("name", &db::Device::name,
"@brief Gets the name of the device.\n"
) +
gsi::method ("trans=", &db::Device::set_trans, gsi::arg ("t"),
"@brief Sets the location of the device.\n"
"The device location is essentially describing the position of the device. The position is typically the center of some "
"recognition shape. In this case the transformation is a plain displacement to the center of this shape."
) +
gsi::method ("trans", &db::Device::trans,
"@brief Gets the location of the device.\n"
"See \\trans= for details about this method."
) +
gsi::method ("expanded_name", &db::Device::expanded_name,
"@brief Gets the expanded name of the device.\n"
"The expanded name takes the name of the device. If the name is empty, the numeric ID will be used to build a name. "
@@ -331,6 +331,11 @@ Class<GenericDeviceExtractor> decl_GenericDeviceExtractor (decl_dbNetlistDeviceE
gsi::method ("dbu", &GenericDeviceExtractor::dbu,
"@brief Gets the database unit\n"
) +
gsi::method ("sdbu", &GenericDeviceExtractor::sdbu,
"@brief Gets the scaled database unit\n"
"Use this unit to compute device properties. It is the database unit multiplied with the\n"
"device scaling factor."
) +
gsi::method ("error", (void (GenericDeviceExtractor::*) (const std::string &)) &GenericDeviceExtractor::error,
gsi::arg ("message"),
"@brief Issues an error with the given message\n"
+145 -9
View File
@@ -1066,10 +1066,11 @@ TEST(4_ResAndCapExtraction)
" device PMOS $2 (S=VDD,G=IN,D=$3) (L=0.4,W=2.3,AS=1.38,AD=1.38,PS=5.8,PD=5.8);\n"
" device NMOS $3 (S=VSS,G=$4,D=OUT) (L=0.4,W=4.6,AS=2.185,AD=2.185,PS=8.8,PD=8.8);\n"
" device MIM_CAP $5 (A=$4,B=VSS) (C=2.622e-14,A=26.22,P=29.8);\n"
" device POLY_RES $7 (A=$3,B=$4) (R=750,A=2.4,P=13.6);\n"
" device POLY_RES $9 (A=$4,B=VSS) (R=1825,A=5.84,P=30);\n"
" device POLY_RES $7 (A=$3,B=$4) (R=750,L=12,W=0.8,A=2.4,P=13.6);\n"
" device POLY_RES $9 (A=$4,B=VSS) (R=1825,L=29.2,W=0.8,A=5.84,P=30);\n"
" device NMOS $10 (S=VSS,G=IN,D=$3) (L=0.4,W=3.1,AS=1.86,AD=1.86,PS=7.4,PD=7.4);\n"
"end;\n"
"end;\n",
true /*exact parameter compare*/
);
// compare the collected test data
@@ -1339,10 +1340,11 @@ TEST(5_ResAndCapWithBulkExtraction)
" device NMOS $3 (S=VSS,G=$4,D=OUT,B=BULK) (L=0.4,W=4.6,AS=2.185,AD=2.185,PS=8.8,PD=8.8);\n"
" device MIM_CAP_SUBSTRATE $5 (A=$4,B=VSS,W=BULK) (C=1.334e-14,A=13.34,P=15);\n"
" device MIM_CAP_NWELL $6 (A=$4,B=VSS,W=NWELL) (C=1.288e-14,A=12.88,P=14.8);\n"
" device POLY_RES_NWELL $7 (A=$3,B=$4,W=NWELL) (R=750,A=2.4,P=13.6);\n"
" device POLY_RES_SUBSTRATE $9 (A=$4,B=VSS,W=BULK) (R=1825,A=5.84,P=30);\n"
" device POLY_RES_NWELL $7 (A=$3,B=$4,W=NWELL) (R=750,L=12,W=0.8,A=2.4,P=13.6);\n"
" device POLY_RES_SUBSTRATE $9 (A=$4,B=VSS,W=BULK) (R=1825,L=29.2,W=0.8,A=5.84,P=30);\n"
" device NMOS $10 (S=VSS,G=IN,D=$3,B=BULK) (L=0.4,W=3.1,AS=1.86,AD=1.86,PS=7.4,PD=7.4);\n"
"end;\n"
"end;\n",
true /*exact parameter compare*/
);
// compare the collected test data
@@ -1582,9 +1584,10 @@ TEST(6_BJT3TransistorExtraction)
" device PMOS $3 (S=VDD,G=IN,D=$3,B=VDD) (L=0.4,W=2.3,AS=1.38,AD=1.38,PS=5.8,PD=5.8);\n"
" device NMOS $4 (S=VSS,G=$4,D=OUT,B=BULK) (L=0.4,W=4.6,AS=2.185,AD=2.185,PS=8.8,PD=8.8);\n"
" device PNP $6 (C=BULK,B=$3,E=$3) (AE=3.06,PE=7,AB=25.2,PB=21.2,AC=25.2,PC=21.2,NE=1);\n"
" device PNP $7 (C=BULK,B=$3,E=$4) (AE=6.12,PE=14,AB=50.4,PB=42.4,AC=50.4,PC=42.4,NE=2);\n"
" device PNP $7 (C=BULK,B=$3,E=$4) (AE=6.12,PE=14,AB=25.2,PB=21.2,AC=25.2,PC=21.2,NE=2);\n"
" device NMOS $9 (S=VSS,G=IN,D=$3,B=BULK) (L=0.4,W=3.1,AS=1.86,AD=1.86,PS=7.4,PD=7.4);\n"
"end;\n"
"end;\n",
true /*exact parameter compare*/
);
// compare the collected test data
@@ -1716,7 +1719,140 @@ TEST(7_DiodeExtraction)
db::compare_netlist (_this, nl,
"circuit TOP (A=A,C=C);\n"
" device DIODE $1 (A=A,C=C) (A=9.18,P=21);\n"
"end;\n"
"end;\n",
true /*exact parameter compare*/
);
// compare the collected test data
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "diode_devices_nets.gds");
db::compare_layouts (_this, ly, au);
}
TEST(8_DiodeExtractionScaled)
{
db::Layout ly;
db::LayerMap lmap;
unsigned int nwell = define_layer (ly, lmap, 1);
unsigned int active = define_layer (ly, lmap, 2);
unsigned int diff_cont = define_layer (ly, lmap, 4);
unsigned int metal1 = define_layer (ly, lmap, 6);
unsigned int metal1_lbl = define_layer (ly, lmap, 6, 1);
unsigned int pplus = define_layer (ly, lmap, 9);
unsigned int nplus = define_layer (ly, lmap, 10);
{
db::LoadLayoutOptions options;
options.get_options<db::CommonReaderOptions> ().layer_map = lmap;
options.get_options<db::CommonReaderOptions> ().create_other_layers = false;
std::string fn (tl::testsrc ());
fn = tl::combine_path (fn, "testdata");
fn = tl::combine_path (fn, "algo");
fn = tl::combine_path (fn, "diode_devices_test.oas");
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly, options);
}
db::Cell &tc = ly.cell (*ly.begin_top_down ());
db::DeepShapeStore dss;
dss.set_text_enlargement (1);
dss.set_text_property_name (tl::Variant ("LABEL"));
// original layers
db::Region rnwell (db::RecursiveShapeIterator (ly, tc, nwell), dss);
db::Region ractive (db::RecursiveShapeIterator (ly, tc, active), dss);
db::Region rdiff_cont (db::RecursiveShapeIterator (ly, tc, diff_cont), dss);
db::Region rmetal1 (db::RecursiveShapeIterator (ly, tc, metal1), dss);
db::Region rmetal1_lbl (db::RecursiveShapeIterator (ly, tc, metal1_lbl), dss);
db::Region rpplus (db::RecursiveShapeIterator (ly, tc, pplus), dss);
db::Region rnplus (db::RecursiveShapeIterator (ly, tc, nplus), dss);
// derived regions
db::Region rn = ractive & rnwell;
db::Region rntie = rnwell & rnplus;
// return the computed layers into the original layout and write it for debugging purposes
unsigned int ln = ly.insert_layer (db::LayerProperties (10, 0)); // 10/0 -> N layer
unsigned int lntie = ly.insert_layer (db::LayerProperties (11, 0)); // 11/0 -> N contact
rn.insert_into (&ly, tc.cell_index (), ln);
rntie.insert_into (&ly, tc.cell_index (), lntie);
// perform the extraction
db::Netlist nl;
db::hier_clusters<db::PolygonRef> cl;
db::NetlistDeviceExtractorDiode diode_ex ("DIODE");
db::NetlistDeviceExtractor::input_layers dl;
dl["N"] = &rn;
dl["P"] = &rpplus;
dl["tC"] = &rnwell;
diode_ex.extract (dss, 0, dl, nl, cl, 2.0);
// perform the net extraction
db::NetlistExtractor net_ex;
db::Connectivity conn;
// Intra-layer
conn.connect (rnwell);
conn.connect (rntie);
conn.connect (rpplus);
conn.connect (rdiff_cont);
conn.connect (rmetal1);
// Inter-layer
conn.connect (rntie, rnwell);
conn.connect (rntie, rdiff_cont);
conn.connect (rpplus, rdiff_cont);
conn.connect (rdiff_cont, rmetal1);
conn.connect (rmetal1, rmetal1_lbl); // attaches labels
// extract the nets
net_ex.extract_nets (dss, 0, conn, nl, cl, "*");
// cleanup + completion
nl.combine_devices ();
nl.make_top_level_pins ();
nl.purge ();
EXPECT_EQ (all_net_names_unique (nl), true);
// debug layers produced for nets
// 201/0 -> n well
// 204/0 -> Diffusion contacts
// 206/0 -> Metal1
// 210/0 -> N tiedown
std::map<unsigned int, unsigned int> dump_map;
dump_map [layer_of (rntie) ] = ly.insert_layer (db::LayerProperties (210, 0));
dump_map [layer_of (rnwell) ] = ly.insert_layer (db::LayerProperties (201, 0));
dump_map [layer_of (rdiff_cont)] = ly.insert_layer (db::LayerProperties (204, 0));
dump_map [layer_of (rmetal1) ] = ly.insert_layer (db::LayerProperties (206, 0));
// write nets to layout
db::CellMapping cm = dss.cell_mapping_to_original (0, &ly, tc.cell_index ());
dump_nets_to_layout (nl, cl, ly, dump_map, cm, true /*with device cells*/);
// compare netlist as string
CHECKPOINT ();
db::compare_netlist (_this, nl,
"circuit TOP (A=A,C=C);\n"
" device DIODE $1 (A=A,C=C) (A=36.72,P=42);\n"
"end;\n",
true /*exact parameter compare*/
);
// compare the collected test data
+7 -1
View File
@@ -1159,6 +1159,12 @@ CODE
# @synopsis l2n_data
# See \Netter#l2n_data for a description of that function.
# %DRC%
# @name device_scaling
# @brief Specifies a dimension scale factor for the geometrical device properties
# @synopsis device_scaling(factor)
# See \Netter#device_scaling for a description of that function.
# %DRC%
# @name extract_devices
# @brief Extracts devices for a given device extractor and device layer selection
@@ -1173,7 +1179,7 @@ CODE
# yet, this method will trigger the extraction process.
# See \Netter#netlist for a description of this function.
%w(connect connect_global clear_connections connect_implicit antenna_check l2n_data extract_devices netlist).each do |f|
%w(connect connect_global clear_connections connect_implicit antenna_check l2n_data device_scaling extract_devices netlist).each do |f|
eval <<"CODE"
def #{f}(*args)
_netter.#{f}(*args)
@@ -68,6 +68,7 @@ module DRC
@connect_implicit = []
@l2n = nil
@lnum = 0
@device_scaling = 1.0
end
# %DRC%
@@ -178,6 +179,19 @@ module DRC
@engine._cmd(@l2n, :extract_devices, devex, ls)
end
# %DRC%
# @name device_scaling
# @brief Specifies a dimension scale factor for the geometrical device properties
# @synopsis device_scaling(factor)
# Specifying a factor of 2 will make all devices being extracted as if the
# geometries were two times larger. This feature is useful when the drawn layout
# does not correspond to the physical dimensions.
def device_scaling(factor)
@device_scaling = factor
@l2n && @l2n.device_scaling = factor
end
# %DRC%
# @name clear_connections
@@ -378,6 +392,7 @@ module DRC
if !@l2n
@layers = {}
_make_data
@l2n.device_scaling = @device_scaling
end
end
+9
View File
@@ -185,6 +185,15 @@ implied always. Sometimes cell variants will be created.
</p><p>
Deep mode can be cancelled with <a href="#tiles">tiles</a> or <a href="#flat">flat</a>.
</p>
<h2>"device_scaling" - Specifies a dimension scale factor for the geometrical device properties</h2>
<keyword name="device_scaling"/>
<a name="device_scaling"/><p>Usage:</p>
<ul>
<li><tt>device_scaling(factor)</tt></li>
</ul>
<p>
See <a href="/about/drc_ref_netter.xml#device_scaling">Netter#device_scaling</a> for a description of that function.
</p>
<h2>"diode" - Supplies the diode extractor class</h2>
<keyword name="diode"/>
<a name="diode"/><p>Usage:</p>
+11
View File
@@ -198,6 +198,17 @@ component.
The implicit connections are applied on the next net extraction and cleared
on "clear_connections".
</p>
<h2>"device_scaling" - Specifies a dimension scale factor for the geometrical device properties</h2>
<keyword name="device_scaling"/>
<a name="device_scaling"/><p>Usage:</p>
<ul>
<li><tt>device_scaling(factor)</tt></li>
</ul>
<p>
Specifying a factor of 2 will make all devices being extracted as if the
geometries were two times larger. This feature is useful when the drawn layout
does not correspond to the physical dimensions.
</p>
<h2>"extract_devices" - Extracts devices based on the given extractor class, name and device layer selection</h2>
<keyword name="extract_devices"/>
<a name="extract_devices"/><p>Usage:</p>
+5
View File
@@ -124,3 +124,8 @@ TEST(10_simplification_with_align)
run_test (_this, "ringo_simple_simplification_with_align", "ringo_for_simplification.gds");
}
TEST(11_device_scaling)
{
run_test (_this, "ringo_simple_device_scaling", "ringo.gds");
}