mirror of https://github.com/KLayout/klayout.git
commit
9e30539476
|
|
@ -396,6 +396,22 @@ void Netlist::flatten_circuit (Circuit *circuit)
|
|||
delete circuit;
|
||||
}
|
||||
|
||||
void Netlist::flatten ()
|
||||
{
|
||||
std::set<db::Circuit *> top_circuits;
|
||||
size_t ntop = top_circuit_count ();
|
||||
for (db::Netlist::top_down_circuit_iterator tc = begin_top_down (); tc != end_top_down () && ntop > 0; ++tc) {
|
||||
top_circuits.insert (tc.operator-> ());
|
||||
--ntop;
|
||||
}
|
||||
|
||||
for (db::Netlist::bottom_up_circuit_iterator c = begin_bottom_up (); c != end_bottom_up(); ++c) {
|
||||
if (top_circuits.find (c.operator-> ()) == top_circuits.end ()) {
|
||||
flatten_circuit (c.operator-> ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeviceClass *Netlist::device_class_by_name (const std::string &name)
|
||||
{
|
||||
for (device_class_iterator d = begin_device_classes (); d != end_device_classes (); ++d) {
|
||||
|
|
|
|||
|
|
@ -174,6 +174,11 @@ public:
|
|||
*/
|
||||
void flatten_circuit (Circuit *circuit);
|
||||
|
||||
/**
|
||||
* @brief Flattens the netlist
|
||||
*/
|
||||
void flatten ();
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the circuits of the netlist (non-const version)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1388,6 +1388,10 @@ Class<db::Netlist> decl_dbNetlist ("db", "Netlist",
|
|||
"A circuit with references (see \\has_refs?) should not be removed as the "
|
||||
"subcircuits calling it would afterwards point to nothing."
|
||||
) +
|
||||
gsi::method ("flatten", &db::Netlist::flatten,
|
||||
"@brief Flattens all circuits of the netlist\n"
|
||||
"After calling this method, only the top circuits will remain."
|
||||
) +
|
||||
gsi::method ("flatten_circuit", &db::Netlist::flatten_circuit, gsi::arg ("circuit"),
|
||||
"@brief Flattens a subcircuit\n"
|
||||
"This method will substitute all instances (subcircuits) of the given circuit by it's "
|
||||
|
|
|
|||
|
|
@ -1188,6 +1188,20 @@ TEST(20_FlattenSubCircuit)
|
|||
" device NMOS $4 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
|
||||
db::Netlist nl3;
|
||||
|
||||
nl3 = nl;
|
||||
nl3.flatten ();
|
||||
|
||||
EXPECT_EQ (nl3.to_string (),
|
||||
"circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);\n"
|
||||
" device PMOS $1 (S=$5,G=IN,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
" device PMOS $2 (S=$5,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
" device NMOS $3 (S=$4,G=IN,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
" device NMOS $4 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
}
|
||||
|
||||
TEST(21_FlattenSubCircuit2)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
<pre>same_nets("LOGIC", "VDD", "VDD:P")</pre>
|
||||
|
||||
<p>
|
||||
In this example it is assumed that the power net is labelled "VDD" in the
|
||||
In this example it is assumed that the power net is labeled "VDD" in the
|
||||
layout and called "VDD:P" in the schematic. Don't leave this statement in
|
||||
the script for final verification as it may mask real errors.
|
||||
</p>
|
||||
|
|
@ -160,7 +160,8 @@ same_device_classes("NMOS_IN_LAYOUT", "NMOS_IN_SCHEMATIC")</pre>
|
|||
</p>
|
||||
|
||||
<p>
|
||||
In general, it's a good idea to include "align" before the "compare" step.
|
||||
In general, it's a good idea to include "align" before "netlist.simplify" or
|
||||
similar netlist manipulation and the "compare" step.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ connect(metal2, metal2_labels)</pre>
|
|||
|
||||
<p>
|
||||
If labels are connected to metal layers, their text strings will be used to assign
|
||||
net names to the resulting nets. Ideally, one net is labelled with a single text
|
||||
net names to the resulting nets. Ideally, one net is labeled with a single text
|
||||
or with texts with the same text string. In this case, the net name will
|
||||
be non-ambiguous. If multiple labels with different strings are present on a net,
|
||||
the net name will be made from a combination of these names.
|
||||
|
|
|
|||
|
|
@ -156,6 +156,9 @@ connect_global(nwell, "NWELL")
|
|||
|
||||
schematic("inv.cir")
|
||||
|
||||
align # flattens unpaired circuits
|
||||
netlist.simplify # removes floating nets, combines devices
|
||||
|
||||
compare</pre>
|
||||
|
||||
<p>
|
||||
|
|
@ -336,11 +339,35 @@ connect_global(nwell, "NWELL")</pre>
|
|||
|
||||
<p>
|
||||
We have now provided all the essential inputs for the netlist formation.
|
||||
We only have to specify the reference netlist:
|
||||
We now have to specify the reference netlist:
|
||||
</p>
|
||||
|
||||
<pre>schematic("inv.cir")</pre>
|
||||
|
||||
<p>
|
||||
Two optional, but recommended steps are hierarchy alignment and extracted
|
||||
netlist simplification:
|
||||
</p>
|
||||
|
||||
<pre>align # flattens unpaired circuits
|
||||
netlist.simplify # removes floating nets, combines devices
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
"align" will remove circuits which are not present in the other netlist by
|
||||
integrating their content into the parent cell. This will remove auxiliary cells
|
||||
which are usually present in a layout but don't map to a schematic cell (e.g.
|
||||
device PCells). "netlist.simplify" reduces the netlist by floating nets,
|
||||
performs device combination (e.g. fingered transistors). This method will
|
||||
also create pins from labeled nets in the top level circuit.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The order should be "align", then "netlist.simplify". Both have to happen before
|
||||
"compare" to be effective. "align" is described in <link href="/manual/lvs_compare.xml"/>,
|
||||
"netlist.simplify" in <link href="/manual/lvs_tweaks.xml"/>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Finally after having set this up, we can trigger the compare step:
|
||||
</p>
|
||||
|
|
@ -498,6 +525,9 @@ connect_global(ptie, "SUBSTRATE")
|
|||
|
||||
schematic("inv2.cir")
|
||||
|
||||
align
|
||||
netlist.simplify
|
||||
|
||||
compare</pre>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
<p>
|
||||
KLayout offers a function to create top-level pins using
|
||||
a simple heuristics: for every named (i.e. labelled) net in the top level
|
||||
a simple heuristics: for every named (i.e. labeled) net in the top level
|
||||
circuit a pin will be created (<class_doc href="Netlist#make_top_level_pins"/>):
|
||||
</p>
|
||||
|
||||
|
|
@ -199,9 +199,16 @@ netlist.purge_nets</pre>
|
|||
|
||||
<p>
|
||||
<class_doc href="Netlist#simplify"/> is a wrapper for "make_top_level_pins",
|
||||
"combine_devices" and "purge" in the recommended order:
|
||||
"purge", "combine_devices" and "purge_nets" in this recommended order:
|
||||
</p>
|
||||
|
||||
<pre>netlist.simplify</pre>
|
||||
|
||||
<p>
|
||||
As a technical detail, "make_top_level_pins" is included in this sequence as with
|
||||
pins, nets are not considered floating. So "purge_nets" will maintain pins for
|
||||
labeled nets even if these nets are not connected to devices. This allows adding
|
||||
optional pins while maintaining the top level circuit's interface.
|
||||
</p>
|
||||
|
||||
</doc>
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@
|
|||
<li>Export all or selected nets to layout, save the netlist (with shapes) to a file, load it back from a file and manage
|
||||
the netlist database. Use the "File" menu button in the right upper corner.
|
||||
</li>
|
||||
<li>Search for net names (if labelled) and circuits using the search edit box.
|
||||
<li>Search for net names (if labeled) and circuits using the search edit box.
|
||||
</li>
|
||||
<li>Navigate through the history using the "back" and "forward" buttons at the top left.
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -559,13 +559,15 @@ NetTracerDialog::menu_activated (const std::string &symbol)
|
|||
|
||||
layer_stack_clicked ();
|
||||
|
||||
} else if (symbol == "lay::trace_all_nets") {
|
||||
} else if (symbol == "lay::trace_all_nets" || symbol == "lay::trace_all_nets_flat") {
|
||||
|
||||
bool flat = symbol == "lay::trace_all_nets_flat";
|
||||
|
||||
const lay::CellView &cv = view ()->cellview (view ()->active_cellview_index ());
|
||||
if (cv.is_valid ()) {
|
||||
db::RecursiveShapeIterator si (cv->layout (), *cv.cell (), std::vector<unsigned int> ());
|
||||
std::auto_ptr <db::LayoutToNetlist> l2ndb (new db::LayoutToNetlist (si));
|
||||
trace_all_nets (l2ndb.get (), cv);
|
||||
trace_all_nets (l2ndb.get (), cv, flat);
|
||||
unsigned int l2ndb_index = view ()->add_l2ndb (l2ndb.release ());
|
||||
view ()->open_l2ndb_browser (l2ndb_index, view ()->index_of_cellview (&cv));
|
||||
}
|
||||
|
|
@ -1658,7 +1660,7 @@ NetTracerDialog::clear_markers ()
|
|||
}
|
||||
|
||||
void
|
||||
NetTracerDialog::trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv)
|
||||
NetTracerDialog::trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv, bool flat)
|
||||
{
|
||||
db::NetTracerData tracer_data;
|
||||
if (! get_net_tracer_setup (cv, tracer_data)) {
|
||||
|
|
@ -1668,6 +1670,10 @@ NetTracerDialog::trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView
|
|||
tracer_data.configure_l2n (*l2ndb);
|
||||
|
||||
l2ndb->extract_netlist ();
|
||||
|
||||
if (flat) {
|
||||
l2ndb->netlist ()->flatten ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ private:
|
|||
void release_mouse ();
|
||||
db::NetTracerNet *do_trace (const db::DBox &start_search_box, const db::DBox &stop_search_box, bool trace_path);
|
||||
bool get_net_tracer_setup (const lay::CellView &cv, db::NetTracerData &data);
|
||||
void trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv);
|
||||
void trace_all_nets (db::LayoutToNetlist *l2ndb, const lay::CellView &cv, bool flat);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,9 @@ public:
|
|||
lay::PluginDeclaration::get_menu_entries (menu_entries);
|
||||
menu_entries.push_back (lay::MenuEntry ("net_trace_group", "tools_menu.end"));
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::net_trace", "net_trace", "tools_menu.end", tl::to_string (QObject::tr ("Trace Net"))));
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::trace_all_nets", "trace_all_nets", "tools_menu.end", tl::to_string (QObject::tr ("Trace All Nets"))));
|
||||
menu_entries.push_back (lay::MenuEntry ("", "trace_all_nets_menu", "tools_menu.end", tl::to_string (QObject::tr ("Trace All Nets")), true));
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::trace_all_nets", "trace_all_nets", "tools_menu.trace_all_nets_menu.end", tl::to_string (QObject::tr ("Hierarchical"))));
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::trace_all_nets_flat", "trace_all_nets_flat", "tools_menu.trace_all_nets_menu.end", tl::to_string (QObject::tr ("Flat"))));
|
||||
menu_entries.push_back (lay::MenuEntry ("lay::edit_layer_stack", "edit_layer_stack", "tools_menu.end", tl::to_string (QObject::tr ("Edit Layer Stack"))));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue