Resolved conflicts for issue-419 merge

This commit is contained in:
Matthias Koefferlein 2019-11-22 23:34:03 +01:00
commit 2757b22da6
9 changed files with 361 additions and 60 deletions

View File

@ -294,7 +294,7 @@ size_t LayoutToNetlist::global_net_id (const std::string &name)
return m_conn.global_net_id (name);
}
void LayoutToNetlist::extract_netlist (const std::string &joined_net_names)
void LayoutToNetlist::extract_netlist (const std::string &joined_net_names, bool include_floating_subcircuits)
{
if (m_netlist_extracted) {
throw tl::Exception (tl::to_string (tr ("The netlist has already been extracted")));
@ -302,7 +302,9 @@ void LayoutToNetlist::extract_netlist (const std::string &joined_net_names)
ensure_netlist ();
db::NetlistExtractor netex;
netex.extract_nets (dss (), m_layout_index, m_conn, *mp_netlist, m_net_clusters, joined_net_names);
netex.set_joined_net_names (joined_net_names);
netex.set_include_floating_subcircuits (include_floating_subcircuits);
netex.extract_nets (dss (), m_layout_index, m_conn, *mp_netlist, m_net_clusters);
m_netlist_extracted = true;
}

View File

@ -389,7 +389,7 @@ public:
* @brief Runs the netlist extraction
* See the class description for more details.
*/
void extract_netlist (const std::string &joined_net_names = std::string ());
void extract_netlist (const std::string &joined_net_names = std::string (), bool include_floating_subcircuits = false);
/**
* @brief Marks the netlist as extracted

View File

@ -2624,18 +2624,15 @@ compute_device_key (const db::Device &device, const db::NetGraph &g, bool strict
return k;
}
static std::vector<std::pair<size_t, size_t> >
compute_subcircuit_key (const db::SubCircuit &subcircuit, const db::NetGraph &g, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map)
static bool
compute_subcircuit_key (const db::SubCircuit &subcircuit, const db::NetGraph &g, const std::map<const db::Circuit *, CircuitMapper> *circuit_map, const CircuitPinMapper *pin_map, std::vector<std::pair<size_t, size_t> > &k)
{
std::vector<std::pair<size_t, size_t> > k;
const db::Circuit *cr = subcircuit.circuit_ref ();
std::map<const db::Circuit *, CircuitMapper>::const_iterator icm = circuit_map->find (cr);
if (icm == circuit_map->end ()) {
// this can happen if the other circuit does not exist - in this case the key is an invalid one which cannot
// be produced by a regular subcircuit.
return k;
// this can happen if the other circuit does not exist - report invalid mapping.
return false;
}
const CircuitMapper *cm = & icm->second;
@ -2660,7 +2657,7 @@ compute_subcircuit_key (const db::SubCircuit &subcircuit, const db::NetGraph &g,
std::sort (k.begin (), k.end ());
return k;
return true;
}
namespace {
@ -3349,7 +3346,8 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG
continue;
}
std::vector<std::pair<size_t, size_t> > k = compute_subcircuit_key (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper);
std::vector<std::pair<size_t, size_t> > k;
bool valid = compute_subcircuit_key (*sc, g1, &c12_circuit_and_pin_mapping, &circuit_pin_mapper, k);
bool mapped = true;
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end () && mapped; ++i) {
@ -3363,7 +3361,7 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG
mp_logger->subcircuit_mismatch (sc.operator-> (), 0);
}
good = false;
} else if (! k.empty ()) {
} else if (valid) {
// TODO: report devices which cannot be distiguished topologically?
subcircuit_map.insert (std::make_pair (k, std::make_pair (sc.operator-> (), sc_cat)));
}
@ -3381,7 +3379,8 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG
continue;
}
std::vector<std::pair<size_t, size_t> > k = compute_subcircuit_key (*sc, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper);
std::vector<std::pair<size_t, size_t> > k;
compute_subcircuit_key (*sc, g2, &c22_circuit_and_pin_mapping, &circuit_pin_mapper, k);
bool mapped = true;
for (std::vector<std::pair<size_t, size_t> >::iterator i = k.begin (); i != k.end (); ++i) {
@ -3407,18 +3406,50 @@ NetlistComparer::do_subcircuit_assignment (const db::Circuit *c1, const db::NetG
db::SubCircuitCompare scc;
if (! scc.equals (scm->second, std::make_pair (sc.operator-> (), sc_cat))) {
if (mp_logger) {
mp_logger->subcircuit_mismatch (scm->second.first, sc.operator-> ());
}
good = false;
} else {
if (mp_logger) {
mp_logger->match_subcircuits (scm->second.first, sc.operator-> ());
std::multimap<std::vector<std::pair<size_t, size_t> >, std::pair<const db::SubCircuit *, size_t> >::iterator scm_start = scm;
bool found = false;
size_t nscm = 0;
while (! found && scm != subcircuit_map.end () && scm->first == k) {
++nscm;
if (scc.equals (scm->second, std::make_pair (sc.operator-> (), sc_cat))) {
found = true;
}
}
subcircuit_map.erase (scm);
if (! found) {
if (nscm == 1) {
// unique match, but doesn't fit: report this one as paired, but mismatching:
if (mp_logger) {
mp_logger->subcircuit_mismatch (scm_start->second.first, sc.operator-> ());
}
// no longer look for this one
subcircuit_map.erase (scm_start);
} else {
// no unqiue match
if (mp_logger) {
mp_logger->subcircuit_mismatch (0, sc.operator-> ());
}
}
good = false;
} else {
if (mp_logger) {
mp_logger->match_subcircuits (scm->second.first, sc.operator-> ());
}
// no longer look for this one
subcircuit_map.erase (scm);
}
}

View File

@ -29,11 +29,21 @@ namespace db
{
NetlistExtractor::NetlistExtractor ()
: mp_clusters (0), mp_layout (0), mp_cell (0)
: mp_clusters (0), mp_layout (0), mp_cell (0), m_include_floating_subcircuits (false)
{
// .. nothing yet ..
}
void NetlistExtractor::set_joined_net_names (const std::string &jnn)
{
m_joined_net_names = jnn;
}
void NetlistExtractor::set_include_floating_subcircuits (bool f)
{
m_include_floating_subcircuits = f;
}
static void
build_net_name_equivalence (const db::Layout *layout, db::property_names_id_type net_name_id, const std::string &joined_net_names, tl::equivalence_clusters<unsigned int> &eq)
{
@ -62,7 +72,7 @@ build_net_name_equivalence (const db::Layout *layout, db::property_names_id_type
}
void
NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layout_index, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters, const std::string &joined_net_names)
NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layout_index, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters)
{
mp_clusters = &clusters;
mp_layout = &dss.const_layout (layout_index);
@ -81,8 +91,8 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
// the big part: actually extract the nets
tl::equivalence_clusters<unsigned int> net_name_equivalence;
if (m_text_annot_name_id.first && ! joined_net_names.empty ()) {
build_net_name_equivalence (mp_layout, m_text_annot_name_id.second, joined_net_names, net_name_equivalence);
if (m_text_annot_name_id.first && ! m_joined_net_names.empty ()) {
build_net_name_equivalence (mp_layout, m_text_annot_name_id.second, m_joined_net_names, net_name_equivalence);
}
mp_clusters->build (*mp_layout, *mp_cell, db::ShapeIterator::Polygons, conn, &net_name_equivalence);
@ -98,9 +108,25 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
std::map<db::cell_index_type, std::map<size_t, size_t> > pins_per_cluster_per_cell;
for (db::Layout::bottom_up_const_iterator cid = mp_layout->begin_bottom_up (); cid != mp_layout->end_bottom_up (); ++cid) {
const db::Cell &cell = mp_layout->cell (*cid);
const connected_clusters_type &clusters = mp_clusters->clusters_per_cell (*cid);
if (clusters.empty ()) {
continue;
bool any_good = false;
// in case of "include floating subcircuits" check whether we have a child cell which has a circuit attached in this case
if (include_floating_subcircuits ()) {
for (db::Cell::child_cell_iterator cc = cell.begin_child_cells (); ! any_good && ! cc.at_end (); ++cc) {
any_good = (circuits.find (*cc) != circuits.end ());
}
}
if (! any_good) {
// skip this cell
continue;
}
}
db::DeviceAbstract *dm = nl.device_abstract_by_cell_index (*cid);
@ -128,6 +154,16 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layo
std::map<std::pair<db::cell_index_type, db::ICplxTrans>, db::SubCircuit *> subcircuits;
if (include_floating_subcircuits ()) {
// Make sure we create one subcircuit for each instance of cells which do have circuits
// associated.
for (db::Cell::const_iterator inst = cell.begin (); ! inst.at_end (); ++inst) {
make_subcircuit (circuit, inst->cell_index (), inst->complex_trans (), subcircuits, circuits);
}
}
for (connected_clusters_type::all_iterator c = clusters.begin_all (); ! c.at_end (); ++c) {
const db::local_cluster<db::PolygonRef> &lc = clusters.cluster_by_id (*c);
@ -315,6 +351,39 @@ void NetlistExtractor::connect_devices (db::Circuit *circuit,
}
}
db::SubCircuit * NetlistExtractor::make_subcircuit (db::Circuit *circuit,
db::cell_index_type inst_cell_index,
const db::ICplxTrans &inst_trans,
std::map<std::pair<db::cell_index_type, db::ICplxTrans>, db::SubCircuit *> &subcircuits,
const std::map<db::cell_index_type, db::Circuit *> &circuits)
{
db::SubCircuit *subcircuit = 0;
std::pair<db::cell_index_type, db::ICplxTrans> subcircuit_key (inst_cell_index, inst_trans);
std::map<std::pair<db::cell_index_type, db::ICplxTrans>, db::SubCircuit *>::const_iterator j = subcircuits.find (subcircuit_key);
if (j == subcircuits.end ()) {
// make subcircuit if required
std::map<db::cell_index_type, db::Circuit *>::const_iterator k = circuits.find (inst_cell_index);
if (k == circuits.end ()) {
return 0;
}
subcircuit = new db::SubCircuit (k->second);
db::CplxTrans dbu_trans (mp_layout->dbu ());
subcircuit->set_trans (dbu_trans * inst_trans * dbu_trans.inverted ());
circuit->add_subcircuit (subcircuit);
subcircuits.insert (std::make_pair (subcircuit_key, subcircuit));
} else {
subcircuit = j->second;
}
return subcircuit;
}
void NetlistExtractor::make_and_connect_subcircuits (db::Circuit *circuit,
const connected_clusters_type &clusters,
size_t cid,
@ -335,27 +404,8 @@ void NetlistExtractor::make_and_connect_subcircuits (db::Circuit *circuit,
continue;
}
db::SubCircuit *subcircuit = 0;
std::pair<db::cell_index_type, db::ICplxTrans> subcircuit_key (inst_cell_index, inst_trans);
std::map<std::pair<db::cell_index_type, db::ICplxTrans>, db::SubCircuit *>::const_iterator j = subcircuits.find (subcircuit_key);
if (j == subcircuits.end ()) {
// make subcircuit if required
std::map<db::cell_index_type, db::Circuit *>::const_iterator k = circuits.find (inst_cell_index);
tl_assert (k != circuits.end ()); // because we walk bottom-up
subcircuit = new db::SubCircuit (k->second);
db::CplxTrans dbu_trans (mp_layout->dbu ());
subcircuit->set_trans (dbu_trans * inst_trans * dbu_trans.inverted ());
circuit->add_subcircuit (subcircuit);
subcircuits.insert (std::make_pair (subcircuit_key, subcircuit));
} else {
subcircuit = j->second;
}
db::SubCircuit *subcircuit = make_subcircuit (circuit, inst_cell_index, inst_trans, subcircuits, circuits);
tl_assert (subcircuit != 0);
// create the pin connection to the subcircuit
std::map<db::cell_index_type, std::map<size_t, size_t> >::const_iterator icc2p = pins_per_cluster.find (inst_cell_index);

View File

@ -80,11 +80,45 @@ public:
*/
NetlistExtractor ();
/**
* @brief Sets a flag indicating whether floating circuits shall be included as subcircuits
* If this attribute is set to true, disconnected subcircuits (such that do not have a pin)
* are included per instance of a cell. Such subcircuits do not have a connection to their
* parent circuit but reflect the hierarchy they are present it. This is useful when the
* netlist is supposed to be flattened later, because then each subcircuit will render floating
* nets in the parent circuit. With this flag set to false, floating circuits will always appear
* as additional top cells.
*/
void set_include_floating_subcircuits (bool f);
/**
* @brief Gets a flag indicating whether floating circuits shall be included as subcircuits
*/
bool include_floating_subcircuits () const
{
return m_include_floating_subcircuits;
}
/**
* @brief Sets the joined net names attribute
* This is a glob expression rendering net names where partial nets with the
* same name are joined even without explicit connection.
*/
void set_joined_net_names (const std::string &jnn);
/**
* @brief Gets the joined net names expression
*/
const std::string &joined_net_names () const
{
return m_joined_net_names;
}
/**
* @brief Extract the nets
* See the class description for more details.
*/
void extract_nets (const db::DeepShapeStore &dss, unsigned int layout_index, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters, const std::string &joined_net_names = std::string ());
void extract_nets (const db::DeepShapeStore &dss, unsigned int layout_index, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters);
private:
hier_clusters_type *mp_clusters;
@ -93,6 +127,8 @@ private:
std::pair<bool, db::property_names_id_type> m_text_annot_name_id;
std::pair<bool, db::property_names_id_type> m_device_annot_name_id;
std::pair<bool, db::property_names_id_type> m_terminal_annot_name_id;
std::string m_joined_net_names;
bool m_include_floating_subcircuits;
bool instance_is_device (db::properties_id_type prop_id) const;
db::Device *device_from_instance (db::properties_id_type prop_id, db::Circuit *circuit) const;
@ -106,6 +142,18 @@ private:
*/
size_t make_pin (db::Circuit *circuit, db::Net *net);
/**
* @brief Makes a subcircuit for the given instance (by cell index and transformation)
* This method maintains a subcircuit cache in "subcircuits" and will pull the subcircuit from there
* if possible.
* It returns the new or old subcircuit.
*/
db::SubCircuit *make_subcircuit (Circuit *circuit,
db::cell_index_type inst_cell_index,
const db::ICplxTrans &inst_trans,
std::map<std::pair<db::cell_index_type, db::ICplxTrans>, db::SubCircuit *> &subcircuits,
const std::map<db::cell_index_type, db::Circuit *> &circuits);
/**
* @brief Turns the connections of a cluster into subcircuit instances
*

View File

@ -329,7 +329,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
gsi::method ("global_net_name", &db::LayoutToNetlist::global_net_name, gsi::arg ("global_net_id"),
"@brief Gets the global net name for the given global net ID."
) +
gsi::method ("extract_netlist", &db::LayoutToNetlist::extract_netlist, gsi::arg ("join_net_names", std::string ()),
gsi::method ("extract_netlist", &db::LayoutToNetlist::extract_netlist, gsi::arg ("join_net_names", std::string ()), gsi::arg ("include_floating_subcircuits", false),
"@brief Runs the netlist extraction\n"
"'join_net_names' is a glob expression for labels. Nets on top level carrying the same label which matches this glob "
"expression will be connected implicitly even if there is no physical connection. This feature is useful to simulate a connection "
@ -346,7 +346,14 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"\n"
"Label matching is case sensitive.\n"
"\n"
"With 'include_floating_subcircuits' set to true, subcircuits with no connection to their parent "
"circuit are still included in the circuit as floating subcircuits. Specifically on flattening this "
"means that these subcircuits are property propagated to their parent instead of appearing as "
"additional top circuits.\n"
"\n"
"See the class description for more details.\n"
"\n"
"The 'include_floating_subcircuits' argument has been introduced in version 0.26.2."
) +
gsi::method_ext ("internal_layout", &l2n_internal_layout,
"@brief Gets the internal layout\n"

View File

@ -741,16 +741,19 @@ TEST(3_DeviceAndNetExtractionWithImplicitConnections)
// extract the nets
db::Netlist nl2 = nl;
net_ex.extract_nets (dss, 0, conn, nl2, cl, "{VDDZ,VSSZ,NEXT,FB}");
net_ex.set_joined_net_names ("{VDDZ,VSSZ,NEXT,FB}");
net_ex.extract_nets (dss, 0, conn, nl2, cl);
EXPECT_EQ (all_net_names_unique (nl2), true);
nl2 = nl;
net_ex.extract_nets (dss, 0, conn, nl2, cl, "{VDDZ,VSSZ,NEXT}");
net_ex.set_joined_net_names ("{VDDZ,VSSZ,NEXT}");
net_ex.extract_nets (dss, 0, conn, nl2, cl);
EXPECT_EQ (all_net_names_unique (nl2), false);
net_ex.extract_nets (dss, 0, conn, nl, cl, "*");
net_ex.set_joined_net_names ("*");
net_ex.extract_nets (dss, 0, conn, nl, cl);
EXPECT_EQ (all_net_names_unique (nl), true);
@ -1012,7 +1015,8 @@ TEST(4_ResAndCapExtraction)
// extract the nets
net_ex.extract_nets (dss, 0, conn, nl, cl, "*");
net_ex.set_joined_net_names ("*");
net_ex.extract_nets (dss, 0, conn, nl, cl);
// Flatten device circuits
@ -1285,7 +1289,8 @@ TEST(5_ResAndCapWithBulkExtraction)
// extract the nets
net_ex.extract_nets (dss, 0, conn, nl, cl, "*");
net_ex.set_joined_net_names ("*");
net_ex.extract_nets (dss, 0, conn, nl, cl);
// Flatten device circuits
@ -1526,7 +1531,8 @@ TEST(6_BJT3TransistorExtraction)
// extract the nets
net_ex.extract_nets (dss, 0, conn, nl, cl, "*");
net_ex.set_joined_net_names ("*");
net_ex.extract_nets (dss, 0, conn, nl, cl);
// Flatten device circuits
@ -1691,7 +1697,8 @@ TEST(7_DiodeExtraction)
// extract the nets
net_ex.extract_nets (dss, 0, conn, nl, cl, "*");
net_ex.set_joined_net_names ("*");
net_ex.extract_nets (dss, 0, conn, nl, cl);
// cleanup + completion
nl.combine_devices ();
@ -1823,7 +1830,8 @@ TEST(8_DiodeExtractionScaled)
// extract the nets
net_ex.extract_nets (dss, 0, conn, nl, cl, "*");
net_ex.set_joined_net_names ("*");
net_ex.extract_nets (dss, 0, conn, nl, cl);
// cleanup + completion
nl.combine_devices ();
@ -2410,3 +2418,158 @@ TEST(11_DeviceExtractionWithSameClass)
CHECKPOINT ();
db::compare_netlist (_this, nl, nl_au_string_post);
}
TEST(12_FloatingSubcircuitExtraction)
{
db::Layout ly;
db::LayerMap lmap;
unsigned int nwell = define_layer (ly, lmap, 1);
unsigned int active = define_layer (ly, lmap, 2);
unsigned int poly = define_layer (ly, lmap, 3);
unsigned int poly_lbl = define_layer (ly, lmap, 3, 1);
unsigned int diff_cont = define_layer (ly, lmap, 4);
unsigned int poly_cont = define_layer (ly, lmap, 5);
unsigned int metal1 = define_layer (ly, lmap, 6);
unsigned int metal1_lbl = define_layer (ly, lmap, 6, 1);
unsigned int via1 = define_layer (ly, lmap, 7);
unsigned int metal2 = define_layer (ly, lmap, 8);
unsigned int metal2_lbl = define_layer (ly, lmap, 8, 1);
{
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, "device_extract_l1_floating_subcircuits.gds");
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 rpoly (db::RecursiveShapeIterator (ly, tc, poly), dss);
db::Region rpoly_lbl (db::RecursiveShapeIterator (ly, tc, poly_lbl), dss);
db::Region rdiff_cont (db::RecursiveShapeIterator (ly, tc, diff_cont), dss);
db::Region rpoly_cont (db::RecursiveShapeIterator (ly, tc, poly_cont), dss);
db::Region rmetal1 (db::RecursiveShapeIterator (ly, tc, metal1), dss);
db::Region rmetal1_lbl (db::RecursiveShapeIterator (ly, tc, metal1_lbl), dss);
db::Region rvia1 (db::RecursiveShapeIterator (ly, tc, via1), dss);
db::Region rmetal2 (db::RecursiveShapeIterator (ly, tc, metal2), dss);
db::Region rmetal2_lbl (db::RecursiveShapeIterator (ly, tc, metal2_lbl), dss);
// derived regions
db::Region rpactive = ractive & rnwell;
db::Region rpgate = rpactive & rpoly;
db::Region rpsd = rpactive - rpgate;
db::Region rnactive = ractive - rnwell;
db::Region rngate = rnactive & rpoly;
db::Region rnsd = rnactive - rngate;
// perform the extraction
db::Netlist nl;
db::hier_clusters<db::PolygonRef> cl;
db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS");
db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS");
db::NetlistDeviceExtractor::input_layers dl;
dl["SD"] = &rpsd;
dl["G"] = &rpgate;
dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes
pmos_ex.extract (dss, 0, dl, nl, cl);
dl["SD"] = &rnsd;
dl["G"] = &rngate;
dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes
nmos_ex.extract (dss, 0, dl, nl, cl);
// perform the net extraction
db::Connectivity conn;
// Intra-layer
conn.connect (rpsd);
conn.connect (rnsd);
conn.connect (rpoly);
conn.connect (rdiff_cont);
conn.connect (rpoly_cont);
conn.connect (rmetal1);
conn.connect (rvia1);
conn.connect (rmetal2);
// Inter-layer
conn.connect (rpsd, rdiff_cont);
conn.connect (rnsd, rdiff_cont);
conn.connect (rpoly, rpoly_cont);
conn.connect (rpoly_cont, rmetal1);
conn.connect (rdiff_cont, rmetal1);
conn.connect (rmetal1, rvia1);
conn.connect (rvia1, rmetal2);
conn.connect (rpoly, rpoly_lbl); // attaches labels
conn.connect (rmetal1, rmetal1_lbl); // attaches labels
conn.connect (rmetal2, rmetal2_lbl); // attaches labels
// extract the nets
db::NetlistExtractor net_ex;
net_ex.set_include_floating_subcircuits (true);
net_ex.extract_nets (dss, 0, conn, nl, cl);
// compare netlist as string
CHECKPOINT ();
db::compare_netlist (_this, nl,
"circuit RINGO ();\n"
" subcircuit INV2 $1 (IN=FB,$2=$I29,OUT=$I1,$4=VSS,$5=VDD);\n"
" subcircuit INV2 $2 (IN=$I1,$2=$I30,OUT=$I2,$4=VSS,$5=VDD);\n"
" subcircuit INV2X $3 ($1=VDD,$2=VSS,$3=$I25,$4=$I11);\n"
" subcircuit TRANSISO $4 ();\n" // effect of "include floating subcircuits"!
" subcircuit INV2 $5 (IN=$I9,$2=$I31,OUT=$I3,$4=VSS,$5=VDD);\n"
" subcircuit INV2 $6 (IN=$I3,$2=$I32,OUT=$I25,$4=VSS,$5=VDD);\n"
" subcircuit TRANSISOB $7 ();\n" // effect of "include floating subcircuits"!
" subcircuit INV2 $7 (IN=$I11,$2=$I33,OUT=$I5,$4=VSS,$5=VDD);\n"
" subcircuit INV2 $8 (IN=$I5,$2=FB,OUT=OSC,$4=VSS,$5=VDD);\n"
" subcircuit INV2X $9 ($1=VDD,$2=VSS,$3=$I2,$4=$I9);\n"
"end;\n"
"circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);\n"
" device PMOS $1 (S=$2,G=IN,D=$5) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device PMOS $2 (S=$5,G=$2,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" device NMOS $3 (S=$2,G=IN,D=$4) (L=0.25,W=0.95,AS=0.49875,AD=0.26125,PS=2.95,PD=1.5);\n"
" device NMOS $4 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0.26125,AD=0.49875,PS=1.5,PD=2.95);\n"
" subcircuit TRANS $1 ($1=$2,$2=$4,$3=IN);\n"
" subcircuit TRANS $2 ($1=$2,$2=$5,$3=IN);\n"
" subcircuit TRANS $3 ($1=$4,$2=OUT,$3=$2);\n"
" subcircuit TRANS $4 ($1=$5,$2=OUT,$3=$2);\n"
"end;\n"
"circuit TRANS ($1=$1,$2=$2,$3=$3);\n"
"end;\n"
"circuit INV2X ($1=$I4,$2=$I3,$3=$I2,$4=$I1);\n"
" subcircuit INV2 $1 (IN=$I2,$2=$I6,OUT=$I5,$4=$I3,$5=$I4);\n"
" subcircuit INV2 $2 (IN=$I5,$2=$I7,OUT=$I1,$4=$I3,$5=$I4);\n"
" subcircuit TRANSISO $3 ();\n" // effect of "include floating subcircuits"!
" subcircuit TRANSISO $4 ();\n" // effect of "include floating subcircuits"!
" subcircuit TRANSISOB $5 ();\n" // effect of "include floating subcircuits"!
"end;\n"
"circuit TRANSISO ();\n"
" device NMOS $1 (S=$1,G=$2,D=$1) (L=0.25,W=0.95,AS=0.49875,AD=0.49875,PS=2.95,PD=2.95);\n"
"end;\n"
"circuit TRANSISOB ();\n"
" device NMOS $1 (S=$1,G=$2,D=$1) (L=0.25,W=0.95,AS=0.49875,AD=0.49875,PS=2.95,PD=2.95);\n"
"end;\n"
);
}

View File

@ -1669,7 +1669,7 @@ NetTracerDialog::trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView
tracer_data.configure_l2n (*l2ndb);
l2ndb->extract_netlist ();
l2ndb->extract_netlist (std::string (), flat /*include floating subcircuits for netlist to flatten*/);
if (flat) {
l2ndb->netlist ()->flatten ();

Binary file not shown.