WIP: some refactoring for better consistency and easier usage of the device extractor.

This commit is contained in:
Matthias Koefferlein 2018-12-27 10:33:08 +01:00
parent bfae347ffb
commit 639b0026d3
9 changed files with 261 additions and 152 deletions

View File

@ -171,15 +171,15 @@ DeepRegion::begin_merged () const
std::pair<db::RecursiveShapeIterator, db::ICplxTrans>
DeepRegion::begin_iter () const
{
const db::Layout *layout = m_deep_layer.layout ();
if (layout->cells () == 0) {
const db::Layout &layout = m_deep_layer.layout ();
if (layout.cells () == 0) {
return std::make_pair (db::RecursiveShapeIterator (), db::ICplxTrans ());
} else {
const db::Cell &top_cell = layout->cell (*layout->begin_top_down ());
db::RecursiveShapeIterator iter (*m_deep_layer.layout (), top_cell, m_deep_layer.layer ());
const db::Cell &top_cell = layout.cell (*layout.begin_top_down ());
db::RecursiveShapeIterator iter (m_deep_layer.layout (), top_cell, m_deep_layer.layer ());
return std::make_pair (iter, db::ICplxTrans ());
}
@ -236,7 +236,7 @@ bool
DeepRegion::equals (const Region &other) const
{
const DeepRegion *other_delegate = dynamic_cast<const DeepRegion *> (other.delegate ());
if (other_delegate && other_delegate->m_deep_layer.layout () == m_deep_layer.layout ()
if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()
&& other_delegate->m_deep_layer.layer () == m_deep_layer.layer ()) {
return true;
} else {
@ -248,7 +248,7 @@ bool
DeepRegion::less (const Region &other) const
{
const DeepRegion *other_delegate = dynamic_cast<const DeepRegion *> (other.delegate ());
if (other_delegate && other_delegate->m_deep_layer.layout () == m_deep_layer.layout ()) {
if (other_delegate && &other_delegate->m_deep_layer.layout () == &m_deep_layer.layout ()) {
return other_delegate->m_deep_layer.layer () < m_deep_layer.layer ();
} else {
return AsIfFlatRegion::less (other);
@ -348,7 +348,7 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
db::BoolAndOrNotLocalOperation op (and_op, m_deep_layer.store ()->max_area_ratio (), m_deep_layer.store ()->max_vertex_count ());
db::LocalProcessor proc (const_cast <db::Layout *> (m_deep_layer.layout ()), const_cast <db::Cell *> (m_deep_layer.initial_cell ()), other->deep_layer ().layout (), other->deep_layer ().initial_cell ());
db::LocalProcessor proc (const_cast<db::Layout *> (&m_deep_layer.layout ()), const_cast<db::Cell *> (&m_deep_layer.initial_cell ()), &other->deep_layer ().layout (), &other->deep_layer ().initial_cell ());
proc.set_threads (m_deep_layer.store ()->threads ());
proc.run (&op, m_deep_layer.layer (), other->deep_layer ().layer (), dl_out.layer ());
@ -392,20 +392,20 @@ DeepRegion::xor_with (const Region &other) const
void
DeepRegion::add_from (const DeepLayer &dl)
{
if (dl.layout () == deep_layer ().layout ()) {
if (&dl.layout () == &deep_layer ().layout ()) {
// intra-layout merge
deep_layer ().layout ()->copy_layer (dl.layer (), deep_layer ().layer ());
deep_layer ().layout ().copy_layer (dl.layer (), deep_layer ().layer ());
} else {
// inter-layout merge
db::cell_index_type into_cell = deep_layer ().initial_cell ()->cell_index ();
db::Layout *into_layout = deep_layer ().layout ();
db::cell_index_type source_cell = dl.initial_cell ()->cell_index ();
const db::Layout *source_layout = dl.layout ();
db::cell_index_type into_cell = deep_layer ().initial_cell ().cell_index ();
db::Layout *into_layout = &deep_layer ().layout ();
db::cell_index_type source_cell = dl.initial_cell ().cell_index ();
const db::Layout *source_layout = &dl.layout ();
db::CellMapping cm;
cm.create_from_geometry_full (*into_layout, into_cell, *source_layout, source_cell);
@ -439,7 +439,7 @@ DeepRegion::add_in_place (const Region &other)
// non-deep to deep merge (flat)
db::Shapes &shapes = deep_layer ().initial_cell ()->shapes (deep_layer ().layer ());
db::Shapes &shapes = deep_layer ().initial_cell ().shapes (deep_layer ().layer ());
for (db::Region::const_iterator p = other.begin (); ! p.at_end (); ++p) {
shapes.insert (*p);
}

View File

@ -24,6 +24,8 @@
#include "dbDeepShapeStore.h"
#include "dbCellMapping.h"
#include "dbLayoutUtils.h"
#include "dbRegion.h"
#include "dbDeepRegion.h"
#include "tlTimer.h"
@ -38,6 +40,14 @@ DeepLayer::DeepLayer ()
// .. nothing yet ..
}
DeepLayer::DeepLayer (const Region &region)
: mp_store (), m_layout (0), m_layer (0)
{
const db::DeepRegion *dr = dynamic_cast<db::DeepRegion *> (region.delegate ());
tl_assert (dr != 0);
*this = dr->deep_layer ();
}
DeepLayer::DeepLayer (const DeepLayer &x)
: mp_store (x.mp_store), m_layout (x.m_layout), m_layer (x.m_layer)
{
@ -82,7 +92,7 @@ DeepLayer::~DeepLayer ()
DeepLayer
DeepLayer::derived () const
{
return DeepLayer (const_cast <db::DeepShapeStore *> (mp_store.get ()), m_layout, const_cast <db::Layout *> (layout ())->insert_layer ());
return DeepLayer (const_cast <db::DeepShapeStore *> (mp_store.get ()), m_layout, const_cast <db::Layout &> (layout ()).insert_layer ());
}
DeepLayer
@ -91,9 +101,7 @@ DeepLayer::copy () const
DeepLayer new_layer (derived ());
db::DeepShapeStore *non_const_store = const_cast<db::DeepShapeStore *> (mp_store.get ());
if (non_const_store->layout (m_layout)) {
non_const_store->layout (m_layout)->copy_layer (m_layer, new_layer.layer ());
}
non_const_store->layout (m_layout).copy_layer (m_layer, new_layer.layer ());
return new_layer;
}
@ -105,34 +113,32 @@ DeepLayer::insert_into (db::Layout *into_layout, db::cell_index_type into_cell,
const_cast<db::DeepShapeStore *> (mp_store.get ())->insert (*this, into_layout, into_cell, into_layer);
}
db::Layout *
db::Layout &
DeepLayer::layout ()
{
check_dss ();
return mp_store->layout (m_layout);
}
const db::Layout *
const db::Layout &
DeepLayer::layout () const
{
check_dss ();
return const_cast<db::DeepShapeStore *> (mp_store.get ())->layout (m_layout);
}
db::Cell *
db::Cell &
DeepLayer::initial_cell ()
{
db::Layout *ly = layout ();
tl_assert (ly->begin_top_down () != ly->end_top_down ());
return &ly->cell (*ly->begin_top_down ());
check_dss ();
return mp_store->initial_cell (m_layout);
}
const db::Cell *
const db::Cell &
DeepLayer::initial_cell () const
{
const db::Layout *ly = layout ();
tl_assert (ly->begin_top_down () != ly->end_top_down ());
return &ly->cell (*ly->begin_top_down ());
check_dss ();
return mp_store->const_initial_cell (m_layout);
}
void
@ -192,6 +198,32 @@ DeepShapeStore::~DeepShapeStore ()
m_layouts.clear ();
}
bool DeepShapeStore::is_singular () const
{
return m_layouts.size () == 1;
}
void DeepShapeStore::require_singular () const
{
if (! is_singular ()) {
throw tl::Exception (tl::to_string (tr ("Internal error: deep shape store isn't singular. This may happen if you try to mix hierarchical layers from different sources our you use clipping.")));
}
}
Cell &DeepShapeStore::initial_cell(unsigned int n)
{
db::Layout &ly = layout (n);
tl_assert (ly.cells () > 0);
return ly.cell (*ly.begin_top_down ());
}
const db::Cell &DeepShapeStore::const_initial_cell (unsigned int n) const
{
const db::Layout &ly = const_layout (n);
tl_assert (ly.cells () > 0);
return ly.cell (*ly.begin_top_down ());
}
void DeepShapeStore::set_text_enlargement (int enl)
{
m_text_enlargement = enl;
@ -207,16 +239,16 @@ bool DeepShapeStore::is_valid_layout_index (unsigned int n) const
return (n < (unsigned int) m_layouts.size () && m_layouts[n] != 0);
}
const db::Layout *DeepShapeStore::const_layout (unsigned int n) const
const db::Layout &DeepShapeStore::const_layout (unsigned int n) const
{
tl_assert (is_valid_layout_index (n));
return &(m_layouts [n]->layout);
return m_layouts [n]->layout;
}
db::Layout *DeepShapeStore::layout (unsigned int n)
db::Layout &DeepShapeStore::layout (unsigned int n)
{
tl_assert (is_valid_layout_index (n));
return &(m_layouts [n]->layout);
return m_layouts [n]->layout;
}
size_t DeepShapeStore::instance_count ()
@ -395,14 +427,14 @@ DeepShapeStore::cell_mapping_to_original (size_t layout_index, db::Layout *into_
void
DeepShapeStore::insert (const DeepLayer &deep_layer, db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer)
{
const db::Layout *source_layout = deep_layer.layout ();
if (source_layout->begin_top_down () == source_layout->end_top_cells ()) {
const db::Layout &source_layout = deep_layer.layout ();
if (source_layout.begin_top_down () == source_layout.end_top_cells ()) {
// empty source - nothing to do.
return;
}
// prepare the transformation
db::ICplxTrans trans (source_layout->dbu () / into_layout->dbu ());
db::ICplxTrans trans (source_layout.dbu () / into_layout->dbu ());
// prepare a layer map
std::map<unsigned int, unsigned int> lm;
@ -413,10 +445,10 @@ DeepShapeStore::insert (const DeepLayer &deep_layer, db::Layout *into_layout, db
// prepare a vector with the source cells
std::vector <db::cell_index_type> source_cells;
source_cells.push_back (*source_layout->begin_top_down());
source_cells.push_back (*source_layout.begin_top_down());
// actually copy the shapes
db::copy_shapes (*into_layout, *source_layout, trans, source_cells, cm.table (), lm);
db::copy_shapes (*into_layout, source_layout, trans, source_cells, cm.table (), lm);
}
}

View File

@ -40,6 +40,7 @@
namespace db {
class DeepShapeStore;
class Region;
/**
* @brief Represents a shape collection from the deep shape store
@ -60,6 +61,12 @@ public:
*/
~DeepLayer ();
/**
* @brief Conversion operator from Region to DeepLayer
* This requires the Region to be a DeepRegion. Otherwise, this constructor will assert
*/
DeepLayer (const Region &region);
/**
* @brief Copy constructor
*/
@ -74,23 +81,23 @@ public:
* @brief Gets the layout object
* The return value is guaranteed to be non-null.
*/
db::Layout *layout ();
Layout &layout();
/**
* @brief Gets the layout object (const version)
*/
const db::Layout *layout () const;
const db::Layout &layout () const;
/**
* @brief Gets the layout object
* The return value is guaranteed to be non-null.
*/
db::Cell *initial_cell ();
Cell &initial_cell();
/**
* @brief Gets the initial cell object (const version)
*/
const db::Cell *initial_cell () const;
const db::Cell &initial_cell () const;
/**
* @brief Gets the layer
@ -185,6 +192,20 @@ public:
*/
~DeepShapeStore ();
/**
* @brief Returns true, if the DeepShapeStore is singular
*
* A "singular" shape store needs a single layout to keep the information.
* This is the case, if all Regions derived from it share the same origin
* and do not use clipping or region selection. Singular shape stores are
* required for netlist extraction for example.
*
* For a singular shape store, "layout()" will return the layout
* object and "initial_cell()" will return the initial cell of the
* only layout.
*/
bool is_singular () const;
/**
* @brief Inserts a polygon layer into the deep shape store
*
@ -219,7 +240,72 @@ public:
/**
* @brief Gets the nth layout (const version)
*/
const db::Layout *const_layout (unsigned int n) const;
const db::Layout &const_layout (unsigned int n) const;
/**
* @brief Gets the nth layout (non-const version)
*
* Don't try to mess too much with the layout object, you'll screw up the internals.
*/
db::Layout &layout (unsigned int n);
/**
* @brief Gets the initial cell of the nth layout (const version)
*/
const db::Cell &const_initial_cell (unsigned int n) const;
/**
* @brief Gets the initial cell of the nth layout (non-const version)
*
* Don't try to mess too much with the cell object, you'll screw up the internals.
*/
db::Cell &initial_cell (unsigned int n);
/**
* @brief Gets the singular layout (const version)
*
* This method will throw an exception if the deep shape store is not singular.
*/
const db::Layout &const_layout () const
{
require_singular ();
return const_layout (0);
}
/**
* @brief Gets the singular layout (non-const version)
*
* This method will throw an exception if the deep shape store is not singular.
* Don't try to mess too much with the layout object, you'll screw up the internals.
*/
db::Layout &layout ()
{
require_singular ();
return layout (0);
}
/**
* @brief Gets the initial cell of the singular layout (const version)
*
* This method will throw an exception if the deep shape store is not singular.
*/
const db::Cell &const_initial_cell () const
{
require_singular ();
return const_initial_cell (0);
}
/**
* @brief Gets the initial cell of the singular layout (non-const version)
*
* This method will throw an exception if the deep shape store is not singular.
* Don't try to mess too much with the cell object, you'll screw up the internals.
*/
db::Cell &initial_cell ()
{
require_singular ();
return initial_cell (0);
}
/**
* @brief Gets the number of layouts
@ -324,11 +410,11 @@ private:
struct LayoutHolder;
db::Layout *layout (unsigned int n);
void add_ref (unsigned int layout, unsigned int layer);
void remove_ref (unsigned int layout, unsigned int layer);
void require_singular () const;
typedef std::map<db::RecursiveShapeIterator, unsigned int, RecursiveShapeIteratorCompareForTargetHierarchy> layout_map_type;
// no copying

View File

@ -28,6 +28,7 @@
#include "dbPolygon.h"
#include "dbPolygonTools.h"
#include "dbBoxScanner.h"
#include "dbDeepRegion.h"
#include "tlProgress.h"
#include "tlLog.h"
#include "tlTimer.h"
@ -64,6 +65,18 @@ Connectivity::connect (unsigned int l)
m_all_layers.insert (l);
}
void
Connectivity::connect (const db::DeepLayer &l)
{
connect (l.layer ());
}
void
Connectivity::connect (const db::DeepLayer &la, const db::DeepLayer &lb)
{
connect (la.layer (), lb.layer ());
}
Connectivity::layer_iterator
Connectivity::begin_layers () const
{

View File

@ -36,6 +36,8 @@
namespace db {
class DeepLayer;
/**
* @brief Defines the connectivity
*
@ -61,6 +63,20 @@ public:
*/
void connect (unsigned int la, unsigned int lb);
/**
* @brief Adds intra-layer connectivity for layer l
* This is a convenience method that takes a db::DeepLayer object.
* It is assumed that all those layers originate from the same deep shape store.
*/
void connect (const db::DeepLayer &l);
/**
* @brief Adds inter-layer connectivity
* This is a convenience method that takes a db::DeepLayer object.
* It is assumed that all those layers originate from the same deep shape store.
*/
void connect (const db::DeepLayer &la, const db::DeepLayer &lb);
/**
* @brief Adds intra-layer connectivity for layer l
*/

View File

@ -62,49 +62,26 @@ static void insert_into_region (const db::PolygonRef &s, const db::ICplxTrans &t
region.insert (s.obj ().transformed (tr * db::ICplxTrans (s.trans ())));
}
void NetlistDeviceExtractor::extract (const std::vector<db::Region *> regions)
void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, const std::vector<db::DeepLayer> &deep_layers, db::Netlist *nl)
{
tl_assert (! regions.empty ());
db::Layout &layout = dss.layout ();
db::Cell &cell = dss.initial_cell ();
const db::Layout *layout = 0;
const db::Cell *cell = 0;
std::vector<unsigned int> layers;
layers.reserve (regions.size ());
for (std::vector<db::Region *>::const_iterator r = regions.begin (); r != regions.end (); ++r) {
// TODO: this is clumsy ...
db::DeepRegion *dr = dynamic_cast<db::DeepRegion *> ((*r)->delegate ());
tl_assert (dr != 0);
db::DeepLayer dl = dr->deep_layer ();
tl_assert (dl.layout () != 0);
tl_assert (dl.initial_cell () != 0);
if (! layout) {
layout = dl.layout ();
} else {
tl_assert (layout == dl.layout ());
}
if (! cell) {
cell = dl.initial_cell ();
} else {
tl_assert (cell == dl.initial_cell ());
}
layers.push_back (dl.layer ());
layers.reserve (deep_layers.size ());
for (std::vector<db::DeepLayer>::const_iterator dl = deep_layers.begin (); dl != deep_layers.end (); ++dl) {
tl_assert (&dl->layout () == &layout);
layers.push_back (dl->layer ());
}
// NOTE: the const_cast's are there because the extraction will annotate the layout with port
// shapes. That's not part of the initial design, where the underlying deep shape store is
// immutable from the outside. But we know what we're doing.
extract (const_cast<db::Layout &> (*layout), const_cast<db::Cell &> (*cell), layers);
extract (layout, cell, layers, nl);
}
void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const std::vector<unsigned int> &layers)
void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const std::vector<unsigned int> &layers, db::Netlist *nl)
{
initialize (nl);
typedef db::PolygonRef shape_type;
db::ShapeIterator::flags_type shape_iter_flags = db::ShapeIterator::Polygons;

View File

@ -27,6 +27,7 @@
#include "dbNetlist.h"
#include "dbLayout.h"
#include "dbHierNetworkProcessor.h"
#include "dbDeepShapeStore.h"
#include "gsiObject.h"
@ -63,12 +64,6 @@ public:
*/
static const tl::Variant &terminal_property_name ();
/**
* @brief Initializes the extractor
* This method will produce the device classes required for the device extraction.
*/
void initialize (db::Netlist *nl);
/**
* @brief Performs the extraction
*
@ -87,21 +82,17 @@ public:
*
* NOTE: The extractor expects "PolygonRef" type layers.
*/
void extract (Layout &layout, Cell &cell, const std::vector<unsigned int> &layers);
void extract (Layout &layout, Cell &cell, const std::vector<unsigned int> &layers, Netlist *netlist);
/**
* @brief Extracts the devices from a list of regions
*
* This method behaves identical to the other "extract" method, but accepts
* regions for input.
*
* As a requirement, the layout and initial cell of all of the regions
* has to be identical.
*
* Currently, the regions have to be deep regions.
* DeepShape layers for input. By definition, these already have the "PolygonRef" type.
*/
void extract (const std::vector<db::Region *> regions);
void extract (DeepShapeStore &dss, const std::vector<DeepLayer> &layers, Netlist *netlist);
protected:
/**
* @brief Creates the device classes
* At least one device class needs to be defined. Use "register_device_class" to register
@ -131,7 +122,6 @@ public:
*/
virtual void extract_devices (const std::vector<db::Region> &layer_geometry);
protected:
/**
* @brief Registers a device class
* The device class object will become owned by the netlist and must not be deleted by
@ -205,6 +195,12 @@ private:
std::vector<db::DeviceClass *> m_device_classes;
std::vector<unsigned int> m_layers;
unsigned int m_device_name_index;
/**
* @brief Initializes the extractor
* This method will produce the device classes required for the device extraction.
*/
void initialize (db::Netlist *nl);
};
}

View File

@ -42,12 +42,12 @@ TEST(1)
EXPECT_EQ (dl1.layer (), l1);
EXPECT_EQ (dl2.layer (), l2);
EXPECT_EQ (dl1.layout (), dl2.layout ());
EXPECT_EQ (&dl1.layout (), &dl2.layout ());
EXPECT_EQ (store.layouts (), (unsigned int) 1);
db::DeepLayer dl3 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c2), l1));
EXPECT_EQ (dl3.layer (), l1);
EXPECT_NE (dl1.layout (), dl3.layout ());
EXPECT_NE (&dl1.layout (), &dl3.layout ());
EXPECT_EQ (store.layouts (), (unsigned int) 2);
db::DeepLayer dl4 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l1, db::Box (0, 1, 2, 3)));
@ -58,13 +58,13 @@ TEST(1)
db::DeepLayer dl6 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l1, db::Box (0, 1, 2, 3)));
EXPECT_EQ (dl6.layer (), l2); // a new layer (a copy)
EXPECT_EQ (dl6.layout (), dl4.layout ());
EXPECT_EQ (&dl6.layout (), &dl4.layout ());
EXPECT_EQ (store.layouts (), (unsigned int) 4);
}
static size_t shapes_in_top (const db::Layout *layout, unsigned int layer)
static size_t shapes_in_top (const db::Layout &layout, unsigned int layer)
{
const db::Cell &top = layout->cell (*layout->begin_top_down ());
const db::Cell &top = layout.cell (*layout.begin_top_down ());
return top.shapes (layer).size ();
}
@ -162,23 +162,23 @@ TEST(3_TextTreatment)
db::DeepLayer dl1 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l1));
EXPECT_EQ (store.layouts (), (unsigned int) 1);
EXPECT_EQ (dl1.initial_cell ()->shapes (dl1.layer ()).empty (), true);
EXPECT_EQ (dl1.initial_cell ().shapes (dl1.layer ()).empty (), true);
store.set_text_enlargement (1);
dl1 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l1));
EXPECT_EQ (store.layouts (), (unsigned int) 1);
EXPECT_EQ (dl1.initial_cell ()->shapes (dl1.layer ()).size (), size_t (1));
EXPECT_EQ (dl1.initial_cell ()->shapes (dl1.layer ()).begin (db::ShapeIterator::All)->to_string (), "polygon (999,1999;999,2001;1001,2001;1001,1999)");
EXPECT_EQ (dl1.initial_cell ().shapes (dl1.layer ()).size (), size_t (1));
EXPECT_EQ (dl1.initial_cell ().shapes (dl1.layer ()).begin (db::ShapeIterator::All)->to_string (), "polygon (999,1999;999,2001;1001,2001;1001,1999)");
store.set_text_property_name (tl::Variant ("text"));
dl1 = store.create_polygon_layer (db::RecursiveShapeIterator (layout, layout.cell (c1), l1));
EXPECT_EQ (store.layouts (), (unsigned int) 1);
EXPECT_EQ (dl1.initial_cell ()->shapes (dl1.layer ()).size (), size_t (1));
EXPECT_EQ (dl1.initial_cell ()->shapes (dl1.layer ()).begin (db::ShapeIterator::All)->to_string (), "polygon (999,1999;999,2001;1001,2001;1001,1999) prop_id=1");
EXPECT_EQ (dl1.initial_cell ().shapes (dl1.layer ()).size (), size_t (1));
EXPECT_EQ (dl1.initial_cell ().shapes (dl1.layer ()).begin (db::ShapeIterator::All)->to_string (), "polygon (999,1999;999,2001;1001,2001;1001,1999) prop_id=1");
const db::Layout *dss_layout = store.const_layout (0);
const db::Layout *dss_layout = &store.const_layout (0);
db::PropertiesRepository::properties_set ps = dss_layout->properties_repository ().properties (1);
EXPECT_EQ (ps.size (), size_t (1));
EXPECT_EQ (dss_layout->properties_repository ().prop_name (ps.begin ()->first).to_string (), "text");

View File

@ -48,10 +48,9 @@ class MOSFETExtractor
: public db::NetlistDeviceExtractor
{
public:
MOSFETExtractor (db::Netlist &nl, db::Layout *debug_out)
MOSFETExtractor (db::Layout *debug_out)
: db::NetlistDeviceExtractor (), mp_debug_out (debug_out), m_ldiff (0), m_lgate (0)
{
initialize (&nl);
if (mp_debug_out) {
m_ldiff = mp_debug_out->insert_layer (db::LayerProperties (100, 0));
m_lgate = mp_debug_out->insert_layer (db::LayerProperties (101, 0));
@ -230,14 +229,9 @@ static unsigned int define_layer (db::Layout &ly, db::LayerMap &lmap, int gds_la
return lid;
}
// @@@ TODO: move somewhere else
static unsigned int layer_of (const db::Region &region)
{
// TODO: this is clumsy ...
db::DeepRegion *dr = dynamic_cast<db::DeepRegion *> (region.delegate ());
tl_assert (dr != 0);
return dr->deep_layer ().layer ();
return db::DeepLayer (region).layer ();
}
// @@@ TODO: move somewhere else
@ -255,42 +249,37 @@ public:
void extract_nets (const db::DeepShapeStore &dss, const db::Connectivity &conn, db::Netlist *nl)
{
// only works for singular-layout stores currently. This rules out layers from different sources
// and clipping.
tl_assert (dss.layouts () == 1);
const db::Layout *layout = dss.const_layout (0);
tl_assert (layout->cells () != 0);
const db::Cell &cell = layout->cell (*layout->begin_top_down ());
const db::Layout &layout = dss.const_layout ();
const db::Cell &cell = dss.const_initial_cell ();
// gets the text annotation property ID -
// this is how the texts are passed for annotating the net names
std::pair<bool, db::property_names_id_type> text_annot_name_id (false, 0);
if (! dss.text_property_name ().is_nil ()) {
text_annot_name_id = layout->properties_repository ().get_id_of_name (dss.text_property_name ());
text_annot_name_id = layout.properties_repository ().get_id_of_name (dss.text_property_name ());
}
// gets the device terminal annotation property ID -
// this is how the device extractor conveys terminal shape annotations.
std::pair<bool, db::property_names_id_type> terminal_annot_name_id;
terminal_annot_name_id = layout->properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::terminal_property_name ());
terminal_annot_name_id = layout.properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::terminal_property_name ());
// the big part: actually extract the nets
m_net_clusters.build (*layout, cell, db::ShapeIterator::Polygons, conn);
m_net_clusters.build (layout, cell, db::ShapeIterator::Polygons, conn);
// reverse lookup for Circuit vs. cell index
std::map<db::cell_index_type, db::Circuit *> circuits;
// some circuits may be there because of device extraction
for (db::Netlist::circuit_iterator c = nl->begin_circuits (); c != nl->end_circuits (); ++c) {
tl_assert (layout->is_valid_cell_index (c->cell_index ()));
tl_assert (layout.is_valid_cell_index (c->cell_index ()));
circuits.insert (std::make_pair (c->cell_index (), c.operator-> ()));
}
std::map<db::cell_index_type, std::map<size_t, size_t> > pins_per_cluster;
for (db::Layout::bottom_up_const_iterator cid = layout->begin_bottom_up (); cid != layout->end_bottom_up (); ++cid) {
for (db::Layout::bottom_up_const_iterator cid = layout.begin_bottom_up (); cid != layout.end_bottom_up (); ++cid) {
const connected_clusters_type &clusters = m_net_clusters.clusters_per_cell (*cid);
if (clusters.empty ()) {
@ -305,7 +294,7 @@ public:
if (k == circuits.end ()) {
circuit = new db::Circuit ();
nl->add_circuit (circuit);
circuit->set_name (layout->cell_name (*cid));
circuit->set_name (layout.cell_name (*cid));
circuit->set_cell_index (*cid);
circuits.insert (std::make_pair (*cid, circuit));
} else {
@ -348,7 +337,7 @@ public:
tl_assert (k != circuits.end ()); // because we walk bottom-up
subcircuit = new db::SubCircuit (k->second);
db::CplxTrans dbu_trans (layout->dbu ());
db::CplxTrans dbu_trans (layout.dbu ());
subcircuit->set_trans (dbu_trans * i->inst ().complex_trans () * dbu_trans.inverted ());
circuit->add_subcircuit (subcircuit);
subcircuits.insert (std::make_pair (i->inst (), subcircuit));
@ -371,7 +360,7 @@ public:
const local_cluster_type &lc = clusters.cluster_by_id (*c);
for (local_cluster_type::attr_iterator a = lc.begin_attr (); a != lc.end_attr (); ++a) {
const db::PropertiesRepository::properties_set &ps = layout->properties_repository ().properties (*a);
const db::PropertiesRepository::properties_set &ps = layout.properties_repository ().properties (*a);
for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) {
if (terminal_annot_name_id.first && j->first == terminal_annot_name_id.second) {
@ -624,15 +613,15 @@ TEST(1_DeviceNetExtraction)
// NOTE: the device extractor will add more debug layers for the transistors:
// 20/0 -> Diffusion
// 21/0 -> Gate
MOSFETExtractor ex (nl, &ly);
MOSFETExtractor ex (&ly);
std::vector<db::Region *> region_ptrs;
region_ptrs.push_back (&rpdiff);
region_ptrs.push_back (&rndiff);
region_ptrs.push_back (&rgate);
region_ptrs.push_back (&rpoly);
std::vector<db::DeepLayer> dl;
dl.push_back (rpdiff);
dl.push_back (rndiff);
dl.push_back (rgate);
dl.push_back (rpoly);
ex.extract (region_ptrs);
ex.extract (dss, dl, &nl);
// perform the net extraction
@ -640,25 +629,25 @@ TEST(1_DeviceNetExtraction)
db::Connectivity conn;
// Intra-layer
conn.connect (layer_of (rpdiff));
conn.connect (layer_of (rndiff));
conn.connect (layer_of (rpoly));
conn.connect (layer_of (rdiff_cont));
conn.connect (layer_of (rpoly_cont));
conn.connect (layer_of (rmetal1));
conn.connect (layer_of (rvia1));
conn.connect (layer_of (rmetal2));
conn.connect (rpdiff);
conn.connect (rndiff);
conn.connect (rpoly);
conn.connect (rdiff_cont);
conn.connect (rpoly_cont);
conn.connect (rmetal1);
conn.connect (rvia1);
conn.connect (rmetal2);
// Inter-layer
conn.connect (layer_of (rpdiff), layer_of (rdiff_cont));
conn.connect (layer_of (rndiff), layer_of (rdiff_cont));
conn.connect (layer_of (rpoly), layer_of (rpoly_cont));
conn.connect (layer_of (rpoly_cont), layer_of (rmetal1));
conn.connect (layer_of (rdiff_cont), layer_of (rmetal1));
conn.connect (layer_of (rmetal1), layer_of (rvia1));
conn.connect (layer_of (rvia1), layer_of (rmetal2));
conn.connect (layer_of (rpoly), layer_of (rpoly_lbl)); // attaches labels
conn.connect (layer_of (rmetal1), layer_of (rmetal1_lbl)); // attaches labels
conn.connect (layer_of (rmetal2), layer_of (rmetal2_lbl)); // attaches labels
conn.connect (rpdiff, rdiff_cont);
conn.connect (rndiff, rdiff_cont);
conn.connect (rpoly, rpoly_cont);
conn.connect (rpoly_cont, rmetal1);
conn.connect (rdiff_cont, rmetal1);
conn.connect (rmetal1, rvia1);
conn.connect (rvia1, rmetal2);
conn.connect (rpoly, rpoly_lbl); // attaches labels
conn.connect (rmetal1, rmetal1_lbl); // attaches labels
conn.connect (rmetal2, rmetal2_lbl); // attaches labels
// extract the nets