mirror of https://github.com/KLayout/klayout.git
LayoutToNetlist enhancements in the area of the dumper.
This commit is contained in:
parent
438f50091f
commit
56bb39a273
|
|
@ -2029,6 +2029,27 @@ recursive_cluster_shape_iterator<T> &recursive_cluster_shape_iterator<T>::operat
|
|||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void recursive_cluster_shape_iterator<T>::skip_cell ()
|
||||
{
|
||||
m_shape_iter = typename db::local_cluster<T>::shape_iterator ();
|
||||
|
||||
do {
|
||||
|
||||
up ();
|
||||
if (m_conn_iter_stack.empty ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
++m_conn_iter_stack.back ().first;
|
||||
|
||||
} while (m_conn_iter_stack.back ().first == m_conn_iter_stack.back ().second);
|
||||
|
||||
while (m_shape_iter.at_end () && ! m_conn_iter_stack.empty ()) {
|
||||
next_conn ();
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void recursive_cluster_shape_iterator<T>::next_conn ()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -882,6 +882,11 @@ public:
|
|||
*/
|
||||
recursive_cluster_shape_iterator &operator++ ();
|
||||
|
||||
/**
|
||||
* @brief Skips the current cell and advances to the next cell and shape
|
||||
*/
|
||||
void skip_cell ();
|
||||
|
||||
private:
|
||||
typedef typename db::connected_clusters<T>::connections_type connections_type;
|
||||
|
||||
|
|
|
|||
|
|
@ -78,28 +78,43 @@ size_t LayoutToNetlist::max_vertex_count () const
|
|||
return m_dss.max_vertex_count ();
|
||||
}
|
||||
|
||||
db::Region *LayoutToNetlist::make_layer (unsigned int layer_index)
|
||||
db::Region *LayoutToNetlist::make_layer (unsigned int layer_index, const std::string &n)
|
||||
{
|
||||
db::RecursiveShapeIterator si (m_iter);
|
||||
si.set_layer (layer_index);
|
||||
si.shape_flags (db::ShapeIterator::All);
|
||||
return new db::Region (si, m_dss);
|
||||
|
||||
db::Region *region = new db::Region (si, m_dss);
|
||||
if (! n.empty ()) {
|
||||
name (*region, n);
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
db::Region *LayoutToNetlist::make_text_layer (unsigned int layer_index)
|
||||
db::Region *LayoutToNetlist::make_text_layer (unsigned int layer_index, const std::string &n)
|
||||
{
|
||||
db::RecursiveShapeIterator si (m_iter);
|
||||
si.set_layer (layer_index);
|
||||
si.shape_flags (db::ShapeIterator::Texts);
|
||||
return new db::Region (si, m_dss);
|
||||
|
||||
db::Region *region = new db::Region (si, m_dss);
|
||||
if (! n.empty ()) {
|
||||
name (*region, n);
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
db::Region *LayoutToNetlist::make_polygon_layer (unsigned int layer_index)
|
||||
db::Region *LayoutToNetlist::make_polygon_layer (unsigned int layer_index, const std::string &n)
|
||||
{
|
||||
db::RecursiveShapeIterator si (m_iter);
|
||||
si.set_layer (layer_index);
|
||||
si.shape_flags (db::ShapeIterator::Paths | db::ShapeIterator::Polygons | db::ShapeIterator::Boxes);
|
||||
return new db::Region (si, m_dss);
|
||||
|
||||
db::Region *region = new db::Region (si, m_dss);
|
||||
if (! n.empty ()) {
|
||||
name (*region, n);
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
void LayoutToNetlist::extract_devices (db::NetlistDeviceExtractor &extractor, const std::map<std::string, db::Region *> &layers)
|
||||
|
|
@ -202,6 +217,15 @@ const db::Cell *LayoutToNetlist::internal_top_cell () const
|
|||
return &m_dss.const_initial_cell ();
|
||||
}
|
||||
|
||||
void LayoutToNetlist::name (const db::Region ®ion, const std::string &name)
|
||||
{
|
||||
unsigned int li = layer_of (region);
|
||||
db::Layout &ly = m_dss.layout ();
|
||||
db::LayerProperties lp = ly.get_properties (li);
|
||||
lp.name = name;
|
||||
ly.set_properties (li, lp);
|
||||
}
|
||||
|
||||
unsigned int LayoutToNetlist::layer_of (const db::Region ®ion) const
|
||||
{
|
||||
const db::DeepRegion *dr = dynamic_cast<const db::DeepRegion *> (region.delegate ());
|
||||
|
|
|
|||
|
|
@ -114,6 +114,25 @@ public:
|
|||
*/
|
||||
size_t max_vertex_count () const;
|
||||
|
||||
/**
|
||||
* @brief Names a layer
|
||||
* This is a formal name for the layer. Using a name or layer properties
|
||||
* (see below) enhances readability of backannotated information
|
||||
* if layers are involved. Use this method or the other variants to
|
||||
* attach a name or standard layer properties to a region delivered
|
||||
* by "make_layer" or derived from other regions through boolean
|
||||
* operations.
|
||||
*/
|
||||
void name (const db::Region ®ion, const std::string &name);
|
||||
|
||||
/**
|
||||
* @brief Gets the name of the given layer
|
||||
*/
|
||||
std::string name (const db::Region ®ion) const
|
||||
{
|
||||
return internal_layout ()->get_properties (layer_of (region)).name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new region representing an original layer
|
||||
* "layer_index" is the layer index of the desired layer in the original layout.
|
||||
|
|
@ -122,19 +141,19 @@ public:
|
|||
* A variant not taking texts is "make_polygon_layer". A Variant only taking
|
||||
* texts is "make_text_layer".
|
||||
*/
|
||||
db::Region *make_layer (unsigned int layer_index);
|
||||
db::Region *make_layer (unsigned int layer_index, const std::string &name = std::string ());
|
||||
|
||||
/**
|
||||
* @brief Creates a new region representing an original layer taking texts only
|
||||
* See "make_layer" for details.
|
||||
*/
|
||||
db::Region *make_text_layer (unsigned int layer_index);
|
||||
db::Region *make_text_layer (unsigned int layer_index, const std::string &name = std::string ());
|
||||
|
||||
/**
|
||||
* @brief Creates a new region representing an original layer taking polygons and texts
|
||||
* See "make_layer" for details.
|
||||
*/
|
||||
db::Region *make_polygon_layer (unsigned int layer_index);
|
||||
db::Region *make_polygon_layer (unsigned int layer_index, const std::string &name = std::string ());
|
||||
|
||||
/**
|
||||
* @brief Extracts devices
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ namespace db
|
|||
* connect(<layer1> <name> ...) - connects layer1 with the following layers [short key: C]
|
||||
* global(<layer> <net> ...) - connects a layer with the given global nets [short key: G]
|
||||
* circuit(<name> [circuit-def]) - circuit (cell) [short key: X]
|
||||
* device(<name> <class> [device-footprint-def])
|
||||
* - device footprint [short key: D]
|
||||
* device(<name> <class> [device-abstract-def])
|
||||
* - device abstract [short key: D]
|
||||
*
|
||||
* [circuit-def]:
|
||||
*
|
||||
|
|
@ -72,7 +72,7 @@ namespace db
|
|||
* rect(<layer> <left> <bottom> <right> <top>)
|
||||
* - defines a rectangle [short key: R]
|
||||
*
|
||||
* [device-footprint-def]:
|
||||
* [device-abstract-def]:
|
||||
*
|
||||
* terminal(<terminal-name> [geometry-def])
|
||||
* - specifies the terminal geometry [short key: empty]
|
||||
|
|
@ -80,7 +80,7 @@ namespace db
|
|||
* [device-def]:
|
||||
*
|
||||
* param(<name> <value>) - defines a parameter [short key P]
|
||||
* footprint(<name>) - links to a geometrical device footprint on top level [short key F]
|
||||
* abstract(<name>) - links to a geometrical device abstract on top level [short key A]
|
||||
* terminal(<terminal-name> <net-name>)
|
||||
* - specifies connection of the terminal with
|
||||
* a net (short key: empty)
|
||||
|
|
@ -110,7 +110,7 @@ static std::string subcircuit_key ("subcircuit");
|
|||
static std::string polygon_key ("polygon");
|
||||
static std::string rect_key ("rect");
|
||||
static std::string terminal_key ("terminal");
|
||||
static std::string footprint_key ("footprint");
|
||||
static std::string abstract_key ("abstract");
|
||||
static std::string label_key ("label");
|
||||
static std::string param_key ("param");
|
||||
static std::string location_key ("location");
|
||||
|
|
@ -140,20 +140,31 @@ static std::string name_for_layer (const db::Layout *layout, unsigned int l)
|
|||
|
||||
void LayoutToNetlistStandardWriter::write (const db::LayoutToNetlist *l2n)
|
||||
{
|
||||
const int version = 1;
|
||||
bool any = false;
|
||||
|
||||
const int version = 0;
|
||||
|
||||
const db::Layout *ly = l2n->internal_layout ();
|
||||
const db::Netlist *nl = l2n->netlist ();
|
||||
|
||||
*mp_stream << "# General" << endl;
|
||||
*mp_stream << version_key << "(" << version << ")" << endl;
|
||||
*mp_stream << "# General section" << endl;
|
||||
*mp_stream << "# Lists general definitions." << endl << endl;
|
||||
if (version > 0) {
|
||||
*mp_stream << version_key << "(" << version << ")" << endl;
|
||||
}
|
||||
*mp_stream << top_key << "(" << tl::to_word_or_quoted_string (ly->cell_name (l2n->internal_top_cell ()->cell_index ())) << ")" << endl;
|
||||
*mp_stream << unit_key << "(" << ly->dbu () << ")" << endl;
|
||||
|
||||
*mp_stream << endl << "# Layers" << endl;
|
||||
for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) {
|
||||
*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;
|
||||
for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) {
|
||||
*mp_stream << layer_key << "(" << name_for_layer (ly, *l) << ")" << endl;
|
||||
}
|
||||
|
||||
*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);
|
||||
db::Connectivity::layer_iterator cb = l2n->connectivity ().begin_connected (*l);
|
||||
|
|
@ -165,9 +176,18 @@ void LayoutToNetlistStandardWriter::write (const db::LayoutToNetlist *l2n)
|
|||
*mp_stream << ")" << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
any = false;
|
||||
for (db::Connectivity::layer_iterator l = l2n->connectivity ().begin_layers (); l != l2n->connectivity ().end_layers (); ++l) {
|
||||
|
||||
db::Connectivity::global_nets_iterator ge = l2n->connectivity ().end_global_connections (*l);
|
||||
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;
|
||||
any = true;
|
||||
}
|
||||
*mp_stream << global_key << "(" << name_for_layer (ly, *l);
|
||||
for (db::Connectivity::global_nets_iterator g = gb; g != ge; ++g) {
|
||||
*mp_stream << " " << tl::to_word_or_quoted_string (l2n->connectivity ().global_net_name (*g));
|
||||
|
|
@ -177,7 +197,10 @@ void LayoutToNetlistStandardWriter::write (const db::LayoutToNetlist *l2n)
|
|||
|
||||
}
|
||||
|
||||
*mp_stream << endl << "# Device footprints" << endl;
|
||||
if (nl->begin_device_models () != nl->end_device_models ()) {
|
||||
*mp_stream << endl << "# Device abstracts section" << endl;
|
||||
*mp_stream << "# Device abstracts list the pin shapes of the devices." << endl;
|
||||
}
|
||||
for (db::Netlist::const_device_model_iterator m = nl->begin_device_models (); m != nl->end_device_models (); ++m) {
|
||||
if (m->device_class ()) {
|
||||
*mp_stream << device_key << "(" << tl::to_word_or_quoted_string (m->name ()) << " " << tl::to_word_or_quoted_string (m->device_class ()->name ()) << endl;
|
||||
|
|
@ -186,6 +209,8 @@ void LayoutToNetlistStandardWriter::write (const db::LayoutToNetlist *l2n)
|
|||
}
|
||||
}
|
||||
|
||||
*mp_stream << endl << "# Circuit section" << endl;
|
||||
*mp_stream << "# Circuits are the hierarchical building blocks of the netlist." << endl;
|
||||
for (db::Netlist::const_top_down_circuit_iterator i = nl->begin_top_down (); i != nl->end_top_down (); ++i) {
|
||||
const db::Circuit *x = *i;
|
||||
*mp_stream << endl << "# Circuit " << x->name () << endl;
|
||||
|
|
@ -197,24 +222,38 @@ void LayoutToNetlistStandardWriter::write (const db::LayoutToNetlist *l2n)
|
|||
|
||||
void LayoutToNetlistStandardWriter::write (const db::LayoutToNetlist *l2n, const db::Circuit &circuit)
|
||||
{
|
||||
for (db::Circuit::const_net_iterator n = circuit.begin_nets (); n != circuit.end_nets (); ++n) {
|
||||
write (l2n, *n);
|
||||
}
|
||||
|
||||
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) {
|
||||
*mp_stream << indent1 << pin_key << "(" << tl::to_word_or_quoted_string (p->expanded_name ()) << " " << tl::to_word_or_quoted_string (net->expanded_name ()) << ")" << endl;
|
||||
if (circuit.begin_nets () != circuit.end_nets ()) {
|
||||
*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);
|
||||
}
|
||||
}
|
||||
|
||||
for (db::Circuit::const_device_iterator d = circuit.begin_devices (); d != circuit.end_devices (); ++d) {
|
||||
write (l2n, *d);
|
||||
if (circuit.begin_pins () != circuit.end_pins ()) {
|
||||
*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) {
|
||||
*mp_stream << indent1 << pin_key << "(" << tl::to_word_or_quoted_string (p->expanded_name ()) << " " << tl::to_word_or_quoted_string (net->expanded_name ()) << ")" << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (db::Circuit::const_subcircuit_iterator x = circuit.begin_subcircuits (); x != circuit.end_subcircuits (); ++x) {
|
||||
write (l2n, *x);
|
||||
if (circuit.begin_devices () != circuit.end_devices ()) {
|
||||
*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;
|
||||
for (db::Circuit::const_subcircuit_iterator x = circuit.begin_subcircuits (); x != circuit.end_subcircuits (); ++x) {
|
||||
write (l2n, *x);
|
||||
}
|
||||
}
|
||||
|
||||
*mp_stream << endl;
|
||||
}
|
||||
|
||||
template <class T, class Tr>
|
||||
|
|
@ -226,12 +265,14 @@ void write_points (tl::OutputStream &stream, const T &poly, const Tr &tr)
|
|||
}
|
||||
}
|
||||
|
||||
void LayoutToNetlistStandardWriter::write (const db::PolygonRef *s, const std::string &lname)
|
||||
void LayoutToNetlistStandardWriter::write (const db::PolygonRef *s, const db::ICplxTrans &tr, const std::string &lname)
|
||||
{
|
||||
db::ICplxTrans t = tr * db::ICplxTrans (s->trans ());
|
||||
|
||||
const db::Polygon &poly = s->obj ();
|
||||
if (poly.is_box ()) {
|
||||
|
||||
db::Box box = s->trans () * poly.box ();
|
||||
db::Box box = t * poly.box ();
|
||||
*mp_stream << rect_key << "(" << lname;
|
||||
*mp_stream << " " << box.left () << " " << box.bottom ();
|
||||
*mp_stream << " " << box.right () << " " << box.top ();
|
||||
|
|
@ -242,9 +283,9 @@ void LayoutToNetlistStandardWriter::write (const db::PolygonRef *s, const std::s
|
|||
*mp_stream << polygon_key << "(" << lname;
|
||||
if (poly.holes () > 0) {
|
||||
db::SimplePolygon sp (poly);
|
||||
write_points (*mp_stream, sp, s->trans ());
|
||||
write_points (*mp_stream, sp, t);
|
||||
} else {
|
||||
write_points (*mp_stream, poly, s->trans ());
|
||||
write_points (*mp_stream, poly, t);
|
||||
}
|
||||
*mp_stream << ")";
|
||||
|
||||
|
|
@ -262,18 +303,36 @@ void LayoutToNetlistStandardWriter::write (const db::LayoutToNetlist *l2n, const
|
|||
|
||||
for (db::Connectivity::layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
|
||||
|
||||
const db::local_cluster<db::PolygonRef> &lc = clusters.clusters_per_cell (circuit->cell_index ()).cluster_by_id (net.cluster_id ());
|
||||
for (db::local_cluster<db::PolygonRef>::shape_iterator s = lc.begin (*l); ! s.at_end (); ++s) {
|
||||
db::cell_index_type cci = circuit->cell_index ();
|
||||
db::cell_index_type prev_ci = cci;
|
||||
|
||||
for (db::recursive_cluster_shape_iterator<db::PolygonRef> si (clusters, *l, cci, net.cluster_id ()); ! si.at_end (); ) {
|
||||
|
||||
// NOTE: we don't recursive into circuits which will later be output. However, as circuits may
|
||||
// vanish in "purge" but the clusters will still be there we need to recursive into clusters from
|
||||
// unknown cells.
|
||||
db::cell_index_type ci = si.cell_index ();
|
||||
if (ci != prev_ci && ci != cci && l2n->netlist ()->circuit_by_cell_index (ci)) {
|
||||
|
||||
si.skip_cell ();
|
||||
|
||||
} else {
|
||||
|
||||
if (! any) {
|
||||
*mp_stream << indent1 << net_key << "(" << tl::to_word_or_quoted_string (net.expanded_name ()) << endl;
|
||||
any = true;
|
||||
}
|
||||
|
||||
*mp_stream << indent2;
|
||||
write (si.operator-> (), si.trans (), name_for_layer (ly, *l));
|
||||
*mp_stream << endl;
|
||||
|
||||
prev_ci = ci;
|
||||
|
||||
++si;
|
||||
|
||||
if (! any) {
|
||||
*mp_stream << indent1 << net_key << "(" << tl::to_word_or_quoted_string (net.expanded_name ()) << endl;
|
||||
any = true;
|
||||
}
|
||||
|
||||
*mp_stream << indent2;
|
||||
write (s.operator-> (), name_for_layer (ly, *l));
|
||||
*mp_stream << endl;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -341,21 +400,25 @@ void LayoutToNetlistStandardWriter::write (const db::LayoutToNetlist *l2n, const
|
|||
const db::hier_clusters<db::PolygonRef> &clusters = l2n->net_clusters ();
|
||||
const db::Connectivity &conn = l2n->connectivity ();
|
||||
|
||||
for (db::Connectivity::layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
|
||||
for (std::vector<db::DeviceTerminalDefinition>::const_iterator t = td.begin (); t != td.end (); ++t) {
|
||||
|
||||
for (std::vector<db::DeviceTerminalDefinition>::const_iterator t = td.begin (); t != td.end (); ++t) {
|
||||
*mp_stream << indent1 << terminal_key << "(" << t->name () << endl;
|
||||
|
||||
for (db::Connectivity::layer_iterator l = conn.begin_layers (); l != conn.end_layers (); ++l) {
|
||||
|
||||
const db::local_cluster<db::PolygonRef> &lc = clusters.clusters_per_cell (device_model.cell_index ()).cluster_by_id (device_model.cluster_id_for_terminal (t->id ()));
|
||||
for (db::local_cluster<db::PolygonRef>::shape_iterator s = lc.begin (*l); ! s.at_end (); ++s) {
|
||||
|
||||
*mp_stream << indent1;
|
||||
write (s.operator-> (), name_for_layer (ly, *l));
|
||||
*mp_stream << indent2;
|
||||
write (s.operator-> (), db::ICplxTrans (), name_for_layer (ly, *l));
|
||||
*mp_stream << endl;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*mp_stream << indent1 << ")" << endl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -370,7 +433,7 @@ void LayoutToNetlistStandardWriter::write (const db::LayoutToNetlist *l2n, const
|
|||
*mp_stream << indent2 << location_key << "(" << device.position ().x () / dbu << " " << device.position ().y () / dbu << ")" << endl;
|
||||
|
||||
if (device.device_model ()) {
|
||||
*mp_stream << indent2 << footprint_key << "(" << tl::to_word_or_quoted_string (device.device_model ()->name ()) << ")" << endl;
|
||||
*mp_stream << indent2 << abstract_key << "(" << tl::to_word_or_quoted_string (device.device_model ()->name ()) << ")" << endl;
|
||||
}
|
||||
|
||||
const std::vector<DeviceParameterDefinition> &pd = device.device_class ()->parameter_definitions ();
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ private:
|
|||
void write (const db::LayoutToNetlist *l2n, const db::SubCircuit &subcircuit);
|
||||
void write (const db::LayoutToNetlist *l2n, const db::Device &device);
|
||||
void write (const db::LayoutToNetlist *l2n, const db::DeviceModel &device_model);
|
||||
void write (const db::PolygonRef *s, const std::string &lname);
|
||||
void write (const db::PolygonRef *s, const db::ICplxTrans &tr, const std::string &lname);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,21 +95,34 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
|
|||
gsi::method ("max_vertex_count", &db::LayoutToNetlist::max_vertex_count,
|
||||
"See \\max_vertex_count= for details about this attribute."
|
||||
) +
|
||||
gsi::method ("make_layer", &db::LayoutToNetlist::make_layer, gsi::arg ("layer_index"),
|
||||
"@brief Creates a new region representing an original layer\n"
|
||||
"'layer_index'' is the layer index of the desired layer in the original layout.\n"
|
||||
"The Region object returned is a new object and must be deleted by the caller.\n"
|
||||
gsi::method ("name", &db::LayoutToNetlist::name, gsi::arg ("l"),
|
||||
"@brief Names the given layer\n"
|
||||
"'l' must be a hierarchical region derived with \\make_layer, \\make_text_layer or \\make_polygon_layer or "
|
||||
"a region derived from those by boolean operations or other hierarchical operations.\n"
|
||||
"\n"
|
||||
"Naming a layer allows the system to indicate the layer in various contexts, i.e. "
|
||||
"when writing the data to a file.\n"
|
||||
) +
|
||||
gsi::method ("make_layer", &db::LayoutToNetlist::make_layer, gsi::arg ("layer_index"), gsi::arg ("name", std::string ()),
|
||||
"@brief Creates a new hierarchical region representing an original layer\n"
|
||||
"'layer_index' is the layer index of the desired layer in the original layout.\n"
|
||||
"This variant produces polygons and takes texts for net name annotation.\n"
|
||||
"A variant not taking texts is \\make_polygon_layer. A Variant only taking\n"
|
||||
"texts is \\make_text_layer.\n"""
|
||||
"texts is \\make_text_layer.\n"
|
||||
"\n"
|
||||
"The name is optional. If given, the layer will already be named accordingly (see \\name).\n"
|
||||
) +
|
||||
gsi::method ("make_text_layer", &db::LayoutToNetlist::make_text_layer, gsi::arg ("layer_index"),
|
||||
gsi::method ("make_text_layer", &db::LayoutToNetlist::make_text_layer, gsi::arg ("layer_index"), gsi::arg ("name", std::string ()),
|
||||
"@brief Creates a new region representing an original layer taking texts only\n"
|
||||
"See \\make_layer for details.\n"
|
||||
"\n"
|
||||
"The name is optional. If given, the layer will already be named accordingly (see \\name).\n"
|
||||
) +
|
||||
gsi::method ("make_polygon_layer", &db::LayoutToNetlist::make_polygon_layer, gsi::arg ("layer_index"),
|
||||
gsi::method ("make_polygon_layer", &db::LayoutToNetlist::make_polygon_layer, gsi::arg ("layer_index"), gsi::arg ("name", std::string ()),
|
||||
"@brief Creates a new region representing an original layer taking polygons and texts\n"
|
||||
"See \\make_layer for details.\n"
|
||||
"\n"
|
||||
"The name is optional. If given, the layer will already be named accordingly (see \\name).\n"
|
||||
) +
|
||||
gsi::method ("extract_devices", &db::LayoutToNetlist::extract_devices, gsi::arg ("extractor"), gsi::arg ("layers"),
|
||||
"@brief Extracts devices\n"
|
||||
|
|
|
|||
|
|
@ -702,10 +702,14 @@ static std::string path2string (const db::Layout &ly, db::cell_index_type ci, co
|
|||
return res;
|
||||
}
|
||||
|
||||
static std::string rcsiter2string (const db::Layout &ly, db::cell_index_type ci, db::recursive_cluster_shape_iterator<db::PolygonRef> si)
|
||||
static std::string rcsiter2string (const db::Layout &ly, db::cell_index_type ci, db::recursive_cluster_shape_iterator<db::PolygonRef> si, db::cell_index_type ci2skip = std::numeric_limits<db::cell_index_type>::max ())
|
||||
{
|
||||
std::string res;
|
||||
while (! si.at_end ()) {
|
||||
if (si.cell_index () == ci2skip) {
|
||||
si.skip_cell ();
|
||||
continue;
|
||||
}
|
||||
db::Polygon poly = si->obj ();
|
||||
poly.transform (si->trans ());
|
||||
poly.transform (si.trans ());
|
||||
|
|
@ -766,6 +770,16 @@ TEST(41_HierClustersRecursiveClusterShapeIterator)
|
|||
}
|
||||
EXPECT_EQ (n, 1);
|
||||
EXPECT_EQ (res, "TOP:(0,0;0,1000;1000,1000;1000,0);TOP/C1:(0,10;0,510;2000,510;2000,10);TOP/C2:(0,30;0,2030;500,2030;500,30);TOP/C2/C1:(0,50;0,550;2000,550;2000,50)");
|
||||
|
||||
res.clear ();
|
||||
n = 0;
|
||||
cluster = &hc.clusters_per_cell (top.cell_index ());
|
||||
for (db::connected_clusters<db::PolygonRef>::const_iterator i = cluster->begin (); i != cluster->end (); ++i) {
|
||||
res = rcsiter2string (ly, top.cell_index (), db::recursive_cluster_shape_iterator<db::PolygonRef> (hc, l1, top.cell_index (), i->id ()), c1.cell_index ());
|
||||
++n;
|
||||
}
|
||||
EXPECT_EQ (n, 1);
|
||||
EXPECT_EQ (res, "TOP:(0,0;0,1000;1000,1000;1000,0);TOP/C2:(0,30;0,2030;500,2030;500,30)");
|
||||
}
|
||||
|
||||
TEST(41_HierClustersRecursiveClusterIterator)
|
||||
|
|
|
|||
|
|
@ -72,27 +72,33 @@ TEST(1_WriterBasic)
|
|||
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> rnwell (l2n.make_layer (nwell));
|
||||
std::auto_ptr<db::Region> ractive (l2n.make_layer (active));
|
||||
std::auto_ptr<db::Region> rpoly (l2n.make_polygon_layer (poly));
|
||||
std::auto_ptr<db::Region> rpoly_lbl (l2n.make_text_layer (poly_lbl));
|
||||
std::auto_ptr<db::Region> rdiff_cont (l2n.make_polygon_layer (diff_cont));
|
||||
std::auto_ptr<db::Region> rpoly_cont (l2n.make_polygon_layer (poly_cont));
|
||||
std::auto_ptr<db::Region> rmetal1 (l2n.make_polygon_layer (metal1));
|
||||
std::auto_ptr<db::Region> rmetal1_lbl (l2n.make_text_layer (metal1_lbl));
|
||||
std::auto_ptr<db::Region> rvia1 (l2n.make_polygon_layer (via1));
|
||||
std::auto_ptr<db::Region> rmetal2 (l2n.make_polygon_layer (metal2));
|
||||
std::auto_ptr<db::Region> rmetal2_lbl (l2n.make_text_layer (metal2_lbl));
|
||||
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> 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 rpactive = *ractive & *rnwell;
|
||||
db::Region rpgate = rpactive & *rpoly;
|
||||
db::Region rpsd = rpactive - rpgate;
|
||||
l2n.name (rpactive, "pactive");
|
||||
l2n.name (rpgate, "pgate");
|
||||
l2n.name (rpsd, "psd");
|
||||
|
||||
db::Region rnactive = *ractive - *rnwell;
|
||||
db::Region rngate = rnactive & *rpoly;
|
||||
db::Region rnsd = rnactive - rngate;
|
||||
l2n.name (rnactive, "nactive");
|
||||
l2n.name (rngate, "ngate");
|
||||
l2n.name (rnsd, "nsd");
|
||||
|
||||
db::NetlistDeviceExtractorMOS3Transistor pmos_ex ("PMOS");
|
||||
db::NetlistDeviceExtractorMOS3Transistor nmos_ex ("NMOS");
|
||||
|
|
@ -157,18 +163,23 @@ TEST(1_WriterBasic)
|
|||
rpoly_lbl.reset (0);
|
||||
|
||||
l2n.extract_netlist ();
|
||||
l2n.netlist ()->purge ();
|
||||
|
||||
tl::OutputMemoryStream mem;
|
||||
std::string path = tmp_file ("tmp_l2nwriter_1.txt");
|
||||
{
|
||||
tl::OutputStream stream (mem);
|
||||
tl::OutputStream stream (path);
|
||||
db::LayoutToNetlistStandardWriter writer (stream);
|
||||
writer.write (&l2n);
|
||||
}
|
||||
|
||||
// TODO: too big for inlined text ...
|
||||
#if 0
|
||||
EXPECT_EQ (std::string (mem.data (), mem.size ()),
|
||||
""
|
||||
);
|
||||
#endif
|
||||
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);
|
||||
|
||||
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)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,477 @@
|
|||
# General section
|
||||
# Lists general definitions.
|
||||
|
||||
top(RINGO)
|
||||
unit(0.001)
|
||||
|
||||
# Layer section
|
||||
# This section lists the mask layers (drawing or derived) and their connections.
|
||||
|
||||
# Mask layers
|
||||
layer(poly)
|
||||
layer(poly_lbl)
|
||||
layer(diff_cont)
|
||||
layer(poly_cont)
|
||||
layer(metal1)
|
||||
layer(metal1_lbl)
|
||||
layer(via1)
|
||||
layer(metal2)
|
||||
layer(metal2_lbl)
|
||||
layer(psd)
|
||||
layer(nsd)
|
||||
|
||||
# Mask layer connectivity
|
||||
connect(poly poly poly_lbl poly_cont)
|
||||
connect(poly_lbl poly)
|
||||
connect(diff_cont diff_cont metal1 psd 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(psd diff_cont psd)
|
||||
connect(nsd diff_cont nsd)
|
||||
|
||||
# Device abstracts section
|
||||
# Device abstracts list the pin shapes of the devices.
|
||||
device(D$PMOS PMOS
|
||||
terminal(S
|
||||
rect(poly -125 -475 125 475)
|
||||
)
|
||||
terminal(G
|
||||
rect(psd -650 -475 -125 475)
|
||||
)
|
||||
terminal(D
|
||||
rect(psd 125 -475 675 475)
|
||||
)
|
||||
)
|
||||
device(D$PMOS$1 PMOS
|
||||
terminal(S
|
||||
rect(poly -125 -475 125 475)
|
||||
)
|
||||
terminal(G
|
||||
rect(psd -675 -475 -125 475)
|
||||
)
|
||||
terminal(D
|
||||
rect(psd 125 -475 650 475)
|
||||
)
|
||||
)
|
||||
device(D$NMOS NMOS
|
||||
terminal(S
|
||||
rect(poly -125 -475 125 475)
|
||||
)
|
||||
terminal(G
|
||||
rect(nsd -650 -475 -125 475)
|
||||
)
|
||||
terminal(D
|
||||
rect(nsd 125 -475 675 475)
|
||||
)
|
||||
)
|
||||
device(D$NMOS$1 NMOS
|
||||
terminal(S
|
||||
rect(poly -125 -475 125 475)
|
||||
)
|
||||
terminal(G
|
||||
rect(nsd -675 -475 -125 475)
|
||||
)
|
||||
terminal(D
|
||||
rect(nsd 125 -475 650 475)
|
||||
)
|
||||
)
|
||||
|
||||
# Circuit section
|
||||
# Circuits are the hierarchical building blocks of the netlist.
|
||||
|
||||
# Circuit RINGO
|
||||
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(VSS
|
||||
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 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 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 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 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 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 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 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(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(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 5100 -380 5460 380)
|
||||
rect(metal1 5100 -380 5460 380)
|
||||
rect(metal1 7740 -380 8100 380)
|
||||
rect(metal1 7740 -380 8100 380)
|
||||
rect(metal1 10380 -380 10740 380)
|
||||
rect(metal1 10380 -380 10740 380)
|
||||
rect(metal1 13020 -380 13380 380)
|
||||
rect(metal1 13020 -380 13380 380)
|
||||
rect(metal1 15660 -380 16020 380)
|
||||
rect(metal1 15660 -380 16020 380)
|
||||
rect(metal1 18300 -380 18660 380)
|
||||
rect(metal1 18300 -380 18660 380)
|
||||
rect(metal1 20940 -380 21300 380)
|
||||
rect(metal1 20940 -380 21300 380)
|
||||
rect(metal1 23580 -380 23940 380)
|
||||
rect(metal1 23580 -380 23940 380)
|
||||
rect(metal2_lbl -1 -1 1 1)
|
||||
)
|
||||
net(VDD
|
||||
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 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 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 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 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 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 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 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(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(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 5100 2420 5460 3180)
|
||||
rect(metal1 5100 2420 5460 3180)
|
||||
rect(metal1 7740 2420 8100 3180)
|
||||
rect(metal1 7740 2420 8100 3180)
|
||||
rect(metal1 10380 2420 10740 3180)
|
||||
rect(metal1 10380 2420 10740 3180)
|
||||
rect(metal1 13020 2420 13380 3180)
|
||||
rect(metal1 13020 2420 13380 3180)
|
||||
rect(metal1 15660 2420 16020 3180)
|
||||
rect(metal1 15660 2420 16020 3180)
|
||||
rect(metal1 18300 2420 18660 3180)
|
||||
rect(metal1 18300 2420 18660 3180)
|
||||
rect(metal1 20940 2420 21300 3180)
|
||||
rect(metal1 20940 2420 21300 3180)
|
||||
rect(metal1 23580 2420 23940 3180)
|
||||
rect(metal1 23580 2420 23940 3180)
|
||||
rect(metal2_lbl -1 2799 1 2801)
|
||||
)
|
||||
net($I19
|
||||
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)
|
||||
)
|
||||
net($I8
|
||||
rect(diff_cont 21810 2890 22030 3110)
|
||||
rect(diff_cont 21810 2490 22030 2710)
|
||||
rect(diff_cont 21810 90 22030 310)
|
||||
rect(diff_cont 21810 -310 22030 -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 16530 2890 16750 3110)
|
||||
rect(diff_cont 16530 2490 16750 2710)
|
||||
rect(diff_cont 16530 90 16750 310)
|
||||
rect(diff_cont 16530 -310 16750 -90)
|
||||
)
|
||||
net($I5
|
||||
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($I4
|
||||
rect(diff_cont 11250 2890 11470 3110)
|
||||
rect(diff_cont 11250 2490 11470 2710)
|
||||
rect(diff_cont 11250 90 11470 310)
|
||||
rect(diff_cont 11250 -310 11470 -90)
|
||||
)
|
||||
net($I3
|
||||
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)
|
||||
)
|
||||
net($I2
|
||||
rect(diff_cont 5970 2890 6190 3110)
|
||||
rect(diff_cont 5970 2490 6190 2710)
|
||||
rect(diff_cont 5970 90 6190 310)
|
||||
rect(diff_cont 5970 -310 6190 -90)
|
||||
)
|
||||
net($I1
|
||||
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)
|
||||
)
|
||||
|
||||
# Subcircuits and their connections
|
||||
subcircuit($1 location(23760 0)
|
||||
pin(IN $I8)
|
||||
pin($1 FB)
|
||||
pin($3 VSS)
|
||||
pin($4 VDD)
|
||||
)
|
||||
subcircuit($2 location(0 0)
|
||||
pin(IN FB)
|
||||
pin(OUT $I19)
|
||||
pin($3 VSS)
|
||||
pin($4 VDD)
|
||||
)
|
||||
subcircuit($3 location(2640 0)
|
||||
pin(IN $I19)
|
||||
pin(OUT $I1)
|
||||
pin($3 VSS)
|
||||
pin($4 VDD)
|
||||
)
|
||||
subcircuit($4 location(5280 0)
|
||||
pin(IN $I1)
|
||||
pin(OUT $I2)
|
||||
pin($3 VSS)
|
||||
pin($4 VDD)
|
||||
)
|
||||
subcircuit($5 location(7920 0)
|
||||
pin(IN $I2)
|
||||
pin(OUT $I3)
|
||||
pin($3 VSS)
|
||||
pin($4 VDD)
|
||||
)
|
||||
subcircuit($6 location(10560 0)
|
||||
pin(IN $I3)
|
||||
pin(OUT $I4)
|
||||
pin($3 VSS)
|
||||
pin($4 VDD)
|
||||
)
|
||||
subcircuit($7 location(13200 0)
|
||||
pin(IN $I4)
|
||||
pin(OUT $I5)
|
||||
pin($3 VSS)
|
||||
pin($4 VDD)
|
||||
)
|
||||
subcircuit($8 location(15840 0)
|
||||
pin(IN $I5)
|
||||
pin(OUT $I6)
|
||||
pin($3 VSS)
|
||||
pin($4 VDD)
|
||||
)
|
||||
subcircuit($9 location(18480 0)
|
||||
pin(IN $I6)
|
||||
pin(OUT $I7)
|
||||
pin($3 VSS)
|
||||
pin($4 VDD)
|
||||
)
|
||||
subcircuit($10 location(21120 0)
|
||||
pin(IN $I7)
|
||||
pin(OUT $I8)
|
||||
pin($3 VSS)
|
||||
pin($4 VDD)
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
# Circuit INV2
|
||||
circuit(INV2
|
||||
|
||||
# Nets with their geometries
|
||||
net(IN
|
||||
rect(poly -525 -250 -275 2250)
|
||||
rect(poly -1700 1620 -400 1980)
|
||||
rect(poly -525 -800 -275 800)
|
||||
rect(poly -525 -475 -275 475)
|
||||
rect(poly -525 2000 -275 3600)
|
||||
rect(poly -525 2325 -275 3275)
|
||||
rect(poly_lbl -801 1799 -799 1801)
|
||||
rect(poly_cont -1630 1690 -1410 1910)
|
||||
)
|
||||
net($2
|
||||
rect(poly 275 -250 525 2250)
|
||||
rect(poly 220 820 580 1180)
|
||||
rect(poly 275 2000 525 3600)
|
||||
rect(poly 275 2325 525 3275)
|
||||
rect(poly 275 -800 525 800)
|
||||
rect(poly 275 -475 525 475)
|
||||
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(psd -1050 2325 -525 3275)
|
||||
rect(nsd -1050 -475 -525 475)
|
||||
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(psd 525 2325 1050 3275)
|
||||
rect(nsd 525 -475 1050 475)
|
||||
rect(nsd 525 -475 1050 475)
|
||||
)
|
||||
net($4
|
||||
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(nsd -275 -475 275 475)
|
||||
rect(nsd -275 -475 275 475)
|
||||
rect(nsd -275 -475 275 475)
|
||||
)
|
||||
net($5
|
||||
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(psd -275 2325 275 3275)
|
||||
rect(psd -275 2325 275 3275)
|
||||
rect(psd -275 2325 275 3275)
|
||||
)
|
||||
|
||||
# Outgoing pins and their connections to nets
|
||||
pin(IN IN)
|
||||
pin($1 $2)
|
||||
pin(OUT OUT)
|
||||
pin($3 $4)
|
||||
pin($4 $5)
|
||||
|
||||
# Devices and their connections
|
||||
device($1 PMOS
|
||||
location(-400 2800)
|
||||
abstract(D$PMOS)
|
||||
param(L 0.25)
|
||||
param(W 0.95)
|
||||
param(AS 0.49875)
|
||||
param(AD 0.26125)
|
||||
terminal(S $2)
|
||||
terminal(G IN)
|
||||
terminal(D $5)
|
||||
)
|
||||
device($2 PMOS
|
||||
location(400 2800)
|
||||
abstract(D$PMOS$1)
|
||||
param(L 0.25)
|
||||
param(W 0.95)
|
||||
param(AS 0.26125)
|
||||
param(AD 0.49875)
|
||||
terminal(S $5)
|
||||
terminal(G $2)
|
||||
terminal(D OUT)
|
||||
)
|
||||
device($3 NMOS
|
||||
location(-400 0)
|
||||
abstract(D$NMOS)
|
||||
param(L 0.25)
|
||||
param(W 0.95)
|
||||
param(AS 0.49875)
|
||||
param(AD 0.26125)
|
||||
terminal(S $2)
|
||||
terminal(G IN)
|
||||
terminal(D $4)
|
||||
)
|
||||
device($4 NMOS
|
||||
location(400 0)
|
||||
abstract(D$NMOS$1)
|
||||
param(L 0.25)
|
||||
param(W 0.95)
|
||||
param(AS 0.26125)
|
||||
param(AD 0.49875)
|
||||
terminal(S $4)
|
||||
terminal(G $2)
|
||||
terminal(D OUT)
|
||||
)
|
||||
|
||||
)
|
||||
Loading…
Reference in New Issue