mirror of https://github.com/KLayout/klayout.git
Netlist: flatten subcircuits, circuits
This commit is contained in:
parent
18ee59023e
commit
df2bd5e80a
|
|
@ -317,6 +317,87 @@ void Circuit::unregister_ref (SubCircuit *r)
|
|||
m_refs.erase (r);
|
||||
}
|
||||
|
||||
void Circuit::flatten_subcircuit (SubCircuit *subcircuit)
|
||||
{
|
||||
const db::Circuit *c = subcircuit->circuit_ref ();
|
||||
|
||||
// copy the nets, produce a net map
|
||||
|
||||
std::map<const db::Net *, db::Net *> net2net;
|
||||
|
||||
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
|
||||
|
||||
// TODO: cannot join pins through subcircuits currently
|
||||
tl_assert (n->pin_count () <= 1);
|
||||
|
||||
db::Net *outside_net = 0;
|
||||
|
||||
if (n->pin_count () > 0) {
|
||||
size_t pin_id = n->begin_pins ()->pin_id ();
|
||||
outside_net = subcircuit->net_for_pin (pin_id);
|
||||
} else {
|
||||
outside_net = new db::Net ();
|
||||
if (! n->name ().empty ()) {
|
||||
outside_net->set_name (subcircuit->expanded_name () + "." + n->name ());
|
||||
}
|
||||
add_net (outside_net);
|
||||
}
|
||||
|
||||
net2net.insert (std::make_pair (n.operator-> (), outside_net));
|
||||
|
||||
}
|
||||
|
||||
// copy the devices
|
||||
|
||||
for (db::Circuit::const_device_iterator d = c->begin_devices (); d != c->end_devices (); ++d) {
|
||||
|
||||
db::Device *device = new db::Device (*d);
|
||||
if (! d->name ().empty ()) {
|
||||
device->set_name (subcircuit->expanded_name () + "." + d->name ());
|
||||
}
|
||||
add_device (device);
|
||||
|
||||
const std::vector<db::DeviceTerminalDefinition> &td = d->device_class ()->terminal_definitions ();
|
||||
for (std::vector<db::DeviceTerminalDefinition>::const_iterator t = td.begin (); t != td.end (); ++t) {
|
||||
|
||||
const db::Net *tnet = d->net_for_terminal (t->id ());
|
||||
if (tnet) {
|
||||
std::map<const db::Net *, db::Net *>::const_iterator n2n = net2net.find (tnet);
|
||||
tl_assert (n2n != net2net.end ());
|
||||
device->connect_terminal (t->id (), n2n->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// copy the subcircuits
|
||||
|
||||
for (db::Circuit::const_subcircuit_iterator sc = c->begin_subcircuits (); sc != c->end_subcircuits (); ++sc) {
|
||||
|
||||
db::SubCircuit *new_subcircuit = new db::SubCircuit (*sc);
|
||||
if (! new_subcircuit->name ().empty ()) {
|
||||
new_subcircuit->set_name (subcircuit->expanded_name () + "." + new_subcircuit->name ());
|
||||
}
|
||||
add_subcircuit (new_subcircuit);
|
||||
|
||||
const db::Circuit *cr = sc->circuit_ref ();
|
||||
for (db::Circuit::const_pin_iterator p = cr->begin_pins (); p != cr->end_pins (); ++p) {
|
||||
|
||||
const db::Net *pnet = sc->net_for_pin (p->id ());
|
||||
if (pnet) {
|
||||
std::map<const db::Net *, db::Net *>::const_iterator n2n = net2net.find (pnet);
|
||||
tl_assert (n2n != net2net.end ());
|
||||
new_subcircuit->connect_pin (p->id (), n2n->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
remove_subcircuit (subcircuit);
|
||||
}
|
||||
|
||||
void Circuit::translate_circuits (const std::map<const Circuit *, Circuit *> &map)
|
||||
{
|
||||
for (subcircuit_iterator i = m_subcircuits.begin (); i != m_subcircuits.end (); ++i) {
|
||||
|
|
|
|||
|
|
@ -589,6 +589,15 @@ public:
|
|||
*/
|
||||
void combine_devices ();
|
||||
|
||||
/**
|
||||
* @brief Flattens the given subcircuit
|
||||
*
|
||||
* The subcircuit is resolved into the parent circuit and finally removed.
|
||||
* Net, device and subcircuit names are decorated with the subcircuit's name
|
||||
* if required.
|
||||
*/
|
||||
void flatten_subcircuit (SubCircuit *subcircuit);
|
||||
|
||||
private:
|
||||
friend class Netlist;
|
||||
friend class Net;
|
||||
|
|
|
|||
|
|
@ -369,6 +369,20 @@ void Netlist::remove_circuit (Circuit *circuit)
|
|||
m_circuits.erase (circuit);
|
||||
}
|
||||
|
||||
void Netlist::flatten_circuit (Circuit *circuit)
|
||||
{
|
||||
std::vector<db::SubCircuit *> refs;
|
||||
for (db::Circuit::refs_iterator sc = circuit->begin_refs (); sc != circuit->end_refs (); ++sc) {
|
||||
refs.push_back (sc.operator-> ());
|
||||
}
|
||||
|
||||
for (std::vector<db::SubCircuit *>::const_iterator r = refs.begin (); r != refs.end (); ++r) {
|
||||
(*r)->circuit ()->flatten_subcircuit (*r);
|
||||
}
|
||||
|
||||
remove_circuit (circuit);
|
||||
}
|
||||
|
||||
DeviceClass *Netlist::device_class_by_name (const std::string &name)
|
||||
{
|
||||
for (device_class_iterator d = begin_device_classes (); d != end_device_classes (); ++d) {
|
||||
|
|
|
|||
|
|
@ -138,6 +138,12 @@ public:
|
|||
*/
|
||||
void remove_circuit (Circuit *circuit);
|
||||
|
||||
/**
|
||||
* @brief Flattens the given circuit
|
||||
* All subcircuit references are replaced by the content of this circuit.
|
||||
*/
|
||||
void flatten_circuit (Circuit *circuit);
|
||||
|
||||
/**
|
||||
* @brief Begin iterator for the circuits of the netlist (non-const version)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -956,6 +956,11 @@ Class<db::Circuit> decl_dbCircuit ("db", "Circuit",
|
|||
gsi::method ("remove_subcircuit", &db::Circuit::remove_subcircuit, gsi::arg ("subcircuit"),
|
||||
"@brief Removes the given subcircuit from the circuit\n"
|
||||
) +
|
||||
gsi::method ("flatten_subcircuit", &db::Circuit::flatten_subcircuit, gsi::arg ("subcircuit"),
|
||||
"@brief Flattens a subcircuit\n"
|
||||
"This method will substitute the given subcircuit by it's contents. The subcircuit is removed "
|
||||
"after this."
|
||||
) +
|
||||
gsi::iterator ("each_subcircuit", (db::Circuit::subcircuit_iterator (db::Circuit::*) ()) &db::Circuit::begin_subcircuits, (db::Circuit::subcircuit_iterator (db::Circuit::*) ()) &db::Circuit::end_subcircuits,
|
||||
"@brief Iterates over the subcircuits of the circuit"
|
||||
) +
|
||||
|
|
@ -1084,6 +1089,11 @@ Class<db::Netlist> decl_dbNetlist ("db", "Netlist",
|
|||
"@brief Removes the given circuit object from the netlist\n"
|
||||
"After the object has been removed, it becomes invalid and cannot be used further."
|
||||
) +
|
||||
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 "
|
||||
"contents. After this, the circuit is removed."
|
||||
) +
|
||||
gsi::method ("circuit_by_cell_index", (db::Circuit *(db::Netlist::*) (db::cell_index_type)) &db::Netlist::circuit_by_cell_index, gsi::arg ("cell_index"),
|
||||
"@brief Gets the circuit object for a given cell index.\n"
|
||||
"If the cell index is not valid or no circuit is registered with this index, nil is returned."
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
|
||||
#include "dbNetlist.h"
|
||||
#include "dbNetlistDeviceClasses.h"
|
||||
|
||||
#include "tlUnitTest.h"
|
||||
#include "tlString.h"
|
||||
|
|
@ -1104,3 +1105,176 @@ TEST(13_DeviceAbstract)
|
|||
EXPECT_EQ (nl.begin_device_abstracts () == nl.end_device_abstracts (), true);
|
||||
}
|
||||
|
||||
TEST(20_FlattenSubCircuit)
|
||||
{
|
||||
db::Netlist nl;
|
||||
|
||||
db::DeviceClass *dc;
|
||||
|
||||
dc = new db::DeviceClassMOS3Transistor ();
|
||||
dc->set_name ("NMOS");
|
||||
nl.add_device_class (dc);
|
||||
|
||||
dc = new db::DeviceClassMOS3Transistor ();
|
||||
dc->set_name ("PMOS");
|
||||
nl.add_device_class (dc);
|
||||
|
||||
nl.from_string (
|
||||
"circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);\n"
|
||||
" subcircuit PTRANS SC1 ($1=$5,$2=$2,$3=IN);\n"
|
||||
" subcircuit NTRANS SC2 ($1=$4,$2=$2,$3=IN);\n"
|
||||
" subcircuit PTRANS SC3 ($1=$5,$2=OUT,$3=$2);\n"
|
||||
" subcircuit NTRANS SC4 ($1=$4,$2=OUT,$3=$2);\n"
|
||||
"end;\n"
|
||||
"circuit PTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device PMOS $1 (S=$1,D=$2,G=$3) (L=0.25,W=0.95);\n"
|
||||
"end;\n"
|
||||
"circuit NTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device NMOS $1 (S=$1,D=$2,G=$3) (L=0.25,W=0.95);\n"
|
||||
"end;\n"
|
||||
);
|
||||
|
||||
db::Netlist nl2;
|
||||
|
||||
nl2 = nl;
|
||||
db::Circuit *inv2 = nl2.circuit_by_name ("INV2");
|
||||
inv2->flatten_subcircuit (inv2->subcircuit_by_name ("SC1"));
|
||||
|
||||
EXPECT_EQ (nl2.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"
|
||||
" subcircuit NTRANS SC2 ($1=$4,$2=$2,$3=IN);\n"
|
||||
" subcircuit PTRANS SC3 ($1=$5,$2=OUT,$3=$2);\n"
|
||||
" subcircuit NTRANS SC4 ($1=$4,$2=OUT,$3=$2);\n"
|
||||
"end;\n"
|
||||
"circuit PTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device PMOS $1 (S=$1,G=$3,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
"circuit NTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device NMOS $1 (S=$1,G=$3,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
|
||||
nl2.flatten_circuit (nl2.circuit_by_name ("PTRANS"));
|
||||
nl2.flatten_circuit (nl2.circuit_by_name ("NTRANS"));
|
||||
|
||||
EXPECT_EQ (nl2.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)
|
||||
{
|
||||
db::Netlist nl;
|
||||
|
||||
db::DeviceClass *dc;
|
||||
|
||||
dc = new db::DeviceClassMOS3Transistor ();
|
||||
dc->set_name ("NMOS");
|
||||
nl.add_device_class (dc);
|
||||
|
||||
dc = new db::DeviceClassMOS3Transistor ();
|
||||
dc->set_name ("PMOS");
|
||||
nl.add_device_class (dc);
|
||||
|
||||
nl.from_string (
|
||||
"circuit RINGO (IN=IN,OSC=OSC,VSS=VSS,VDD=VDD);\n"
|
||||
" subcircuit INV2 INV2_SC1 (IN=$I8,$2=FB,OUT=OSC,$4=VSS,$5=VDD);\n"
|
||||
" subcircuit INV2 INV2_SC2 (IN=FB,$2=(null),OUT=$I8,$4=VSS,$5=VDD);\n"
|
||||
"end;\n"
|
||||
"circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);\n"
|
||||
" subcircuit PTRANS SC1 ($1=$5,$2=$2,$3=IN);\n"
|
||||
" subcircuit NTRANS SC2 ($1=$4,$2=$2,$3=IN);\n"
|
||||
" subcircuit PTRANS SC3 ($1=$5,$2=OUT,$3=$2);\n"
|
||||
" subcircuit NTRANS SC4 ($1=$4,$2=OUT,$3=$2);\n"
|
||||
"end;\n"
|
||||
"circuit PTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device PMOS $1 (S=$1,D=$2,G=$3) (L=0.25,W=0.95);\n"
|
||||
"end;\n"
|
||||
"circuit NTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device NMOS $1 (S=$1,D=$2,G=$3) (L=0.25,W=0.95);\n"
|
||||
"end;\n"
|
||||
);
|
||||
|
||||
db::Netlist nl2;
|
||||
|
||||
nl2 = nl;
|
||||
db::Circuit *inv2 = nl2.circuit_by_name ("RINGO");
|
||||
inv2->flatten_subcircuit (inv2->subcircuit_by_name ("INV2_SC1"));
|
||||
|
||||
EXPECT_EQ (nl2.to_string (),
|
||||
"circuit RINGO (IN=IN,OSC=OSC,VSS=VSS,VDD=VDD);\n"
|
||||
" subcircuit INV2 INV2_SC2 (IN=FB,$2=(null),OUT=$I8,$4=VSS,$5=VDD);\n"
|
||||
" subcircuit PTRANS INV2_SC1.SC1 ($1=VDD,$2=FB,$3=$I8);\n"
|
||||
" subcircuit NTRANS INV2_SC1.SC2 ($1=VSS,$2=FB,$3=$I8);\n"
|
||||
" subcircuit PTRANS INV2_SC1.SC3 ($1=VDD,$2=OSC,$3=FB);\n"
|
||||
" subcircuit NTRANS INV2_SC1.SC4 ($1=VSS,$2=OSC,$3=FB);\n"
|
||||
"end;\n"
|
||||
"circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);\n"
|
||||
" subcircuit PTRANS SC1 ($1=$5,$2=$2,$3=IN);\n"
|
||||
" subcircuit NTRANS SC2 ($1=$4,$2=$2,$3=IN);\n"
|
||||
" subcircuit PTRANS SC3 ($1=$5,$2=OUT,$3=$2);\n"
|
||||
" subcircuit NTRANS SC4 ($1=$4,$2=OUT,$3=$2);\n"
|
||||
"end;\n"
|
||||
"circuit PTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device PMOS $1 (S=$1,G=$3,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
"circuit NTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device NMOS $1 (S=$1,G=$3,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
|
||||
inv2->flatten_subcircuit (inv2->subcircuit_by_name ("INV2_SC2"));
|
||||
|
||||
EXPECT_EQ (nl2.to_string (),
|
||||
"circuit RINGO (IN=IN,OSC=OSC,VSS=VSS,VDD=VDD);\n"
|
||||
" subcircuit PTRANS INV2_SC1.SC1 ($1=VDD,$2=FB,$3=$I8);\n"
|
||||
" subcircuit NTRANS INV2_SC1.SC2 ($1=VSS,$2=FB,$3=$I8);\n"
|
||||
" subcircuit PTRANS INV2_SC1.SC3 ($1=VDD,$2=OSC,$3=FB);\n"
|
||||
" subcircuit NTRANS INV2_SC1.SC4 ($1=VSS,$2=OSC,$3=FB);\n"
|
||||
" subcircuit PTRANS INV2_SC2.SC1 ($1=VDD,$2=(null),$3=FB);\n"
|
||||
" subcircuit NTRANS INV2_SC2.SC2 ($1=VSS,$2=(null),$3=FB);\n"
|
||||
" subcircuit PTRANS INV2_SC2.SC3 ($1=VDD,$2=$I8,$3=(null));\n"
|
||||
" subcircuit NTRANS INV2_SC2.SC4 ($1=VSS,$2=$I8,$3=(null));\n"
|
||||
"end;\n"
|
||||
"circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);\n"
|
||||
" subcircuit PTRANS SC1 ($1=$5,$2=$2,$3=IN);\n"
|
||||
" subcircuit NTRANS SC2 ($1=$4,$2=$2,$3=IN);\n"
|
||||
" subcircuit PTRANS SC3 ($1=$5,$2=OUT,$3=$2);\n"
|
||||
" subcircuit NTRANS SC4 ($1=$4,$2=OUT,$3=$2);\n"
|
||||
"end;\n"
|
||||
"circuit PTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device PMOS $1 (S=$1,G=$3,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
"circuit NTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device NMOS $1 (S=$1,G=$3,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
|
||||
nl2 = nl;
|
||||
nl2.flatten_circuit (nl2.circuit_by_name ("INV2"));
|
||||
|
||||
EXPECT_EQ (nl2.to_string (),
|
||||
"circuit RINGO (IN=IN,OSC=OSC,VSS=VSS,VDD=VDD);\n"
|
||||
" subcircuit PTRANS INV2_SC1.SC1 ($1=VDD,$2=FB,$3=$I8);\n"
|
||||
" subcircuit NTRANS INV2_SC1.SC2 ($1=VSS,$2=FB,$3=$I8);\n"
|
||||
" subcircuit PTRANS INV2_SC1.SC3 ($1=VDD,$2=OSC,$3=FB);\n"
|
||||
" subcircuit NTRANS INV2_SC1.SC4 ($1=VSS,$2=OSC,$3=FB);\n"
|
||||
" subcircuit PTRANS INV2_SC2.SC1 ($1=VDD,$2=(null),$3=FB);\n"
|
||||
" subcircuit NTRANS INV2_SC2.SC2 ($1=VSS,$2=(null),$3=FB);\n"
|
||||
" subcircuit PTRANS INV2_SC2.SC3 ($1=VDD,$2=$I8,$3=(null));\n"
|
||||
" subcircuit NTRANS INV2_SC2.SC4 ($1=VSS,$2=$I8,$3=(null));\n"
|
||||
"end;\n"
|
||||
"circuit PTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device PMOS $1 (S=$1,G=$3,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
"circuit NTRANS ($1=$1,$2=$2,$3=$3);\n"
|
||||
" device NMOS $1 (S=$1,G=$3,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);\n"
|
||||
"end;\n"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -714,6 +714,66 @@ END
|
|||
|
||||
end
|
||||
|
||||
def test_11_FlattenCircuits
|
||||
|
||||
nl = RBA::Netlist::new
|
||||
|
||||
dc = RBA::DeviceClassMOS3Transistor::new
|
||||
dc.name = "NMOS"
|
||||
nl.add(dc)
|
||||
|
||||
dc = RBA::DeviceClassMOS3Transistor::new
|
||||
dc.name = "PMOS"
|
||||
nl.add(dc)
|
||||
|
||||
nl.from_s(<<"END")
|
||||
circuit INV2 (IN=IN,$2=$2,OUT=OUT,$4=$4,$5=$5);
|
||||
subcircuit PTRANS SC1 ($1=$5,$2=$2,$3=IN);
|
||||
subcircuit NTRANS SC2 ($1=$4,$2=$2,$3=IN);
|
||||
subcircuit PTRANS SC3 ($1=$5,$2=OUT,$3=$2);
|
||||
subcircuit NTRANS SC4 ($1=$4,$2=OUT,$3=$2);
|
||||
end;
|
||||
circuit PTRANS ($1=$1,$2=$2,$3=$3);
|
||||
device PMOS $1 (S=$1,D=$2,G=$3) (L=0.25,W=0.95);
|
||||
end;
|
||||
circuit NTRANS ($1=$1,$2=$2,$3=$3);
|
||||
device NMOS $1 (S=$1,D=$2,G=$3) (L=0.25,W=0.95);
|
||||
end;
|
||||
END
|
||||
|
||||
nl2 = nl.dup
|
||||
inv2 = nl2.circuit_by_name("INV2")
|
||||
inv2.flatten_subcircuit(inv2.subcircuit_by_name("SC1"))
|
||||
|
||||
assert_equal(nl2.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);
|
||||
subcircuit NTRANS SC2 ($1=$4,$2=$2,$3=IN);
|
||||
subcircuit PTRANS SC3 ($1=$5,$2=OUT,$3=$2);
|
||||
subcircuit NTRANS SC4 ($1=$4,$2=OUT,$3=$2);
|
||||
end;
|
||||
circuit PTRANS ($1=$1,$2=$2,$3=$3);
|
||||
device PMOS $1 (S=$1,G=$3,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
|
||||
end;
|
||||
circuit NTRANS ($1=$1,$2=$2,$3=$3);
|
||||
device NMOS $1 (S=$1,G=$3,D=$2) (L=0.25,W=0.95,AS=0,AD=0,PS=0,PD=0);
|
||||
end;
|
||||
END
|
||||
|
||||
nl2.flatten_circuit(nl2.circuit_by_name("PTRANS"))
|
||||
nl2.flatten_circuit(nl2.circuit_by_name("NTRANS"))
|
||||
|
||||
assert_equal(nl2.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);
|
||||
end;
|
||||
END
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
load("test_epilogue.rb")
|
||||
|
|
|
|||
Loading…
Reference in New Issue