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);
|
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)
|
void Netlist::flatten_circuit (Circuit *circuit)
|
||||||
{
|
{
|
||||||
tl_assert (circuit != 0);
|
tl_assert (circuit != 0);
|
||||||
|
|
|
||||||
|
|
@ -174,6 +174,12 @@ public:
|
||||||
*/
|
*/
|
||||||
void flatten_circuit (Circuit *circuit);
|
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
|
* @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)
|
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);
|
tl::GlobPattern pat (name_pattern);
|
||||||
for (db::Netlist::circuit_iterator c = nl->begin_circuits (); c != nl->end_circuits (); ++c) {
|
for (db::Netlist::circuit_iterator c = nl->begin_circuits (); c != nl->end_circuits (); ++c) {
|
||||||
if (pat.match (c->name ())) {
|
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) {
|
nl->flatten_circuits (circuits_to_flatten);
|
||||||
if (c->get ()) {
|
|
||||||
nl->flatten_circuit (c->get ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void blank_circuit_by_name (db::Netlist *nl, const std::string &name_pattern)
|
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"
|
"@brief Flattens all circuits of the netlist\n"
|
||||||
"After calling this method, only the top circuits will remain."
|
"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"),
|
gsi::method ("flatten_circuit", &db::Netlist::flatten_circuit, gsi::arg ("circuit"),
|
||||||
"@brief Flattens a subcircuit\n"
|
"@brief Flattens a subcircuit\n"
|
||||||
"This method will substitute all instances (subcircuits) of the given circuit by it's "
|
"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
|
# flatten layout cells for which there is no corresponding schematic circuit
|
||||||
unmatched_a.each do |c|
|
unmatched_a.each do |c|
|
||||||
@engine.info("Flatten layout cell (no schematic): #{c.name}")
|
@engine.info("Flatten layout cell (no schematic): #{c.name}")
|
||||||
nl[0].flatten_circuit(c)
|
|
||||||
end
|
end
|
||||||
|
nl[0].flatten_circuits(unmatched_a)
|
||||||
|
|
||||||
# flatten schematic circuits for which there is no corresponding layout cell
|
# 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}")
|
@engine.info("Flatten schematic circuit (no layout): #{c.name}")
|
||||||
nl[1].flatten_circuit(c)
|
|
||||||
end
|
end
|
||||||
|
nl[1].flatten_circuits(unmatched_b)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -841,25 +841,36 @@ end;
|
||||||
END
|
END
|
||||||
|
|
||||||
nl3 = nl2.dup
|
nl3 = nl2.dup
|
||||||
nl2.flatten_circuit(nl2.circuit_by_name("PTRANS"))
|
nl3.flatten_circuit(nl3.circuit_by_name("NTRANS"))
|
||||||
nl2.flatten_circuit(nl2.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);
|
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 $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 $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=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 NMOS $4 (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;
|
||||||
END
|
END
|
||||||
|
|
||||||
nl3.flatten_circuit("{N,P}TRANS")
|
nl4 = nl2.dup
|
||||||
assert_equal(nl3.to_s, nl2.to_s)
|
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 = nl.dup
|
||||||
nl2.flatten_circuit("*") # smoke test
|
nl2.flatten_circuit("*") # smoke test
|
||||||
assert_equal(nl2.to_s, "")
|
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
|
end
|
||||||
|
|
||||||
def test_12_BlankAndPurgeCircuits
|
def test_12_BlankAndPurgeCircuits
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue