mirror of https://github.com/KLayout/klayout.git
WIP: speedup LVS 'align' by flattening top-down
This commit is contained in:
parent
f0635589f7
commit
36ee1efe16
|
|
@ -380,6 +380,30 @@ void Netlist::purge_circuit (Circuit *circuit)
|
|||
remove_circuit (circuit);
|
||||
}
|
||||
|
||||
void Netlist::flatten_circuits (const std::vector<Circuit *> &circuits)
|
||||
{
|
||||
if (circuits.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::set<Circuit *> circuits_set (circuits.begin (), circuits.end ());
|
||||
|
||||
std::vector<Circuit *> to_flatten;
|
||||
to_flatten.reserve (circuits.size ());
|
||||
|
||||
// Before flatten, we sort top-down. This optimizes for the case of flattening away
|
||||
// some hierarchy above a certain circuit.
|
||||
for (top_down_circuit_iterator c = begin_top_down (); c != end_top_down (); ++c) {
|
||||
if (circuits_set.find (c.operator-> ()) != circuits_set.end ()) {
|
||||
to_flatten.push_back (c.operator-> ());
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<Circuit *>::const_iterator c = to_flatten.begin (); c != to_flatten.end (); ++c) {
|
||||
flatten_circuit (*c);
|
||||
}
|
||||
}
|
||||
|
||||
void Netlist::flatten_circuit (Circuit *circuit)
|
||||
{
|
||||
tl_assert (circuit != 0);
|
||||
|
|
|
|||
|
|
@ -174,6 +174,12 @@ public:
|
|||
*/
|
||||
void flatten_circuit (Circuit *circuit);
|
||||
|
||||
/**
|
||||
* @brief Flattens the given circuits
|
||||
* This is basically equivalent to calling flatten on all given circuits, but more efficient.
|
||||
*/
|
||||
void flatten_circuits (const std::vector<Circuit *> &circuits);
|
||||
|
||||
/**
|
||||
* @brief Flattens the netlist
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1345,7 +1345,7 @@ static void read_netlist (db::Netlist *nl, const std::string &file, db::NetlistR
|
|||
|
||||
static void flatten_circuit_by_name (db::Netlist *nl, const std::string &name_pattern)
|
||||
{
|
||||
std::list<tl::weak_ptr<db::Circuit> > circuits_to_flatten;
|
||||
std::vector<db::Circuit *> circuits_to_flatten;
|
||||
tl::GlobPattern pat (name_pattern);
|
||||
for (db::Netlist::circuit_iterator c = nl->begin_circuits (); c != nl->end_circuits (); ++c) {
|
||||
if (pat.match (c->name ())) {
|
||||
|
|
@ -1353,11 +1353,7 @@ static void flatten_circuit_by_name (db::Netlist *nl, const std::string &name_pa
|
|||
}
|
||||
}
|
||||
|
||||
for (std::list<tl::weak_ptr<db::Circuit> >::iterator c = circuits_to_flatten.begin (); c != circuits_to_flatten.end (); ++c) {
|
||||
if (c->get ()) {
|
||||
nl->flatten_circuit (c->get ());
|
||||
}
|
||||
}
|
||||
nl->flatten_circuits (circuits_to_flatten);
|
||||
}
|
||||
|
||||
static void blank_circuit_by_name (db::Netlist *nl, const std::string &name_pattern)
|
||||
|
|
@ -1399,6 +1395,12 @@ Class<db::Netlist> decl_dbNetlist ("db", "Netlist",
|
|||
"@brief Flattens all circuits of the netlist\n"
|
||||
"After calling this method, only the top circuits will remain."
|
||||
) +
|
||||
gsi::method ("flatten_circuits", &db::Netlist::flatten_circuits,
|
||||
"@brief Flattens all given circuits of the netlist\n"
|
||||
"This method is equivalent to calling \\flatten_circuit for all given circuits, but more efficient.\n"
|
||||
"\n"
|
||||
"This method has been introduced in version 0.26.1"
|
||||
) +
|
||||
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 "
|
||||
|
|
|
|||
|
|
@ -137,14 +137,15 @@ module LVS
|
|||
# flatten layout cells for which there is no corresponding schematic circuit
|
||||
unmatched_a.each do |c|
|
||||
@engine.info("Flatten layout cell (no schematic): #{c.name}")
|
||||
nl[0].flatten_circuit(c)
|
||||
end
|
||||
nl[0].flatten_circuits(unmatched_a)
|
||||
|
||||
# flatten schematic circuits for which there is no corresponding layout cell
|
||||
comparer.unmatched_circuits_b(*nl).each do |c|
|
||||
unmatched_b = comparer.unmatched_circuits_b(*nl)
|
||||
unmatched_b.each do |c|
|
||||
@engine.info("Flatten schematic circuit (no layout): #{c.name}")
|
||||
nl[1].flatten_circuit(c)
|
||||
end
|
||||
nl[1].flatten_circuits(unmatched_b)
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -841,25 +841,36 @@ end;
|
|||
END
|
||||
|
||||
nl3 = nl2.dup
|
||||
nl2.flatten_circuit(nl2.circuit_by_name("PTRANS"))
|
||||
nl2.flatten_circuit(nl2.circuit_by_name("NTRANS"))
|
||||
nl3.flatten_circuit(nl3.circuit_by_name("NTRANS"))
|
||||
nl3.flatten_circuit(nl3.circuit_by_name("PTRANS"))
|
||||
|
||||
assert_equal(nl2.to_s, <<"END")
|
||||
assert_equal(nl3.to_s, <<"END")
|
||||
circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);
|
||||
device PMOS $1 (S=$5,G=IN,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
|
||||
device PMOS $2 (S=$5,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
|
||||
device NMOS $3 (S=$4,G=IN,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
|
||||
device NMOS $4 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
|
||||
device NMOS $2 (S=$4,G=IN,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
|
||||
device NMOS $3 (S=$4,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
|
||||
device PMOS $4 (S=$5,G=$2,D=OUT) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
|
||||
end;
|
||||
END
|
||||
|
||||
nl3.flatten_circuit("{N,P}TRANS")
|
||||
assert_equal(nl3.to_s, nl2.to_s)
|
||||
nl4 = nl2.dup
|
||||
nl4.flatten_circuit("{P,N}TRANS")
|
||||
assert_equal(nl4.to_s, nl3.to_s)
|
||||
|
||||
nl4 = nl2.dup
|
||||
nl4.flatten_circuits([ nl4.circuit_by_name("PTRANS"), nl4.circuit_by_name("NTRANS") ])
|
||||
assert_equal(nl4.to_s, nl3.to_s)
|
||||
|
||||
nl2 = nl.dup
|
||||
nl2.flatten_circuit("*") # smoke test
|
||||
assert_equal(nl2.to_s, "")
|
||||
|
||||
nl2 = nl.dup
|
||||
cc = []
|
||||
nl2.each_circuit { |c| cc << c }
|
||||
nl2.flatten_circuits(cc)
|
||||
assert_equal(nl2.to_s, "")
|
||||
|
||||
end
|
||||
|
||||
def test_12_BlankAndPurgeCircuits
|
||||
|
|
|
|||
Loading…
Reference in New Issue