mirror of https://github.com/KLayout/klayout.git
WIP Netlist probing will deliver an instantiation path now.
This commit is contained in:
parent
b72f819d57
commit
880b9904cf
|
|
@ -1041,9 +1041,9 @@ LayoutToNetlist::build_nets (const std::vector<const db::Net *> *nets, const db:
|
|||
}
|
||||
}
|
||||
|
||||
db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoint &point)
|
||||
db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::DPoint &point, std::vector<db::SubCircuit *> *sc_path_out)
|
||||
{
|
||||
return probe_net (of_region, db::CplxTrans (internal_layout ()->dbu ()).inverted () * point);
|
||||
return probe_net (of_region, db::CplxTrans (internal_layout ()->dbu ()).inverted () * point, sc_path_out);
|
||||
}
|
||||
|
||||
size_t LayoutToNetlist::search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<db::NetShape> &test_cluster, std::vector<db::InstElement> &rev_inst_path)
|
||||
|
|
@ -1077,7 +1077,7 @@ size_t LayoutToNetlist::search_net (const db::ICplxTrans &trans, const db::Cell
|
|||
return 0;
|
||||
}
|
||||
|
||||
db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Point &point)
|
||||
db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Point &point, std::vector<db::SubCircuit *> *sc_path_out)
|
||||
{
|
||||
if (! m_netlist_extracted) {
|
||||
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
|
||||
|
|
@ -1142,38 +1142,57 @@ db::Net *LayoutToNetlist::probe_net (const db::Region &of_region, const db::Poin
|
|||
|
||||
}
|
||||
|
||||
std::vector<db::SubCircuit *> sc_path;
|
||||
|
||||
db::Net *topmost_net = net;
|
||||
|
||||
// follow the path up in the net hierarchy using the transformation and the upper cell index as the
|
||||
// guide line
|
||||
while (! inst_path.empty () && net->pin_count () > 0) {
|
||||
while (circuit && ! inst_path.empty ()) {
|
||||
|
||||
cell_indexes.pop_back ();
|
||||
|
||||
const db::Pin *pin = circuit->pin_by_id (net->begin_pins ()->pin_id ());
|
||||
tl_assert (pin != 0);
|
||||
const db::Pin *pin = 0;
|
||||
if (net && net->pin_count () > 0) {
|
||||
pin = circuit->pin_by_id (net->begin_pins ()->pin_id ());
|
||||
tl_assert (pin != 0);
|
||||
}
|
||||
|
||||
db::DCplxTrans dtrans = dbu_trans * inst_path.back ().complex_trans () * dbu_trans_inv;
|
||||
|
||||
// try to find a parent circuit which connects to this net
|
||||
db::Circuit *upper_circuit = 0;
|
||||
db::SubCircuit *subcircuit = 0;
|
||||
db::Net *upper_net = 0;
|
||||
for (db::Circuit::refs_iterator r = circuit->begin_refs (); r != circuit->end_refs () && ! upper_net; ++r) {
|
||||
for (db::Circuit::refs_iterator r = circuit->begin_refs (); r != circuit->end_refs () && ! upper_circuit; ++r) {
|
||||
if (r->trans ().equal (dtrans) && r->circuit () && r->circuit ()->cell_index () == cell_indexes.back ()) {
|
||||
upper_net = r->net_for_pin (pin->id ());
|
||||
upper_circuit = r->circuit ();
|
||||
subcircuit = r.operator-> ();
|
||||
if (pin) {
|
||||
upper_net = subcircuit->net_for_pin (pin->id ());
|
||||
}
|
||||
upper_circuit = subcircuit->circuit ();
|
||||
}
|
||||
}
|
||||
|
||||
net = upper_net;
|
||||
|
||||
if (upper_net) {
|
||||
circuit = upper_circuit;
|
||||
net = upper_net;
|
||||
inst_path.pop_back ();
|
||||
topmost_net = upper_net;
|
||||
} else {
|
||||
break;
|
||||
sc_path.push_back (subcircuit);
|
||||
}
|
||||
|
||||
circuit = upper_circuit;
|
||||
inst_path.pop_back ();
|
||||
|
||||
}
|
||||
|
||||
return net;
|
||||
if (sc_path_out) {
|
||||
std::reverse (sc_path.begin (), sc_path.end ());
|
||||
*sc_path_out = sc_path;
|
||||
}
|
||||
|
||||
return topmost_net;
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -709,8 +709,11 @@ public:
|
|||
*
|
||||
* This variant accepts a micrometer-unit location. The location is given in the
|
||||
* coordinate space of the initial cell.
|
||||
*
|
||||
* The subcircuit path leading to the topmost net is stored in *sc_path_out if this
|
||||
* pointer is non-null.
|
||||
*/
|
||||
db::Net *probe_net (const db::Region &of_region, const db::DPoint &point);
|
||||
db::Net *probe_net (const db::Region &of_region, const db::DPoint &point, std::vector<SubCircuit *> *sc_path_out = 0);
|
||||
|
||||
/**
|
||||
* @brief Finds the net by probing a specific location on the given layer
|
||||
|
|
@ -718,7 +721,7 @@ public:
|
|||
* This variant accepts a database-unit location. The location is given in the
|
||||
* coordinate space of the initial cell.
|
||||
*/
|
||||
db::Net *probe_net (const db::Region &of_region, const db::Point &point);
|
||||
db::Net *probe_net (const db::Region &of_region, const db::Point &point, std::vector<SubCircuit *> *sc_path_out = 0);
|
||||
|
||||
/**
|
||||
* @brief Runs an antenna check on the extracted clusters
|
||||
|
|
|
|||
|
|
@ -543,7 +543,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
|||
gsi::method_ext ("build_nets", &build_nets, gsi::arg ("nets"), gsi::arg ("cmap"), gsi::arg ("target"), gsi::arg ("lmap"), gsi::arg ("net_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("netname_prop", tl::Variant (), "nil"), gsi::arg ("hier_mode", db::LayoutToNetlist::BNH_Flatten, "BNH_Flatten"), gsi::arg ("circuit_cell_name_prefix", tl::Variant (), "nil"), gsi::arg ("device_cell_name_prefix", tl::Variant (), "nil"),
|
||||
"@brief Like \\build_all_nets, but with the ability to select some nets."
|
||||
) +
|
||||
gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"),
|
||||
gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::DPoint &, std::vector<db::SubCircuit *> *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector<db::SubCircuit *> *) 0, "nil"),
|
||||
"@brief Finds the net by probing a specific location on the given layer\n"
|
||||
"\n"
|
||||
"This method will find a net looking at the given layer at the specific position.\n"
|
||||
|
|
@ -557,14 +557,21 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
|||
"Optimization functions such as \\Netlist#purge will remove parts of the net which means\n"
|
||||
"shape to net probing may no longer work for these nets.\n"
|
||||
"\n"
|
||||
"If non-null and an array, 'sc_path_out' will receive a list of \\SubCircuits objects which lead to the "
|
||||
"net from the top circuit of the database.\n"
|
||||
"\n"
|
||||
"This variant accepts a micrometer-unit location. The location is given in the\n"
|
||||
"coordinate space of the initial cell.\n"
|
||||
"\n"
|
||||
"The \\sc_path_out parameter has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::Point &)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"),
|
||||
gsi::method ("probe_net", (db::Net *(db::LayoutToNetlist::*) (const db::Region &, const db::Point &, std::vector<db::SubCircuit *> *)) &db::LayoutToNetlist::probe_net, gsi::arg ("of_layer"), gsi::arg ("point"), gsi::arg ("sc_path_out", (std::vector<db::SubCircuit *> *) 0, "nil"),
|
||||
"@brief Finds the net by probing a specific location on the given layer\n"
|
||||
"See the description of the other \\probe_net variant.\n"
|
||||
"This variant accepts a database-unit location. The location is given in the\n"
|
||||
"coordinate space of the initial cell.\n"
|
||||
"\n"
|
||||
"The \\sc_path_out parameter has been added in version 0.27.\n"
|
||||
) +
|
||||
gsi::method ("write|write_l2n", &db::LayoutToNetlist::save, gsi::arg ("path"), gsi::arg ("short_format", false),
|
||||
"@brief Writes the extracted netlist to a file.\n"
|
||||
|
|
|
|||
|
|
@ -466,6 +466,21 @@ Class<db::SubCircuit> decl_dbSubCircuit (decl_dbNetlistObject, "db", "SubCircuit
|
|||
gsi::method_ext ("disconnect_pin", &gsi::subcircuit_disconnect_pin1, gsi::arg ("pin"),
|
||||
"@brief Disconnects the given pin from any net.\n"
|
||||
"This version takes a \\Pin reference instead of a pin ID."
|
||||
) +
|
||||
gsi::method ("trans", &db::SubCircuit::trans,
|
||||
"@brief Gets the physical transformation for the subcircuit.\n"
|
||||
"\n"
|
||||
"This property applies to subcircuits derived from a layout. It specifies the "
|
||||
"placement of the respective cell.\n"
|
||||
"\n"
|
||||
"This property has been introduced in version 0.27."
|
||||
) +
|
||||
gsi::method ("trans=", &db::SubCircuit::set_trans, gsi::arg ("trans"),
|
||||
"@brief Sets the physical transformation for the subcircuit.\n"
|
||||
"\n"
|
||||
"See \\trans for details about this property.\n"
|
||||
"\n"
|
||||
"This property has been introduced in version 0.27."
|
||||
),
|
||||
"@brief A subcircuit inside a circuit.\n"
|
||||
"Circuits may instantiate other circuits as subcircuits similar to cells "
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2020 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "gsiDecl.h"
|
||||
#include "gsiDeclBasic.h"
|
||||
#include "layNetlistBrowserDialog.h"
|
||||
#include "layLayoutView.h"
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
// disable copy and default constructor for NetlistBrowserDialog
|
||||
template <> struct type_traits<lay::NetlistBrowserDialog> : public type_traits<void>
|
||||
{
|
||||
typedef tl::false_tag has_copy_constructor;
|
||||
typedef tl::false_tag has_default_constructor;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace gsi
|
||||
{
|
||||
|
||||
Class<lay::NetlistBrowserDialog> decl_NetlistBrowserDialog ("lay", "NetlistBrowserDialog",
|
||||
gsi::Methods (),
|
||||
"@brief ..."
|
||||
);
|
||||
|
||||
static lay::NetlistBrowserDialog *netlist_browser (lay::LayoutView *lv)
|
||||
{
|
||||
return lv->get_plugin<lay::NetlistBrowserDialog> ();
|
||||
}
|
||||
|
||||
// extend lay::LayoutView with the getter for the netlist browser
|
||||
static
|
||||
gsi::ClassExt<lay::LayoutView> decl_ext_layout_view (
|
||||
gsi::method_ext ("netlist_browser", &netlist_browser,
|
||||
"@brief Gets the netlist browser object for the given layout view\n"
|
||||
"\n"
|
||||
"\nThis method has been added in version 0.27.\n"
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +183,8 @@ SOURCES = \
|
|||
layGenericSyntaxHighlighter.cc \
|
||||
layDispatcher.cc \
|
||||
laySelectCellViewForm.cc \
|
||||
layLayoutStatisticsForm.cc
|
||||
layLayoutStatisticsForm.cc \
|
||||
gsiDeclLayNetlistBrowserDialog.cc
|
||||
|
||||
HEADERS = \
|
||||
gtf.h \
|
||||
|
|
|
|||
|
|
@ -935,6 +935,12 @@ struct test_arg_func<gsi::VectorType>
|
|||
{
|
||||
void operator() (bool *ret, PyObject *arg, const gsi::ArgType &atype, bool loose)
|
||||
{
|
||||
if ((atype.is_cptr () || atype.is_ptr ()) && arg == Py_None) {
|
||||
// for ptr or cptr, null is an allowed value
|
||||
*ret = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (! PyTuple_Check (arg) && ! PyList_Check (arg)) {
|
||||
*ret = false;
|
||||
return;
|
||||
|
|
@ -971,6 +977,12 @@ struct test_arg_func<gsi::MapType>
|
|||
{
|
||||
void operator () (bool *ret, PyObject *arg, const gsi::ArgType &atype, bool loose)
|
||||
{
|
||||
if ((atype.is_cptr () || atype.is_ptr ()) && arg == Py_None) {
|
||||
// for ptr or cptr, null is an allowed value
|
||||
*ret = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (! PyDict_Check (arg)) {
|
||||
*ret = false;
|
||||
return;
|
||||
|
|
@ -999,6 +1011,7 @@ struct test_arg_func<gsi::MapType>
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct test_arg_func<gsi::ObjectType>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -956,7 +956,7 @@ struct test_arg_func<gsi::VectorType>
|
|||
if ((atype.is_cptr () || atype.is_ptr ()) && arg == Qnil) {
|
||||
// for pointers to vectors, nil is a valid value
|
||||
*ret = true;
|
||||
} if (TYPE (arg) != T_ARRAY) {
|
||||
} else if (TYPE (arg) != T_ARRAY) {
|
||||
*ret = false;
|
||||
} else {
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class DBLayoutToNetlistTests(unittest.TestCase):
|
|||
ut_testsrc = os.getenv("TESTSRC")
|
||||
|
||||
ly = pya.Layout()
|
||||
ly.read(os.path.join(ut_testsrc, "testdata", "algo", "device_extract_l1.gds"))
|
||||
ly.read(os.path.join(ut_testsrc, "testdata", "algo", "device_extract_l1_with_inv_nodes.gds"))
|
||||
|
||||
l2n = pya.LayoutToNetlist(pya.RecursiveShapeIterator(ly, ly.top_cell(), []))
|
||||
|
||||
|
|
@ -97,40 +97,56 @@ class DBLayoutToNetlistTests(unittest.TestCase):
|
|||
|
||||
self.assertEqual(str(l2n.netlist()), """circuit TRANS ($1=$1,$2=$2);
|
||||
end;
|
||||
circuit INV2 (OUT=OUT,$2=$2,$3=$3,$4=$4);
|
||||
circuit INV2 (OUT=OUT,$2=$3,$3=$4);
|
||||
subcircuit TRANS $1 ($1=$4,$2=OUT);
|
||||
subcircuit TRANS $2 ($1=$3,$2=OUT);
|
||||
subcircuit TRANS $3 ($1=$2,$2=$4);
|
||||
subcircuit TRANS $4 ($1=$2,$2=$3);
|
||||
end;
|
||||
circuit RINGO ();
|
||||
subcircuit INV2 $1 (OUT=OSC,$2=FB,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $2 (OUT=$I29,$2=$I20,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $3 (OUT=$I28,$2=$I19,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $4 (OUT=$I30,$2=$I21,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $5 (OUT=$I31,$2=$I22,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $6 (OUT=$I32,$2=$I23,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $7 (OUT=$I33,$2=$I24,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $8 (OUT=$I34,$2=$I25,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $9 (OUT=$I35,$2=$I26,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $10 (OUT=$I36,$2=$I27,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $1 (OUT='FB,OSC',$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $2 (OUT=$I20,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $3 (OUT=$I19,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $4 (OUT=$I21,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $5 (OUT=$I22,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $6 (OUT=$I23,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $7 (OUT=$I24,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $8 (OUT=$I25,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $9 (OUT=$I26,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $10 (OUT=$I27,$2=VSS,$3=VDD);
|
||||
end;
|
||||
""")
|
||||
|
||||
self.assertEqual(str(l2n.probe_net(rmetal2, pya.DPoint(0.0, 1.8))), "RINGO:FB")
|
||||
self.assertEqual(str(l2n.probe_net(rmetal2, pya.DPoint(0.0, 1.8))), "RINGO:FB,OSC")
|
||||
sc_path = []
|
||||
self.assertEqual(str(l2n.probe_net(rmetal2, pya.DPoint(0.0, 1.8), sc_path)), "RINGO:FB,OSC")
|
||||
self.assertEqual(len(sc_path), 0)
|
||||
self.assertEqual(repr(l2n.probe_net(rmetal2, pya.DPoint(-2.0, 1.8))), "None")
|
||||
|
||||
n = l2n.probe_net(rmetal1, pya.Point(2600, 1000))
|
||||
self.assertEqual(str(n), "RINGO:$I20")
|
||||
n = l2n.probe_net(rmetal1, pya.Point(2600, 1000), None)
|
||||
self.assertEqual(str(n), "INV2:$2")
|
||||
sc_path = []
|
||||
n = l2n.probe_net(rmetal1, pya.Point(2600, 1000), sc_path)
|
||||
self.assertEqual(str(n), "INV2:$2")
|
||||
self.assertEqual(len(sc_path), 1)
|
||||
a = []
|
||||
t = pya.DCplxTrans()
|
||||
for sc in sc_path:
|
||||
a.append(sc.expanded_name())
|
||||
t = t * sc.trans
|
||||
self.assertEqual(",".join(a), "$2")
|
||||
self.assertEqual(str(t), "r0 *1 2.64,0")
|
||||
|
||||
self.assertEqual(str(l2n.shapes_of_net(n, rmetal1, True)), "(1660,-420;1660,2420;2020,2420;2020,-420);(1840,820;1840,1180;3220,1180;3220,820);(1660,2420;1660,3180;2020,3180;2020,2420);(1660,-380;1660,380;2020,380;2020,-380)")
|
||||
self.assertEqual(str(l2n.shapes_of_net(n, rmetal1, True)),
|
||||
"(-980,-420;-980,2420;-620,2420;-620,-420);(-800,820;-800,1180;580,1180;580,820);(-980,2420;-980,3180;-620,3180;-620,2420);(-980,-380;-980,380;-620,380;-620,-380)")
|
||||
|
||||
shapes = pya.Shapes()
|
||||
l2n.shapes_of_net(n, rmetal1, True, shapes)
|
||||
r = pya.Region()
|
||||
for s in shapes.each():
|
||||
r.insert(s.polygon)
|
||||
self.assertEqual(str(r), "(1660,-420;1660,2420;2020,2420;2020,-420);(1840,820;1840,1180;3220,1180;3220,820);(1660,2420;1660,3180;2020,3180;2020,2420);(1660,-380;1660,380;2020,380;2020,-380)")
|
||||
for s in shapes.each():
|
||||
r.insert(s.polygon)
|
||||
self.assertEqual(str(r),
|
||||
"(-980,-420;-980,2420;-620,2420;-620,-420);(-800,820;-800,1180;580,1180;580,820);(-980,2420;-980,3180;-620,3180;-620,2420);(-980,-380;-980,380;-620,380;-620,-380)")
|
||||
|
||||
def test_10_LayoutToNetlistExtractionWithoutDevices(self):
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ class DBLayoutToNetlist_TestClass < TestBase
|
|||
def test_2_ShapesFromNet
|
||||
|
||||
ly = RBA::Layout::new
|
||||
ly.read(File.join($ut_testsrc, "testdata", "algo", "device_extract_l1.gds"))
|
||||
ly.read(File.join($ut_testsrc, "testdata", "algo", "device_extract_l1_with_inv_nodes.gds"))
|
||||
|
||||
l2n = RBA::LayoutToNetlist::new(RBA::RecursiveShapeIterator::new(ly, ly.top_cell, []))
|
||||
|
||||
|
|
@ -133,39 +133,50 @@ class DBLayoutToNetlist_TestClass < TestBase
|
|||
assert_equal(l2n.netlist.to_s, <<END)
|
||||
circuit TRANS ($1=$1,$2=$2);
|
||||
end;
|
||||
circuit INV2 (OUT=OUT,$2=$2,$3=$3,$4=$4);
|
||||
circuit INV2 (OUT=OUT,$2=$3,$3=$4);
|
||||
subcircuit TRANS $1 ($1=$4,$2=OUT);
|
||||
subcircuit TRANS $2 ($1=$3,$2=OUT);
|
||||
subcircuit TRANS $3 ($1=$2,$2=$4);
|
||||
subcircuit TRANS $4 ($1=$2,$2=$3);
|
||||
end;
|
||||
circuit RINGO ();
|
||||
subcircuit INV2 $1 (OUT=OSC,$2=FB,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $2 (OUT=$I29,$2=$I20,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $3 (OUT=$I28,$2=$I19,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $4 (OUT=$I30,$2=$I21,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $5 (OUT=$I31,$2=$I22,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $6 (OUT=$I32,$2=$I23,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $7 (OUT=$I33,$2=$I24,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $8 (OUT=$I34,$2=$I25,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $9 (OUT=$I35,$2=$I26,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $10 (OUT=$I36,$2=$I27,$3=VSS,$4=VDD);
|
||||
subcircuit INV2 $1 (OUT='FB,OSC',$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $2 (OUT=$I20,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $3 (OUT=$I19,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $4 (OUT=$I21,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $5 (OUT=$I22,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $6 (OUT=$I23,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $7 (OUT=$I24,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $8 (OUT=$I25,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $9 (OUT=$I26,$2=VSS,$3=VDD);
|
||||
subcircuit INV2 $10 (OUT=$I27,$2=VSS,$3=VDD);
|
||||
end;
|
||||
END
|
||||
|
||||
assert_equal(l2n.probe_net(rmetal2, RBA::DPoint::new(0.0, 1.8)).to_s, "RINGO:FB")
|
||||
assert_equal(l2n.probe_net(rmetal2, RBA::DPoint::new(0.0, 1.8)).to_s, "RINGO:FB,OSC")
|
||||
sc_path = []
|
||||
assert_equal(l2n.probe_net(rmetal2, RBA::DPoint::new(0.0, 1.8), sc_path).to_s, "RINGO:FB,OSC")
|
||||
assert_equal(sc_path.size, 0)
|
||||
assert_equal(l2n.probe_net(rmetal2, RBA::DPoint::new(-2.0, 1.8)).inspect, "nil")
|
||||
|
||||
n = l2n.probe_net(rmetal1, RBA::Point::new(2600, 1000))
|
||||
assert_equal(n.to_s, "RINGO:$I20")
|
||||
n = l2n.probe_net(rmetal1, RBA::Point::new(2600, 1000), nil)
|
||||
assert_equal(n.to_s, "INV2:$2")
|
||||
sc_path = []
|
||||
n = l2n.probe_net(rmetal1, RBA::Point::new(2600, 1000), sc_path)
|
||||
assert_equal(n.to_s, "INV2:$2")
|
||||
assert_equal(sc_path.size, 1)
|
||||
assert_equal(sc_path.collect(&:expanded_name).join(","), "$2")
|
||||
assert_equal(sc_path.collect(&:trans).inject(&:*).to_s, "r0 *1 2.64,0")
|
||||
|
||||
assert_equal(l2n.shapes_of_net(n, rmetal1, true).to_s, "(1660,-420;1660,2420;2020,2420;2020,-420);(1840,820;1840,1180;3220,1180;3220,820);(1660,2420;1660,3180;2020,3180;2020,2420);(1660,-380;1660,380;2020,380;2020,-380)")
|
||||
assert_equal(l2n.shapes_of_net(n, rmetal1, true).to_s,
|
||||
"(-980,-420;-980,2420;-620,2420;-620,-420);(-800,820;-800,1180;580,1180;580,820);(-980,2420;-980,3180;-620,3180;-620,2420);(-980,-380;-980,380;-620,380;-620,-380)")
|
||||
|
||||
shapes = RBA::Shapes::new
|
||||
l2n.shapes_of_net(n, rmetal1, true, shapes)
|
||||
r = RBA::Region::new
|
||||
shapes.each { |s| r.insert(s.polygon) }
|
||||
assert_equal(r.to_s, "(1660,-420;1660,2420;2020,2420;2020,-420);(1840,820;1840,1180;3220,1180;3220,820);(1660,2420;1660,3180;2020,3180;2020,2420);(1660,-380;1660,380;2020,380;2020,-380)")
|
||||
assert_equal(r.to_s,
|
||||
"(-980,-420;-980,2420;-620,2420;-620,-420);(-800,820;-800,1180;580,1180;580,820);(-980,2420;-980,3180;-620,3180;-620,2420);(-980,-380;-980,380;-620,380;-620,-380)")
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue