Generalization of layout index for LayoutToNetlist

This commit is contained in:
Matthias Koefferlein 2019-03-03 18:10:52 +01:00
parent 49621aa13a
commit 604a634bf1
11 changed files with 95 additions and 76 deletions

View File

@ -481,6 +481,25 @@ DeepShapeStore::layout_for_iter (const db::RecursiveShapeIterator &si, const db:
}
}
void DeepShapeStore::make_layout (unsigned int layout_index, const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans)
{
tl_assert (m_layout_map.find (std::make_pair (si, trans)) == m_layout_map.end ());
while (m_layouts.size () <= layout_index) {
m_layouts.push_back (0);
}
m_layouts[layout_index] = new LayoutHolder (trans);
db::Layout &layout = m_layouts[layout_index]->layout;
layout.hier_changed_event.add (this, &DeepShapeStore::invalidate_hier);
if (si.layout ()) {
layout.dbu (si.layout ()->dbu () / trans.mag ());
}
m_layout_map[std::make_pair (si, trans)] = layout_index;
}
DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count, const db::ICplxTrans &trans)
{
if (max_area_ratio == 0.0) {

View File

@ -283,6 +283,14 @@ public:
*/
std::pair<bool, DeepLayer> layer_for_flat (size_t region_id) const;
/**
* @brief Creates a layout with the given iterator and transformation for the given index
*
* This method is intended for classes that need more control over the layouts per index
* (LayoutToNetlist).
*/
void make_layout (unsigned int layout_index, const db::RecursiveShapeIterator &si, const db::ICplxTrans &trans = db::ICplxTrans ());
/**
* @brief Inserts a polygon layer into the deep shape store
*

View File

@ -30,46 +30,51 @@
namespace db
{
static const unsigned int singular_layout_index = 0;
// the iterator provides the hierarchical selection (enabling/disabling cells etc.)
LayoutToNetlist::LayoutToNetlist (const db::RecursiveShapeIterator &iter)
: m_iter (iter), m_netlist_extracted (false), m_is_flat (false)
: m_iter (iter), m_layout_index (0), m_netlist_extracted (false), m_is_flat (false)
{
// check the iterator
if (iter.has_complex_region () || iter.region () != db::Box::world ()) {
throw tl::Exception (tl::to_string (tr ("The netlist extractor cannot work on clipped layouts")));
}
mp_internal_dss.reset (new db::DeepShapeStore ());
mp_dss.reset (mp_internal_dss.get ());
// the dummy layer acts as a reference holder for the layout
// NOTE: this probably can be done better
db::RecursiveShapeIterator empty_iter = iter;
empty_iter.set_layers (std::vector<unsigned int> ());
m_dummy_layer = dss ().create_polygon_layer (empty_iter);
init ();
}
LayoutToNetlist::LayoutToNetlist (db::DeepShapeStore *dss, unsigned int layout_index)
: mp_dss (dss), m_netlist_extracted (false), m_is_flat (false)
: mp_dss (dss), m_layout_index (layout_index), m_netlist_extracted (false), m_is_flat (false)
{
m_iter = db::RecursiveShapeIterator (dss->layout (layout_index), dss->initial_cell (layout_index), std::set<unsigned int> ());
if (dss->is_valid_layout_index (m_layout_index)) {
m_iter = db::RecursiveShapeIterator (dss->layout (m_layout_index), dss->initial_cell (m_layout_index), std::set<unsigned int> ());
}
init ();
}
LayoutToNetlist::LayoutToNetlist (db::DeepShapeStore *dss)
: mp_dss (dss), m_netlist_extracted (false), m_is_flat (false)
{
init ();
}
LayoutToNetlist::LayoutToNetlist (const std::string &topcell_name, double dbu)
: m_iter (), m_netlist_extracted (false), m_is_flat (true)
{
mp_internal_dss.reset (new db::DeepShapeStore (topcell_name, dbu));
mp_dss.reset (mp_internal_dss.get ());
m_layout_index = 0 ;
init ();
}
LayoutToNetlist::LayoutToNetlist ()
: m_iter (), mp_internal_dss (new db::DeepShapeStore ()), mp_dss (mp_internal_dss.get ()), m_netlist_extracted (false), m_is_flat (false)
: m_iter (), mp_internal_dss (new db::DeepShapeStore ()), mp_dss (mp_internal_dss.get ()), m_layout_index (0),
m_netlist_extracted (false), m_is_flat (false)
{
init ();
}
@ -86,11 +91,6 @@ LayoutToNetlist::~LayoutToNetlist ()
void LayoutToNetlist::init ()
{
if (! mp_dss.get ()) {
mp_internal_dss.reset (new db::DeepShapeStore ());
mp_dss.reset (mp_internal_dss.get ());
}
dss ().set_text_enlargement (1);
dss ().set_text_property_name (tl::Variant ("LABEL"));
}
@ -184,7 +184,7 @@ void LayoutToNetlist::extract_devices (db::NetlistDeviceExtractor &extractor, co
if (! mp_netlist.get ()) {
mp_netlist.reset (new db::Netlist ());
}
extractor.extract(dss (), layers, *mp_netlist, m_net_clusters);
extractor.extract (dss (), m_layout_index, layers, *mp_netlist, m_net_clusters);
}
void LayoutToNetlist::connect (const db::Region &l)
@ -261,7 +261,7 @@ void LayoutToNetlist::extract_netlist (bool join_nets_by_label)
}
db::NetlistExtractor netex;
netex.extract_nets(dss (), m_conn, *mp_netlist, m_net_clusters, join_nets_by_label);
netex.extract_nets (dss (), m_layout_index, m_conn, *mp_netlist, m_net_clusters, join_nets_by_label);
m_netlist_extracted = true;
}
@ -273,30 +273,40 @@ void LayoutToNetlist::set_netlist_extracted ()
const db::Layout *LayoutToNetlist::internal_layout () const
{
return &dss ().const_layout ();
ensure_layout ();
return &dss ().const_layout (m_layout_index);
}
const db::Cell *LayoutToNetlist::internal_top_cell () const
{
return &dss ().const_initial_cell ();
}
void LayoutToNetlist::ensure_internal_layout ()
{
if (dss ().layouts () == 0) {
// the dummy layer acts as a reference holder for the layout
m_dummy_layer = dss ().create_polygon_layer (db::RecursiveShapeIterator ());
}
ensure_layout ();
return &dss ().const_initial_cell (m_layout_index);
}
db::Layout *LayoutToNetlist::internal_layout ()
{
return &dss ().layout ();
ensure_layout ();
return &dss ().layout (m_layout_index);
}
db::Cell *LayoutToNetlist::internal_top_cell ()
{
return &dss ().initial_cell ();
ensure_layout ();
return &dss ().initial_cell (m_layout_index);
}
void LayoutToNetlist::ensure_layout () const
{
if (! dss ().is_valid_layout_index (m_layout_index)) {
LayoutToNetlist *non_const_this = const_cast<LayoutToNetlist *> (this);
non_const_this->dss ().make_layout (m_layout_index, db::RecursiveShapeIterator ());
// the dummy layer acts as a reference holder for the layout
unsigned int dummy_layer_index = non_const_this->dss ().layout (m_layout_index).insert_layer ();
non_const_this->m_dummy_layer = db::DeepLayer (& non_const_this->dss (), m_layout_index, dummy_layer_index);
}
}
void LayoutToNetlist::register_layer (const db::Region &region, const std::string &n)
@ -317,7 +327,7 @@ void LayoutToNetlist::register_layer (const db::Region &region, const std::strin
if (! delegate) {
if (region.empty ()) {
dl = dss ().empty_layer ();
dl = dss ().empty_layer (m_layout_index);
} else {
throw tl::Exception (tl::to_string (tr ("Layer is not a deep region and cannot be registered with name: ")) + n);
}
@ -394,7 +404,7 @@ db::DeepLayer LayoutToNetlist::deep_layer_of (const db::Region &region) const
return lff.second;
} else if (region.empty ()) {
// provide a substitute empty layer for empty
return dss ().empty_layer ();
return dss ().empty_layer (m_layout_index);
} else {
throw (tl::Exception (tl::to_string (tr ("Non-hierarchical layers cannot be used in netlist extraction"))));
}
@ -418,7 +428,7 @@ db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell
}
}
return dss ().cell_mapping_to_original (singular_layout_index, &layout, cell.cell_index (), &device_cells);
return dss ().cell_mapping_to_original (m_layout_index, &layout, cell.cell_index (), &device_cells);
}
db::CellMapping LayoutToNetlist::const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell)
@ -869,10 +879,10 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, const db::Reg
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
}
db::Layout &ly = dss ().layout ();
db::Layout &ly = dss ().layout (m_layout_index);
double dbu = ly.dbu ();
db::DeepLayer dl (&dss (), singular_layout_index, ly.insert_layer ());
db::DeepLayer dl (&dss (), m_layout_index, ly.insert_layer ());
for (db::Layout::bottom_up_const_iterator cid = ly.begin_bottom_up (); cid != ly.end_bottom_up (); ++cid) {

View File

@ -93,20 +93,7 @@ public:
* NOTE: if using make_layer, these new layers will be created in the DSS
* given in this constructor.
*/
LayoutToNetlist (db::DeepShapeStore *dss, unsigned int layout_index);
/**
* @brief Alternative constructor using an external deep shape storage
*
* This constructor allows using an external DSS. It's intended to be used
* with existing DSS instances. Existing layers can be registered with
* "register_layer". The LayoutToNetlist object will hold a weak reference
* to the DSS but not own the DSS.
*
* NOTE: this version cannot create layers but just register layers
* which are present inside the DSS given as the argument.
*/
LayoutToNetlist (db::DeepShapeStore *dss);
LayoutToNetlist (db::DeepShapeStore *dss, unsigned int layout_index = 0);
/**
* @brief Alternative constructor for flat mode
@ -338,11 +325,6 @@ public:
*/
db::Cell *internal_top_cell ();
/**
* @brief Ensures the internal layout is made
*/
void ensure_internal_layout ();
/**
* @brief Gets the connectivity object
*/
@ -533,6 +515,7 @@ private:
db::RecursiveShapeIterator m_iter;
std::auto_ptr<db::DeepShapeStore> mp_internal_dss;
tl::weak_ptr<db::DeepShapeStore> mp_dss;
unsigned int m_layout_index;
db::Connectivity m_conn;
db::hier_clusters<db::PolygonRef> m_net_clusters;
std::auto_ptr<db::Netlist> mp_netlist;
@ -560,6 +543,7 @@ private:
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;
db::DeepLayer deep_layer_of (const db::Region &region) const;
void ensure_layout () const;
};
}

View File

@ -159,8 +159,6 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
int version = 0;
std::string description;
// TODO: there probably is a more efficient way to force the layout inside l2n to be made
l2n->ensure_internal_layout ();
tl_assert (l2n->internal_layout ());
l2n->internal_layout ()->dbu (1.0); // mainly for testing

View File

@ -123,7 +123,7 @@ 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 (db::DeepShapeStore &dss, const NetlistDeviceExtractor::input_layers &layer_map, db::Netlist &nl, hier_clusters_type &clusters)
void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, unsigned int layout_index, const NetlistDeviceExtractor::input_layers &layer_map, db::Netlist &nl, hier_clusters_type &clusters)
{
initialize (&nl);
@ -147,14 +147,14 @@ void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, const NetlistDevi
layers.push_back (alias.second.layer ());
} else if (l->second->empty ()) {
// provide a substitute empty layer
layers.push_back (dss.empty_layer ().layer ());
layers.push_back (dss.empty_layer (layout_index).layer ());
} else {
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Invalid region passed to input layer '%s' for device extraction: must be of deep region kind")), ld->name));
}
} else {
if (&dr->deep_layer ().layout () != &dss.layout () || &dr->deep_layer ().initial_cell () != &dss.initial_cell ()) {
if (&dr->deep_layer ().layout () != &dss.layout (layout_index) || &dr->deep_layer ().initial_cell () != &dss.initial_cell (layout_index)) {
throw tl::Exception (tl::sprintf (tl::to_string (tr ("Invalid region passed to input layer '%s' for device extraction: not originating from the same source")), ld->name));
}
@ -164,7 +164,7 @@ void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, const NetlistDevi
}
extract_without_initialize (dss.layout (), dss.initial_cell (), clusters, layers);
extract_without_initialize (dss.layout (layout_index), dss.initial_cell (layout_index), clusters, layers);
}
void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const std::vector<unsigned int> &layers, db::Netlist *nl, hier_clusters_type &clusters)

View File

@ -266,7 +266,7 @@ public:
* named regions for input. These regions need to be of deep region type and
* originate from the same layout than the DeepShapeStore.
*/
void extract (DeepShapeStore &dss, const input_layers &layers, Netlist &netlist, hier_clusters_type &clusters);
void extract (DeepShapeStore &dss, unsigned int layout_index, const input_layers &layers, Netlist &netlist, hier_clusters_type &clusters);
/**
* @brief Gets the error iterator, begin

View File

@ -58,11 +58,11 @@ build_net_name_equivalence (const db::Layout *layout, db::property_names_id_type
}
void
NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters, bool join_nets_by_label)
NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, unsigned int layout_index, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters, bool join_nets_by_label)
{
mp_clusters = &clusters;
mp_layout = &dss.const_layout ();
mp_cell = &dss.const_initial_cell ();
mp_layout = &dss.const_layout (layout_index);
mp_cell = &dss.const_initial_cell (layout_index);
// gets the text annotation property ID -
// this is how the texts are passed for annotating the net names

View File

@ -82,7 +82,7 @@ public:
* @brief Extract the nets
* See the class description for more details.
*/
void extract_nets (const db::DeepShapeStore &dss, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters, bool join_nets_by_label = true);
void extract_nets (const db::DeepShapeStore &dss, unsigned int layout_index, const db::Connectivity &conn, db::Netlist &nl, hier_clusters_type &clusters, bool join_nets_by_label = true);
private:
hier_clusters_type *mp_clusters;

View File

@ -218,12 +218,12 @@ TEST(1_DeviceAndNetExtraction)
dl["SD"] = &rpsd;
dl["G"] = &rpgate;
dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes
pmos_ex.extract (dss, dl, nl, cl);
pmos_ex.extract (dss, 0, dl, nl, cl);
dl["SD"] = &rnsd;
dl["G"] = &rngate;
dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes
nmos_ex.extract (dss, dl, nl, cl);
nmos_ex.extract (dss, 0, dl, nl, cl);
// perform the net extraction
@ -253,7 +253,7 @@ TEST(1_DeviceAndNetExtraction)
// extract the nets
net_ex.extract_nets (dss, conn, nl, cl);
net_ex.extract_nets (dss, 0, conn, nl, cl);
// debug layers produced for nets
// 202/0 -> Active
@ -430,12 +430,12 @@ TEST(2_DeviceAndNetExtractionFlat)
dl["SD"] = &rpsd;
dl["G"] = &rpgate;
dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes
pmos_ex.extract (dss, dl, nl, cl);
pmos_ex.extract (dss, 0, dl, nl, cl);
dl["SD"] = &rnsd;
dl["G"] = &rngate;
dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes
nmos_ex.extract (dss, dl, nl, cl);
nmos_ex.extract (dss, 0, dl, nl, cl);
// perform the net extraction
@ -466,7 +466,7 @@ TEST(2_DeviceAndNetExtractionFlat)
// extract the nets
// don't use "join_nets_by_label" because the flattened texts will spoil everything
net_ex.extract_nets (dss, conn, nl, cl, false);
net_ex.extract_nets (dss, 0, conn, nl, cl, false);
// debug layers produced for nets
// 202/0 -> Active
@ -664,12 +664,12 @@ TEST(3_DeviceAndNetExtractionWithImplicitConnections)
dl["SD"] = &rpsd;
dl["G"] = &rpgate;
dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes
pmos_ex.extract (dss, dl, nl, cl);
pmos_ex.extract (dss, 0, dl, nl, cl);
dl["SD"] = &rnsd;
dl["G"] = &rngate;
dl["P"] = &rpoly; // not needed for extraction but to return terminal shapes
nmos_ex.extract (dss, dl, nl, cl);
nmos_ex.extract (dss, 0, dl, nl, cl);
// perform the net extraction
@ -699,7 +699,7 @@ TEST(3_DeviceAndNetExtractionWithImplicitConnections)
// extract the nets
net_ex.extract_nets (dss, conn, nl, cl);
net_ex.extract_nets (dss, 0, conn, nl, cl);
EXPECT_EQ (all_net_names_unique (nl), true);

View File

@ -3772,7 +3772,7 @@ CODE
# Multiple diode specifications are allowed. Just add them
# to the antenna_check call.
#
# The error shapes produced by the antenna check are a copy
# The error shapes produced by the antenna check are copies
# of the metal shapes on the metal layers of each network
# violating the antenna rule.