WIP: Enabled layout generation from read l2n data.

This commit is contained in:
Matthias Koefferlein 2019-01-20 02:50:23 +01:00
parent a5e2cf58c3
commit dd39168dc8
14 changed files with 2098 additions and 85 deletions

View File

@ -217,6 +217,11 @@ void LayoutToNetlist::extract_netlist ()
m_netlist_extracted = true;
}
void LayoutToNetlist::set_netlist_extracted ()
{
m_netlist_extracted = true;
}
const db::Layout *LayoutToNetlist::internal_layout () const
{
return &m_dss.const_layout ();
@ -293,19 +298,30 @@ db::Netlist *LayoutToNetlist::make_netlist ()
return mp_netlist.get ();
}
namespace
{
struct StopOnFirst { };
}
template <class Tr>
static void deliver_shape (const db::PolygonRef &pr, db::Region &region, const Tr &tr)
static bool deliver_shape (const db::PolygonRef &, StopOnFirst, const Tr &)
{
return false;
}
template <class Tr>
static bool deliver_shape (const db::PolygonRef &pr, db::Region &region, const Tr &tr)
{
if (pr.obj ().is_box ()) {
region.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr));
} else {
region.insert (pr.obj ().transformed (pr.trans ()).transformed (tr));
}
return true;
}
template <class Tr>
static void deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const Tr &tr)
static bool deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const Tr &tr)
{
if (pr.obj ().is_box ()) {
shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr));
@ -317,25 +333,51 @@ static void deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const T
shapes.insert (pr.obj ().transformed (pr.trans ()).transformed (tr));
}
}
return true;
}
template <class To>
static void deliver_shapes_of_net_recursive (const db::hier_clusters<db::PolygonRef> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, To &to)
static bool deliver_shapes_of_net_recursive (const db::Netlist * /*nl*/, const db::hier_clusters<db::PolygonRef> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, const db::ICplxTrans &tr, To &to)
{
// deliver the net shapes
for (db::recursive_cluster_shape_iterator<db::PolygonRef> rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) {
deliver_shape (*rci, to, rci.trans ());
if (! deliver_shape (*rci, to, tr * rci.trans ())) {
return false;
}
}
return true;
}
template <class To>
static void deliver_shapes_of_net_nonrecursive (const db::hier_clusters<db::PolygonRef> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, To &to)
static bool deliver_shapes_of_net_nonrecursive (const db::Netlist *nl, const db::hier_clusters<db::PolygonRef> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, const db::ICplxTrans &tr, To &to)
{
const db::local_cluster<db::PolygonRef> &lc = clusters.clusters_per_cell (ci).cluster_by_id (cid);
// NOTE: this scheme will deliver the shapes from the cell, including (!)
// subcells that are purged
db::cell_index_type prev_ci = ci;
// deliver the net shapes
for (db::recursive_cluster_shape_iterator<db::PolygonRef> rci (clusters, layer_id, ci, cid); !rci.at_end (); ) {
db::cell_index_type cci = rci.cell_index ();
if (cci != prev_ci && cci != ci && (! nl || nl->circuit_by_cell_index (cci) || nl->device_model_by_cell_index (cci))) {
rci.skip_cell ();
} else {
if (! deliver_shape (*rci, to, tr * rci.trans ())) {
return false;
}
prev_ci = cci;
++rci;
}
for (db::local_cluster<db::PolygonRef>::shape_iterator s = lc.begin (layer_id); !s.at_end (); ++s) {
deliver_shape (*s, to, db::UnitTrans ());
}
return true;
}
void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to) const
@ -345,9 +387,9 @@ void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_la
tl_assert (circuit != 0);
if (! recursive) {
deliver_shapes_of_net_nonrecursive (m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, to);
deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), to);
} else {
deliver_shapes_of_net_recursive (m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, to);
deliver_shapes_of_net_recursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), to);
}
}
@ -360,31 +402,60 @@ db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region
std::auto_ptr<db::Region> res (new db::Region ());
if (! recursive) {
deliver_shapes_of_net_nonrecursive (m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, *res);
deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), *res);
} else {
deliver_shapes_of_net_recursive (m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, *res);
deliver_shapes_of_net_recursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), *res);
}
return res.release ();
}
void
LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap) const
LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, const db::ICplxTrans &tr) const
{
const db::Circuit *circuit = net.circuit ();
tl_assert (circuit != 0);
build_net_rec (circuit->cell_index (), net.cluster_id (), target, target_cell, lmap, cell_name_prefix, device_cell_name_prefix, cmap);
build_net_rec (circuit->cell_index (), net.cluster_id (), target, target_cell, lmap, &net, net_cell_name_prefix, cell_name_prefix, device_cell_name_prefix, cmap, tr);
}
void
LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap) const
LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &tc, const std::map<unsigned int, const db::Region *> &lmap, const db::Net *net, const char *net_cell_name_prefix, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, const db::ICplxTrans &tr) const
{
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
deliver_shapes_of_net_nonrecursive (m_net_clusters, ci, cid, layer_of (*l->second), target_cell.shapes (l->first));
db::Cell *target_cell = &tc;
if (net_cell_name_prefix) {
const db::connected_clusters<db::PolygonRef> &ccl = m_net_clusters.clusters_per_cell (ci);
bool any_connections = circuit_cell_name_prefix && ! ccl.connections_for_cluster (cid).empty ();
if (! any_connections) {
bool consider_cell = any_connections;
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end () && !consider_cell; ++l) {
StopOnFirst sof;
consider_cell = deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, sof);
}
if (! consider_cell) {
// shortcut if cell is empty -> no net cell will be produced
return;
}
}
// make a specific cell for the net if requested
target_cell = &target.cell (target.add_cell ((std::string (net_cell_name_prefix) + net->expanded_name ()).c_str ()));
tc.insert (db::CellInstArray (db::CellInst (target_cell->cell_index ()), db::Trans ()));
}
if (! cell_name_prefix && ! device_cell_name_prefix) {
for (std::map<unsigned int, const db::Region *>::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, target_cell->shapes (l->first));
}
if (! circuit_cell_name_prefix && ! device_cell_name_prefix) {
return;
}
@ -403,7 +474,7 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
if (mp_netlist->device_model_by_cell_index (subci)) {
name_prefix = device_cell_name_prefix;
} else {
name_prefix = cell_name_prefix;
name_prefix = circuit_cell_name_prefix;
}
if (name_prefix) {
@ -413,7 +484,7 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
db::cell_index_type target_ci = target.add_cell ((std::string (name_prefix) + cell_name).c_str ());
cm = cmap.insert (std::make_pair (std::make_pair (subci, subcid), target_ci)).first;
build_net_rec (subci, subcid, target, target.cell (target_ci), lmap, cell_name_prefix, device_cell_name_prefix, cmap);
build_net_rec (subci, subcid, target, target.cell (target_ci), lmap, 0, 0, circuit_cell_name_prefix, device_cell_name_prefix, cmap, db::ICplxTrans ());
} else {
cm = cmap.insert (std::make_pair (std::make_pair (subci, subcid), std::numeric_limits<db::cell_index_type>::max ())).first;
@ -422,7 +493,7 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
}
if (cm->second != std::numeric_limits<db::cell_index_type>::max ()) {
target_cell.insert (db::CellInstArray (db::CellInst (cm->second), c->inst ().complex_trans ()));
target_cell->insert (db::CellInstArray (db::CellInst (cm->second), tr * c->inst ().complex_trans ()));
}
}
@ -437,7 +508,7 @@ LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &ta
std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> cell_map;
build_net_rec (net, target, target_cell, lmap, cell_name_prefix, device_cell_name_prefix, cell_map);
build_net_rec (net, target, target_cell, lmap, 0, cell_name_prefix, device_cell_name_prefix, cell_map, db::ICplxTrans ());
}
void
@ -456,39 +527,55 @@ LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target
continue;
}
bool is_top_circuit = c->begin_parents () == c->end_parents ();
db::cell_index_type target_ci = cmap.cell_mapping (c->cell_index ());
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
// exlude local nets in recursive mode
if (circuit_cell_name_prefix && n->pin_count () > 0) {
if (circuit_cell_name_prefix && ! is_top_circuit && n->pin_count () > 0) {
continue;
}
const db::connected_clusters<db::PolygonRef> &ccl = m_net_clusters.clusters_per_cell (c->cell_index ());
const db::local_cluster<db::PolygonRef> &cl = ccl.cluster_by_id (n->cluster_id ());
build_net_rec (*n, target, target.cell (target_ci), lmap, net_cell_name_prefix, circuit_cell_name_prefix, device_cell_name_prefix, cell_map, db::ICplxTrans ());
bool any_connections = ! ccl.connections_for_cluster (n->cluster_id ()).empty ();
}
bool any_shapes = false;
for (std::map<unsigned int, const db::Region *>::const_iterator m = lmap.begin (); m != lmap.end () && !any_shapes; ++m) {
any_shapes = ! cl.begin (layer_of (*m->second)).at_end ();
}
if (circuit_cell_name_prefix) {
if (any_shapes || (circuit_cell_name_prefix && any_connections)) {
// with recursive nets we skip nets in subcircuits which are connected upwards. This means, nets will
// get lost if there is no connection to this pin from the outside. Hence we need to deliver nets from
// subcircuits as part of the circuit which calls the subcircuit - but NOT in a subcircuit cell, because
// this will just apply to nets from certain instances. But the net cell name will be formed as "subcircuit:net"
db::cell_index_type net_ci = target_ci;
const db::Circuit &circuit = *c;
for (db::Circuit::const_subcircuit_iterator sc = circuit.begin_subcircuits (); sc != circuit.end_subcircuits (); ++sc) {
if (net_cell_name_prefix) {
const db::SubCircuit &subcircuit = *sc;
for (db::Circuit::const_pin_iterator p = subcircuit.circuit_ref ()->begin_pins (); p != subcircuit.circuit_ref ()->end_pins (); ++p) {
db::Cell &tc = target.cell (target_ci);
net_ci = target.add_cell ((std::string (net_cell_name_prefix) + n->expanded_name ()).c_str ());
tc.insert (db::CellInstArray (db::CellInst (net_ci), db::Trans ()));
if (! subcircuit.net_for_pin (p->id ())) {
const db::Net *n = subcircuit.circuit_ref ()->net_for_pin (p->id ());
if (n) {
double dbu = target.dbu ();
db::ICplxTrans tr = db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu);
if (net_cell_name_prefix) {
std::string ncn = std::string (net_cell_name_prefix) + subcircuit.expanded_name () + ":";
build_net_rec (*n, target, target.cell (target_ci), lmap, ncn.c_str (), circuit_cell_name_prefix, device_cell_name_prefix, cell_map, tr);
} else {
build_net_rec (*n, target, target.cell (target_ci), lmap, net_cell_name_prefix, circuit_cell_name_prefix, device_cell_name_prefix, cell_map, tr);
}
}
}
}
build_net_rec (*n, target, target.cell (net_ci), lmap, circuit_cell_name_prefix, device_cell_name_prefix, cell_map);
}
}

View File

@ -141,7 +141,6 @@ public:
/**
* @brief Creates a new region representing an original layer
* "layer_index" is the layer index of the desired layer in the original layout.
* The Region object returned is a new object and must be deleted by the caller.
* This variant produces polygons and takes texts for net name annotation.
* A variant not taking texts is "make_polygon_layer". A Variant only taking
* texts is "make_text_layer".
@ -211,6 +210,13 @@ public:
*/
void extract_netlist ();
/**
* @brief Marks the netlist as extracted
* NOTE: this method is provided for special cases such as netlist readers. Don't
* use it.
*/
void set_netlist_extracted ();
/**
* @brief Gets the internal layout
*/
@ -268,6 +274,8 @@ public:
/**
* @brief gets the netlist extracted or make on if none exists yet.
* NOTE: this method is provided for special cases like readers of persisted
* layout to netlist data.
*/
db::Netlist *make_netlist ();
@ -401,8 +409,8 @@ private:
bool m_netlist_extracted;
size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster<db::PolygonRef> &test_cluster, std::vector<db::InstElement> &rev_inst_path);
void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap) const;
void build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap) const;
void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, const ICplxTrans &tr) const;
void build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map<unsigned int, const db::Region *> &lmap, const Net *net, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map<std::pair<db::cell_index_type, size_t>, db::cell_index_type> &cmap, const ICplxTrans &tr) const;
};
}

View File

@ -110,6 +110,8 @@ namespace l2n_std_format
param_key, location_key, rotation_key,
mirror_key, scale_key, pin_key,
indent1, indent2;
inline static bool is_short () { return Short; }
};
}

View File

@ -51,6 +51,11 @@ public:
m_layers.insert (std::make_pair (name, region));
}
bool has_layer (const std::string &name) const
{
return m_layers.find (name) != m_layers.end ();
}
db::Region &layer (const std::string &name)
{
std::map<std::string, db::Region *>::const_iterator l = m_layers.find (name);
@ -180,6 +185,11 @@ void LayoutToNetlistStandardReader::read (db::LayoutToNetlist *l2n)
}
}
const db::Region *LayoutToNetlistStandardReader::layer_by_name (const std::string &name)
{
return mp_layers->has_layer (name) ? &mp_layers->layer (name) : 0;
}
void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
{
int version = 0;
@ -191,7 +201,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
l2n->make_netlist ();
Layers layers;
mp_layers.reset (new Layers ());
while (! at_end ()) {
@ -227,7 +237,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
Brace br (this);
std::string layer;
read_word_or_quoted (layer);
layers.add (layer, l2n->make_layer (layer));
mp_layers->add (layer, l2n->make_layer (layer));
br.done ();
} else if (test (skeys::connect_key) || test (lkeys::connect_key)) {
@ -238,7 +248,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
while (br) {
std::string l2;
read_word_or_quoted (l2);
l2n->connect (layers.layer (l1), layers.layer (l2));
l2n->connect (mp_layers->layer (l1), mp_layers->layer (l2));
}
br.done ();
@ -250,7 +260,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
while (br) {
std::string g;
read_word_or_quoted (g);
l2n->connect_global (layers.layer (l1), g);
l2n->connect_global (mp_layers->layer (l1), g);
}
br.done ();
@ -265,7 +275,8 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
l2n->netlist ()->add_circuit (circuit);
db::Layout *ly = l2n->internal_layout ();
db::cell_index_type ci = ly->add_cell (name.c_str ());
std::pair<bool, db::cell_index_type> ci_old = ly->cell_by_name (name.c_str ());
db::cell_index_type ci = ci_old.first ? ci_old.second : ly->add_cell (name.c_str ());
circuit->set_cell_index (ci);
std::map<db::CellInstArray, std::list<Connections> > connections;
@ -273,7 +284,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
while (br) {
if (test (skeys::net_key) || test (lkeys::net_key)) {
read_net (l2n, circuit, layers);
read_net (l2n, circuit);
} else if (test (skeys::pin_key) || test (lkeys::pin_key)) {
read_pin (l2n, circuit);
} else if (test (skeys::device_key) || test (lkeys::device_key)) {
@ -340,7 +351,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
while (br) {
if (test (skeys::terminal_key) || test (lkeys::terminal_key)) {
read_abstract_terminal (l2n, dm, gen_dc ? dc : 0, layers);
read_abstract_terminal (l2n, dm, gen_dc ? dc : 0);
} else {
throw tl::Exception (tl::to_string (tr ("Invalid keyword inside device abstract definition (terminal expected)")));
}
@ -352,10 +363,12 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
}
}
l2n->set_netlist_extracted ();
}
std::pair<unsigned int, db::PolygonRef>
LayoutToNetlistStandardReader::read_geometry (db::LayoutToNetlist *l2n, Layers &layers)
LayoutToNetlistStandardReader::read_geometry (db::LayoutToNetlist *l2n)
{
std::string lname;
@ -364,7 +377,7 @@ LayoutToNetlistStandardReader::read_geometry (db::LayoutToNetlist *l2n, Layers &
Brace br (this);
read_word_or_quoted (lname);
unsigned int lid = l2n->layer_of (layers.layer (lname));
unsigned int lid = l2n->layer_of (mp_layers->layer (lname));
db::Coord l = read_coord ();
db::Coord b = read_coord ();
@ -381,7 +394,7 @@ LayoutToNetlistStandardReader::read_geometry (db::LayoutToNetlist *l2n, Layers &
Brace br (this);
read_word_or_quoted (lname);
unsigned int lid = l2n->layer_of (layers.layer (lname));
unsigned int lid = l2n->layer_of (mp_layers->layer (lname));
std::vector<db::Point> pt;
@ -403,7 +416,7 @@ LayoutToNetlistStandardReader::read_geometry (db::LayoutToNetlist *l2n, Layers &
}
void
LayoutToNetlistStandardReader::read_net (db::LayoutToNetlist *l2n, db::Circuit *circuit, Layers &layers)
LayoutToNetlistStandardReader::read_net (db::LayoutToNetlist *l2n, db::Circuit *circuit)
{
Brace br (this);
@ -421,7 +434,7 @@ LayoutToNetlistStandardReader::read_net (db::LayoutToNetlist *l2n, db::Circuit *
db::Cell &cell = l2n->internal_layout ()->cell (circuit->cell_index ());
while (br) {
std::pair<unsigned int, db::PolygonRef> pr = read_geometry (l2n, layers);
std::pair<unsigned int, db::PolygonRef> pr = read_geometry (l2n);
lc.add (pr.second, pr.first);
cell.shapes (pr.first).insert (pr.second);
}
@ -675,7 +688,7 @@ LayoutToNetlistStandardReader::read_subcircuit (db::LayoutToNetlist *l2n, db::Ci
}
void
LayoutToNetlistStandardReader::read_abstract_terminal (db::LayoutToNetlist *l2n, db::DeviceModel *dm, db::DeviceClass *dc, Layers &layers)
LayoutToNetlistStandardReader::read_abstract_terminal (db::LayoutToNetlist *l2n, db::DeviceModel *dm, db::DeviceClass *dc)
{
Brace br (this);
@ -707,7 +720,7 @@ LayoutToNetlistStandardReader::read_abstract_terminal (db::LayoutToNetlist *l2n,
db::Cell &cell = l2n->internal_layout ()->cell (dm->cell_index ());
while (br) {
std::pair<unsigned int, db::PolygonRef> pr = read_geometry (l2n, layers);
std::pair<unsigned int, db::PolygonRef> pr = read_geometry (l2n);
lc.add (pr.second, pr.first);
cell.shapes (pr.first).insert (pr.second);
}

View File

@ -40,6 +40,7 @@ class Circuit;
class Cell;
class DeviceModel;
class DeviceClass;
class Region;
/**
* @brief The base class for a LayoutToNetlist writer
@ -64,6 +65,8 @@ public:
void read (db::LayoutToNetlist *l2n);
const db::Region *layer_by_name (const std::string &name);
private:
friend class l2n_std_reader::Brace;
typedef l2n_std_reader::Brace Brace;
@ -82,6 +85,7 @@ private:
std::string m_path;
std::string m_line;
tl::Extractor m_ex;
std::auto_ptr<Layers> mp_layers;
void do_read (db::LayoutToNetlist *l2n);
@ -94,12 +98,12 @@ private:
bool at_end ();
void skip ();
void read_net (db::LayoutToNetlist *l2n, db::Circuit *circuit, Layers &layers);
void read_net (db::LayoutToNetlist *l2n, db::Circuit *circuit);
void read_pin (db::LayoutToNetlist *l2n, db::Circuit *circuit);
db::CellInstArray read_device (db::LayoutToNetlist *l2n, db::Circuit *circuit, std::list<Connections> &refs);
db::CellInstArray read_subcircuit (db::LayoutToNetlist *l2n, db::Circuit *circuit, std::list<Connections> &refs);
void read_abstract_terminal (db::LayoutToNetlist *l2n, db::DeviceModel *dm, db::DeviceClass *dc, Layers &layers);
std::pair<unsigned int, db::PolygonRef> read_geometry (db::LayoutToNetlist *l2n, Layers &layers);
void read_abstract_terminal (db::LayoutToNetlist *l2n, db::DeviceModel *dm, db::DeviceClass *dc);
std::pair<unsigned int, db::PolygonRef> read_geometry (db::LayoutToNetlist *l2n);
};
}

View File

@ -83,23 +83,33 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n)
const db::Layout *ly = l2n->internal_layout ();
const db::Netlist *nl = l2n->netlist ();
*mp_stream << "# General section" << endl;
*mp_stream << "# Lists general definitions." << endl << endl;
*mp_stream << "#%l2n-klayout" << endl;
if (! Keys::is_short ()) {
*mp_stream << endl << "# General section" << endl << endl;
}
if (version > 0) {
*mp_stream << Keys::version_key << "(" << version << ")" << endl;
}
*mp_stream << Keys::top_key << "(" << tl::to_word_or_quoted_string (ly->cell_name (l2n->internal_top_cell ()->cell_index ())) << ")" << endl;
*mp_stream << Keys::unit_key << "(" << ly->dbu () << ")" << endl;
*mp_stream << endl << "# Layer section" << endl;
*mp_stream << "# This section lists the mask layers (drawing or derived) and their connections." << endl;
if (! Keys::is_short ()) {
*mp_stream << endl << "# Layer section" << endl;
*mp_stream << "# This section lists the mask layers (drawing or derived) and their connections." << endl;
}
*mp_stream << endl << "# Mask layers" << endl;
if (! Keys::is_short ()) {
*mp_stream << endl << "# Mask layers" << endl;
}
for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) {
*mp_stream << Keys::layer_key << "(" << name_for_layer (ly, *l) << ")" << endl;
}
*mp_stream << endl << "# Mask layer connectivity" << endl;
if (! Keys::is_short ()) {
*mp_stream << endl << "# Mask layer connectivity" << endl;
}
for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) {
db::Connectivity::layer_iterator ce = l2n->connectivity ().end_connected (*l);
@ -121,7 +131,9 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n)
db::Connectivity::global_nets_iterator gb = l2n->connectivity ().begin_global_connections (*l);
if (gb != ge) {
if (! any) {
*mp_stream << endl << "# Global nets and connectivity" << endl;
if (! Keys::is_short ()) {
*mp_stream << endl << "# Global nets and connectivity" << endl;
}
any = true;
}
*mp_stream << Keys::global_key << "(" << name_for_layer (ly, *l);
@ -133,7 +145,7 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n)
}
if (nl->begin_device_models () != nl->end_device_models ()) {
if (nl->begin_device_models () != nl->end_device_models () && ! Keys::is_short ()) {
*mp_stream << endl << "# Device abstracts section" << endl;
*mp_stream << "# Device abstracts list the pin shapes of the devices." << endl;
}
@ -145,8 +157,10 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n)
}
}
*mp_stream << endl << "# Circuit section" << endl;
*mp_stream << "# Circuits are the hierarchical building blocks of the netlist." << endl;
if (! Keys::is_short ()) {
*mp_stream << endl << "# Circuit section" << endl;
*mp_stream << "# Circuits are the hierarchical building blocks of the netlist." << endl;
}
for (db::Netlist::const_bottom_up_circuit_iterator i = nl->begin_bottom_up (); i != nl->end_bottom_up (); ++i) {
const db::Circuit *x = *i;
*mp_stream << Keys::circuit_key << "(" << tl::to_word_or_quoted_string (x->name ()) << endl;
@ -159,14 +173,18 @@ template <class Keys>
void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n, const db::Circuit &circuit)
{
if (circuit.begin_nets () != circuit.end_nets ()) {
*mp_stream << endl << indent1 << "# Nets with their geometries" << endl;
if (! Keys::is_short ()) {
*mp_stream << endl << indent1 << "# Nets with their geometries" << endl;
}
for (db::Circuit::const_net_iterator n = circuit.begin_nets (); n != circuit.end_nets (); ++n) {
write (l2n, *n);
}
}
if (circuit.begin_pins () != circuit.end_pins ()) {
*mp_stream << endl << indent1 << "# Outgoing pins and their connections to nets" << endl;
if (! Keys::is_short ()) {
*mp_stream << endl << indent1 << "# Outgoing pins and their connections to nets" << endl;
}
for (db::Circuit::const_pin_iterator p = circuit.begin_pins (); p != circuit.end_pins (); ++p) {
const db::Net *net = circuit.net_for_pin (p->id ());
if (net) {
@ -176,20 +194,26 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n, const db::Cir
}
if (circuit.begin_devices () != circuit.end_devices ()) {
*mp_stream << endl << indent1 << "# Devices and their connections" << endl;
if (! Keys::is_short ()) {
*mp_stream << endl << indent1 << "# Devices and their connections" << endl;
}
for (db::Circuit::const_device_iterator d = circuit.begin_devices (); d != circuit.end_devices (); ++d) {
write (l2n, *d);
}
}
if (circuit.begin_subcircuits () != circuit.end_subcircuits ()) {
*mp_stream << endl << indent1 << "# Subcircuits and their connections" << endl;
if (! Keys::is_short ()) {
*mp_stream << endl << indent1 << "# Subcircuits and their connections" << endl;
}
for (db::Circuit::const_subcircuit_iterator x = circuit.begin_subcircuits (); x != circuit.end_subcircuits (); ++x) {
write (l2n, *x);
}
}
*mp_stream << endl;
if (! Keys::is_short ()) {
*mp_stream << endl;
}
}
template <class T, class Tr>

View File

@ -26,6 +26,7 @@
#include "dbStream.h"
#include "dbCommonReader.h"
#include "dbNetlistDeviceExtractorClasses.h"
#include "dbTestSupport.h"
#include "tlUnitTest.h"
#include "tlStream.h"
@ -64,17 +65,59 @@ TEST(1_ReaderBasic)
tl::absolute_file_path (au_path)));
}
// test build_all_nets from read l2n
#if 0
{
db::Layout ly2;
ly2.dbu (ly.dbu ());
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
std::string path = tmp_file ("tmp_l2nwriter_1.txt");
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/);
std::map<unsigned int, const db::Region *> lmap;
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = reader.layer_by_name ("psd");
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = reader.layer_by_name ("nsd");
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = reader.layer_by_name ("poly");
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = reader.layer_by_name ("diff_cont");
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = reader.layer_by_name ("poly_cont");
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = reader.layer_by_name ("metal1");
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = reader.layer_by_name ("via1");
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = reader.layer_by_name ("metal2");
l2n.build_all_nets (cm, ly2, lmap, "NET_", 0, "DEVICE_");
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "l2n_writer_au.gds");
db::compare_layouts (_this, ly2, au);
}
}
TEST(2_ReaderBasicShort)
{
db::Layout ly;
db::Cell &tc = ly.cell (ly.add_cell ("TOP"));
db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set<unsigned int> ()));
std::string in_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au_s.txt");
tl::InputStream is_in (in_path);
db::LayoutToNetlistStandardReader reader (is_in);
reader.read (&l2n);
// verify against the input
std::string path = tmp_file ("tmp_l2nreader_2.txt");
{
tl::OutputStream stream (path);
db::LayoutToNetlistStandardWriter writer (stream, false);
db::LayoutToNetlistStandardWriter writer (stream, true);
writer.write (&l2n);
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au.txt");
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au_s.txt");
tl::InputStream is (path);
tl::InputStream is_au (au_path);
@ -85,5 +128,4 @@ TEST(1_ReaderBasic)
tl::absolute_file_path (au_path)));
}
#endif
}

View File

@ -25,6 +25,7 @@
#include "dbStream.h"
#include "dbCommonReader.h"
#include "dbNetlistDeviceExtractorClasses.h"
#include "dbTestSupport.h"
#include "tlUnitTest.h"
#include "tlStream.h"
@ -163,6 +164,7 @@ TEST(1_WriterBasic)
rpoly_lbl.reset (0);
l2n.extract_netlist ();
l2n.netlist ()->make_top_level_pins ();
l2n.netlist ()->purge ();
std::string path = tmp_file ("tmp_l2nwriter_1.txt");
@ -174,12 +176,289 @@ TEST(1_WriterBasic)
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au.txt");
tl::InputStream is (path);
tl::InputStream is_au (au_path);
{
tl::InputStream is (path);
tl::InputStream is_au (au_path);
if (is.read_all () != is_au.read_all ()) {
_this->raise (tl::sprintf ("Compare failed - see\n actual: %s\n golden: %s",
tl::absolute_file_path (path),
tl::absolute_file_path (au_path)));
if (is.read_all () != is_au.read_all ()) {
_this->raise (tl::sprintf ("Compare failed - see\n actual: %s\n golden: %s",
tl::absolute_file_path (path),
tl::absolute_file_path (au_path)));
}
}
path = tmp_file ("tmp_l2nwriter_1s.txt");
{
tl::OutputStream stream (path);
db::LayoutToNetlistStandardWriter writer (stream, true);
writer.write (&l2n);
}
au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au_s.txt");
{
tl::InputStream is (path);
tl::InputStream is_au (au_path);
if (is.read_all () != is_au.read_all ()) {
_this->raise (tl::sprintf ("Compare failed - see\n actual: %s\n golden: %s",
tl::absolute_file_path (path),
tl::absolute_file_path (au_path)));
}
}
// test build_all_nets (verify reference for reader)
{
db::Layout ly2;
ly2.dbu (ly.dbu ());
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/);
std::map<unsigned int, const db::Region *> lmap;
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = &rpsd;
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = &rnsd;
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = rpoly.get ();
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = rdiff_cont.get ();
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = rpoly_cont.get ();
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = rmetal1.get ();
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, "NET_", 0, "DEVICE_");
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "l2n_writer_au.gds");
db::compare_layouts (_this, ly2, au);
}
}
TEST(2_WriterWithGlobalNets)
{
db::Layout ly;
db::LayerMap lmap;
unsigned int nwell = define_layer (ly, lmap, 1);
unsigned int active = define_layer (ly, lmap, 2);
unsigned int pplus = define_layer (ly, lmap, 10);
unsigned int nplus = define_layer (ly, lmap, 11);
unsigned int poly = define_layer (ly, lmap, 3);
unsigned int poly_lbl = define_layer (ly, lmap, 3, 1);
unsigned int diff_cont = define_layer (ly, lmap, 4);
unsigned int poly_cont = define_layer (ly, lmap, 5);
unsigned int metal1 = define_layer (ly, lmap, 6);
unsigned int metal1_lbl = define_layer (ly, lmap, 6, 1);
unsigned int via1 = define_layer (ly, lmap, 7);
unsigned int metal2 = define_layer (ly, lmap, 8);
unsigned int metal2_lbl = define_layer (ly, lmap, 8, 1);
{
db::LoadLayoutOptions options;
options.get_options<db::CommonReaderOptions> ().layer_map = lmap;
options.get_options<db::CommonReaderOptions> ().create_other_layers = false;
std::string fn (tl::testsrc ());
fn = tl::combine_path (fn, "testdata");
fn = tl::combine_path (fn, "algo");
fn = tl::combine_path (fn, "device_extract_l3.gds");
tl::InputStream stream (fn);
db::Reader reader (stream);
reader.read (ly, options);
}
db::Cell &tc = ly.cell (*ly.begin_top_down ());
db::LayoutToNetlist l2n (db::RecursiveShapeIterator (ly, tc, std::set<unsigned int> ()));
std::auto_ptr<db::Region> rbulk (l2n.make_layer (ly.insert_layer (), "rbulk"));
std::auto_ptr<db::Region> rnwell (l2n.make_layer (nwell, "nwell"));
std::auto_ptr<db::Region> ractive (l2n.make_layer (active, "active"));
std::auto_ptr<db::Region> rpplus (l2n.make_layer (pplus, "pplus"));
std::auto_ptr<db::Region> rnplus (l2n.make_layer (nplus, "nplus"));
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly, "poly"));
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl, "poly_lbl"));
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont, "diff_cont"));
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont, "poly_cont"));
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1, "metal1"));
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl, "metal1_lbl"));
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1, "via1"));
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2, "metal2"));
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl, "metal2_lbl"));
// derived regions
db::Region ractive_in_nwell = *ractive & *rnwell;
db::Region rpactive = ractive_in_nwell & *rpplus;
db::Region rntie = ractive_in_nwell & *rnplus;
db::Region rpgate = rpactive & *rpoly;
db::Region rpsd = rpactive - rpgate;
l2n.name (rpactive, "pactive");
l2n.name (rntie, "ntie");
l2n.name (rpgate, "pgate");
l2n.name (rpsd, "psd");
db::Region ractive_outside_nwell = *ractive - *rnwell;
db::Region rnactive = ractive_outside_nwell & *rnplus;
db::Region rptie = ractive_outside_nwell & *rpplus;
db::Region rngate = rnactive & *rpoly;
db::Region rnsd = rnactive - rngate;
l2n.name (rnactive, "nactive");
l2n.name (rptie, "ptie");
l2n.name (rngate, "ngate");
l2n.name (rnsd, "nsd");
// return the computed layers into the original layout and write it for debugging purposes
unsigned int lgate = ly.insert_layer (db::LayerProperties (20, 0)); // 20/0 -> Gate
unsigned int lsd = ly.insert_layer (db::LayerProperties (21, 0)); // 21/0 -> Source/Drain
unsigned int lpdiff = ly.insert_layer (db::LayerProperties (22, 0)); // 22/0 -> P Diffusion
unsigned int lndiff = ly.insert_layer (db::LayerProperties (23, 0)); // 23/0 -> N Diffusion
unsigned int lptie = ly.insert_layer (db::LayerProperties (24, 0)); // 24/0 -> P Tie
unsigned int lntie = ly.insert_layer (db::LayerProperties (25, 0)); // 25/0 -> N Tie
rpgate.insert_into (&ly, tc.cell_index (), lgate);
rngate.insert_into (&ly, tc.cell_index (), lgate);
rpsd.insert_into (&ly, tc.cell_index (), lsd);
rnsd.insert_into (&ly, tc.cell_index (), lsd);
rpsd.insert_into (&ly, tc.cell_index (), lpdiff);
rnsd.insert_into (&ly, tc.cell_index (), lndiff);
rpsd.insert_into (&ly, tc.cell_index (), lptie);
rnsd.insert_into (&ly, tc.cell_index (), lntie);
db::NetlistDeviceExtractorMOS4Transistor pmos_ex ("PMOS");
db::NetlistDeviceExtractorMOS4Transistor nmos_ex ("NMOS");
// device extraction
db::NetlistDeviceExtractor::input_layers dl;
dl["SD"] = &rpsd;
dl["G"] = &rpgate;
dl["P"] = rpoly.get (); // not needed for extraction but to return terminal shapes
dl["W"] = rnwell.get ();
l2n.extract_devices (pmos_ex, dl);
dl["SD"] = &rnsd;
dl["G"] = &rngate;
dl["P"] = rpoly.get (); // not needed for extraction but to return terminal shapes
dl["W"] = rbulk.get ();
l2n.extract_devices (nmos_ex, dl);
// net extraction
// Intra-layer
l2n.connect (rpsd);
l2n.connect (rnsd);
l2n.connect (*rnwell);
l2n.connect (*rpoly);
l2n.connect (*rdiff_cont);
l2n.connect (*rpoly_cont);
l2n.connect (*rmetal1);
l2n.connect (*rvia1);
l2n.connect (*rmetal2);
l2n.connect (rptie);
l2n.connect (rntie);
// Inter-layer
l2n.connect (rpsd, *rdiff_cont);
l2n.connect (rnsd, *rdiff_cont);
l2n.connect (*rpoly, *rpoly_cont);
l2n.connect (*rpoly_cont, *rmetal1);
l2n.connect (*rdiff_cont, *rmetal1);
l2n.connect (*rdiff_cont, rptie);
l2n.connect (*rdiff_cont, rntie);
l2n.connect (*rnwell, rntie);
l2n.connect (*rmetal1, *rvia1);
l2n.connect (*rvia1, *rmetal2);
l2n.connect (*rpoly, *rpoly_lbl); // attaches labels
l2n.connect (*rmetal1, *rmetal1_lbl); // attaches labels
l2n.connect (*rmetal2, *rmetal2_lbl); // attaches labels
// Global
l2n.connect_global (rptie, "BULK");
l2n.connect_global (*rbulk, "BULK");
// create some mess - we have to keep references to the layers to make them not disappear
rmetal1_lbl.reset (0);
rmetal2_lbl.reset (0);
rpoly_lbl.reset (0);
l2n.extract_netlist ();
l2n.netlist ()->make_top_level_pins ();
l2n.netlist ()->purge ();
std::string path = tmp_file ("tmp_l2nwriter_2.txt");
{
tl::OutputStream stream (path);
db::LayoutToNetlistStandardWriter writer (stream, false);
writer.write (&l2n);
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au_2.txt");
{
tl::InputStream is (path);
tl::InputStream is_au (au_path);
if (is.read_all () != is_au.read_all ()) {
_this->raise (tl::sprintf ("Compare failed - see\n actual: %s\n golden: %s",
tl::absolute_file_path (path),
tl::absolute_file_path (au_path)));
}
}
path = tmp_file ("tmp_l2nwriter_2s.txt");
{
tl::OutputStream stream (path);
db::LayoutToNetlistStandardWriter writer (stream, true);
writer.write (&l2n);
}
au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au_2s.txt");
{
tl::InputStream is (path);
tl::InputStream is_au (au_path);
if (is.read_all () != is_au.read_all ()) {
_this->raise (tl::sprintf ("Compare failed - see\n actual: %s\n golden: %s",
tl::absolute_file_path (path),
tl::absolute_file_path (au_path)));
}
}
// test build_all_nets
{
db::Layout ly2;
ly2.dbu (ly.dbu ());
db::Cell &top2 = ly2.cell (ly2.add_cell ("TOP"));
db::CellMapping cm = l2n.cell_mapping_into (ly2, top2, true /*with device cells*/);
std::map<unsigned int, const db::Region *> lmap;
lmap [ly2.insert_layer (db::LayerProperties (10, 0))] = &rpsd;
lmap [ly2.insert_layer (db::LayerProperties (11, 0))] = &rnsd;
lmap [ly2.insert_layer (db::LayerProperties (12, 0))] = rbulk.get ();
lmap [ly2.insert_layer (db::LayerProperties (13, 0))] = &rptie;
lmap [ly2.insert_layer (db::LayerProperties (14, 0))] = &rntie;
lmap [ly2.insert_layer (db::LayerProperties (1, 0)) ] = rnwell.get ();
lmap [ly2.insert_layer (db::LayerProperties (3, 0)) ] = rpoly.get ();
lmap [ly2.insert_layer (db::LayerProperties (4, 0)) ] = rdiff_cont.get ();
lmap [ly2.insert_layer (db::LayerProperties (5, 0)) ] = rpoly_cont.get ();
lmap [ly2.insert_layer (db::LayerProperties (6, 0)) ] = rmetal1.get ();
lmap [ly2.insert_layer (db::LayerProperties (7, 0)) ] = rvia1.get ();
lmap [ly2.insert_layer (db::LayerProperties (8, 0)) ] = rmetal2.get ();
l2n.build_all_nets (cm, ly2, lmap, "NET_", "CIRCUIT_", "DEVICE_");
std::string au = tl::testsrc ();
au = tl::combine_path (au, "testdata");
au = tl::combine_path (au, "algo");
au = tl::combine_path (au, "l2n_writer_au_2.gds");
db::compare_layouts (_this, ly2, au);
}
}

BIN
testdata/algo/l2n_writer_au.gds vendored Normal file

Binary file not shown.

View File

@ -1,5 +1,6 @@
#%l2n-klayout
# General section
# Lists general definitions.
top(RINGO)
unit(0.001)
@ -211,6 +212,15 @@ circuit(RINGO
rect(metal2 -1720 1600 23160 2000)
rect(metal2_lbl -1 1799 1 1801)
)
net(OSC
rect(diff_cont 24450 2890 24670 3110)
rect(diff_cont 24450 2490 24670 2710)
rect(diff_cont 24450 90 24670 310)
rect(diff_cont 24450 -310 24670 -90)
rect(via1 24435 1675 24685 1925)
rect(metal2 24360 1600 24760 2000)
rect(metal2_lbl 24559 1799 24561 1801)
)
net(VSS
rect(diff_cont 2530 -310 2750 -90)
rect(diff_cont 2530 90 2750 310)
@ -392,10 +402,17 @@ circuit(RINGO
rect(diff_cont 3330 -310 3550 -90)
)
# Outgoing pins and their connections to nets
pin(FB FB)
pin(OSC OSC)
pin(VSS VSS)
pin(VDD VDD)
# Subcircuits and their connections
circuit($1 INV2 location(23760 0)
pin(IN $I8)
pin($1 FB)
pin(OUT OSC)
pin($3 VSS)
pin($4 VDD)
)

BIN
testdata/algo/l2n_writer_au_2.gds vendored Normal file

Binary file not shown.

566
testdata/algo/l2n_writer_au_2.txt vendored Normal file
View File

@ -0,0 +1,566 @@
#%l2n-klayout
# General section
top(RINGO)
unit(0.001)
# Layer section
# This section lists the mask layers (drawing or derived) and their connections.
# Mask layers
layer(rbulk)
layer(nwell)
layer(poly)
layer(poly_lbl)
layer(diff_cont)
layer(poly_cont)
layer(metal1)
layer(metal1_lbl)
layer(via1)
layer(metal2)
layer(metal2_lbl)
layer(ntie)
layer(psd)
layer(ptie)
layer(nsd)
# Mask layer connectivity
connect(nwell nwell ntie)
connect(poly poly poly_lbl poly_cont)
connect(poly_lbl poly)
connect(diff_cont diff_cont metal1 ntie psd ptie nsd)
connect(poly_cont poly poly_cont metal1)
connect(metal1 diff_cont poly_cont metal1 metal1_lbl via1)
connect(metal1_lbl metal1)
connect(via1 metal1 via1 metal2)
connect(metal2 via1 metal2 metal2_lbl)
connect(metal2_lbl metal2)
connect(ntie nwell diff_cont ntie)
connect(psd diff_cont psd)
connect(ptie diff_cont ptie)
connect(nsd diff_cont nsd)
# Global nets and connectivity
global(rbulk BULK)
global(ptie BULK)
# Device abstracts section
# Device abstracts list the pin shapes of the devices.
device(D$PMOS PMOS
terminal(S
rect(psd -650 -475 -125 475)
)
terminal(G
rect(poly -125 -475 125 475)
)
terminal(D
rect(psd 125 -475 675 475)
)
terminal(B
rect(nwell -125 -475 125 475)
)
)
device(D$PMOS$1 PMOS
terminal(S
rect(psd -675 -475 -125 475)
)
terminal(G
rect(poly -125 -475 125 475)
)
terminal(D
rect(psd 125 -475 650 475)
)
terminal(B
rect(nwell -125 -475 125 475)
)
)
device(D$NMOS NMOS
terminal(S
rect(nsd -650 -475 -125 475)
)
terminal(G
rect(poly -125 -475 125 475)
)
terminal(D
rect(nsd 125 -475 675 475)
)
terminal(B
rect(rbulk -125 -475 125 475)
)
)
device(D$NMOS$1 NMOS
terminal(S
rect(nsd -675 -475 -125 475)
)
terminal(G
rect(poly -125 -475 125 475)
)
terminal(D
rect(nsd 125 -475 650 475)
)
terminal(B
rect(rbulk -125 -475 125 475)
)
)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(INV2
# Nets with their geometries
net($1
rect(nwell -1400 1800 1400 4580)
rect(diff_cont -110 3930 110 4150)
rect(ntie -400 3700 400 4380)
)
net(IN
rect(poly -525 -250 -275 2250)
rect(poly -1700 1620 -400 1980)
rect(poly -525 -800 -275 800)
rect(poly -525 2000 -275 3600)
rect(poly_lbl -801 1799 -799 1801)
rect(poly_cont -1630 1690 -1410 1910)
)
net($3
rect(poly 275 -250 525 2250)
rect(poly 220 820 580 1180)
rect(poly 275 2000 525 3600)
rect(poly 275 -800 525 800)
rect(diff_cont -910 2490 -690 2710)
rect(diff_cont -910 2890 -690 3110)
rect(diff_cont -910 -310 -690 -90)
rect(diff_cont -910 90 -690 310)
rect(poly_cont 290 890 510 1110)
rect(metal1 -800 820 580 1180)
rect(metal1 -980 -420 -620 2420)
rect(metal1 -980 2420 -620 3180)
rect(metal1 -980 -380 -620 380)
rect(psd -1050 2325 -525 3275)
rect(nsd -1050 -475 -525 475)
)
net(OUT
rect(diff_cont 690 2890 910 3110)
rect(diff_cont 690 2490 910 2710)
rect(diff_cont 690 90 910 310)
rect(diff_cont 690 -310 910 -90)
polygon(metal1 800 20 800 380 940 380 940 1620 620 1620 620 2420 980 2420 980 1980 1300 1980 1300 20)
rect(metal1 620 2420 980 3180)
rect(metal1 620 -380 980 380)
rect(metal1_lbl 799 1799 801 1801)
rect(psd 525 2325 1050 3275)
rect(nsd 525 -475 1050 475)
)
net(VSS
rect(diff_cont -110 -310 110 -90)
rect(diff_cont -110 90 110 310)
rect(diff_cont -110 90 110 310)
rect(diff_cont -110 -310 110 -90)
rect(metal1 -180 -380 180 380)
rect(metal1 -180 -380 180 380)
rect(via1 -125 -325 125 -75)
rect(via1 -125 75 125 325)
rect(metal2 -1400 -450 1400 450)
rect(metal2_lbl 1239 -91 1241 -89)
rect(nsd -275 -475 275 475)
)
net(VDD
rect(diff_cont -110 2490 110 2710)
rect(diff_cont -110 2890 110 3110)
rect(diff_cont -110 2890 110 3110)
rect(diff_cont -110 2490 110 2710)
rect(metal1 -180 2420 180 3180)
rect(metal1 -180 2420 180 3180)
rect(via1 -125 2475 125 2725)
rect(via1 -125 2875 125 3125)
rect(metal2 -1400 2350 1400 3250)
rect(metal2_lbl 1249 2799 1251 2801)
rect(psd -275 2325 275 3275)
)
net(BULK
rect(diff_cont -110 -1360 110 -1140)
rect(ptie -400 -1590 400 -910)
)
# Outgoing pins and their connections to nets
pin($0 $1)
pin(IN IN)
pin($2 $3)
pin(OUT OUT)
pin(VSS VSS)
pin(VDD VDD)
pin(BULK BULK)
# Devices and their connections
device($1 D$PMOS
location(-400 2800)
param(L 0.25)
param(W 0.95)
param(AS 0.49875)
param(AD 0.26125)
terminal(S $3)
terminal(G IN)
terminal(D VDD)
terminal(B $1)
)
device($2 D$PMOS$1
location(400 2800)
param(L 0.25)
param(W 0.95)
param(AS 0.26125)
param(AD 0.49875)
terminal(S VDD)
terminal(G $3)
terminal(D OUT)
terminal(B $1)
)
device($3 D$NMOS
location(-400 0)
param(L 0.25)
param(W 0.95)
param(AS 0.49875)
param(AD 0.26125)
terminal(S $3)
terminal(G IN)
terminal(D VSS)
terminal(B BULK)
)
device($4 D$NMOS$1
location(400 0)
param(L 0.25)
param(W 0.95)
param(AS 0.26125)
param(AD 0.49875)
terminal(S VSS)
terminal(G $3)
terminal(D OUT)
terminal(B BULK)
)
)
circuit(INV2PAIR
# Nets with their geometries
net(BULK)
net($I8
rect(diff_cont 3430 3290 3650 3510)
rect(diff_cont 3430 3690 3650 3910)
rect(diff_cont 3430 490 3650 710)
rect(diff_cont 3430 890 3650 1110)
)
net($I6
rect(diff_cont 4230 3290 4450 3510)
rect(diff_cont 4230 3690 4450 3910)
rect(diff_cont 4230 3690 4450 3910)
rect(diff_cont 4230 3290 4450 3510)
rect(diff_cont 1590 3290 1810 3510)
rect(diff_cont 1590 3690 1810 3910)
rect(diff_cont 1590 3690 1810 3910)
rect(diff_cont 1590 3290 1810 3510)
rect(metal1 4160 3220 4520 3980)
rect(metal1 4160 3220 4520 3980)
rect(metal1 1520 3220 1880 3980)
rect(metal1 1520 3220 1880 3980)
)
net($I5
rect(diff_cont 4230 490 4450 710)
rect(diff_cont 4230 890 4450 1110)
rect(diff_cont 4230 890 4450 1110)
rect(diff_cont 4230 490 4450 710)
rect(diff_cont 1590 490 1810 710)
rect(diff_cont 1590 890 1810 1110)
rect(diff_cont 1590 890 1810 1110)
rect(diff_cont 1590 490 1810 710)
rect(metal1 4160 420 4520 1180)
rect(metal1 4160 420 4520 1180)
rect(metal1 1520 420 1880 1180)
rect(metal1 1520 420 1880 1180)
)
net($I4
rect(diff_cont 2390 3690 2610 3910)
rect(diff_cont 2390 3290 2610 3510)
rect(diff_cont 2390 890 2610 1110)
rect(diff_cont 2390 490 2610 710)
)
net($I3)
net($I2
rect(diff_cont 5030 3690 5250 3910)
rect(diff_cont 5030 3290 5250 3510)
rect(diff_cont 5030 890 5250 1110)
rect(diff_cont 5030 490 5250 710)
)
net($I1)
# Outgoing pins and their connections to nets
pin(BULK BULK)
pin($1 $I8)
pin($2 $I6)
pin($3 $I5)
pin($4 $I3)
pin($5 $I2)
pin($6 $I1)
# Subcircuits and their connections
circuit($1 INV2 location(1700 800)
pin($0 $I1)
pin(IN $I3)
pin(OUT $I4)
pin(VSS $I5)
pin(VDD $I6)
pin(BULK BULK)
)
circuit($2 INV2 location(4340 800)
pin($0 $I1)
pin(IN $I4)
pin($2 $I8)
pin(OUT $I2)
pin(VSS $I5)
pin(VDD $I6)
pin(BULK BULK)
)
)
circuit(RINGO
# Nets with their geometries
net(FB
rect(diff_cont 22850 2490 23070 2710)
rect(diff_cont 22850 2890 23070 3110)
rect(diff_cont 22850 -310 23070 -90)
rect(diff_cont 22850 90 23070 310)
rect(metal1 -1700 1620 -1340 1980)
rect(via1 -1645 1675 -1395 1925)
rect(via1 22835 1675 23085 1925)
rect(metal2 -1720 1600 23160 2000)
rect(metal2_lbl -1 1799 1 1801)
)
net(OSC
rect(diff_cont 24450 2890 24670 3110)
rect(diff_cont 24450 2490 24670 2710)
rect(diff_cont 24450 90 24670 310)
rect(diff_cont 24450 -310 24670 -90)
rect(via1 24435 1675 24685 1925)
rect(metal2 24360 1600 24760 2000)
rect(metal2_lbl 24559 1799 24561 1801)
)
net(VDD
rect(diff_cont 7810 2490 8030 2710)
rect(diff_cont 7810 2890 8030 3110)
rect(diff_cont 7810 2890 8030 3110)
rect(diff_cont 7810 2490 8030 2710)
rect(diff_cont 5170 2490 5390 2710)
rect(diff_cont 5170 2890 5390 3110)
rect(diff_cont 5170 2890 5390 3110)
rect(diff_cont 5170 2490 5390 2710)
rect(diff_cont 2530 2490 2750 2710)
rect(diff_cont 2530 2890 2750 3110)
rect(diff_cont 2530 2890 2750 3110)
rect(diff_cont 2530 2490 2750 2710)
rect(diff_cont -110 2490 110 2710)
rect(diff_cont -110 2890 110 3110)
rect(diff_cont -110 2890 110 3110)
rect(diff_cont -110 2490 110 2710)
rect(diff_cont 13090 2490 13310 2710)
rect(diff_cont 13090 2890 13310 3110)
rect(diff_cont 13090 2890 13310 3110)
rect(diff_cont 13090 2490 13310 2710)
rect(diff_cont 10450 2490 10670 2710)
rect(diff_cont 10450 2890 10670 3110)
rect(diff_cont 10450 2890 10670 3110)
rect(diff_cont 10450 2490 10670 2710)
rect(diff_cont 18370 2490 18590 2710)
rect(diff_cont 18370 2890 18590 3110)
rect(diff_cont 18370 2890 18590 3110)
rect(diff_cont 18370 2490 18590 2710)
rect(diff_cont 15730 2490 15950 2710)
rect(diff_cont 15730 2890 15950 3110)
rect(diff_cont 15730 2890 15950 3110)
rect(diff_cont 15730 2490 15950 2710)
rect(diff_cont 23650 2490 23870 2710)
rect(diff_cont 23650 2890 23870 3110)
rect(diff_cont 23650 2890 23870 3110)
rect(diff_cont 23650 2490 23870 2710)
rect(diff_cont 21010 2490 21230 2710)
rect(diff_cont 21010 2890 21230 3110)
rect(diff_cont 21010 2890 21230 3110)
rect(diff_cont 21010 2490 21230 2710)
rect(metal1 -180 3100 180 4220)
rect(metal1 2460 3100 2820 4220)
rect(metal1 5100 3100 5460 4220)
rect(metal1 7740 3100 8100 4220)
rect(metal1 10380 3100 10740 4220)
rect(metal1 13020 3100 13380 4220)
rect(metal1 15660 3100 16020 4220)
rect(metal1 18300 3100 18660 4220)
rect(metal1 20940 3100 21300 4220)
rect(metal1 23580 3100 23940 4220)
rect(metal1 7740 2420 8100 3180)
rect(metal1 7740 2420 8100 3180)
rect(metal1 5100 2420 5460 3180)
rect(metal1 5100 2420 5460 3180)
rect(metal1 2460 2420 2820 3180)
rect(metal1 2460 2420 2820 3180)
rect(metal1 -180 2420 180 3180)
rect(metal1 -180 2420 180 3180)
rect(metal1 13020 2420 13380 3180)
rect(metal1 13020 2420 13380 3180)
rect(metal1 10380 2420 10740 3180)
rect(metal1 10380 2420 10740 3180)
rect(metal1 18300 2420 18660 3180)
rect(metal1 18300 2420 18660 3180)
rect(metal1 15660 2420 16020 3180)
rect(metal1 15660 2420 16020 3180)
rect(metal1 23580 2420 23940 3180)
rect(metal1 23580 2420 23940 3180)
rect(metal1 20940 2420 21300 3180)
rect(metal1 20940 2420 21300 3180)
rect(metal2_lbl -1 2799 1 2801)
)
net('BULK,VSS'
rect(diff_cont 7810 -310 8030 -90)
rect(diff_cont 7810 90 8030 310)
rect(diff_cont 7810 90 8030 310)
rect(diff_cont 7810 -310 8030 -90)
rect(diff_cont 5170 -310 5390 -90)
rect(diff_cont 5170 90 5390 310)
rect(diff_cont 5170 90 5390 310)
rect(diff_cont 5170 -310 5390 -90)
rect(diff_cont 2530 -310 2750 -90)
rect(diff_cont 2530 90 2750 310)
rect(diff_cont 2530 90 2750 310)
rect(diff_cont 2530 -310 2750 -90)
rect(diff_cont -110 -310 110 -90)
rect(diff_cont -110 90 110 310)
rect(diff_cont -110 90 110 310)
rect(diff_cont -110 -310 110 -90)
rect(diff_cont 13090 -310 13310 -90)
rect(diff_cont 13090 90 13310 310)
rect(diff_cont 13090 90 13310 310)
rect(diff_cont 13090 -310 13310 -90)
rect(diff_cont 10450 -310 10670 -90)
rect(diff_cont 10450 90 10670 310)
rect(diff_cont 10450 90 10670 310)
rect(diff_cont 10450 -310 10670 -90)
rect(diff_cont 18370 -310 18590 -90)
rect(diff_cont 18370 90 18590 310)
rect(diff_cont 18370 90 18590 310)
rect(diff_cont 18370 -310 18590 -90)
rect(diff_cont 15730 -310 15950 -90)
rect(diff_cont 15730 90 15950 310)
rect(diff_cont 15730 90 15950 310)
rect(diff_cont 15730 -310 15950 -90)
rect(diff_cont 23650 -310 23870 -90)
rect(diff_cont 23650 90 23870 310)
rect(diff_cont 23650 90 23870 310)
rect(diff_cont 23650 -310 23870 -90)
rect(diff_cont 21010 -310 21230 -90)
rect(diff_cont 21010 90 21230 310)
rect(diff_cont 21010 90 21230 310)
rect(diff_cont 21010 -310 21230 -90)
rect(metal1 -180 -1420 180 -300)
rect(metal1 2460 -1420 2820 -300)
rect(metal1 5100 -1420 5460 -300)
rect(metal1 7740 -1420 8100 -300)
rect(metal1 10380 -1420 10740 -300)
rect(metal1 13020 -1420 13380 -300)
rect(metal1 15660 -1420 16020 -300)
rect(metal1 18300 -1420 18660 -300)
rect(metal1 20940 -1420 21300 -300)
rect(metal1 23580 -1420 23940 -300)
rect(metal1 7740 -380 8100 380)
rect(metal1 7740 -380 8100 380)
rect(metal1 5100 -380 5460 380)
rect(metal1 5100 -380 5460 380)
rect(metal1 2460 -380 2820 380)
rect(metal1 2460 -380 2820 380)
rect(metal1 -180 -380 180 380)
rect(metal1 -180 -380 180 380)
rect(metal1 13020 -380 13380 380)
rect(metal1 13020 -380 13380 380)
rect(metal1 10380 -380 10740 380)
rect(metal1 10380 -380 10740 380)
rect(metal1 18300 -380 18660 380)
rect(metal1 18300 -380 18660 380)
rect(metal1 15660 -380 16020 380)
rect(metal1 15660 -380 16020 380)
rect(metal1 23580 -380 23940 380)
rect(metal1 23580 -380 23940 380)
rect(metal1 20940 -380 21300 380)
rect(metal1 20940 -380 21300 380)
rect(metal2_lbl -1 -1 1 1)
)
net($I13
rect(diff_cont 3330 2890 3550 3110)
rect(diff_cont 3330 2490 3550 2710)
rect(diff_cont 3330 90 3550 310)
rect(diff_cont 3330 -310 3550 -90)
)
net($I7
rect(diff_cont 19170 2890 19390 3110)
rect(diff_cont 19170 2490 19390 2710)
rect(diff_cont 19170 90 19390 310)
rect(diff_cont 19170 -310 19390 -90)
)
net($I6
rect(diff_cont 13890 2890 14110 3110)
rect(diff_cont 13890 2490 14110 2710)
rect(diff_cont 13890 90 14110 310)
rect(diff_cont 13890 -310 14110 -90)
)
net($I5
rect(diff_cont 8610 2890 8830 3110)
rect(diff_cont 8610 2490 8830 2710)
rect(diff_cont 8610 90 8830 310)
rect(diff_cont 8610 -310 8830 -90)
)
# Outgoing pins and their connections to nets
pin(FB FB)
pin(OSC OSC)
pin(VDD VDD)
pin('BULK,VSS' 'BULK,VSS')
# Subcircuits and their connections
circuit($1 INV2PAIR location(19420 -800)
pin(BULK 'BULK,VSS')
pin($1 FB)
pin($2 VDD)
pin($3 'BULK,VSS')
pin($4 $I7)
pin($5 OSC)
pin($6 VDD)
)
circuit($2 INV2PAIR location(-1700 -800)
pin(BULK 'BULK,VSS')
pin($2 VDD)
pin($3 'BULK,VSS')
pin($4 FB)
pin($5 $I13)
pin($6 VDD)
)
circuit($3 INV2PAIR location(3580 -800)
pin(BULK 'BULK,VSS')
pin($2 VDD)
pin($3 'BULK,VSS')
pin($4 $I13)
pin($5 $I5)
pin($6 VDD)
)
circuit($4 INV2PAIR location(8860 -800)
pin(BULK 'BULK,VSS')
pin($2 VDD)
pin($3 'BULK,VSS')
pin($4 $I5)
pin($5 $I6)
pin($6 VDD)
)
circuit($5 INV2PAIR location(14140 -800)
pin(BULK 'BULK,VSS')
pin($2 VDD)
pin($3 'BULK,VSS')
pin($4 $I6)
pin($5 $I7)
pin($6 VDD)
)
)

527
testdata/algo/l2n_writer_au_2s.txt vendored Normal file
View File

@ -0,0 +1,527 @@
#%l2n-klayout
W(RINGO)
U(0.001)
L(rbulk)
L(nwell)
L(poly)
L(poly_lbl)
L(diff_cont)
L(poly_cont)
L(metal1)
L(metal1_lbl)
L(via1)
L(metal2)
L(metal2_lbl)
L(ntie)
L(psd)
L(ptie)
L(nsd)
C(nwell nwell ntie)
C(poly poly poly_lbl poly_cont)
C(poly_lbl poly)
C(diff_cont diff_cont metal1 ntie psd ptie nsd)
C(poly_cont poly poly_cont metal1)
C(metal1 diff_cont poly_cont metal1 metal1_lbl via1)
C(metal1_lbl metal1)
C(via1 metal1 via1 metal2)
C(metal2 via1 metal2 metal2_lbl)
C(metal2_lbl metal2)
C(ntie nwell diff_cont ntie)
C(psd diff_cont psd)
C(ptie diff_cont ptie)
C(nsd diff_cont nsd)
G(rbulk BULK)
G(ptie BULK)
D(D$PMOS PMOS
T(S
R(psd -650 -475 -125 475)
)
T(G
R(poly -125 -475 125 475)
)
T(D
R(psd 125 -475 675 475)
)
T(B
R(nwell -125 -475 125 475)
)
)
D(D$PMOS$1 PMOS
T(S
R(psd -675 -475 -125 475)
)
T(G
R(poly -125 -475 125 475)
)
T(D
R(psd 125 -475 650 475)
)
T(B
R(nwell -125 -475 125 475)
)
)
D(D$NMOS NMOS
T(S
R(nsd -650 -475 -125 475)
)
T(G
R(poly -125 -475 125 475)
)
T(D
R(nsd 125 -475 675 475)
)
T(B
R(rbulk -125 -475 125 475)
)
)
D(D$NMOS$1 NMOS
T(S
R(nsd -675 -475 -125 475)
)
T(G
R(poly -125 -475 125 475)
)
T(D
R(nsd 125 -475 650 475)
)
T(B
R(rbulk -125 -475 125 475)
)
)
X(INV2
N($1
R(nwell -1400 1800 1400 4580)
R(diff_cont -110 3930 110 4150)
R(ntie -400 3700 400 4380)
)
N(IN
R(poly -525 -250 -275 2250)
R(poly -1700 1620 -400 1980)
R(poly -525 -800 -275 800)
R(poly -525 2000 -275 3600)
R(poly_lbl -801 1799 -799 1801)
R(poly_cont -1630 1690 -1410 1910)
)
N($3
R(poly 275 -250 525 2250)
R(poly 220 820 580 1180)
R(poly 275 2000 525 3600)
R(poly 275 -800 525 800)
R(diff_cont -910 2490 -690 2710)
R(diff_cont -910 2890 -690 3110)
R(diff_cont -910 -310 -690 -90)
R(diff_cont -910 90 -690 310)
R(poly_cont 290 890 510 1110)
R(metal1 -800 820 580 1180)
R(metal1 -980 -420 -620 2420)
R(metal1 -980 2420 -620 3180)
R(metal1 -980 -380 -620 380)
R(psd -1050 2325 -525 3275)
R(nsd -1050 -475 -525 475)
)
N(OUT
R(diff_cont 690 2890 910 3110)
R(diff_cont 690 2490 910 2710)
R(diff_cont 690 90 910 310)
R(diff_cont 690 -310 910 -90)
Q(metal1 800 20 800 380 940 380 940 1620 620 1620 620 2420 980 2420 980 1980 1300 1980 1300 20)
R(metal1 620 2420 980 3180)
R(metal1 620 -380 980 380)
R(metal1_lbl 799 1799 801 1801)
R(psd 525 2325 1050 3275)
R(nsd 525 -475 1050 475)
)
N(VSS
R(diff_cont -110 -310 110 -90)
R(diff_cont -110 90 110 310)
R(diff_cont -110 90 110 310)
R(diff_cont -110 -310 110 -90)
R(metal1 -180 -380 180 380)
R(metal1 -180 -380 180 380)
R(via1 -125 -325 125 -75)
R(via1 -125 75 125 325)
R(metal2 -1400 -450 1400 450)
R(metal2_lbl 1239 -91 1241 -89)
R(nsd -275 -475 275 475)
)
N(VDD
R(diff_cont -110 2490 110 2710)
R(diff_cont -110 2890 110 3110)
R(diff_cont -110 2890 110 3110)
R(diff_cont -110 2490 110 2710)
R(metal1 -180 2420 180 3180)
R(metal1 -180 2420 180 3180)
R(via1 -125 2475 125 2725)
R(via1 -125 2875 125 3125)
R(metal2 -1400 2350 1400 3250)
R(metal2_lbl 1249 2799 1251 2801)
R(psd -275 2325 275 3275)
)
N(BULK
R(diff_cont -110 -1360 110 -1140)
R(ptie -400 -1590 400 -910)
)
P($0 $1)
P(IN IN)
P($2 $3)
P(OUT OUT)
P(VSS VSS)
P(VDD VDD)
P(BULK BULK)
D($1 D$PMOS
Y(-400 2800)
E(L 0.25)
E(W 0.95)
E(AS 0.49875)
E(AD 0.26125)
T(S $3)
T(G IN)
T(D VDD)
T(B $1)
)
D($2 D$PMOS$1
Y(400 2800)
E(L 0.25)
E(W 0.95)
E(AS 0.26125)
E(AD 0.49875)
T(S VDD)
T(G $3)
T(D OUT)
T(B $1)
)
D($3 D$NMOS
Y(-400 0)
E(L 0.25)
E(W 0.95)
E(AS 0.49875)
E(AD 0.26125)
T(S $3)
T(G IN)
T(D VSS)
T(B BULK)
)
D($4 D$NMOS$1
Y(400 0)
E(L 0.25)
E(W 0.95)
E(AS 0.26125)
E(AD 0.49875)
T(S VSS)
T(G $3)
T(D OUT)
T(B BULK)
)
)
X(INV2PAIR
N(BULK)
N($I8
R(diff_cont 3430 3290 3650 3510)
R(diff_cont 3430 3690 3650 3910)
R(diff_cont 3430 490 3650 710)
R(diff_cont 3430 890 3650 1110)
)
N($I6
R(diff_cont 4230 3290 4450 3510)
R(diff_cont 4230 3690 4450 3910)
R(diff_cont 4230 3690 4450 3910)
R(diff_cont 4230 3290 4450 3510)
R(diff_cont 1590 3290 1810 3510)
R(diff_cont 1590 3690 1810 3910)
R(diff_cont 1590 3690 1810 3910)
R(diff_cont 1590 3290 1810 3510)
R(metal1 4160 3220 4520 3980)
R(metal1 4160 3220 4520 3980)
R(metal1 1520 3220 1880 3980)
R(metal1 1520 3220 1880 3980)
)
N($I5
R(diff_cont 4230 490 4450 710)
R(diff_cont 4230 890 4450 1110)
R(diff_cont 4230 890 4450 1110)
R(diff_cont 4230 490 4450 710)
R(diff_cont 1590 490 1810 710)
R(diff_cont 1590 890 1810 1110)
R(diff_cont 1590 890 1810 1110)
R(diff_cont 1590 490 1810 710)
R(metal1 4160 420 4520 1180)
R(metal1 4160 420 4520 1180)
R(metal1 1520 420 1880 1180)
R(metal1 1520 420 1880 1180)
)
N($I4
R(diff_cont 2390 3690 2610 3910)
R(diff_cont 2390 3290 2610 3510)
R(diff_cont 2390 890 2610 1110)
R(diff_cont 2390 490 2610 710)
)
N($I3)
N($I2
R(diff_cont 5030 3690 5250 3910)
R(diff_cont 5030 3290 5250 3510)
R(diff_cont 5030 890 5250 1110)
R(diff_cont 5030 490 5250 710)
)
N($I1)
P(BULK BULK)
P($1 $I8)
P($2 $I6)
P($3 $I5)
P($4 $I3)
P($5 $I2)
P($6 $I1)
X($1 INV2 Y(1700 800)
P($0 $I1)
P(IN $I3)
P(OUT $I4)
P(VSS $I5)
P(VDD $I6)
P(BULK BULK)
)
X($2 INV2 Y(4340 800)
P($0 $I1)
P(IN $I4)
P($2 $I8)
P(OUT $I2)
P(VSS $I5)
P(VDD $I6)
P(BULK BULK)
)
)
X(RINGO
N(FB
R(diff_cont 22850 2490 23070 2710)
R(diff_cont 22850 2890 23070 3110)
R(diff_cont 22850 -310 23070 -90)
R(diff_cont 22850 90 23070 310)
R(metal1 -1700 1620 -1340 1980)
R(via1 -1645 1675 -1395 1925)
R(via1 22835 1675 23085 1925)
R(metal2 -1720 1600 23160 2000)
R(metal2_lbl -1 1799 1 1801)
)
N(OSC
R(diff_cont 24450 2890 24670 3110)
R(diff_cont 24450 2490 24670 2710)
R(diff_cont 24450 90 24670 310)
R(diff_cont 24450 -310 24670 -90)
R(via1 24435 1675 24685 1925)
R(metal2 24360 1600 24760 2000)
R(metal2_lbl 24559 1799 24561 1801)
)
N(VDD
R(diff_cont 7810 2490 8030 2710)
R(diff_cont 7810 2890 8030 3110)
R(diff_cont 7810 2890 8030 3110)
R(diff_cont 7810 2490 8030 2710)
R(diff_cont 5170 2490 5390 2710)
R(diff_cont 5170 2890 5390 3110)
R(diff_cont 5170 2890 5390 3110)
R(diff_cont 5170 2490 5390 2710)
R(diff_cont 2530 2490 2750 2710)
R(diff_cont 2530 2890 2750 3110)
R(diff_cont 2530 2890 2750 3110)
R(diff_cont 2530 2490 2750 2710)
R(diff_cont -110 2490 110 2710)
R(diff_cont -110 2890 110 3110)
R(diff_cont -110 2890 110 3110)
R(diff_cont -110 2490 110 2710)
R(diff_cont 13090 2490 13310 2710)
R(diff_cont 13090 2890 13310 3110)
R(diff_cont 13090 2890 13310 3110)
R(diff_cont 13090 2490 13310 2710)
R(diff_cont 10450 2490 10670 2710)
R(diff_cont 10450 2890 10670 3110)
R(diff_cont 10450 2890 10670 3110)
R(diff_cont 10450 2490 10670 2710)
R(diff_cont 18370 2490 18590 2710)
R(diff_cont 18370 2890 18590 3110)
R(diff_cont 18370 2890 18590 3110)
R(diff_cont 18370 2490 18590 2710)
R(diff_cont 15730 2490 15950 2710)
R(diff_cont 15730 2890 15950 3110)
R(diff_cont 15730 2890 15950 3110)
R(diff_cont 15730 2490 15950 2710)
R(diff_cont 23650 2490 23870 2710)
R(diff_cont 23650 2890 23870 3110)
R(diff_cont 23650 2890 23870 3110)
R(diff_cont 23650 2490 23870 2710)
R(diff_cont 21010 2490 21230 2710)
R(diff_cont 21010 2890 21230 3110)
R(diff_cont 21010 2890 21230 3110)
R(diff_cont 21010 2490 21230 2710)
R(metal1 -180 3100 180 4220)
R(metal1 2460 3100 2820 4220)
R(metal1 5100 3100 5460 4220)
R(metal1 7740 3100 8100 4220)
R(metal1 10380 3100 10740 4220)
R(metal1 13020 3100 13380 4220)
R(metal1 15660 3100 16020 4220)
R(metal1 18300 3100 18660 4220)
R(metal1 20940 3100 21300 4220)
R(metal1 23580 3100 23940 4220)
R(metal1 7740 2420 8100 3180)
R(metal1 7740 2420 8100 3180)
R(metal1 5100 2420 5460 3180)
R(metal1 5100 2420 5460 3180)
R(metal1 2460 2420 2820 3180)
R(metal1 2460 2420 2820 3180)
R(metal1 -180 2420 180 3180)
R(metal1 -180 2420 180 3180)
R(metal1 13020 2420 13380 3180)
R(metal1 13020 2420 13380 3180)
R(metal1 10380 2420 10740 3180)
R(metal1 10380 2420 10740 3180)
R(metal1 18300 2420 18660 3180)
R(metal1 18300 2420 18660 3180)
R(metal1 15660 2420 16020 3180)
R(metal1 15660 2420 16020 3180)
R(metal1 23580 2420 23940 3180)
R(metal1 23580 2420 23940 3180)
R(metal1 20940 2420 21300 3180)
R(metal1 20940 2420 21300 3180)
R(metal2_lbl -1 2799 1 2801)
)
N('BULK,VSS'
R(diff_cont 7810 -310 8030 -90)
R(diff_cont 7810 90 8030 310)
R(diff_cont 7810 90 8030 310)
R(diff_cont 7810 -310 8030 -90)
R(diff_cont 5170 -310 5390 -90)
R(diff_cont 5170 90 5390 310)
R(diff_cont 5170 90 5390 310)
R(diff_cont 5170 -310 5390 -90)
R(diff_cont 2530 -310 2750 -90)
R(diff_cont 2530 90 2750 310)
R(diff_cont 2530 90 2750 310)
R(diff_cont 2530 -310 2750 -90)
R(diff_cont -110 -310 110 -90)
R(diff_cont -110 90 110 310)
R(diff_cont -110 90 110 310)
R(diff_cont -110 -310 110 -90)
R(diff_cont 13090 -310 13310 -90)
R(diff_cont 13090 90 13310 310)
R(diff_cont 13090 90 13310 310)
R(diff_cont 13090 -310 13310 -90)
R(diff_cont 10450 -310 10670 -90)
R(diff_cont 10450 90 10670 310)
R(diff_cont 10450 90 10670 310)
R(diff_cont 10450 -310 10670 -90)
R(diff_cont 18370 -310 18590 -90)
R(diff_cont 18370 90 18590 310)
R(diff_cont 18370 90 18590 310)
R(diff_cont 18370 -310 18590 -90)
R(diff_cont 15730 -310 15950 -90)
R(diff_cont 15730 90 15950 310)
R(diff_cont 15730 90 15950 310)
R(diff_cont 15730 -310 15950 -90)
R(diff_cont 23650 -310 23870 -90)
R(diff_cont 23650 90 23870 310)
R(diff_cont 23650 90 23870 310)
R(diff_cont 23650 -310 23870 -90)
R(diff_cont 21010 -310 21230 -90)
R(diff_cont 21010 90 21230 310)
R(diff_cont 21010 90 21230 310)
R(diff_cont 21010 -310 21230 -90)
R(metal1 -180 -1420 180 -300)
R(metal1 2460 -1420 2820 -300)
R(metal1 5100 -1420 5460 -300)
R(metal1 7740 -1420 8100 -300)
R(metal1 10380 -1420 10740 -300)
R(metal1 13020 -1420 13380 -300)
R(metal1 15660 -1420 16020 -300)
R(metal1 18300 -1420 18660 -300)
R(metal1 20940 -1420 21300 -300)
R(metal1 23580 -1420 23940 -300)
R(metal1 7740 -380 8100 380)
R(metal1 7740 -380 8100 380)
R(metal1 5100 -380 5460 380)
R(metal1 5100 -380 5460 380)
R(metal1 2460 -380 2820 380)
R(metal1 2460 -380 2820 380)
R(metal1 -180 -380 180 380)
R(metal1 -180 -380 180 380)
R(metal1 13020 -380 13380 380)
R(metal1 13020 -380 13380 380)
R(metal1 10380 -380 10740 380)
R(metal1 10380 -380 10740 380)
R(metal1 18300 -380 18660 380)
R(metal1 18300 -380 18660 380)
R(metal1 15660 -380 16020 380)
R(metal1 15660 -380 16020 380)
R(metal1 23580 -380 23940 380)
R(metal1 23580 -380 23940 380)
R(metal1 20940 -380 21300 380)
R(metal1 20940 -380 21300 380)
R(metal2_lbl -1 -1 1 1)
)
N($I13
R(diff_cont 3330 2890 3550 3110)
R(diff_cont 3330 2490 3550 2710)
R(diff_cont 3330 90 3550 310)
R(diff_cont 3330 -310 3550 -90)
)
N($I7
R(diff_cont 19170 2890 19390 3110)
R(diff_cont 19170 2490 19390 2710)
R(diff_cont 19170 90 19390 310)
R(diff_cont 19170 -310 19390 -90)
)
N($I6
R(diff_cont 13890 2890 14110 3110)
R(diff_cont 13890 2490 14110 2710)
R(diff_cont 13890 90 14110 310)
R(diff_cont 13890 -310 14110 -90)
)
N($I5
R(diff_cont 8610 2890 8830 3110)
R(diff_cont 8610 2490 8830 2710)
R(diff_cont 8610 90 8830 310)
R(diff_cont 8610 -310 8830 -90)
)
P(FB FB)
P(OSC OSC)
P(VDD VDD)
P('BULK,VSS' 'BULK,VSS')
X($1 INV2PAIR Y(19420 -800)
P(BULK 'BULK,VSS')
P($1 FB)
P($2 VDD)
P($3 'BULK,VSS')
P($4 $I7)
P($5 OSC)
P($6 VDD)
)
X($2 INV2PAIR Y(-1700 -800)
P(BULK 'BULK,VSS')
P($2 VDD)
P($3 'BULK,VSS')
P($4 FB)
P($5 $I13)
P($6 VDD)
)
X($3 INV2PAIR Y(3580 -800)
P(BULK 'BULK,VSS')
P($2 VDD)
P($3 'BULK,VSS')
P($4 $I13)
P($5 $I5)
P($6 VDD)
)
X($4 INV2PAIR Y(8860 -800)
P(BULK 'BULK,VSS')
P($2 VDD)
P($3 'BULK,VSS')
P($4 $I5)
P($5 $I6)
P($6 VDD)
)
X($5 INV2PAIR Y(14140 -800)
P(BULK 'BULK,VSS')
P($2 VDD)
P($3 'BULK,VSS')
P($4 $I6)
P($5 $I7)
P($6 VDD)
)
)

444
testdata/algo/l2n_writer_au_s.txt vendored Normal file
View File

@ -0,0 +1,444 @@
#%l2n-klayout
W(RINGO)
U(0.001)
L(poly)
L(poly_lbl)
L(diff_cont)
L(poly_cont)
L(metal1)
L(metal1_lbl)
L(via1)
L(metal2)
L(metal2_lbl)
L(psd)
L(nsd)
C(poly poly poly_lbl poly_cont)
C(poly_lbl poly)
C(diff_cont diff_cont metal1 psd nsd)
C(poly_cont poly poly_cont metal1)
C(metal1 diff_cont poly_cont metal1 metal1_lbl via1)
C(metal1_lbl metal1)
C(via1 metal1 via1 metal2)
C(metal2 via1 metal2 metal2_lbl)
C(metal2_lbl metal2)
C(psd diff_cont psd)
C(nsd diff_cont nsd)
D(D$PMOS PMOS
T(S
R(psd -650 -475 -125 475)
)
T(G
R(poly -125 -475 125 475)
)
T(D
R(psd 125 -475 675 475)
)
)
D(D$PMOS$1 PMOS
T(S
R(psd -675 -475 -125 475)
)
T(G
R(poly -125 -475 125 475)
)
T(D
R(psd 125 -475 650 475)
)
)
D(D$NMOS NMOS
T(S
R(nsd -650 -475 -125 475)
)
T(G
R(poly -125 -475 125 475)
)
T(D
R(nsd 125 -475 675 475)
)
)
D(D$NMOS$1 NMOS
T(S
R(nsd -675 -475 -125 475)
)
T(G
R(poly -125 -475 125 475)
)
T(D
R(nsd 125 -475 650 475)
)
)
X(INV2
N(IN
R(poly -525 -250 -275 2250)
R(poly -1700 1620 -400 1980)
R(poly -525 -800 -275 800)
R(poly -525 2000 -275 3600)
R(poly_lbl -801 1799 -799 1801)
R(poly_cont -1630 1690 -1410 1910)
)
N($2
R(poly 275 -250 525 2250)
R(poly 220 820 580 1180)
R(poly 275 2000 525 3600)
R(poly 275 -800 525 800)
R(diff_cont -910 2490 -690 2710)
R(diff_cont -910 2890 -690 3110)
R(diff_cont -910 -310 -690 -90)
R(diff_cont -910 90 -690 310)
R(poly_cont 290 890 510 1110)
R(metal1 -800 820 580 1180)
R(metal1 -980 -420 -620 2420)
R(metal1 -980 2420 -620 3180)
R(metal1 -980 -380 -620 380)
R(psd -1050 2325 -525 3275)
R(nsd -1050 -475 -525 475)
)
N(OUT
R(diff_cont 690 2890 910 3110)
R(diff_cont 690 2490 910 2710)
R(diff_cont 690 90 910 310)
R(diff_cont 690 -310 910 -90)
Q(metal1 800 20 800 380 940 380 940 1620 620 1620 620 2420 980 2420 980 1980 1300 1980 1300 20)
R(metal1 620 2420 980 3180)
R(metal1 620 -380 980 380)
R(metal1_lbl 799 1799 801 1801)
R(psd 525 2325 1050 3275)
R(nsd 525 -475 1050 475)
)
N($4
R(diff_cont -110 -310 110 -90)
R(diff_cont -110 90 110 310)
R(diff_cont -110 90 110 310)
R(diff_cont -110 -310 110 -90)
R(metal1 -180 -380 180 380)
R(metal1 -180 -380 180 380)
R(via1 -125 -325 125 -75)
R(via1 -125 75 125 325)
R(metal2 -1400 -450 1400 450)
R(nsd -275 -475 275 475)
)
N($5
R(diff_cont -110 2490 110 2710)
R(diff_cont -110 2890 110 3110)
R(diff_cont -110 2890 110 3110)
R(diff_cont -110 2490 110 2710)
R(metal1 -180 2420 180 3180)
R(metal1 -180 2420 180 3180)
R(via1 -125 2475 125 2725)
R(via1 -125 2875 125 3125)
R(metal2 -1400 2350 1400 3250)
R(psd -275 2325 275 3275)
)
P(IN IN)
P($1 $2)
P(OUT OUT)
P($3 $4)
P($4 $5)
D($1 D$PMOS
Y(-400 2800)
E(L 0.25)
E(W 0.95)
E(AS 0.49875)
E(AD 0.26125)
T(S $2)
T(G IN)
T(D $5)
)
D($2 D$PMOS$1
Y(400 2800)
E(L 0.25)
E(W 0.95)
E(AS 0.26125)
E(AD 0.49875)
T(S $5)
T(G $2)
T(D OUT)
)
D($3 D$NMOS
Y(-400 0)
E(L 0.25)
E(W 0.95)
E(AS 0.49875)
E(AD 0.26125)
T(S $2)
T(G IN)
T(D $4)
)
D($4 D$NMOS$1
Y(400 0)
E(L 0.25)
E(W 0.95)
E(AS 0.26125)
E(AD 0.49875)
T(S $4)
T(G $2)
T(D OUT)
)
)
X(RINGO
N(FB
R(diff_cont 22850 2490 23070 2710)
R(diff_cont 22850 2890 23070 3110)
R(diff_cont 22850 -310 23070 -90)
R(diff_cont 22850 90 23070 310)
R(metal1 -1700 1620 -1340 1980)
R(via1 -1645 1675 -1395 1925)
R(via1 22835 1675 23085 1925)
R(metal2 -1720 1600 23160 2000)
R(metal2_lbl -1 1799 1 1801)
)
N(OSC
R(diff_cont 24450 2890 24670 3110)
R(diff_cont 24450 2490 24670 2710)
R(diff_cont 24450 90 24670 310)
R(diff_cont 24450 -310 24670 -90)
R(via1 24435 1675 24685 1925)
R(metal2 24360 1600 24760 2000)
R(metal2_lbl 24559 1799 24561 1801)
)
N(VSS
R(diff_cont 2530 -310 2750 -90)
R(diff_cont 2530 90 2750 310)
R(diff_cont 2530 90 2750 310)
R(diff_cont 2530 -310 2750 -90)
R(diff_cont -110 -310 110 -90)
R(diff_cont -110 90 110 310)
R(diff_cont -110 90 110 310)
R(diff_cont -110 -310 110 -90)
R(diff_cont 5170 -310 5390 -90)
R(diff_cont 5170 90 5390 310)
R(diff_cont 5170 90 5390 310)
R(diff_cont 5170 -310 5390 -90)
R(diff_cont 7810 -310 8030 -90)
R(diff_cont 7810 90 8030 310)
R(diff_cont 7810 90 8030 310)
R(diff_cont 7810 -310 8030 -90)
R(diff_cont 10450 -310 10670 -90)
R(diff_cont 10450 90 10670 310)
R(diff_cont 10450 90 10670 310)
R(diff_cont 10450 -310 10670 -90)
R(diff_cont 13090 -310 13310 -90)
R(diff_cont 13090 90 13310 310)
R(diff_cont 13090 90 13310 310)
R(diff_cont 13090 -310 13310 -90)
R(diff_cont 15730 -310 15950 -90)
R(diff_cont 15730 90 15950 310)
R(diff_cont 15730 90 15950 310)
R(diff_cont 15730 -310 15950 -90)
R(diff_cont 18370 -310 18590 -90)
R(diff_cont 18370 90 18590 310)
R(diff_cont 18370 90 18590 310)
R(diff_cont 18370 -310 18590 -90)
R(diff_cont 21010 -310 21230 -90)
R(diff_cont 21010 90 21230 310)
R(diff_cont 21010 90 21230 310)
R(diff_cont 21010 -310 21230 -90)
R(diff_cont 23650 -310 23870 -90)
R(diff_cont 23650 90 23870 310)
R(diff_cont 23650 90 23870 310)
R(diff_cont 23650 -310 23870 -90)
R(metal1 2460 -380 2820 380)
R(metal1 2460 -380 2820 380)
R(metal1 -180 -380 180 380)
R(metal1 -180 -380 180 380)
R(metal1 5100 -380 5460 380)
R(metal1 5100 -380 5460 380)
R(metal1 7740 -380 8100 380)
R(metal1 7740 -380 8100 380)
R(metal1 10380 -380 10740 380)
R(metal1 10380 -380 10740 380)
R(metal1 13020 -380 13380 380)
R(metal1 13020 -380 13380 380)
R(metal1 15660 -380 16020 380)
R(metal1 15660 -380 16020 380)
R(metal1 18300 -380 18660 380)
R(metal1 18300 -380 18660 380)
R(metal1 20940 -380 21300 380)
R(metal1 20940 -380 21300 380)
R(metal1 23580 -380 23940 380)
R(metal1 23580 -380 23940 380)
R(metal2_lbl -1 -1 1 1)
)
N(VDD
R(diff_cont 2530 2490 2750 2710)
R(diff_cont 2530 2890 2750 3110)
R(diff_cont 2530 2890 2750 3110)
R(diff_cont 2530 2490 2750 2710)
R(diff_cont -110 2490 110 2710)
R(diff_cont -110 2890 110 3110)
R(diff_cont -110 2890 110 3110)
R(diff_cont -110 2490 110 2710)
R(diff_cont 5170 2490 5390 2710)
R(diff_cont 5170 2890 5390 3110)
R(diff_cont 5170 2890 5390 3110)
R(diff_cont 5170 2490 5390 2710)
R(diff_cont 7810 2490 8030 2710)
R(diff_cont 7810 2890 8030 3110)
R(diff_cont 7810 2890 8030 3110)
R(diff_cont 7810 2490 8030 2710)
R(diff_cont 10450 2490 10670 2710)
R(diff_cont 10450 2890 10670 3110)
R(diff_cont 10450 2890 10670 3110)
R(diff_cont 10450 2490 10670 2710)
R(diff_cont 13090 2490 13310 2710)
R(diff_cont 13090 2890 13310 3110)
R(diff_cont 13090 2890 13310 3110)
R(diff_cont 13090 2490 13310 2710)
R(diff_cont 15730 2490 15950 2710)
R(diff_cont 15730 2890 15950 3110)
R(diff_cont 15730 2890 15950 3110)
R(diff_cont 15730 2490 15950 2710)
R(diff_cont 18370 2490 18590 2710)
R(diff_cont 18370 2890 18590 3110)
R(diff_cont 18370 2890 18590 3110)
R(diff_cont 18370 2490 18590 2710)
R(diff_cont 21010 2490 21230 2710)
R(diff_cont 21010 2890 21230 3110)
R(diff_cont 21010 2890 21230 3110)
R(diff_cont 21010 2490 21230 2710)
R(diff_cont 23650 2490 23870 2710)
R(diff_cont 23650 2890 23870 3110)
R(diff_cont 23650 2890 23870 3110)
R(diff_cont 23650 2490 23870 2710)
R(metal1 2460 2420 2820 3180)
R(metal1 2460 2420 2820 3180)
R(metal1 -180 2420 180 3180)
R(metal1 -180 2420 180 3180)
R(metal1 5100 2420 5460 3180)
R(metal1 5100 2420 5460 3180)
R(metal1 7740 2420 8100 3180)
R(metal1 7740 2420 8100 3180)
R(metal1 10380 2420 10740 3180)
R(metal1 10380 2420 10740 3180)
R(metal1 13020 2420 13380 3180)
R(metal1 13020 2420 13380 3180)
R(metal1 15660 2420 16020 3180)
R(metal1 15660 2420 16020 3180)
R(metal1 18300 2420 18660 3180)
R(metal1 18300 2420 18660 3180)
R(metal1 20940 2420 21300 3180)
R(metal1 20940 2420 21300 3180)
R(metal1 23580 2420 23940 3180)
R(metal1 23580 2420 23940 3180)
R(metal2_lbl -1 2799 1 2801)
)
N($I19
R(diff_cont 690 2890 910 3110)
R(diff_cont 690 2490 910 2710)
R(diff_cont 690 90 910 310)
R(diff_cont 690 -310 910 -90)
)
N($I8
R(diff_cont 21810 2890 22030 3110)
R(diff_cont 21810 2490 22030 2710)
R(diff_cont 21810 90 22030 310)
R(diff_cont 21810 -310 22030 -90)
)
N($I7
R(diff_cont 19170 2890 19390 3110)
R(diff_cont 19170 2490 19390 2710)
R(diff_cont 19170 90 19390 310)
R(diff_cont 19170 -310 19390 -90)
)
N($I6
R(diff_cont 16530 2890 16750 3110)
R(diff_cont 16530 2490 16750 2710)
R(diff_cont 16530 90 16750 310)
R(diff_cont 16530 -310 16750 -90)
)
N($I5
R(diff_cont 13890 2890 14110 3110)
R(diff_cont 13890 2490 14110 2710)
R(diff_cont 13890 90 14110 310)
R(diff_cont 13890 -310 14110 -90)
)
N($I4
R(diff_cont 11250 2890 11470 3110)
R(diff_cont 11250 2490 11470 2710)
R(diff_cont 11250 90 11470 310)
R(diff_cont 11250 -310 11470 -90)
)
N($I3
R(diff_cont 8610 2890 8830 3110)
R(diff_cont 8610 2490 8830 2710)
R(diff_cont 8610 90 8830 310)
R(diff_cont 8610 -310 8830 -90)
)
N($I2
R(diff_cont 5970 2890 6190 3110)
R(diff_cont 5970 2490 6190 2710)
R(diff_cont 5970 90 6190 310)
R(diff_cont 5970 -310 6190 -90)
)
N($I1
R(diff_cont 3330 2890 3550 3110)
R(diff_cont 3330 2490 3550 2710)
R(diff_cont 3330 90 3550 310)
R(diff_cont 3330 -310 3550 -90)
)
P(FB FB)
P(OSC OSC)
P(VSS VSS)
P(VDD VDD)
X($1 INV2 Y(23760 0)
P(IN $I8)
P($1 FB)
P(OUT OSC)
P($3 VSS)
P($4 VDD)
)
X($2 INV2 Y(0 0)
P(IN FB)
P(OUT $I19)
P($3 VSS)
P($4 VDD)
)
X($3 INV2 Y(2640 0)
P(IN $I19)
P(OUT $I1)
P($3 VSS)
P($4 VDD)
)
X($4 INV2 Y(5280 0)
P(IN $I1)
P(OUT $I2)
P($3 VSS)
P($4 VDD)
)
X($5 INV2 Y(7920 0)
P(IN $I2)
P(OUT $I3)
P($3 VSS)
P($4 VDD)
)
X($6 INV2 Y(10560 0)
P(IN $I3)
P(OUT $I4)
P($3 VSS)
P($4 VDD)
)
X($7 INV2 Y(13200 0)
P(IN $I4)
P(OUT $I5)
P($3 VSS)
P($4 VDD)
)
X($8 INV2 Y(15840 0)
P(IN $I5)
P(OUT $I6)
P($3 VSS)
P($4 VDD)
)
X($9 INV2 Y(18480 0)
P(IN $I6)
P(OUT $I7)
P($3 VSS)
P($4 VDD)
)
X($10 INV2 Y(21120 0)
P(IN $I7)
P(OUT $I8)
P($3 VSS)
P($4 VDD)
)
)