"breakout cells": attempt to provide a solution for SRAM

Breakout cells can be specified to shortcut hierarchy
evaluation for some cells. This allows treating SRAM cells
as isolated entities - specifically when it comes to extracting
devices.
This commit is contained in:
Matthias Koefferlein 2019-10-16 00:49:41 +02:00
parent 5c44a54676
commit 991778f718
11 changed files with 515 additions and 92 deletions

View File

@ -527,7 +527,7 @@ DeepRegion::and_or_not_with (const DeepRegion *other, bool and_op) const
db::BoolAndOrNotLocalOperation op (and_op);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> 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::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> 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 (), m_deep_layer.breakout_cells (), other->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (m_deep_layer.store ()->threads ());
proc.set_area_ratio (m_deep_layer.store ()->max_area_ratio ());
@ -1501,7 +1501,9 @@ DeepRegion::run_check (db::edge_relation_type rel, bool different_polygons, cons
db::local_processor<db::PolygonRef, db::PolygonRef, db::EdgePair> proc (const_cast<db::Layout *> (&polygons.layout ()),
const_cast<db::Cell *> (&polygons.initial_cell ()),
other_deep ? &other_deep->deep_layer ().layout () : const_cast<db::Layout *> (&polygons.layout ()),
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&polygons.initial_cell ()));
other_deep ? &other_deep->deep_layer ().initial_cell () : const_cast<db::Cell *> (&polygons.initial_cell ()),
m_deep_layer.breakout_cells (),
other_deep ? other_deep->deep_layer ().breakout_cells () : 0);
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
@ -1892,7 +1894,7 @@ DeepRegion::selected_interacting_generic (const Region &other, int mode, bool to
db::InteractingLocalOperation op (mode, touching, inverse);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell ());
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
if (split_after) {
@ -1929,7 +1931,7 @@ DeepRegion::selected_interacting_generic (const Edges &other, bool inverse) cons
db::InteractingWithEdgeLocalOperation op (inverse);
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell ());
db::local_processor<db::PolygonRef, db::Edge, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_deep->deep_layer ().layout (), &other_deep->deep_layer ().initial_cell (), polygons.breakout_cells (), other_deep->deep_layer ().breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
if (split_after) {
@ -1968,7 +1970,7 @@ DeepRegion::pull_generic (const Region &other, int mode, bool touching) const
db::PullLocalOperation op (mode, touching);
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell ());
db::local_processor<db::PolygonRef, db::PolygonRef, db::PolygonRef> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_polygons.layout (), &other_polygons.initial_cell (), polygons.breakout_cells (), other_polygons.breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
if (split_after) {
@ -2004,7 +2006,7 @@ DeepRegion::pull_generic (const Edges &other) const
db::PullWithEdgeLocalOperation op;
db::local_processor<db::PolygonRef, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell ());
db::local_processor<db::PolygonRef, db::Edge, db::Edge> proc (const_cast<db::Layout *> (&polygons.layout ()), const_cast<db::Cell *> (&polygons.initial_cell ()), &other_edges.layout (), &other_edges.initial_cell (), polygons.breakout_cells (), other_edges.breakout_cells ());
proc.set_base_verbosity (base_verbosity ());
proc.set_threads (polygons.store ()->threads ());
proc.run (&op, polygons.layer (), other_edges.layer (), dl_out.layer ());

View File

@ -81,7 +81,6 @@ DeepLayer &DeepLayer::operator= (const DeepLayer &other)
return *this;
}
DeepLayer::~DeepLayer ()
{
if (mp_store.get ()) {
@ -139,6 +138,12 @@ DeepLayer::add_from (const DeepLayer &dl)
}
}
const std::set<db::cell_index_type> *
DeepLayer::breakout_cells () const
{
return store ()->breakout_cells (layout_index ());
}
void
DeepLayer::insert_into (db::Layout *into_layout, db::cell_index_type into_cell, unsigned int into_layer) const
{
@ -251,16 +256,114 @@ struct DeepShapeStore::LayoutHolder
// ----------------------------------------------------------------------------------
DeepShapeStoreState::DeepShapeStoreState ()
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_text_property_name (), m_text_enlargement (-1)
{
// .. nothing yet ..
}
void DeepShapeStoreState::set_text_enlargement (int enl)
{
m_text_enlargement = enl;
}
int DeepShapeStoreState::text_enlargement () const
{
return m_text_enlargement;
}
void DeepShapeStoreState::set_text_property_name (const tl::Variant &pn)
{
m_text_property_name = pn;
}
const tl::Variant &
DeepShapeStoreState::text_property_name () const
{
return m_text_property_name;
}
const std::set<db::cell_index_type> *
DeepShapeStoreState::breakout_cells (unsigned int layout_index) const
{
const std::set<db::cell_index_type> &boc = (const_cast<DeepShapeStoreState *> (this))->ensure_breakout_cells (layout_index);
if (boc.empty ()) {
return 0;
} else {
return &boc;
}
}
void
DeepShapeStoreState::clear_breakout_cells (unsigned int layout_index)
{
ensure_breakout_cells (layout_index).clear ();
}
void
DeepShapeStoreState::set_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &boc)
{
ensure_breakout_cells (layout_index) = boc;
}
void
DeepShapeStoreState::add_breakout_cell (unsigned int layout_index, db::cell_index_type ci)
{
ensure_breakout_cells (layout_index).insert (ci);
}
void
DeepShapeStoreState::add_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &cc)
{
ensure_breakout_cells (layout_index).insert (cc.begin (), cc.end ());
}
void
DeepShapeStoreState::set_threads (int n)
{
m_threads = n;
}
int
DeepShapeStoreState::threads () const
{
return m_threads;
}
void
DeepShapeStoreState::set_max_area_ratio (double ar)
{
m_max_area_ratio = ar;
}
double
DeepShapeStoreState::max_area_ratio () const
{
return m_max_area_ratio;
}
void
DeepShapeStoreState::set_max_vertex_count (size_t n)
{
m_max_vertex_count = n;
}
size_t
DeepShapeStoreState::max_vertex_count () const
{
return m_max_vertex_count;
}
// ----------------------------------------------------------------------------------
static size_t s_instance_count = 0;
DeepShapeStore::DeepShapeStore ()
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_text_property_name (), m_text_enlargement (-1)
{
++s_instance_count;
}
DeepShapeStore::DeepShapeStore (const std::string &topcell_name, double dbu)
: m_threads (1), m_max_area_ratio (3.0), m_max_vertex_count (16), m_text_property_name (), m_text_enlargement (-1)
{
++s_instance_count;
@ -292,17 +395,17 @@ DeepLayer DeepShapeStore::create_from_flat (const db::Region &region, bool for_n
unsigned int layer = layout ().insert_layer ();
if (max_area_ratio == 0.0) {
max_area_ratio = m_max_area_ratio;
max_area_ratio = m_state.max_area_ratio ();
}
if (max_vertex_count == 0) {
max_vertex_count = m_max_vertex_count;
max_vertex_count = m_state.max_vertex_count ();
}
db::Shapes *shapes = &initial_cell ().shapes (layer);
db::Box world = db::Box::world ();
// The chain of operators for producing clipped and reduced polygon references
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (&layout (), m_text_enlargement, m_text_property_name);
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (&layout (), text_enlargement (), text_property_name ());
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count);
// try to maintain the texts on top level - go through shape iterator
@ -399,12 +502,95 @@ const db::Cell &DeepShapeStore::const_initial_cell (unsigned int n) const
void DeepShapeStore::set_text_enlargement (int enl)
{
m_text_enlargement = enl;
m_state.set_text_enlargement (enl);
}
int DeepShapeStore::text_enlargement () const
{
return m_state.text_enlargement ();
}
void DeepShapeStore::set_text_property_name (const tl::Variant &pn)
{
m_text_property_name = pn;
m_state.set_text_property_name (pn);
}
const tl::Variant &DeepShapeStore::text_property_name () const
{
return m_state.text_property_name ();
}
const std::set<db::cell_index_type> *
DeepShapeStore::breakout_cells (unsigned int layout_index) const
{
return m_state.breakout_cells (layout_index);
}
void
DeepShapeStore::clear_breakout_cells (unsigned int layout_index)
{
m_state.clear_breakout_cells (layout_index);
}
void
DeepShapeStore::set_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &boc)
{
m_state.set_breakout_cells (layout_index, boc);
}
void
DeepShapeStore::add_breakout_cell (unsigned int layout_index, db::cell_index_type ci)
{
m_state.add_breakout_cell (layout_index, ci);
}
void
DeepShapeStore::add_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &cc)
{
m_state.add_breakout_cells (layout_index, cc);
}
void DeepShapeStore::set_threads (int n)
{
m_state.set_threads (n);
}
int DeepShapeStore::threads () const
{
return m_state.threads ();
}
void DeepShapeStore::set_max_area_ratio (double ar)
{
m_state.set_max_area_ratio (ar);
}
double DeepShapeStore::max_area_ratio () const
{
return m_state.max_area_ratio ();
}
void DeepShapeStore::set_max_vertex_count (size_t n)
{
m_state.set_max_vertex_count (n);
}
size_t DeepShapeStore::max_vertex_count () const
{
return m_state.max_vertex_count ();
}
void DeepShapeStore::push_state ()
{
m_state_stack.push_back (m_state);
}
void DeepShapeStore::pop_state ()
{
if (! m_state_stack.empty ()) {
m_state = m_state_stack.back ();
m_state_stack.pop_back ();
}
}
bool DeepShapeStore::is_valid_layout_index (unsigned int n) const
@ -429,21 +615,6 @@ size_t DeepShapeStore::instance_count ()
return s_instance_count;
}
void DeepShapeStore::set_threads (int n)
{
m_threads = n;
}
void DeepShapeStore::set_max_area_ratio (double ar)
{
m_max_area_ratio = ar;
}
void DeepShapeStore::set_max_vertex_count (size_t n)
{
m_max_vertex_count = n;
}
void DeepShapeStore::add_ref (unsigned int layout, unsigned int layer)
{
tl::MutexLocker locker (&m_lock);
@ -474,6 +645,7 @@ void DeepShapeStore::remove_ref (unsigned int layout, unsigned int layer)
if ((m_layouts[layout]->refs -= 1) <= 0) {
delete m_layouts[layout];
m_layouts[layout] = 0;
clear_breakout_cells (layout);
}
}
@ -542,10 +714,10 @@ static unsigned int init_layer (db::Layout &layout, const db::RecursiveShapeIter
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) {
max_area_ratio = m_max_area_ratio;
max_area_ratio = m_state.max_area_ratio ();
}
if (max_vertex_count == 0) {
max_vertex_count = m_max_vertex_count;
max_vertex_count = m_state.max_vertex_count ();
}
unsigned int layout_index = layout_for_iter (si, trans);
@ -557,7 +729,7 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
builder.set_target_layer (layer_index);
// The chain of operators for producing clipped and reduced polygon references
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (& layout, m_text_enlargement, m_text_property_name);
db::PolygonReferenceHierarchyBuilderShapeReceiver refs (& layout, text_enlargement (), text_property_name ());
db::ReducingHierarchyBuilderShapeReceiver red (&refs, max_area_ratio, max_vertex_count);
db::ClippingHierarchyBuilderShapeReceiver clip (&red);

View File

@ -40,6 +40,7 @@
namespace db {
class DeepShapeStore;
class DeepShapeStoreState;
class Region;
class Edges;
@ -132,6 +133,13 @@ public:
return m_layout;
}
/**
* @brief Gets the list of breakout cells if there are some
* "breakout cells" are cells which are not considered to participate in hierarchical operations,
* neither as sibling nor in parent-child relationships.
*/
const std::set<db::cell_index_type> *breakout_cells () const;
/**
* @brief Inserts the layer into the given layout, starting from the given cell and into the given layer
*/
@ -200,6 +208,52 @@ private:
unsigned int m_layer;
};
/**
* @brief An object holding the state of a DeepShapeStore
*/
class DB_PUBLIC DeepShapeStoreState
{
public:
DeepShapeStoreState ();
void set_threads (int n);
int threads () const;
void set_max_vertex_count (size_t n);
size_t max_vertex_count () const;
void set_max_area_ratio (double ar);
double max_area_ratio () const;
void set_text_property_name (const tl::Variant &pn);
const tl::Variant &text_property_name () const;
void set_text_enlargement (int enl);
int text_enlargement () const;
const std::set<db::cell_index_type> *breakout_cells (unsigned int layout_index) const;
void clear_breakout_cells (unsigned int layout_index);
void set_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &boc);
void add_breakout_cell (unsigned int layout_index, db::cell_index_type ci);
void add_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &cc);
private:
int m_threads;
double m_max_area_ratio;
size_t m_max_vertex_count;
tl::Variant m_text_property_name;
std::vector<std::set<db::cell_index_type> > m_breakout_cells;
int m_text_enlargement;
std::set<db::cell_index_type> &ensure_breakout_cells (unsigned int layout_index)
{
if (m_breakout_cells.size () <= size_t (layout_index)) {
m_breakout_cells.resize (layout_index + 1, std::set<db::cell_index_type> ());
}
return m_breakout_cells [layout_index];
}
};
struct DB_PUBLIC RecursiveShapeIteratorCompareForTargetHierarchy
{
bool operator () (const std::pair<db::RecursiveShapeIterator, db::ICplxTrans> &a, const std::pair<db::RecursiveShapeIterator, db::ICplxTrans> &b) const
@ -514,10 +568,7 @@ public:
/**
* @brief Gets the number of threads
*/
int threads () const
{
return m_threads;
}
int threads () const;
/**
* @brief Sets the maximum vertex count default value
@ -531,10 +582,7 @@ public:
/**
* @brief Gets the maximum vertex count
*/
size_t max_vertex_count () const
{
return m_max_vertex_count;
}
size_t max_vertex_count () const;
/**
* @brief Sets the max. area ratio for bounding box vs. polygon area
@ -548,10 +596,7 @@ public:
/**
* @brief Gets the max. area ratio
*/
double max_area_ratio () const
{
return m_max_area_ratio;
}
double max_area_ratio () const;
/**
* @brief Sets the text property name
@ -566,10 +611,7 @@ public:
/**
* @brief Gets the text property name
*/
const tl::Variant &text_property_name () const
{
return m_text_property_name;
}
const tl::Variant &text_property_name () const;
/**
* @brief Sets the text enlargement value
@ -584,10 +626,45 @@ public:
/**
* @brief Gets the text enlargement value
*/
int text_enlargement () const
{
return m_text_enlargement;
}
int text_enlargement () const;
/**
* @brief Gets the breakout cells for a given layout
* Returns 0 if there are no breakout cells for this layout.
*/
const std::set<db::cell_index_type> *breakout_cells (unsigned int layout_index) const;
/**
* @brief Clears the breakout cell list for a given layout
*/
void clear_breakout_cells (unsigned int layout_index);
/**
* @brief Sets the breakout cell list for a given layout
*/
void set_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &boc);
/**
* @brief Adds a breakout cell for a given layout
*/
void add_breakout_cell (unsigned int layout_index, db::cell_index_type ci);
/**
* @brief Adds breakout cells for a given layout
*/
void add_breakout_cells (unsigned int layout_index, const std::set<db::cell_index_type> &cc);
/**
* @brief Pushes the state on the state stack
* The state involves threads, max_area_ratio, max_vertex_count, the breakout cells and
* the text representation properties (enlargement, property name).
*/
void push_state ();
/**
* @brief Pops the state (see @ref push_state)
*/
void pop_state ();
private:
friend class DeepLayer;
@ -614,11 +691,8 @@ private:
std::map<size_t, std::pair<unsigned int, unsigned int> > m_layers_for_flat;
std::map<std::pair<unsigned int, unsigned int>, size_t> m_flat_region_id;
layout_map_type m_layout_map;
int m_threads;
double m_max_area_ratio;
size_t m_max_vertex_count;
tl::Variant m_text_property_name;
int m_text_enlargement;
DeepShapeStoreState m_state;
std::list<DeepShapeStoreState> m_state_stack;
tl::Mutex m_lock;
struct DeliveryMappingCacheKey

View File

@ -1117,11 +1117,11 @@ void hier_clusters<T>::clear ()
template <class T>
void
hier_clusters<T>::build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence)
hier_clusters<T>::build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
{
clear ();
cell_clusters_box_converter<T> cbc (layout, *this);
do_build (cbc, layout, cell, shape_flags, conn, attr_equivalence);
do_build (cbc, layout, cell, shape_flags, conn, attr_equivalence, breakout_cells);
}
namespace
@ -1793,7 +1793,7 @@ hier_clusters<T>::make_path (const db::Layout &layout, const db::Cell &cell, siz
template <class T>
void
hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence)
hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence, const std::set<db::cell_index_type> *breakout_cells)
{
tl::SelfTimer timer (tl::verbosity () > m_base_verbosity, tl::to_string (tr ("Computing shape clusters")));
@ -1835,7 +1835,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
todo.push_back (*c);
} else {
tl_assert (! todo.empty ());
build_hier_connections_for_cells (cbc, layout, todo, conn, progress);
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress);
done.insert (todo.begin (), todo.end ());
todo.clear ();
todo.push_back (*c);
@ -1845,7 +1845,7 @@ hier_clusters<T>::do_build (cell_clusters_box_converter<T> &cbc, const db::Layou
}
build_hier_connections_for_cells (cbc, layout, todo, conn, progress);
build_hier_connections_for_cells (cbc, layout, todo, conn, breakout_cells, progress);
}
}
@ -1865,10 +1865,10 @@ hier_clusters<T>::build_local_cluster (const db::Layout &layout, const db::Cell
template <class T>
void
hier_clusters<T>::build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, tl::RelativeProgress &progress)
hier_clusters<T>::build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells, tl::RelativeProgress &progress)
{
for (std::vector<db::cell_index_type>::const_iterator c = cells.begin (); c != cells.end (); ++c) {
build_hier_connections (cbc, layout, layout.cell (*c), conn);
build_hier_connections (cbc, layout, layout.cell (*c), conn, breakout_cells);
++progress;
}
}
@ -1950,9 +1950,14 @@ private:
}
static bool is_breakout_cell (const std::set<db::cell_index_type> *breakout_cells, db::cell_index_type ci)
{
return breakout_cells && breakout_cells->find (ci) != breakout_cells->end ();
}
template <class T>
void
hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn)
hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<db::cell_index_type> *breakout_cells)
{
std::string msg = tl::to_string (tr ("Computing hierarchical clusters for cell: ")) + std::string (layout.cell_name (cell.cell_index ()));
if (tl::verbosity () >= m_base_verbosity + 20) {
@ -1992,7 +1997,9 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
db::box_scanner<db::Instance, unsigned int> bs (true, desc);
for (std::vector<db::Instance>::const_iterator inst = inst_storage.begin (); inst != inst_storage.end (); ++inst) {
bs.insert (inst.operator-> (), 0);
if (! is_breakout_cell (breakout_cells, inst->cell_index ())) {
bs.insert (inst.operator-> (), 0);
}
}
bs.process (*rec, 1 /*touching*/, cibc);
@ -2026,7 +2033,9 @@ hier_clusters<T>::build_hier_connections (cell_clusters_box_converter<T> &cbc, c
}
for (std::vector<db::Instance>::const_iterator inst = inst_storage.begin (); inst != inst_storage.end (); ++inst) {
bs2.insert2 (inst.operator-> (), 0);
if (! is_breakout_cell (breakout_cells, inst->cell_index ())) {
bs2.insert2 (inst.operator-> (), 0);
}
}
bs2.process (*rec, 1 /*touching*/, local_cluster_box_convert<T> (), cibc);

View File

@ -912,7 +912,7 @@ public:
/**
* @brief Builds a hierarchy of clusters from a cell hierarchy and given connectivity
*/
void build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence = 0);
void build (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence = 0, const std::set<cell_index_type> *breakout_cells = 0);
/**
* @brief Gets the connected clusters for a given cell
@ -951,9 +951,9 @@ public:
private:
void build_local_cluster (const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence);
void build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn);
void build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, tl::RelativeProgress &progress);
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence = 0);
void build_hier_connections (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells);
void build_hier_connections_for_cells (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const std::vector<db::cell_index_type> &cells, const db::Connectivity &conn, const std::set<cell_index_type> *breakout_cells, tl::RelativeProgress &progress);
void do_build (cell_clusters_box_converter<T> &cbc, const db::Layout &layout, const db::Cell &cell, db::ShapeIterator::flags_type shape_flags, const db::Connectivity &conn, const tl::equivalence_clusters<unsigned int> *attr_equivalence, const std::set<cell_index_type> *breakout_cells);
std::map<db::cell_index_type, connected_clusters<T> > m_per_cell_clusters;
int m_base_verbosity;

View File

@ -1046,15 +1046,21 @@ template class DB_PUBLIC local_processor_result_computation_task<db::Edge, db::E
// LocalProcessor implementation
template <class TS, class TI, class TR>
local_processor<TS, TI, TR>::local_processor (db::Layout *layout, db::Cell *top)
: mp_subject_layout (layout), mp_intruder_layout (layout), mp_subject_top (top), mp_intruder_top (top), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
local_processor<TS, TI, TR>::local_processor (db::Layout *layout, db::Cell *top, const std::set<db::cell_index_type> *breakout_cells)
: mp_subject_layout (layout), mp_intruder_layout (layout),
mp_subject_top (top), mp_intruder_top (top),
mp_subject_breakout_cells (breakout_cells), mp_intruder_breakout_cells (breakout_cells),
m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
{
// .. nothing yet ..
}
template <class TS, class TI, class TR>
local_processor<TS, TI, TR>::local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_top)
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout), mp_subject_top (subject_top), mp_intruder_top (intruder_top), m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
local_processor<TS, TI, TR>::local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_top, const std::set<cell_index_type> *subject_breakout_cells, const std::set<cell_index_type> *intruder_breakout_cells)
: mp_subject_layout (subject_layout), mp_intruder_layout (intruder_layout),
mp_subject_top (subject_top), mp_intruder_top (intruder_top),
mp_subject_breakout_cells (subject_breakout_cells), mp_intruder_breakout_cells (intruder_breakout_cells),
m_nthreads (0), m_max_vertex_count (0), m_area_ratio (0.0), m_base_verbosity (30), m_progress (0), mp_progress (0)
{
// .. nothing yet ..
}
@ -1265,10 +1271,10 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
unsigned int iid = ++id;
if (! inst_bcs (i->cell_inst ()).empty ()) {
if (! inst_bcs (i->cell_inst ()).empty () && ! subject_cell_is_breakout (i->cell_index ())) {
scanner.insert1 (&i->cell_inst (), iid);
}
if (! inst_bci (i->cell_inst ()).empty ()) {
if (! inst_bci (i->cell_inst ()).empty () && ! intruder_cell_is_breakout (i->cell_index ())) {
scanner.insert2 (&i->cell_inst (), iid);
}
}
@ -1276,14 +1282,14 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
} else {
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
if (! inst_bcs (i->cell_inst ()).empty ()) {
if (! inst_bcs (i->cell_inst ()).empty () && ! subject_cell_is_breakout (i->cell_index ())) {
scanner.insert1 (&i->cell_inst (), ++id);
}
}
if (intruder_cell) {
for (db::Cell::const_iterator i = intruder_cell->begin (); !i.at_end (); ++i) {
if (! inst_bci (i->cell_inst ()).empty ()) {
if (! inst_bci (i->cell_inst ()).empty () && ! intruder_cell_is_breakout (i->cell_index ())) {
scanner.insert2 (&i->cell_inst (), ++id);
}
}
@ -1306,7 +1312,7 @@ void local_processor<TS, TI, TR>::compute_contexts (local_processor_contexts<TS,
interaction_registration_inst2shape<TI> rec (mp_subject_layout, contexts.subject_layer (), dist, &interactions);
for (db::Cell::const_iterator i = subject_cell->begin (); !i.at_end (); ++i) {
if (! inst_bcs (i->cell_inst ()).empty ()) {
if (! inst_bcs (i->cell_inst ()).empty () && ! subject_cell_is_breakout (i->cell_index ())) {
scanner.insert1 (&i->cell_inst (), 0);
}
}
@ -1701,7 +1707,7 @@ local_processor<TS, TI, TR>::compute_local_cell (const db::local_processor_conte
} else if (intruder_cell) {
// TODO: can we confine this search to the subject's (sized) bounding box?
for (db::Cell::const_iterator i = intruder_cell->begin (); !i.at_end (); ++i) {
if (! inst_bci (i->cell_inst ()).empty ()) {
if (! inst_bci (i->cell_inst ()).empty () && ! intruder_cell_is_breakout (i->cell_index ())) {
scanner.insert2 (&i->cell_inst (), ++inst_id);
}
}

View File

@ -368,8 +368,8 @@ template <class TS, class TI, class TR>
class DB_PUBLIC local_processor
{
public:
local_processor (db::Layout *layout, db::Cell *top);
local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell);
local_processor (db::Layout *layout, db::Cell *top, const std::set<db::cell_index_type> *breakout_cells = 0);
local_processor (db::Layout *subject_layout, db::Cell *subject_top, const db::Layout *intruder_layout, const db::Cell *intruder_cell, const std::set<db::cell_index_type> *subject_breakout_cells = 0, const std::set<db::cell_index_type> *intruder_breakout_cells = 0);
void run (local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer, unsigned int output_layer);
void compute_contexts (local_processor_contexts<TS, TI, TR> &contexts, const local_operation<TS, TI, TR> *op, unsigned int subject_layer, unsigned int intruder_layer) const;
void compute_results (local_processor_contexts<TS, TI, TR> &contexts, const local_operation<TS, TI, TR> *op, unsigned int output_layer) const;
@ -427,6 +427,8 @@ private:
const db::Layout *mp_intruder_layout;
db::Cell *mp_subject_top;
const db::Cell *mp_intruder_top;
const std::set<db::cell_index_type> *mp_subject_breakout_cells;
const std::set<db::cell_index_type> *mp_intruder_breakout_cells;
std::string m_description;
unsigned int m_nthreads;
size_t m_max_vertex_count;
@ -445,6 +447,16 @@ private:
void push_results (db::Cell *cell, unsigned int output_layer, const std::unordered_set<TR> &result) const;
void compute_local_cell (const db::local_processor_contexts<TS, TI, TR> &contexts, db::Cell *subject_cell, const db::Cell *intruder_cell, const local_operation<TS, TI, TR> *op, const typename local_processor_cell_contexts<TS, TI, TR>::context_key_type &intruders, std::unordered_set<TR> &result) const;
std::pair<bool, db::CellInstArray> effective_instance (local_processor_contexts<TS, TI, TR> &contexts, db::cell_index_type subject_cell_index, db::cell_index_type intruder_cell_index, const db::ICplxTrans &ti2s, db::Coord dist) const;
bool subject_cell_is_breakout (db::cell_index_type ci) const
{
return mp_subject_breakout_cells && mp_subject_breakout_cells->find (ci) != mp_subject_breakout_cells->end ();
}
bool intruder_cell_is_breakout (db::cell_index_type ci) const
{
return mp_intruder_breakout_cells && mp_intruder_breakout_cells->find (ci) != mp_intruder_breakout_cells->end ();
}
};
}

View File

@ -75,7 +75,7 @@ std::string NetlistDeviceExtractorError::to_string () const
// NetlistDeviceExtractor implementation
NetlistDeviceExtractor::NetlistDeviceExtractor (const std::string &name)
: mp_layout (0), m_cell_index (0), m_device_scaling (1.0), mp_circuit (0)
: mp_layout (0), m_cell_index (0), mp_breakout_cells (0), m_device_scaling (1.0), mp_circuit (0)
{
m_name = name;
m_terminal_id_propname_id = 0;
@ -184,13 +184,13 @@ void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, unsigned int layo
}
extract_without_initialize (dss.layout (layout_index), dss.initial_cell (layout_index), clusters, layers, device_scaling);
extract_without_initialize (dss.layout (layout_index), dss.initial_cell (layout_index), clusters, layers, device_scaling, dss.breakout_cells (layout_index));
}
void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const std::vector<unsigned int> &layers, db::Netlist *nl, hier_clusters_type &clusters, double device_scaling)
void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const std::vector<unsigned int> &layers, db::Netlist *nl, hier_clusters_type &clusters, double device_scaling, const std::set<db::cell_index_type> *breakout_cells)
{
initialize (nl);
extract_without_initialize (layout, cell, clusters, layers, device_scaling);
extract_without_initialize (layout, cell, clusters, layers, device_scaling, breakout_cells);
}
namespace {
@ -203,7 +203,7 @@ struct ExtractorCacheValueType {
}
void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers, double device_scaling)
void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers, double device_scaling, const std::set<db::cell_index_type> *breakout_cells)
{
tl_assert (layers.size () == m_layer_definitions.size ());
@ -214,6 +214,7 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db:
m_layers = layers;
mp_clusters = &clusters;
m_device_scaling = device_scaling;
mp_breakout_cells = breakout_cells;
// terminal properties are kept in a property with the terminal_property_name name
m_terminal_id_propname_id = mp_layout->properties_repository ().prop_name_id (terminal_id_property_name ());
@ -246,7 +247,7 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db:
db::Connectivity device_conn = get_connectivity (layout, layers);
db::hier_clusters<shape_type> device_clusters;
device_clusters.build (layout, cell, shape_iter_flags, device_conn);
device_clusters.build (layout, cell, shape_iter_flags, device_conn, 0, breakout_cells);
tl::SelfTimer timer (tl::verbosity () >= 21, tl::to_string (tr ("Extracting devices")));

View File

@ -263,7 +263,7 @@ public:
*
* NOTE: The extractor expects "PolygonRef" type layers.
*/
void extract (Layout &layout, Cell &cell, const std::vector<unsigned int> &layers, Netlist *netlist, hier_clusters_type &clusters, double device_scaling = 1.0);
void extract (Layout &layout, Cell &cell, const std::vector<unsigned int> &layers, Netlist *netlist, hier_clusters_type &clusters, double device_scaling = 1.0, const std::set<cell_index_type> *breakout_cells = 0);
/**
* @brief Extracts the devices from a list of regions
@ -533,6 +533,7 @@ private:
db::properties_id_type m_terminal_id_propname_id, m_device_id_propname_id, m_device_class_propname_id;
hier_clusters_type *mp_clusters;
db::cell_index_type m_cell_index;
const std::set<db::cell_index_type> *mp_breakout_cells;
double m_device_scaling;
db::Circuit *mp_circuit;
db::DeviceClass *mp_device_class;
@ -553,7 +554,7 @@ private:
*/
void initialize (db::Netlist *nl);
void extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers, double device_scaling);
void extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers, double device_scaling, const std::set<cell_index_type> *breakout_cells);
void push_new_devices (const Vector &disp_cache);
void push_cached_devices (const tl::vector<Device *> &cached_devices, const db::Vector &disp_cache, const db::Vector &new_disp);
};

View File

@ -22,10 +22,78 @@
#include "gsiDecl.h"
#include "dbDeepShapeStore.h"
#include "tlGlobPattern.h"
namespace gsi
{
static void set_or_add_breakout_cells (db::DeepShapeStore *dss, const std::string &pattern, bool add, unsigned int layout_index = std::numeric_limits<unsigned int>::max ())
{
// set or add for all
if (layout_index == std::numeric_limits<unsigned int>::max ()) {
for (unsigned int l = 0; l < dss->layouts (); ++l) {
set_or_add_breakout_cells (dss, pattern, add, l);
}
return;
}
std::set<db::cell_index_type> cc;
if (! pattern.empty ()) {
tl::GlobPattern p (pattern);
const db::Layout &ly = dss->layout (layout_index);
for (db::Layout::const_iterator ci = ly.begin (); ci != ly.end (); ++ci) {
if (p.match (ly.cell_name (ci->cell_index ()))) {
cc.insert (ci->cell_index ());
}
}
}
if (! add) {
dss->clear_breakout_cells (layout_index);
}
if (! cc.empty ()) {
dss->add_breakout_cells (layout_index, cc);
}
}
static void clear_breakout_cells (db::DeepShapeStore *dss)
{
set_or_add_breakout_cells (dss, std::string (), false);
}
static void set_breakout_cells (db::DeepShapeStore *dss, unsigned int layout_index, const std::vector<db::cell_index_type> &cc)
{
std::set<db::cell_index_type> cs (cc.begin (), cc.end ());
dss->set_breakout_cells (layout_index, cs);
}
static void set_breakout_cells2 (db::DeepShapeStore *dss, unsigned int layout_index, const std::string &pattern)
{
set_or_add_breakout_cells (dss, pattern, false, layout_index);
}
static void set_breakout_cells3 (db::DeepShapeStore *dss, const std::string &pattern)
{
set_or_add_breakout_cells (dss, pattern, false);
}
static void add_breakout_cells (db::DeepShapeStore *dss, unsigned int layout_index, const std::vector<db::cell_index_type> &cc)
{
std::set<db::cell_index_type> cs (cc.begin (), cc.end ());
dss->add_breakout_cells (layout_index, cs);
}
static void add_breakout_cells2 (db::DeepShapeStore *dss, unsigned int layout_index, const std::string &pattern)
{
set_or_add_breakout_cells (dss, pattern, true, layout_index);
}
static void add_breakout_cells3 (db::DeepShapeStore *dss, const std::string &pattern)
{
set_or_add_breakout_cells (dss, pattern, true);
}
Class<db::DeepShapeStore> decl_dbDeepShapeStore ("db", "DeepShapeStore",
gsi::method ("instance_count", &db::DeepShapeStore::instance_count,
"@hide\n"
@ -84,6 +152,82 @@ Class<db::DeepShapeStore> decl_dbDeepShapeStore ("db", "DeepShapeStore",
) +
gsi::method ("text_enlargement", &db::DeepShapeStore::text_enlargement,
"@brief Gets the text enlargement value.\n"
) +
gsi::method ("clear_breakout_cells", &db::DeepShapeStore::clear_breakout_cells, gsi::arg ("layout_index"),
"@brief Clears the breakout cells\n"
"Breakout cells are a feature by which hierarchy handling can be disabled for specific cells. "
"If cells are specified as breakout cells, they don't interact with neighbor or parent cells, hence "
"are virtually isolated. Breakout cells are useful to shortcut hierarchy evaluation for cells which "
"are otherwise difficult to handle. An example are memory array cells with overlaps to their neighbors: "
"a precise handling of such cells would generate variants and the boundary of the array. Although precise, "
"this behavior leads to partial flattening and propagation of shapes. In consequence, this will also "
"result in wrong device detection in LVS applications. In such cases, these array cells can be declared "
"'breakout cells' which makes them isolated entities and variant generation does not happen.\n"
"\n"
"See also \\set_breakout_cells and \\add_breakout_cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("clear_breakout_cells", &clear_breakout_cells,
"@brief Clears the breakout cells\n"
"See the other variant of \\clear_breakout_cells for details.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("set_breakout_cells", &set_breakout_cells, gsi::arg ("layout_index"), gsi::arg ("cells"),
"@brief Sets the breakout cell list (as cell indexes) for the given layout inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("set_breakout_cells", &set_breakout_cells2, gsi::arg ("layout_index"), gsi::arg ("pattern"),
"@brief Sets the breakout cell list (as cell name pattern) for the given layout inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("set_breakout_cells", &set_breakout_cells3, gsi::arg ("pattern"),
"@brief Sets the breakout cell list (as cell name pattern) for the all layouts inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("add_breakout_cells", &add_breakout_cells, gsi::arg ("layout_index"), gsi::arg ("cells"),
"@brief Adds cell indexes to the breakout cell list for the given layout inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("add_breakout_cell", &add_breakout_cells, gsi::arg ("layout_index"), gsi::arg ("cell_index"),
"@brief Adds a cell indexe to the breakout cell list for the given layout inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("add_breakout_cells", &add_breakout_cells2, gsi::arg ("layout_index"), gsi::arg ("pattern"),
"@brief Adds cells (given by a cell name pattern) to the breakout cell list for the given layout inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method_ext ("add_breakout_cells", &add_breakout_cells3, gsi::arg ("pattern"),
"@brief Adds cells (given by a cell name pattern) to the breakout cell list to all layouts inside the store\n"
"See \\clear_breakout_cells for an explanation of breakout cells.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method ("push_state", &db::DeepShapeStore::push_state,
"@brief Pushes the store's state on the state state\n"
"This will save the stores state (\\threads, \\max_vertex_count, \\max_area_ratio, breakout cells ...) on "
"the state stack. \\pop_state can be used to restore the state.\n"
"\n"
"This method has been added in version 0.26.1\n"
) +
gsi::method ("pop_state", &db::DeepShapeStore::pop_state,
"@brief Restores the store's state on the state state\n"
"This will restore the state pushed by \\push_state.\n"
"\n"
"This method has been added in version 0.26.1\n"
),
"@brief An opaque layout heap for the deep region processor\n"
"\n"

View File

@ -35,6 +35,8 @@
#include "tlGlobPattern.h"
#include <memory>
#include <vector>
#include <set>
namespace gsi
{
@ -801,7 +803,7 @@ Class<db::Region> decl_Region ("db", "Region",
"See \\strict_handling= for a description of this attribute.\n"
"\n"
"This method has been introduced in version 0.23.2."
) +
) +
method ("min_coherence=", &db::Region::set_min_coherence, gsi::arg ("f"),
"@brief Enable or disable minimum coherence\n"
"If minimum coherence is set, the merge operations (explicit merge with \\merge or\n"