Fixed tests. Note that now a net with two labels carries a combined net name and does not qualify for connect_implicit if one label matches

This commit is contained in:
Matthias Koefferlein 2023-09-23 21:44:35 +02:00
parent c81388d830
commit 4d41ca6f5c
29 changed files with 300 additions and 85 deletions

View File

@ -247,7 +247,7 @@ void LayoutToNetlist::extract_devices (db::NetlistDeviceExtractor &extractor, co
// transfer errors to log entries
for (auto e = extractor.begin_errors (); e != extractor.end_errors (); ++e) {
m_log_entries.push_back (db::LogEntryData (db::Error, e->to_string ()));
m_log_entries.push_back (db::LogEntryData (e->is_warning () ? db::Warning : db::Error, e->to_string ()));
}
}
@ -369,48 +369,7 @@ void LayoutToNetlist::extract_netlist ()
}
ensure_netlist ();
const db::Layout &layout = dss ().layout (m_layout_index);
db::NetlistExtractor netex;
#if 0 // @@@ remove this plus corresponding code inside NetlistExtractor ...
netex.set_joined_net_names (m_joined_net_names);
std::map<std::string, std::list<tl::GlobPattern> > jp_per_cell;
for (std::list<std::pair<tl::GlobPattern, tl::GlobPattern> >::const_iterator j = m_joined_net_names_per_cell.begin (); j != m_joined_net_names_per_cell.end (); ++j) {
if (j->first.is_const ()) {
jp_per_cell [j->first.pattern ()].push_back (j->second);
} else {
for (db::Layout::const_iterator c = layout.begin (); c != layout.end (); ++c) {
if (j->first.match (layout.cell_name (c->cell_index ()))) {
jp_per_cell [layout.cell_name (c->cell_index ())].push_back (j->second);
}
}
}
}
for (std::map<std::string, std::list<tl::GlobPattern> >::const_iterator i = jp_per_cell.begin (); i != jp_per_cell.end (); ++i) {
netex.set_joined_net_names (i->first, i->second);
}
netex.set_joined_nets (m_joined_nets);
std::map<std::string, std::list<std::set<std::string> > > jn_per_cell;
for (std::list<std::pair<tl::GlobPattern, std::set<std::string> > >::const_iterator j = m_joined_nets_per_cell.begin (); j != m_joined_nets_per_cell.end (); ++j) {
if (j->first.is_const ()) {
jn_per_cell [j->first.pattern ()].push_back (j->second);
} else {
for (db::Layout::const_iterator c = layout.begin (); c != layout.end (); ++c) {
if (j->first.match (layout.cell_name (c->cell_index ()))) {
jn_per_cell [layout.cell_name (c->cell_index ())].push_back (j->second);
}
}
}
}
for (std::map<std::string, std::list<std::set<std::string> > >::const_iterator i = jn_per_cell.begin (); i != jn_per_cell.end (); ++i) {
netex.set_joined_nets (i->first, i->second);
}
#endif
netex.set_include_floating_subcircuits (m_include_floating_subcircuits);
netex.extract_nets (dss (), m_layout_index, m_conn, *mp_netlist, m_net_clusters);
@ -423,8 +382,29 @@ void LayoutToNetlist::extract_netlist ()
}
m_netlist_extracted = true;
}
// @@@ raise error on error
void LayoutToNetlist::check_extraction_errors ()
{
int num_errors = 0;
int max_errors = 10;
std::string errors;
for (auto l = m_log_entries.begin (); l != m_log_entries.end (); ++l) {
if (l->severity >= db::Error) {
errors += "\n";
if (++num_errors >= max_errors) {
errors += "...\n";
errors += tl::sprintf (tl::to_string (tr ("(list shortened after %d errrors, see log for all errors)")), max_errors);
break;
} else {
errors += l->msg;
}
}
}
if (num_errors > 0) {
throw tl::Exception (tl::to_string (tr ("Errors encountered during netlist extraction:")) + errors);
}
}
void LayoutToNetlist::join_nets_from_pattern (db::Circuit &c, const tl::GlobPattern &p)
@ -485,7 +465,6 @@ void LayoutToNetlist::check_must_connect (const db::Circuit &c, const db::Net &a
return;
}
// @@@ raise a warning for top level cells?
if (c.begin_refs () != c.end_refs ()) {
if (a.begin_pins () == a.end_pins ()) {
error (tl::sprintf (tl::to_string (tr ("Must-connect net %s from circuit %s is not connected to outside")), a.expanded_name (), c.name ()));
@ -493,11 +472,18 @@ void LayoutToNetlist::check_must_connect (const db::Circuit &c, const db::Net &a
if (b.begin_pins () == b.end_pins ()) {
error (tl::sprintf (tl::to_string (tr ("Must-connect net %s from circuit %s is not connected to outside")), a.expanded_name (), c.name ()));
}
} else {
if (a.expanded_name () == b.expanded_name ()) {
warn (tl::sprintf (tl::to_string (tr ("Must-connect nets %s from circuit %s must be connected further up in the hierarchy. This is an error at the chip top level.")), a.expanded_name (), c.name ()));
} else {
warn (tl::sprintf (tl::to_string (tr ("Must-connect nets %s and %s from circuit %s must be connected further up in the hierarchy. This is an error at the chip top level.")), a.expanded_name (), b.expanded_name (), c.name ()));
}
}
if (a.begin_pins () != a.end_pins () && b.begin_pins () != b.end_pins ()) {
for (auto ref = c.begin_refs (); ref != c.end_refs (); ++ref) {
const db::SubCircuit &sc = *ref;
// TODO: consider the case of multiple pins on a net (rare)
const db::Net *net_a = sc.net_for_pin (a.begin_pins ()->pin_id ());
const db::Net *net_b = sc.net_for_pin (b.begin_pins ()->pin_id ());
if (net_a == 0) {
@ -557,18 +543,29 @@ void LayoutToNetlist::do_join_nets ()
void LayoutToNetlist::error (const std::string &msg)
{
if (m_log_entries.empty () || m_log_entries.back ().severity != db::Error || m_log_entries.back ().msg != msg) {
tl::error << msg;
m_log_entries.push_back (db::LogEntryData (db::Error, msg));
}
}
void LayoutToNetlist::warn (const std::string &msg)
{
if (m_log_entries.empty () || m_log_entries.back ().severity != db::Warning || m_log_entries.back ().msg != msg) {
tl::warn << msg;
m_log_entries.push_back (db::LogEntryData (db::Warning, msg));
}
}
void LayoutToNetlist::info (const std::string &msg)
{
if (m_log_entries.empty () || m_log_entries.back ().severity != db::Info || m_log_entries.back ().msg != msg) {
if (tl::verbosity () >= 10) {
tl::info << msg;
}
m_log_entries.push_back (db::LogEntryData (db::Info, msg));
}
}
void LayoutToNetlist::mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, bool no_self, void *parent) const
{

View File

@ -194,7 +194,6 @@ public:
/**
* @brief Gets the log entries
* @@@ TODO: provide GSI interface
*/
const log_entries_type &log_entries () const
{
@ -203,7 +202,6 @@ public:
/**
* @brief Clears the log entries
* @@@ TODO: provide GSI interface
*/
void clear_log_entries ()
{
@ -212,7 +210,6 @@ public:
/**
* @brief Adds a log entry
* @@@ TODO: provide GSI interface
*/
void log_entry (const db::LogEntryData &log_entry)
{
@ -587,6 +584,8 @@ public:
*/
void extract_netlist ();
void check_extraction_errors ();
/**
* @brief Marks the netlist as extracted
* NOTE: this method is provided for special cases such as netlist readers. Don't

View File

@ -36,12 +36,13 @@ namespace db
// NetlistDeviceExtractorError implementation
NetlistDeviceExtractorError::NetlistDeviceExtractorError ()
: m_warning (false)
{
// .. nothing yet ..
}
NetlistDeviceExtractorError::NetlistDeviceExtractorError (const std::string &cell_name, const std::string &msg)
: m_cell_name (cell_name), m_message (msg)
: m_warning (false), m_cell_name (cell_name), m_message (msg)
{
// .. nothing yet ..
}
@ -626,4 +627,50 @@ void NetlistDeviceExtractor::error (const std::string &category_name, const std:
}
}
void NetlistDeviceExtractor::warn (const std::string &msg)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_errors.back ().set_warning (true);
if (tl::verbosity () >= 20) {
tl::warn << m_errors.back ().to_string ();
}
}
void NetlistDeviceExtractor::warn (const std::string &msg, const db::DPolygon &poly)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_errors.back ().set_geometry (poly);
m_errors.back ().set_warning (true);
if (tl::verbosity () >= 20) {
tl::warn << m_errors.back ().to_string ();
}
}
void NetlistDeviceExtractor::warn (const std::string &category_name, const std::string &category_description, const std::string &msg)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_errors.back ().set_category_name (category_name);
m_errors.back ().set_category_description (category_description);
m_errors.back ().set_warning (true);
if (tl::verbosity () >= 20) {
tl::warn << m_errors.back ().to_string ();
}
}
void NetlistDeviceExtractor::warn (const std::string &category_name, const std::string &category_description, const std::string &msg, const db::DPolygon &poly)
{
m_errors.push_back (db::NetlistDeviceExtractorError (cell_name (), msg));
m_errors.back ().set_category_name (category_name);
m_errors.back ().set_category_description (category_description);
m_errors.back ().set_geometry (poly);
m_errors.back ().set_warning (true);
if (tl::verbosity () >= 20) {
tl::warn << m_errors.back ().to_string ();
}
}
}

View File

@ -54,6 +54,22 @@ public:
*/
NetlistDeviceExtractorError (const std::string &cell_name, const std::string &msg);
/**
* @brief Sets a value indicating whether the error is only a warning
*/
void set_warning (bool f)
{
m_warning = f;
}
/**
* @brief Gets a value indicating whether the error is only a warning
*/
bool is_warning () const
{
return m_warning;
}
/**
* @brief The category name of the error
* Specifying the category name is optional. If a category is given, it will be used for
@ -145,6 +161,7 @@ public:
std::string to_string () const;
private:
bool m_warning;
std::string m_cell_name;
std::string m_message;
db::DPolygon m_geometry;
@ -506,6 +523,42 @@ public:
error (category_name, category_description, msg, poly.transformed (db::CplxTrans (dbu ())));
}
/**
* @brief Issues a warning with the given message
*/
void warn (const std::string &msg);
/**
* @brief Issues a warning with the given message and warn shape
*/
void warn (const std::string &msg, const db::DPolygon &poly);
/**
* @brief Issues a warning with the given message and warn shape
*/
void warn (const std::string &msg, const db::Polygon &poly)
{
warn (msg, poly.transformed (db::CplxTrans (dbu ())));
}
/**
* @brief Issues a warning with the given category name, description and message
*/
void warn (const std::string &category_name, const std::string &category_description, const std::string &msg);
/**
* @brief Issues a warning with the given category name, description and message and warn shape
*/
void warn (const std::string &category_name, const std::string &category_description, const std::string &msg, const db::DPolygon &poly);
/**
* @brief Issues a warning with the given category name, description and message and warn shape
*/
void warn (const std::string &category_name, const std::string &category_description, const std::string &msg, const db::Polygon &poly)
{
warn (category_name, category_description, msg, poly.transformed (db::CplxTrans (dbu ())));
}
/**
* @brief Gets the name of the current cell
*/

View File

@ -136,11 +136,11 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
rdiff2gate.set_base_verbosity (rdiff.base_verbosity ());
if (rdiff2gate.empty ()) {
error (tl::to_string (tr ("Gate shape touches no diffusion - ignored")), *p);
warn (tl::to_string (tr ("Gate shape touches no diffusion - ignored")), *p);
} else {
if (rdiff2gate.count () != 2) {
error (tl::sprintf (tl::to_string (tr ("Expected two polygons on diff interacting with one gate shape (found %d) - gate shape ignored")), int (rdiff2gate.count ())), *p);
warn (tl::sprintf (tl::to_string (tr ("Expected two polygons on diff interacting with one gate shape (found %d) - gate shape ignored")), int (rdiff2gate.count ())), *p);
continue;
}
@ -158,7 +158,7 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
db::Edges edges (rgate.edges () & db::Edges (*d2g));
db::Edges::length_type l = edges.length ();
if (l == 0) {
error (tl::to_string (tr ("Vanishing edges for interaction gate/diff (corner interaction) - gate shape ignored")));
warn (tl::to_string (tr ("Vanishing edges for interaction gate/diff (corner interaction) - gate shape ignored")));
} else {
widths.push_back (l);
}
@ -237,18 +237,18 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
ddiff2gate.set_base_verbosity (ddiff.base_verbosity ());
if (sdiff2gate.empty () && ddiff2gate.empty ()) {
error (tl::to_string (tr ("Gate shape touches no diffusion - ignored")), *p);
warn (tl::to_string (tr ("Gate shape touches no diffusion - ignored")), *p);
} else if (sdiff2gate.empty () || ddiff2gate.empty ()) {
error (tl::to_string (tr ("Gate shape touches a single diffusion only - ignored")), *p);
warn (tl::to_string (tr ("Gate shape touches a single diffusion only - ignored")), *p);
} else {
if (sdiff2gate.count () != 1) {
error (tl::sprintf (tl::to_string (tr ("Expected one polygons on source diff interacting with one gate shape (found %d) - gate shape ignored")), int (sdiff2gate.count ())), *p);
warn (tl::sprintf (tl::to_string (tr ("Expected one polygons on source diff interacting with one gate shape (found %d) - gate shape ignored")), int (sdiff2gate.count ())), *p);
continue;
}
if (ddiff2gate.count () != 1) {
error (tl::sprintf (tl::to_string (tr ("Expected one polygons on drain diff interacting with one gate shape (found %d) - gate shape ignored")), int (ddiff2gate.count ())), *p);
warn (tl::sprintf (tl::to_string (tr ("Expected one polygons on drain diff interacting with one gate shape (found %d) - gate shape ignored")), int (ddiff2gate.count ())), *p);
continue;
}
@ -258,7 +258,7 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
db::Edges edges (rgate.edges () & sdiff2gate.edges ());
sdwidth = edges.length ();
if (sdwidth == 0) {
error (tl::to_string (tr ("Vanishing edges for interaction gate/source diff (corner interaction) - gate shape ignored")));
warn (tl::to_string (tr ("Vanishing edges for interaction gate/source diff (corner interaction) - gate shape ignored")));
continue;
}
}
@ -267,7 +267,7 @@ void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db
db::Edges edges (rgate.edges () & ddiff2gate.edges ());
ddwidth = edges.length ();
if (ddwidth == 0) {
error (tl::to_string (tr ("Vanishing edges for interaction gate/drain diff (corner interaction) - gate shape ignored")));
warn (tl::to_string (tr ("Vanishing edges for interaction gate/drain diff (corner interaction) - gate shape ignored")));
continue;
}
}
@ -438,7 +438,7 @@ void NetlistDeviceExtractorResistor::extract_devices (const std::vector<db::Regi
db::Region contacts_per_res = contact_wo_res.selected_interacting (rres);
if (contacts_per_res.count () != 2) {
error (tl::sprintf (tl::to_string (tr ("Expected two polygons on contacts interacting with one resistor shape (found %d) - resistor shape ignored")), int (contacts_per_res.count ())), *p);
warn (tl::sprintf (tl::to_string (tr ("Expected two polygons on contacts interacting with one resistor shape (found %d) - resistor shape ignored")), int (contacts_per_res.count ())), *p);
continue;
}
@ -458,7 +458,7 @@ void NetlistDeviceExtractorResistor::extract_devices (const std::vector<db::Regi
db::Coord width2 = eperp.length ();
if (width2 < 1) {
error (tl::to_string (tr ("Invalid contact geometry - resistor shape ignored")), *p);
warn (tl::to_string (tr ("Invalid contact geometry - resistor shape ignored")), *p);
continue;
}
@ -681,7 +681,7 @@ void NetlistDeviceExtractorBJT3Transistor::extract_devices (const std::vector<db
db::Region remitter2base = rbase & remitters;
if (remitter2base.empty ()) {
error (tl::to_string (tr ("Base shape without emitters - ignored")), *p);
warn (tl::to_string (tr ("Base shape without emitters - ignored")), *p);
} else {
// collectors inside base

View File

@ -178,6 +178,8 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
m_device_annot_name_id = mp_layout->properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::device_id_property_name ());
// build an attribute equivalence map which lists the "attribute IDs" which are identical in terms of net names
// TODO: this feature is not really used as must-connect nets now are handled in the LayoutToNetlist class on netlist level.
// Remove this later.
std::map<db::cell_index_type, tl::equivalence_clusters<size_t> > net_name_equivalence;
if (m_text_annot_name_id.first) {

View File

@ -106,6 +106,8 @@ public:
* This is a glob expression rendering net names where partial nets with the
* same name are joined even without explicit connection.
* The cell-less version applies to top level cells only.
* NOTE: this feature is not really used as must-connect nets are handled now in the LayoutToNetlist extractor.
* Remove this function later.
*/
void set_joined_net_names (const std::list<tl::GlobPattern> &jnn);
@ -113,6 +115,8 @@ public:
* @brief Sets the joined net names attribute for a given cell name
* While the single-parameter set_joined_net_names only acts on the top cell, this
* version will act on the cell with the given name.
* NOTE: this feature is not really used as must-connect nets are handled now in the LayoutToNetlist extractor.
* Remove this function later.
*/
void set_joined_net_names (const std::string &cell_name, const std::list<tl::GlobPattern> &jnn);
@ -122,11 +126,15 @@ public:
* names that are to be connected. Multiple such groups can be specified. Each net name listed in a
* group implies implicit joining of the corresponding labels into one net.
* The cell-less version applies to top level cells only.
* NOTE: this feature is not really used as must-connect nets are handled now in the LayoutToNetlist extractor.
* Remove this function later.
*/
void set_joined_nets (const std::list<std::set<std::string> > &jnn);
/**
* @brief Sets the joined nets attribute per cell
* NOTE: this feature is not really used as must-connect nets are handled now in the LayoutToNetlist extractor.
* Remove this function later.
*/
void set_joined_nets (const std::string &cell_name, const std::list<std::set<std::string> > &jnn);

View File

@ -530,6 +530,11 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"\n"
"This method has been made parameter-less in version 0.27. Use \\include_floating_subcircuits= and \\join_net_names as substitutes for the arguments of previous versions."
) +
gsi::method ("check_extraction_errors", &db::LayoutToNetlist::check_extraction_errors,
"@brief Raises an exception if extraction errors are present\n"
"\n"
"This method has been introduced in version 0.28.13."
) +
gsi::method_ext ("internal_layout", &l2n_internal_layout,
"@brief Gets the internal layout\n"
"Usually it should not be required to obtain the internal layout. If you need to do so, make sure not to modify the layout as\n"

View File

@ -157,6 +157,14 @@ Class<DeviceClassFactoryImpl> decl_dbDeviceClassFactoryBase ("db", "DeviceClassF
);
Class<db::NetlistDeviceExtractorError> decl_dbNetlistDeviceExtractorError ("db", "NetlistDeviceExtractorError",
gsi::method ("is_warning?|is_warning", &db::NetlistDeviceExtractorError::is_warning,
"@brief Gets a value indicating whether the error is a warning.\n"
"This predicate has been introduced in version 0.28.13."
) +
gsi::method ("warning=", &db::NetlistDeviceExtractorError::set_warning, gsi::arg ("flag"),
"@brief Sets a value indicating whether the error is a warning.\n"
"This predicate has been introduced in version 0.28.13."
) +
gsi::method ("message", &db::NetlistDeviceExtractorError::message,
"@brief Gets the message text.\n"
) +
@ -199,8 +207,12 @@ Class<db::NetlistDeviceExtractorError> decl_dbNetlistDeviceExtractorError ("db",
gsi::method ("category_description=", &db::NetlistDeviceExtractorError::set_category_description, gsi::arg ("description"),
"@brief Sets the category description.\n"
"See \\category_name= for details about categories."
) +
gsi::method ("to_s", &db::NetlistDeviceExtractorError::to_string,
"@brief Gets the string representation of this error or warning.\n"
"This method has been introduced in version 0.28.13."
),
"@brief An error that occurred during device extraction\n"
"@brief An error or a warning that occurred during device extraction\n"
"The device extractor will keep errors that occurred during extraction of the devices. "
"It does not by using this error class.\n"
"\n"
@ -211,7 +223,7 @@ Class<db::NetlistDeviceExtractorError> decl_dbNetlistDeviceExtractorError ("db",
"For categorization of the errors, a category name and description may be specified. If given, the "
"errors will be shown in the specified category. The category description is optional.\n"
"\n"
"This class has been introduced in version 0.26."
"This class has been introduced in version 0.26. Warning mode has been added in version 0.28.13."
);
static const std::string &ld_name (const db::NetlistDeviceExtractorLayerDefinition *ld)
@ -468,6 +480,36 @@ Class<GenericDeviceExtractor> decl_GenericDeviceExtractor (decl_dbNetlistDeviceE
gsi::method ("error", (void (GenericDeviceExtractor::*) (const std::string &, const std::string &, const std::string &, const db::Polygon &)) &GenericDeviceExtractor::error,
gsi::arg ("category_name"), gsi::arg ("category_description"), gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues an error with the given category name and description, message and database-unit polygon geometry\n"
) +
gsi::method ("warn", (void (GenericDeviceExtractor::*) (const std::string &)) &GenericDeviceExtractor::warn,
gsi::arg ("message"),
"@brief Issues a warning with the given message\n"
"Warnings have been introduced in version 0.28.13."
) +
gsi::method ("warn", (void (GenericDeviceExtractor::*) (const std::string &, const db::DPolygon &)) &GenericDeviceExtractor::warn,
gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues a warning with the given message and micrometer-units polygon geometry\n"
"Warnings have been introduced in version 0.28.13."
) +
gsi::method ("warn", (void (GenericDeviceExtractor::*) (const std::string &, const db::Polygon &)) &GenericDeviceExtractor::warn,
gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues a warning with the given message and database-unit polygon geometry\n"
"Warnings have been introduced in version 0.28.13."
) +
gsi::method ("warn", (void (GenericDeviceExtractor::*) (const std::string &, const std::string &, const std::string &)) &GenericDeviceExtractor::warn,
gsi::arg ("category_name"), gsi::arg ("category_description"), gsi::arg ("message"),
"@brief Issues a warning with the given category name and description, message\n"
"Warnings have been introduced in version 0.28.13."
) +
gsi::method ("warn", (void (GenericDeviceExtractor::*) (const std::string &, const std::string &, const std::string &, const db::DPolygon &)) &GenericDeviceExtractor::warn,
gsi::arg ("category_name"), gsi::arg ("category_description"), gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues a warning with the given category name and description, message and micrometer-units polygon geometry\n"
"Warnings have been introduced in version 0.28.13."
) +
gsi::method ("warn", (void (GenericDeviceExtractor::*) (const std::string &, const std::string &, const std::string &, const db::Polygon &)) &GenericDeviceExtractor::warn,
gsi::arg ("category_name"), gsi::arg ("category_description"), gsi::arg ("message"), gsi::arg ("geometry"),
"@brief Issues a warning with the given category name and description, message and database-unit polygon geometry\n"
"Warnings have been introduced in version 0.28.13."
),
"@brief The basic class for implementing custom device extractors.\n"
"\n"

View File

@ -2277,6 +2277,12 @@ CODE
# @synopsis device_scaling(factor)
# See \Netter#device_scaling for a description of that function.
# %DRC%
# @name ignore_extraction_errors
# @brief Specifies whether to ignore extraction errors
# @synopsis ignore_extraction_errors(value)
# See \Netter#ignore_extraction_errors for a description of that function.
# %DRC%
# @name extract_devices
# @brief Extracts devices for a given device extractor and device layer selection
@ -2299,6 +2305,7 @@ CODE
connect_implicit
connect_explicit
device_scaling
ignore_extraction_errors
extract_devices
l2n_data
netlist

View File

@ -69,6 +69,7 @@ module DRC
@l2n = nil
@lnum = 0
@device_scaling = 1.0
@ignore_extraction_errors = false
end
# %DRC%
@ -235,6 +236,18 @@ module DRC
end
end
# %DRC%
# @name ignore_extraction_errors
# @brief Specifies whether to ignore extraction errors
# @synopsis ignore_extraction_errors(value)
# With this value set to false (the default), "extract_netlist" will raise
# an exception upon extraction errors. Otherwise, extraction errors will be logged
# but no error is raised.
def ignore_extraction_errors(value)
@ignore_extraction_errors = value
end
# %DRC%
# @name clear_connections
# @brief Clears all connections stored so far
@ -602,6 +615,11 @@ module DRC
cfg.call(@l2n)
end
# checks for errors if needed
if !@ignore_extraction_errors
@l2n.check_extraction_errors
end
end
@l2n

View File

@ -21,8 +21,8 @@ metal2_lbl = input(8, 1)
# Computed layers
pactive = active & nwell
pgate = active & poly
psd = active - pgate
pgate = pactive & poly
psd = pactive - pgate
nactive = active - nwell
ngate = nactive & poly

View File

@ -5,12 +5,12 @@
* net 1 FB
* net 2 OSC
* net 3 NEXT
* net 4 VSSZ,VSS
* net 5 VDDZ,VDD
* cell instance $1 r180 *1 -0.24,9.18
X$1 16 1 2 4 5 INV2
* cell instance $2 r0 *1 0,0
X$2 1 14 15 4 5 INV2
* net 4 VSSZ
* net 5 VDDZ
* cell instance $1 r0 *1 0,0
X$1 1 14 15 4 5 INV2
* cell instance $2 r180 *1 -0.24,9.18
X$2 16 1 2 4 5 INV2
* cell instance $3 r180 *1 10.32,9.18
X$3 3 9 19 4 5 INV2
* cell instance $4 r0 *1 10.56,0
@ -46,18 +46,14 @@ X$2 2 5 1 TRANS
X$3 5 3 2 TRANS
* cell instance $4 m0 *1 0.4,0
X$4 4 3 2 TRANS
* device instance $1 -0.4,0 PMOS
M$1 2 1 4 2 PMOS L=0.25U W=0.95U AS=0.49875P AD=0.26125P PS=2.95U PD=1.5U
* device instance $2 0.4,0 PMOS
M$2 4 2 3 4 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.49875P PS=1.5U PD=2.95U
* device instance $3 -0.4,2.8 PMOS
M$3 2 1 5 2 PMOS L=0.25U W=0.95U AS=0.49875P AD=0.26125P PS=2.95U PD=1.5U
* device instance $4 0.4,2.8 PMOS
M$4 5 2 3 5 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.49875P PS=1.5U PD=2.95U
* device instance $5 -0.4,0 NMOS
M$5 2 1 4 2 NMOS L=0.25U W=0.95U AS=0.49875P AD=0.26125P PS=2.95U PD=1.5U
* device instance $6 0.4,0 NMOS
M$6 4 2 3 4 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.49875P PS=1.5U PD=2.95U
* device instance $1 r0 *1 -0.4,2.8 PMOS
M$1 5 1 2 2 PMOS L=0.25U W=0.95U AS=0.49875P AD=0.26125P PS=2.95U PD=1.5U
* device instance $2 r0 *1 0.4,2.8 PMOS
M$2 3 2 5 5 PMOS L=0.25U W=0.95U AS=0.26125P AD=0.49875P PS=1.5U PD=2.95U
* device instance $3 r0 *1 -0.4,0 NMOS
M$3 4 1 2 2 NMOS L=0.25U W=0.95U AS=0.49875P AD=0.26125P PS=2.95U PD=1.5U
* device instance $4 r0 *1 0.4,0 NMOS
M$4 3 2 4 4 NMOS L=0.25U W=0.95U AS=0.26125P AD=0.49875P PS=1.5U PD=2.95U
.ENDS INV2
* cell TRANS

Binary file not shown.

View File

@ -3,6 +3,8 @@ source($lvs_test_source)
report_lvs($lvs_test_target_lvsdb)
ignore_extraction_errors(true)
writer = write_spice(true, false)
target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")

View File

@ -27,6 +27,8 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
H(W B('Must-connect nets GND from circuit INVCHAIN must be connected further up in the hierarchy. This is an error at the chip top level.'))
H(W B('Must-connect nets R from circuit INVCHAIN must be connected further up in the hierarchy. This is an error at the chip top level.'))
H(E B('Must-connect nets R from circuit INV2 are not connected in INVCHAIN'))
K(PMOS MOS3)
K(NMOS MOS3)

View File

@ -3,6 +3,8 @@ source($lvs_test_source)
report_lvs($lvs_test_target_lvsdb)
ignore_extraction_errors(true)
writer = write_spice(true, false)
target_netlist($lvs_test_target_cir, writer, "Extracted by KLayout")

View File

@ -27,6 +27,8 @@ J(
C(l2 l6 l2)
C(l5 l6 l5)
G(l14 SUBSTRATE)
H(W B('Must-connect nets GND from circuit INVCHAIN must be connected further up in the hierarchy. This is an error at the chip top level.'))
H(W B('Must-connect nets R from circuit INVCHAIN must be connected further up in the hierarchy. This is an error at the chip top level.'))
H(E B('Must-connect nets R from circuit INV2 are not connected in INVCHAIN'))
K(PMOS MOS3)
K(NMOS MOS3)

View File

@ -38,6 +38,9 @@ layout(
global(l7 SUBSTRATE)
global(l10 SUBSTRATE)
# Log entries
message(warning description('Must-connect nets VDD from circuit RINGO must be connected further up in the hierarchy. This is an error at the chip top level.'))
# Device class section
class(PMOS MOS4)
class(NMOS MOS4)

View File

@ -70,6 +70,9 @@ layout(
global(l1 vss)
global(l6 vss)
# Log entries
message(warning description('Must-connect nets vdd from circuit SP6TArray_2X4 must be connected further up in the hierarchy. This is an error at the chip top level.'))
# Device class section
class(active_res RES)
class(poly_res RES)

View File

@ -70,6 +70,9 @@ layout(
global(l1 vss)
global(l6 vss)
# Log entries
message(warning description('Must-connect nets vdd from circuit SP6TArray_2X4 must be connected further up in the hierarchy. This is an error at the chip top level.'))
# Device class section
class(active_res RES)
class(poly_res RES)

View File

@ -70,6 +70,9 @@ layout(
global(l1 vss)
global(l6 vss)
# Log entries
message(warning description('Must-connect nets vdd from circuit SP6TArray_2X4 must be connected further up in the hierarchy. This is an error at the chip top level.'))
# Device class section
class(active_res RES)
class(poly_res RES)

View File

@ -70,6 +70,9 @@ layout(
global(l1 vss)
global(l6 vss)
# Log entries
message(warning description('Must-connect nets vdd from circuit SP6TArray_2X4 must be connected further up in the hierarchy. This is an error at the chip top level.'))
# Device class section
class(active_res RES)
class(poly_res RES)

View File

@ -70,6 +70,9 @@ layout(
global(l6 vss)
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd from circuit SP6TArray_2X4 must be connected further up in the hierarchy. This is an error at the chip top level.'))
# Device class section
class(active_res RES)
class(poly_res RES)

View File

@ -70,6 +70,9 @@ layout(
global(l6 vss)
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd from circuit SP6TArray_2X4 must be connected further up in the hierarchy. This is an error at the chip top level.'))
# Device class section
class(active_res RES)
class(poly_res RES)

View File

@ -70,6 +70,9 @@ layout(
global(l6 vss)
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd from circuit SP6TArray_2X4 must be connected further up in the hierarchy. This is an error at the chip top level.'))
# Device class section
class(active_res RES)
class(poly_res RES)

View File

@ -70,6 +70,9 @@ layout(
global(l6 vss)
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd from circuit SP6TArray_2X4 must be connected further up in the hierarchy. This is an error at the chip top level.'))
# Device class section
class(active_res RES)
class(poly_res RES)

View File

@ -70,6 +70,9 @@ layout(
global(l6 vss)
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd from circuit SP6TArray_2X4 must be connected further up in the hierarchy. This is an error at the chip top level.'))
# Device class section
class(active_res RES)
class(poly_res RES)

View File

@ -70,6 +70,9 @@ layout(
global(l6 vss)
global(l1 vss)
# Log entries
message(warning description('Must-connect nets vdd from circuit SP6TArray_2X4 must be connected further up in the hierarchy. This is an error at the chip top level.'))
# Device class section
class(active_res RES)
class(poly_res RES)