mirror of https://github.com/KLayout/klayout.git
WIP: provide a way to report user properties to RDB, added antenna rule measurements as user properties.
This commit is contained in:
parent
2cb3e037a9
commit
e4131b45a3
|
|
@ -1366,10 +1366,38 @@ compute_area_and_perimeter_of_net_shapes (const db::hier_clusters<db::NetShape>
|
||||||
perimeter = ap_collector.perimeter ();
|
perimeter = ap_collector.perimeter ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class AntennaShapeGenerator
|
||||||
|
: public PolygonSink
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AntennaShapeGenerator (db::Layout *layout, db::Shapes &shapes, db::properties_id_type prop_id)
|
||||||
|
: PolygonSink (), mp_layout (layout), mp_shapes (&shapes), m_prop_id (prop_id)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
virtual void put (const db::Polygon &polygon)
|
||||||
|
{
|
||||||
|
if (m_prop_id != 0) {
|
||||||
|
mp_shapes->insert (db::PolygonRefWithProperties (db::PolygonRef (polygon, mp_layout->shape_repository ()), m_prop_id));
|
||||||
|
} else {
|
||||||
|
mp_shapes->insert (db::PolygonRef (polygon, mp_layout->shape_repository ()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
db::Layout *mp_layout;
|
||||||
|
db::Shapes *mp_shapes;
|
||||||
|
db::properties_id_type m_prop_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static db::Point
|
static db::Point
|
||||||
get_merged_shapes_of_net (const db::hier_clusters<db::NetShape> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, db::Shapes &shapes)
|
get_merged_shapes_of_net (const db::hier_clusters<db::NetShape> &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, db::Layout *layout, db::Shapes &shapes, db::properties_id_type prop_id)
|
||||||
{
|
{
|
||||||
db::Point ref;
|
db::Point ref;
|
||||||
|
bool any_ref = false;
|
||||||
db::EdgeProcessor ep;
|
db::EdgeProcessor ep;
|
||||||
|
|
||||||
// count vertices and reserve space
|
// count vertices and reserve space
|
||||||
|
|
@ -1386,7 +1414,10 @@ get_merged_shapes_of_net (const db::hier_clusters<db::NetShape> &clusters, db::c
|
||||||
db::PolygonRef::polygon_edge_iterator e = pr.begin_edge ();
|
db::PolygonRef::polygon_edge_iterator e = pr.begin_edge ();
|
||||||
if (! e.at_end ()) {
|
if (! e.at_end ()) {
|
||||||
// pick one reference point for the label
|
// pick one reference point for the label
|
||||||
ref = (*e).p1 ();
|
if (! any_ref && (*e).p1 () < ref) {
|
||||||
|
ref = (*e).p1 ();
|
||||||
|
any_ref = true;
|
||||||
|
}
|
||||||
ep.insert (pr, ++p);
|
ep.insert (pr, ++p);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1394,7 +1425,7 @@ get_merged_shapes_of_net (const db::hier_clusters<db::NetShape> &clusters, db::c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db::ShapeGenerator sg (shapes);
|
db::AntennaShapeGenerator sg (layout, shapes, prop_id);
|
||||||
db::PolygonGenerator pg (sg, false);
|
db::PolygonGenerator pg (sg, false);
|
||||||
db::SimpleMerge op;
|
db::SimpleMerge op;
|
||||||
ep.process (pg, op);
|
ep.process (pg, op);
|
||||||
|
|
@ -1402,52 +1433,51 @@ get_merged_shapes_of_net (const db::hier_clusters<db::NetShape> &clusters, db::c
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string
|
static std::vector<std::pair<std::string, tl::Variant> >
|
||||||
create_antenna_msg (double agate, db::Polygon::area_type agate_int, double gate_area_factor, db::Polygon::perimeter_type pgate_int, double gate_perimeter_factor,
|
create_antenna_values (double agate, db::Polygon::area_type agate_int, double gate_area_factor, db::Polygon::perimeter_type pgate_int, double gate_perimeter_factor,
|
||||||
double ametal, db::Polygon::area_type ametal_int, double metal_area_factor, db::Polygon::perimeter_type pmetal_int, double metal_perimeter_factor,
|
double ametal, db::Polygon::area_type ametal_int, double metal_area_factor, db::Polygon::perimeter_type pmetal_int, double metal_perimeter_factor,
|
||||||
const std::vector<std::pair<const db::Region *, double> > &diodes,
|
const std::vector<std::pair<const db::Region *, double> > &diodes,
|
||||||
const std::vector<db::Polygon::area_type> &adiodes_int,
|
const std::vector<db::Polygon::area_type> &adiodes_int,
|
||||||
double r, double ratio, double dbu)
|
double r, double ratio, double dbu)
|
||||||
{
|
{
|
||||||
std::string msg;
|
std::vector<std::pair<std::string, tl::Variant> > values;
|
||||||
msg += tl::sprintf ("agate_eff: %.12g, ", agate);
|
|
||||||
|
values.push_back (std::make_pair ("agate_eff", agate));
|
||||||
if (fabs (gate_area_factor) > 1e-6) {
|
if (fabs (gate_area_factor) > 1e-6) {
|
||||||
msg += tl::sprintf ("agate: %.12g, agate_factor: %.12g, ", agate_int * dbu * dbu, gate_area_factor);
|
values.push_back (std::make_pair ("agate", agate_int * dbu * dbu));
|
||||||
|
values.push_back (std::make_pair ("agate_factor", gate_area_factor));
|
||||||
}
|
}
|
||||||
if (fabs (gate_perimeter_factor) > 1e-6) {
|
if (fabs (gate_perimeter_factor) > 1e-6) {
|
||||||
msg += tl::sprintf ("pgate: %.12g, pgate_factor: %.12g, ", pgate_int * dbu * dbu, gate_perimeter_factor);
|
values.push_back (std::make_pair ("pgate", pgate_int * dbu));
|
||||||
|
values.push_back (std::make_pair ("pgate_factor", gate_perimeter_factor));
|
||||||
}
|
}
|
||||||
msg += tl::sprintf ("ametal_eff: %.12g, ", ametal);
|
values.push_back (std::make_pair ("ametal_eff", ametal));
|
||||||
if (fabs (metal_area_factor) > 1e-6) {
|
if (fabs (metal_area_factor) > 1e-6) {
|
||||||
msg += tl::sprintf ("ametal: %.12g, ametal_factor: %.12g, ", ametal_int * dbu * dbu, metal_area_factor);
|
values.push_back (std::make_pair ("ametal", ametal_int * dbu * dbu));
|
||||||
|
values.push_back (std::make_pair ("ametal_factor", metal_area_factor));
|
||||||
}
|
}
|
||||||
if (fabs (metal_perimeter_factor) > 1e-6) {
|
if (fabs (metal_perimeter_factor) > 1e-6) {
|
||||||
msg += tl::sprintf ("pmetal: %.12g, pmetal_factor: %.12g, ", pmetal_int * dbu * dbu, metal_perimeter_factor);
|
values.push_back (std::make_pair ("pmetal", pmetal_int * dbu));
|
||||||
|
values.push_back (std::make_pair ("pmetal_factor", metal_perimeter_factor));
|
||||||
}
|
}
|
||||||
if (! adiodes_int.empty ()) {
|
if (! adiodes_int.empty ()) {
|
||||||
msg += "adiodes: [";
|
tl::Variant adiodes;
|
||||||
for (auto d = adiodes_int.begin (); d != adiodes_int.end (); ++d) {
|
for (auto d = adiodes_int.begin (); d != adiodes_int.end (); ++d) {
|
||||||
if (d != adiodes_int.begin ()) {
|
adiodes.push (*d * dbu * dbu);
|
||||||
msg += ", ";
|
|
||||||
}
|
|
||||||
msg += tl::sprintf ("%.12g", *d * dbu * dbu);
|
|
||||||
}
|
}
|
||||||
msg += "], ";
|
values.push_back (std::make_pair ("adiodes", adiodes));
|
||||||
}
|
}
|
||||||
if (! diodes.empty ()) {
|
if (! diodes.empty ()) {
|
||||||
msg += "diode_factors: [";
|
tl::Variant diode_factors;
|
||||||
for (auto d = diodes.begin (); d != diodes.end (); ++d) {
|
for (auto d = diodes.begin (); d != diodes.end (); ++d) {
|
||||||
if (d != diodes.begin ()) {
|
diode_factors.push (d->second);
|
||||||
msg += ", ";
|
|
||||||
}
|
|
||||||
msg += tl::sprintf ("%.12g", d->second);
|
|
||||||
}
|
}
|
||||||
msg += "], ";
|
values.push_back (std::make_pair ("diode_factors", diode_factors));
|
||||||
}
|
}
|
||||||
msg += tl::sprintf ("ratio: %.12g, ", ametal / agate);
|
values.push_back (std::make_pair ("ratio", ametal / agate));
|
||||||
msg += tl::sprintf ("max_ratio_eff: %.12g, ", r);
|
values.push_back (std::make_pair ("max_ratio_eff", r));
|
||||||
msg += tl::sprintf ("max_ratio: %.12g", ratio);
|
values.push_back (std::make_pair ("max_ratio", ratio));
|
||||||
return msg;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_area_factor, double gate_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector<std::pair<const db::Region *, double> > &diodes, db::Texts *values)
|
db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_area_factor, double gate_perimeter_factor, const db::Region &metal, double metal_area_factor, double metal_perimeter_factor, double ratio, const std::vector<std::pair<const db::Region *, double> > &diodes, db::Texts *values)
|
||||||
|
|
@ -1538,25 +1568,50 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, double gate_a
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tl::verbosity () >= 50) {
|
if (tl::verbosity () >= 50) {
|
||||||
tl::info << "cell [" << ly.cell_name (*cid) << "]: " <<
|
std::vector<std::pair<std::string, tl::Variant> > antenna_values =
|
||||||
create_antenna_msg (agate, agate_int, gate_area_factor, pgate_int, gate_perimeter_factor,
|
create_antenna_values (agate, agate_int, gate_area_factor, pgate_int, gate_perimeter_factor,
|
||||||
ametal, ametal_int, metal_area_factor, pmetal_int, metal_perimeter_factor,
|
ametal, ametal_int, metal_area_factor, pmetal_int, metal_perimeter_factor,
|
||||||
diodes, adiodes_int, r, ratio, dbu);
|
diodes, adiodes_int, r, ratio, dbu);
|
||||||
|
tl::info << "cell [" << ly.cell_name (*cid) << "]: ";
|
||||||
|
for (auto v = antenna_values.begin (); v != antenna_values.end (); ++v) {
|
||||||
|
tl::info << " " << v->first << ": " << v->second.to_string ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ametal / agate > r + db::epsilon) {
|
if (ametal / agate > r + db::epsilon) {
|
||||||
|
|
||||||
db::Shapes &shapes = ly.cell (*cid).shapes (dl.layer ());
|
db::Shapes &shapes = ly.cell (*cid).shapes (dl.layer ());
|
||||||
db::Point ref = get_merged_shapes_of_net (m_net_clusters, *cid, *c, layer_of (metal), shapes);
|
|
||||||
|
std::vector<std::pair<std::string, tl::Variant> > antenna_values =
|
||||||
|
create_antenna_values (agate, agate_int, gate_area_factor, pgate_int, gate_perimeter_factor,
|
||||||
|
ametal, ametal_int, metal_area_factor, pmetal_int, metal_perimeter_factor,
|
||||||
|
diodes, adiodes_int, r, ratio, dbu);
|
||||||
|
|
||||||
|
db::properties_id_type prop_id = 0;
|
||||||
|
if (! values) {
|
||||||
|
db::PropertiesRepository::properties_set ps;
|
||||||
|
for (auto v = antenna_values.begin (); v != antenna_values.end (); ++v) {
|
||||||
|
ps.insert (std::make_pair (ly.properties_repository ().prop_name_id (v->first), v->second));
|
||||||
|
}
|
||||||
|
prop_id = ly.properties_repository ().properties_id (ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
db::Point ref = get_merged_shapes_of_net (m_net_clusters, *cid, *c, layer_of (metal), &ly, shapes, prop_id);
|
||||||
|
|
||||||
if (values) {
|
if (values) {
|
||||||
|
|
||||||
// generate a data string with the details of the antenna computation (intentionally like JSON)
|
|
||||||
std::string msg = create_antenna_msg (agate, agate_int, gate_area_factor, pgate_int, gate_perimeter_factor,
|
|
||||||
ametal, ametal_int, metal_area_factor, pmetal_int, metal_perimeter_factor,
|
|
||||||
diodes, adiodes_int, r, ratio, dbu);
|
|
||||||
|
|
||||||
db::Shapes &shapesv = ly.cell (*cid).shapes (dlv.layer ());
|
db::Shapes &shapesv = ly.cell (*cid).shapes (dlv.layer ());
|
||||||
|
|
||||||
|
std::string msg;
|
||||||
|
for (auto v = antenna_values.begin (); v != antenna_values.end (); ++v) {
|
||||||
|
if (v != antenna_values.begin ()) {
|
||||||
|
msg += ", ";
|
||||||
|
}
|
||||||
|
msg += v->first;
|
||||||
|
msg += ": ";
|
||||||
|
msg += v->second.to_string ();
|
||||||
|
}
|
||||||
|
|
||||||
shapesv.insert (db::Text (msg, db::Trans (ref - db::Point ())));
|
shapesv.insert (db::Text (msg, db::Trans (ref - db::Point ())));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -248,42 +248,32 @@ ItemRefUnwrappingIterator category_items_end (const rdb::Category *cat)
|
||||||
return cat->database ()->items_by_category (cat->id ()).second;
|
return cat->database ()->items_by_category (cat->id ()).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scan_layer1 (rdb::Category *cat, const db::Layout &layout, unsigned int layer)
|
static void scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from_cell, int levels, bool with_properties)
|
||||||
{
|
{
|
||||||
rdb::scan_layer (cat, layout, layer);
|
rdb::scan_layer (cat, layout, layer, from_cell, levels, with_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scan_layer2 (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from_cell)
|
static void scan_shapes (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat, bool with_properties)
|
||||||
{
|
{
|
||||||
rdb::scan_layer (cat, layout, layer, from_cell);
|
rdb::scan_layer (cat, iter, flat, with_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scan_layer3 (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from_cell, int levels)
|
static void scan_region (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Region ®ion, bool flat, bool with_properties)
|
||||||
{
|
|
||||||
rdb::scan_layer (cat, layout, layer, from_cell, levels);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void scan_shapes (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat)
|
|
||||||
{
|
|
||||||
rdb::scan_layer (cat, iter, flat);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void scan_region (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Region ®ion, bool flat)
|
|
||||||
{
|
{
|
||||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = region.begin_iter ();
|
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = region.begin_iter ();
|
||||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat);
|
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat, with_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scan_edges (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Edges &edges, bool flat)
|
static void scan_edges (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::Edges &edges, bool flat, bool with_properties)
|
||||||
{
|
{
|
||||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = edges.begin_iter ();
|
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = edges.begin_iter ();
|
||||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat);
|
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat, with_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scan_edge_pairs (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::EdgePairs &edge_pairs, bool flat)
|
static void scan_edge_pairs (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::EdgePairs &edge_pairs, bool flat, bool with_properties)
|
||||||
{
|
{
|
||||||
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = edge_pairs.begin_iter ();
|
std::pair<db::RecursiveShapeIterator, db::ICplxTrans> it = edge_pairs.begin_iter ();
|
||||||
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat);
|
rdb::scan_layer (cat, cell, trans * it.second, it.first, flat, with_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
|
Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
|
||||||
|
|
@ -303,7 +293,7 @@ Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.23."
|
"This method has been introduced in version 0.23."
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("scan_shapes", &scan_shapes, gsi::arg ("iter"), gsi::arg ("flat", false),
|
gsi::method_ext ("scan_shapes", &scan_shapes, gsi::arg ("iter"), gsi::arg ("flat", false), gsi::arg ("with_properties", true),
|
||||||
"@brief Scans the polygon or edge shapes from the shape iterator into the category\n"
|
"@brief Scans the polygon or edge shapes from the shape iterator into the category\n"
|
||||||
"Creates RDB items for each polygon or edge shape read from the iterator and puts them into this category.\n"
|
"Creates RDB items for each polygon or edge shape read from the iterator and puts them into this category.\n"
|
||||||
"A similar, but lower-level method is \\ReportDatabase#create_items with a \\RecursiveShapeIterator argument.\n"
|
"A similar, but lower-level method is \\ReportDatabase#create_items with a \\RecursiveShapeIterator argument.\n"
|
||||||
|
|
@ -311,9 +301,11 @@ Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
|
||||||
"if the \\flat argument is false. In this case, the hierarchy the recursive shape iterator traverses is "
|
"if the \\flat argument is false. In this case, the hierarchy the recursive shape iterator traverses is "
|
||||||
"copied into the report database using sample references.\n"
|
"copied into the report database using sample references.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.23. The flat mode argument has been added in version 0.26.\n"
|
"If 'with_properties' is true, user properties will be turned into tagged values as well.\n"
|
||||||
|
"\n"
|
||||||
|
"This method has been introduced in version 0.23. The flat mode argument has been added in version 0.26. The 'with_properties' argument has been added in version 0.28.\n"
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("scan_collection", &scan_region, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("region"), gsi::arg ("flat", false),
|
gsi::method_ext ("scan_collection", &scan_region, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("region"), gsi::arg ("flat", false), gsi::arg ("with_properties", true),
|
||||||
"@brief Turns the given region into a hierarchical or flat report database\n"
|
"@brief Turns the given region into a hierarchical or flat report database\n"
|
||||||
"The exact behavior depends on the nature of the region. If the region is a hierarchical (original or deep) region "
|
"The exact behavior depends on the nature of the region. If the region is a hierarchical (original or deep) region "
|
||||||
"and the 'flat' argument is false, this method will produce a hierarchical report database in the given category. "
|
"and the 'flat' argument is false, this method will produce a hierarchical report database in the given category. "
|
||||||
|
|
@ -325,44 +317,36 @@ Class<rdb::Category> decl_RdbCategory ("rdb", "RdbCategory",
|
||||||
"\n"
|
"\n"
|
||||||
"The transformation argument needs to supply the dbu-to-micron transformation.\n"
|
"The transformation argument needs to supply the dbu-to-micron transformation.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.26.\n"
|
"If 'with_properties' is true, user properties will be turned into tagged values as well.\n"
|
||||||
|
"\n"
|
||||||
|
"This method has been introduced in version 0.26. The 'with_properties' argument has been added in version 0.28.\n"
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("scan_collection", &scan_edges, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edges"), gsi::arg ("flat", false),
|
gsi::method_ext ("scan_collection", &scan_edges, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edges"), gsi::arg ("flat", false), gsi::arg ("with_properties", true),
|
||||||
"@brief Turns the given edge collection into a hierarchical or flat report database\n"
|
"@brief Turns the given edge collection into a hierarchical or flat report database\n"
|
||||||
"This a another flavour of \\scan_collection accepting an edge collection.\n"
|
"This a another flavour of \\scan_collection accepting an edge collection.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.26.\n"
|
"If 'with_properties' is true, user properties will be turned into tagged values as well.\n"
|
||||||
|
"\n"
|
||||||
|
"This method has been introduced in version 0.26. The 'with_properties' argument has been added in version 0.28.\n"
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("scan_collection", &scan_edge_pairs, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edge_pairs"), gsi::arg ("flat", false),
|
gsi::method_ext ("scan_collection", &scan_edge_pairs, gsi::arg ("cell"), gsi::arg ("trans"), gsi::arg ("edge_pairs"), gsi::arg ("flat", false), gsi::arg ("with_properties", true),
|
||||||
"@brief Turns the given edge pair collection into a hierarchical or flat report database\n"
|
"@brief Turns the given edge pair collection into a hierarchical or flat report database\n"
|
||||||
"This a another flavour of \\scan_collection accepting an edge pair collection.\n"
|
"This a another flavour of \\scan_collection accepting an edge pair collection.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.26.\n"
|
"If 'with_properties' is true, user properties will be turned into tagged values as well.\n"
|
||||||
) +
|
|
||||||
gsi::method_ext ("scan_layer", &scan_layer1, gsi::arg ("layout"), gsi::arg ("layer"),
|
|
||||||
"@brief Scans a layer from a layout into this category\n"
|
|
||||||
"Creates RDB items for each polygon or edge shape read from the each cell in the layout on the given layer and puts them into this category.\n"
|
|
||||||
"New cells will be generated for every cell encountered in the layout.\n"
|
|
||||||
"Other settings like database unit, description, top cell etc. are not made in the RDB.\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.23.\n"
|
"This method has been introduced in version 0.26. The 'with_properties' argument has been added in version 0.28.\n"
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("scan_layer", &scan_layer2, gsi::arg ("layout"), gsi::arg ("layer"), gsi::arg ("cell"),
|
gsi::method_ext ("scan_layer", &scan_layer, gsi::arg ("layout"), gsi::arg ("layer"), gsi::arg ("cell", (const db::Cell *) 0, "nil"), gsi::arg ("levels", -1), gsi::arg ("with_properties", true),
|
||||||
"@brief Scans a layer from a layout into this category, starting with a given cell\n"
|
|
||||||
"Creates RDB items for each polygon or edge shape read from the cell and it's children in the layout on the given layer and puts them into this category.\n"
|
|
||||||
"New cells will be generated when required.\n"
|
|
||||||
"Other settings like database unit, description, top cell etc. are not made in the RDB.\n"
|
|
||||||
"\n"
|
|
||||||
"This method has been introduced in version 0.23.\n"
|
|
||||||
) +
|
|
||||||
gsi::method_ext ("scan_layer", &scan_layer3, gsi::arg ("layout"), gsi::arg ("layer"), gsi::arg ("cell"), gsi::arg ("levels"),
|
|
||||||
"@brief Scans a layer from a layout into this category, starting with a given cell and a depth specification\n"
|
"@brief Scans a layer from a layout into this category, starting with a given cell and a depth specification\n"
|
||||||
"Creates RDB items for each polygon or edge shape read from the cell and it's children in the layout on the given layer and puts them into this category.\n"
|
"Creates RDB items for each polygon or edge shape read from the cell and it's children in the layout on the given layer and puts them into this category.\n"
|
||||||
"New cells will be generated when required.\n"
|
"New cells will be generated when required.\n"
|
||||||
"\"levels\" is the number of hierarchy levels to take the child cells from. 0 means to use only \"cell\" and don't descend, -1 means \"all levels\".\n"
|
"\"levels\" is the number of hierarchy levels to take the child cells from. 0 means to use only \"cell\" and don't descend, -1 means \"all levels\".\n"
|
||||||
"Other settings like database unit, description, top cell etc. are not made in the RDB.\n"
|
"Other settings like database unit, description, top cell etc. are not made in the RDB.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.23.\n"
|
"If 'with_properties' is true, user properties will be turned into tagged values as well.\n"
|
||||||
|
"\n"
|
||||||
|
"This method has been introduced in version 0.23. The 'with_properties' argument has been added in version 0.28.\n"
|
||||||
) +
|
) +
|
||||||
gsi::method ("name", &rdb::Category::name,
|
gsi::method ("name", &rdb::Category::name,
|
||||||
"@brief Gets the category name\n"
|
"@brief Gets the category name\n"
|
||||||
|
|
@ -1209,7 +1193,7 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
||||||
"\n"
|
"\n"
|
||||||
"This convenience method has been added in version 0.25.\n"
|
"This convenience method has been added in version 0.25.\n"
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("create_items", &rdb::create_items_from_iterator, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("iter"),
|
gsi::method_ext ("create_items", &rdb::create_items_from_iterator, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("iter"), gsi::arg ("with_properties", true),
|
||||||
"@brief Creates new items from a shape iterator\n"
|
"@brief Creates new items from a shape iterator\n"
|
||||||
"This method takes the shapes from the given iterator and produces items from them.\n"
|
"This method takes the shapes from the given iterator and produces items from them.\n"
|
||||||
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
||||||
|
|
@ -1217,39 +1201,42 @@ Class<rdb::Database> decl_ReportDatabase ("rdb", "ReportDatabase",
|
||||||
"A similar method, which is intended for production of polygon or edge error layers and also provides hierarchical database "
|
"A similar method, which is intended for production of polygon or edge error layers and also provides hierarchical database "
|
||||||
"construction is \\RdbCategory#scan_shapes.\n"
|
"construction is \\RdbCategory#scan_shapes.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.25.3.\n"
|
"This method has been introduced in version 0.25.3. The 'with_properties' argument has been added in version 0.28.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||||
"@param category_id The ID of the category to which the item is associated\n"
|
"@param category_id The ID of the category to which the item is associated\n"
|
||||||
"@param iter The iterator (a \\RecursiveShapeIterator object) from which to take the items\n"
|
"@param iter The iterator (a \\RecursiveShapeIterator object) from which to take the items\n"
|
||||||
|
"@param with_properties If true, user properties will be turned into tagged values as well\n"
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("create_item", &rdb::create_item_from_shape, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shape"),
|
gsi::method_ext ("create_item", &rdb::create_item_from_shape, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shape"), gsi::arg ("with_properties", true),
|
||||||
"@brief Creates a new item from a single shape\n"
|
"@brief Creates a new item from a single shape\n"
|
||||||
"This method produces an item from the given shape.\n"
|
"This method produces an item from the given shape.\n"
|
||||||
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
||||||
"converts them to a corresponding item. The transformation argument can be used to "
|
"converts them to a corresponding item. The transformation argument can be used to "
|
||||||
"supply the transformation that applies the database unit for example.\n"
|
"supply the transformation that applies the database unit for example.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.25.3.\n"
|
"This method has been introduced in version 0.25.3. The 'with_properties' argument has been added in version 0.28.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||||
"@param category_id The ID of the category to which the item is associated\n"
|
"@param category_id The ID of the category to which the item is associated\n"
|
||||||
"@param shape The shape to take the geometrical object from\n"
|
"@param shape The shape to take the geometrical object from\n"
|
||||||
"@param trans The transformation to apply\n"
|
"@param trans The transformation to apply\n"
|
||||||
|
"@param with_properties If true, user properties will be turned into tagged values as well\n"
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("create_items", &rdb::create_items_from_shapes, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shapes"),
|
gsi::method_ext ("create_items", &rdb::create_items_from_shapes, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("shapes"), gsi::arg ("with_properties", true),
|
||||||
"@brief Creates new items from a shape container\n"
|
"@brief Creates new items from a shape container\n"
|
||||||
"This method takes the shapes from the given container and produces items from them.\n"
|
"This method takes the shapes from the given container and produces items from them.\n"
|
||||||
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
"It accepts various kind of shapes, such as texts, polygons, boxes and paths and "
|
||||||
"converts them to corresponding items. The transformation argument can be used to "
|
"converts them to corresponding items. The transformation argument can be used to "
|
||||||
"supply the transformation that applies the database unit for example.\n"
|
"supply the transformation that applies the database unit for example.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"This method has been introduced in version 0.25.3.\n"
|
"This method has been introduced in version 0.25.3. The 'with_properties' argument has been added in version 0.28.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"@param cell_id The ID of the cell to which the item is associated\n"
|
"@param cell_id The ID of the cell to which the item is associated\n"
|
||||||
"@param category_id The ID of the category to which the item is associated\n"
|
"@param category_id The ID of the category to which the item is associated\n"
|
||||||
"@param shapes The shape container from which to take the items\n"
|
"@param shapes The shape container from which to take the items\n"
|
||||||
"@param trans The transformation to apply\n"
|
"@param trans The transformation to apply\n"
|
||||||
|
"@param with_properties If true, user properties will be turned into tagged values as well\n"
|
||||||
) +
|
) +
|
||||||
gsi::method_ext ("create_items", &rdb::create_items_from_region, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("region"),
|
gsi::method_ext ("create_items", &rdb::create_items_from_region, gsi::arg ("cell_id"), gsi::arg ("category_id"), gsi::arg ("trans"), gsi::arg ("region"),
|
||||||
"@brief Creates new polygon items for the given cell/category combination\n"
|
"@brief Creates new polygon items for the given cell/category combination\n"
|
||||||
|
|
|
||||||
|
|
@ -860,9 +860,11 @@ public:
|
||||||
* @brief Add a value in a generic way
|
* @brief Add a value in a generic way
|
||||||
*/
|
*/
|
||||||
template <class V>
|
template <class V>
|
||||||
void add_value (const V &v)
|
ValueBase *add_value (const V &v, id_type tag_id = 0)
|
||||||
{
|
{
|
||||||
values ().add (new Value<V> (v));
|
ValueBase *value = new Value<V> (v);
|
||||||
|
values ().add (value, tag_id);
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace rdb
|
||||||
{
|
{
|
||||||
|
|
||||||
void
|
void
|
||||||
scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from, int levels)
|
scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from, int levels, bool with_properties)
|
||||||
{
|
{
|
||||||
rdb::Database *rdb = cat->database ();
|
rdb::Database *rdb = cat->database ();
|
||||||
if (! rdb) {
|
if (! rdb) {
|
||||||
|
|
@ -78,7 +78,7 @@ scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, co
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
create_items_from_shapes (rdb, rdb_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()), cell.shapes (layer));
|
create_items_from_shapes (rdb, rdb_cell->id (), cat->id (), db::CplxTrans (layout.dbu ()), cell.shapes (layer), with_properties);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,8 +92,8 @@ class CreateItemsRecursiveReceiver
|
||||||
: public db::RecursiveShapeReceiver
|
: public db::RecursiveShapeReceiver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CreateItemsRecursiveReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell)
|
CreateItemsRecursiveReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell, bool with_properties)
|
||||||
: mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell)
|
: mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell), m_with_properties (with_properties)
|
||||||
{
|
{
|
||||||
// just in case the iterator is non-hierarchical
|
// just in case the iterator is non-hierarchical
|
||||||
if (cell) {
|
if (cell) {
|
||||||
|
|
@ -159,7 +159,7 @@ public:
|
||||||
virtual void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans & /*always_apply*/, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
virtual void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans & /*always_apply*/, const db::ICplxTrans & /*trans*/, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||||
{
|
{
|
||||||
tl_assert (! m_cell_stack.empty ());
|
tl_assert (! m_cell_stack.empty ());
|
||||||
create_item_from_shape (mp_rdb, m_cell_stack.back ()->id (), mp_cat->id (), m_trans, shape);
|
create_item_from_shape (mp_rdb, m_cell_stack.back ()->id (), mp_cat->id (), m_trans, shape, m_with_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -169,6 +169,7 @@ public:
|
||||||
std::map<db::cell_index_type, const rdb::Cell *> m_id_to_cell;
|
std::map<db::cell_index_type, const rdb::Cell *> m_id_to_cell;
|
||||||
db::CplxTrans m_trans;
|
db::CplxTrans m_trans;
|
||||||
rdb::Cell *mp_rdb_cell;
|
rdb::Cell *mp_rdb_cell;
|
||||||
|
bool m_with_properties;
|
||||||
|
|
||||||
const rdb::Cell *cell_for_id (const db::Layout *layout, db::cell_index_type ci)
|
const rdb::Cell *cell_for_id (const db::Layout *layout, db::cell_index_type ci)
|
||||||
{
|
{
|
||||||
|
|
@ -187,8 +188,8 @@ class CreateItemsFlatReceiver
|
||||||
: public db::RecursiveShapeReceiver
|
: public db::RecursiveShapeReceiver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CreateItemsFlatReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell)
|
CreateItemsFlatReceiver (rdb::Category *cat, const db::CplxTrans &trans, rdb::Cell *cell, bool with_properties)
|
||||||
: mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell)
|
: mp_cat (cat), mp_rdb (cat->database ()), m_trans (trans), mp_rdb_cell (cell), m_with_properties (with_properties)
|
||||||
{
|
{
|
||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
@ -211,7 +212,7 @@ public:
|
||||||
|
|
||||||
virtual void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans & /*always_apply*/, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
virtual void shape (const db::RecursiveShapeIterator * /*iter*/, const db::Shape &shape, const db::ICplxTrans & /*always_apply*/, const db::ICplxTrans &trans, const db::Box & /*region*/, const box_tree_type * /*complex_region*/)
|
||||||
{
|
{
|
||||||
create_item_from_shape (mp_rdb, mp_rdb_cell->id (), mp_cat->id (), m_trans * trans, shape);
|
create_item_from_shape (mp_rdb, mp_rdb_cell->id (), mp_cat->id (), m_trans * trans, shape, m_with_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -219,23 +220,24 @@ public:
|
||||||
rdb::Database *mp_rdb;
|
rdb::Database *mp_rdb;
|
||||||
db::CplxTrans m_trans;
|
db::CplxTrans m_trans;
|
||||||
const rdb::Cell *mp_rdb_cell;
|
const rdb::Cell *mp_rdb_cell;
|
||||||
|
bool m_with_properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat)
|
scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat, bool with_properties)
|
||||||
{
|
{
|
||||||
if (! iter.top_cell () || ! iter.layout ()) {
|
if (! iter.top_cell () || ! iter.layout ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
db::CplxTrans trans (iter.layout ()->dbu ());
|
db::CplxTrans trans (iter.layout ()->dbu ());
|
||||||
scan_layer (cat, 0, trans, iter, flat);
|
scan_layer (cat, 0, trans, iter, flat, with_properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat)
|
scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat, bool with_properties)
|
||||||
{
|
{
|
||||||
if (! cat->database ()) {
|
if (! cat->database ()) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -243,9 +245,9 @@ scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, con
|
||||||
|
|
||||||
std::unique_ptr<db::RecursiveShapeReceiver> rec;
|
std::unique_ptr<db::RecursiveShapeReceiver> rec;
|
||||||
if (flat) {
|
if (flat) {
|
||||||
rec.reset (new CreateItemsFlatReceiver (cat, trans, cell));
|
rec.reset (new CreateItemsFlatReceiver (cat, trans, cell, with_properties));
|
||||||
} else {
|
} else {
|
||||||
rec.reset (new CreateItemsRecursiveReceiver (cat, trans, cell));
|
rec.reset (new CreateItemsRecursiveReceiver (cat, trans, cell, with_properties));
|
||||||
}
|
}
|
||||||
|
|
||||||
db::RecursiveShapeIterator (iter).push (rec.get ());
|
db::RecursiveShapeIterator (iter).push (rec.get ());
|
||||||
|
|
@ -253,37 +255,47 @@ scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, con
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter)
|
void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter, bool with_properties)
|
||||||
{
|
{
|
||||||
tl_assert (iter.layout ());
|
tl_assert (iter.layout ());
|
||||||
double dbu = iter.layout ()->dbu ();
|
double dbu = iter.layout ()->dbu ();
|
||||||
|
|
||||||
for (db::RecursiveShapeIterator i = iter; !i.at_end (); ++i) {
|
for (db::RecursiveShapeIterator i = iter; !i.at_end (); ++i) {
|
||||||
std::unique_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*i, db::CplxTrans (dbu) * i.trans ()));
|
create_item_from_shape (db, cell_id, cat_id, db::CplxTrans (dbu) * i.trans (), *i, with_properties);
|
||||||
if (value.get ()) {
|
|
||||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
|
||||||
item->values ().add (value.release ());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes)
|
void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes, bool with_properties)
|
||||||
{
|
{
|
||||||
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::All); !s.at_end (); ++s) {
|
for (db::Shapes::shape_iterator s = shapes.begin (db::ShapeIterator::All); !s.at_end (); ++s) {
|
||||||
std::unique_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (*s, trans));
|
create_item_from_shape (db, cell_id, cat_id, trans, *s, with_properties);
|
||||||
if (value.get ()) {
|
|
||||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
|
||||||
item->values ().add (value.release ());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape)
|
void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape, bool with_properties)
|
||||||
{
|
{
|
||||||
std::unique_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (shape, trans));
|
std::unique_ptr<rdb::ValueBase> value (rdb::ValueBase::create_from_shape (shape, trans));
|
||||||
if (value.get ()) {
|
if (! value.get ()) {
|
||||||
rdb::Item *item = db->create_item (cell_id, cat_id);
|
return;
|
||||||
item->values ().add (value.release ());
|
}
|
||||||
|
|
||||||
|
rdb::Item *item = db->create_item (cell_id, cat_id);
|
||||||
|
item->values ().add (value.release ());
|
||||||
|
|
||||||
|
// translate properties
|
||||||
|
if (with_properties && shape.has_prop_id () && shape.shapes () && shape.shapes ()->cell ()) {
|
||||||
|
|
||||||
|
const db::Layout *layout = shape.shapes ()->cell ()->layout ();
|
||||||
|
if (layout) {
|
||||||
|
|
||||||
|
auto ps = layout->properties_repository ().properties (shape.prop_id ());
|
||||||
|
for (auto i = ps.begin (); i != ps.end (); ++i) {
|
||||||
|
id_type tag_id = db->tags ().tag (layout->properties_repository ().prop_name (i->first).to_string (), true /*user tag*/).id ();
|
||||||
|
add_item_value (item, i->second, trans, tag_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -317,50 +329,97 @@ void create_items_from_edge_pairs (rdb::Database *db, rdb::id_type cell_id, rdb:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_item_value (rdb::Item *item, const tl::Variant &v, double dbu)
|
ValueBase *add_item_value (rdb::Item *item, const tl::Variant &v, const db::CplxTrans &trans, rdb::id_type tag_id)
|
||||||
{
|
{
|
||||||
if (dbu > 0 && v.is_user<db::Box> ()) {
|
if (v.is_user<db::Box> ()) {
|
||||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::Box> ());
|
return item->add_value (trans * v.to_user<db::Box> (), tag_id);
|
||||||
} else if (dbu > 0 && v.is_user<db::Point> ()) {
|
} else if (v.is_user<db::Point> ()) {
|
||||||
db::DPoint p = db::CplxTrans (dbu) * v.to_user<db::Point> ();
|
db::DPoint p = trans * v.to_user<db::Point> ();
|
||||||
item->add_value (db::DEdge (p, p));
|
return item->add_value (db::DEdge (p, p), tag_id);
|
||||||
} else if (dbu > 0 && v.is_user<db::Polygon> ()) {
|
} else if (v.is_user<db::Polygon> ()) {
|
||||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::Polygon> ());
|
return item->add_value (trans * v.to_user<db::Polygon> (), tag_id);
|
||||||
} else if (dbu > 0 && v.is_user<db::SimplePolygon> ()) {
|
} else if (v.is_user<db::SimplePolygon> ()) {
|
||||||
db::DPolygon p;
|
db::DPolygon p;
|
||||||
db::DSimplePolygon sp = db::CplxTrans (dbu) * v.to_user<db::SimplePolygon> ();
|
db::DSimplePolygon sp = trans * v.to_user<db::SimplePolygon> ();
|
||||||
p.assign_hull (sp.begin_hull (), sp.end_hull ());
|
p.assign_hull (sp.begin_hull (), sp.end_hull ());
|
||||||
item->add_value (p);
|
return item->add_value (p, tag_id);
|
||||||
} else if (dbu > 0 && v.is_user<db::Edge> ()) {
|
} else if (v.is_user<db::Edge> ()) {
|
||||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::Edge> ());
|
return item->add_value (trans * v.to_user<db::Edge> (), tag_id);
|
||||||
} else if (dbu > 0 && v.is_user<db::EdgePair> ()) {
|
} else if (v.is_user<db::EdgePair> ()) {
|
||||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::EdgePair> ());
|
return item->add_value (trans * v.to_user<db::EdgePair> (), tag_id);
|
||||||
} else if (dbu > 0 && v.is_user<db::Path> ()) {
|
} else if (v.is_user<db::Path> ()) {
|
||||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::Path> ());
|
return item->add_value (trans * v.to_user<db::Path> (), tag_id);
|
||||||
} else if (dbu > 0 && v.is_user<db::Text> ()) {
|
} else if (v.is_user<db::Text> ()) {
|
||||||
item->add_value (db::CplxTrans (dbu) * v.to_user<db::Text> ());
|
return item->add_value (trans * v.to_user<db::Text> (), tag_id);
|
||||||
} else if (v.is_user<db::DBox> ()) {
|
} else if (v.is_user<db::DBox> ()) {
|
||||||
item->add_value (v.to_user<db::DBox> ());
|
return item->add_value (v.to_user<db::DBox> (), tag_id);
|
||||||
} else if (v.is_user<db::DPoint> ()) {
|
} else if (v.is_user<db::DPoint> ()) {
|
||||||
db::DPoint p = v.to_user<db::DPoint> ();
|
db::DPoint p = v.to_user<db::DPoint> ();
|
||||||
item->add_value (db::DEdge (p, p));
|
return item->add_value (db::DEdge (p, p), tag_id);
|
||||||
} else if (v.is_user<db::DPolygon> ()) {
|
} else if (v.is_user<db::DPolygon> ()) {
|
||||||
item->add_value (v.to_user<db::DPolygon> ());
|
return item->add_value (v.to_user<db::DPolygon> (), tag_id);
|
||||||
} else if (v.is_user<db::DSimplePolygon> ()) {
|
} else if (v.is_user<db::DSimplePolygon> ()) {
|
||||||
db::DPolygon p;
|
db::DPolygon p;
|
||||||
db::DSimplePolygon sp = v.to_user<db::DSimplePolygon> ();
|
db::DSimplePolygon sp = v.to_user<db::DSimplePolygon> ();
|
||||||
p.assign_hull (sp.begin_hull (), sp.end_hull ());
|
p.assign_hull (sp.begin_hull (), sp.end_hull ());
|
||||||
item->add_value (p);
|
return item->add_value (p, tag_id);
|
||||||
} else if (v.is_user<db::DEdge> ()) {
|
} else if (v.is_user<db::DEdge> ()) {
|
||||||
item->add_value (v.to_user<db::DEdge> ());
|
return item->add_value (v.to_user<db::DEdge> (), tag_id);
|
||||||
} else if (v.is_user<db::DEdgePair> ()) {
|
} else if (v.is_user<db::DEdgePair> ()) {
|
||||||
item->add_value (v.to_user<db::DEdgePair> ());
|
return item->add_value (v.to_user<db::DEdgePair> (), tag_id);
|
||||||
} else if (v.is_user<db::DPath> ()) {
|
} else if (v.is_user<db::DPath> ()) {
|
||||||
item->add_value (v.to_user<db::DPath> ());
|
return item->add_value (v.to_user<db::DPath> (), tag_id);
|
||||||
} else if (v.is_user<db::DText> ()) {
|
} else if (v.is_user<db::DText> ()) {
|
||||||
item->add_value (v.to_user<db::DText> ());
|
return item->add_value (v.to_user<db::DText> (), tag_id);
|
||||||
} else {
|
} else {
|
||||||
item->add_value (std::string (v.to_string ()));
|
return item->add_value (std::string (v.to_string ()), tag_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueBase *add_item_value(rdb::Item *item, const tl::Variant &v, double dbu, rdb::id_type tag_id)
|
||||||
|
{
|
||||||
|
if (dbu > 0 && v.is_user<db::Box> ()) {
|
||||||
|
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::Box> (), tag_id);
|
||||||
|
} else if (dbu > 0 && v.is_user<db::Point> ()) {
|
||||||
|
db::DPoint p = db::CplxTrans (dbu) * v.to_user<db::Point> ();
|
||||||
|
return item->add_value (db::DEdge (p, p), tag_id);
|
||||||
|
} else if (dbu > 0 && v.is_user<db::Polygon> ()) {
|
||||||
|
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::Polygon> (), tag_id);
|
||||||
|
} else if (dbu > 0 && v.is_user<db::SimplePolygon> ()) {
|
||||||
|
db::DPolygon p;
|
||||||
|
db::DSimplePolygon sp = db::CplxTrans (dbu) * v.to_user<db::SimplePolygon> ();
|
||||||
|
p.assign_hull (sp.begin_hull (), sp.end_hull ());
|
||||||
|
return item->add_value (p, tag_id);
|
||||||
|
} else if (dbu > 0 && v.is_user<db::Edge> ()) {
|
||||||
|
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::Edge> (), tag_id);
|
||||||
|
} else if (dbu > 0 && v.is_user<db::EdgePair> ()) {
|
||||||
|
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::EdgePair> (), tag_id);
|
||||||
|
} else if (dbu > 0 && v.is_user<db::Path> ()) {
|
||||||
|
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::Path> (), tag_id);
|
||||||
|
} else if (dbu > 0 && v.is_user<db::Text> ()) {
|
||||||
|
return item->add_value (db::CplxTrans (dbu) * v.to_user<db::Text> (), tag_id);
|
||||||
|
} else if (v.is_user<db::DBox> ()) {
|
||||||
|
return item->add_value (v.to_user<db::DBox> (), tag_id);
|
||||||
|
} else if (v.is_user<db::DPoint> ()) {
|
||||||
|
db::DPoint p = v.to_user<db::DPoint> ();
|
||||||
|
return item->add_value (db::DEdge (p, p), tag_id);
|
||||||
|
} else if (v.is_user<db::DPolygon> ()) {
|
||||||
|
return item->add_value (v.to_user<db::DPolygon> (), tag_id);
|
||||||
|
} else if (v.is_user<db::DSimplePolygon> ()) {
|
||||||
|
db::DPolygon p;
|
||||||
|
db::DSimplePolygon sp = v.to_user<db::DSimplePolygon> ();
|
||||||
|
p.assign_hull (sp.begin_hull (), sp.end_hull ());
|
||||||
|
return item->add_value (p, tag_id);
|
||||||
|
} else if (v.is_user<db::DEdge> ()) {
|
||||||
|
return item->add_value (v.to_user<db::DEdge> (), tag_id);
|
||||||
|
} else if (v.is_user<db::DEdgePair> ()) {
|
||||||
|
return item->add_value (v.to_user<db::DEdgePair> (), tag_id);
|
||||||
|
} else if (v.is_user<db::DPath> ()) {
|
||||||
|
return item->add_value (v.to_user<db::DPath> (), tag_id);
|
||||||
|
} else if (v.is_user<db::DText> ()) {
|
||||||
|
return item->add_value (v.to_user<db::DText> (), tag_id);
|
||||||
|
} else {
|
||||||
|
return item->add_value (std::string (v.to_string ()), tag_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,45 +51,63 @@ namespace rdb
|
||||||
*
|
*
|
||||||
* If "from" is 0, all cells will be scanned. Levels are the number of hierarchy levels scanned if
|
* If "from" is 0, all cells will be scanned. Levels are the number of hierarchy levels scanned if
|
||||||
* "from" is given. -1 means "all levels".
|
* "from" is given. -1 means "all levels".
|
||||||
|
*
|
||||||
|
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||||
|
* to the property names.
|
||||||
*/
|
*/
|
||||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from_cell = 0, int levels = -1);
|
RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::Layout &layout, unsigned int layer, const db::Cell *from_cell = 0, int levels = -1, bool with_properties = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Scans a recursive shape iterator into a RDB category
|
* @brief Scans a recursive shape iterator into a RDB category
|
||||||
|
*
|
||||||
|
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||||
|
* to the property names.
|
||||||
*/
|
*/
|
||||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat = false);
|
RDB_PUBLIC void scan_layer (rdb::Category *cat, const db::RecursiveShapeIterator &iter, bool flat = false, bool with_properties = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Scans a recursive shape iterator into a RDB category
|
* @brief Scans a recursive shape iterator into a RDB category
|
||||||
*
|
*
|
||||||
* This version allows supplying a cell and a transformation. With this information, the function can also handle
|
* This version allows supplying a cell and a transformation. With this information, the function can also handle
|
||||||
* pseudo-iterators which don't deliver the information from a layout from from a plain shape collection.
|
* pseudo-iterators which don't deliver the information from a layout from from a plain shape collection.
|
||||||
|
*
|
||||||
|
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||||
|
* to the property names.
|
||||||
*/
|
*/
|
||||||
RDB_PUBLIC void scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat = false);
|
RDB_PUBLIC void scan_layer (rdb::Category *cat, rdb::Cell *cell, const db::CplxTrans &trans, const db::RecursiveShapeIterator &iter, bool flat = false, bool with_properties = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates RDB items from a recursive shape iterator
|
* @brief Creates RDB items from a recursive shape iterator
|
||||||
*
|
*
|
||||||
* This function will produce items from the flattened shape iterator. The items will be stored under
|
* This function will produce items from the flattened shape iterator. The items will be stored under
|
||||||
* the given cell.
|
* the given cell.
|
||||||
|
*
|
||||||
|
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||||
|
* to the property names.
|
||||||
*/
|
*/
|
||||||
RDB_PUBLIC void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter);
|
RDB_PUBLIC void create_items_from_iterator (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::RecursiveShapeIterator &iter, bool with_properties = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates RDB items from a shape collection
|
* @brief Creates RDB items from a shape collection
|
||||||
*
|
*
|
||||||
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
||||||
* This transformation is useful for providing the DBU-to-micron conversion.
|
* This transformation is useful for providing the DBU-to-micron conversion.
|
||||||
|
*
|
||||||
|
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||||
|
* to the property names.
|
||||||
*/
|
*/
|
||||||
RDB_PUBLIC void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes);
|
RDB_PUBLIC void create_items_from_shapes (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shapes &shapes, bool with_properties = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates RDB items from a single shape
|
* @brief Creates RDB items from a single shape
|
||||||
*
|
*
|
||||||
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
* An arbitrary transformation can be applied to translate the shapes before turning them to items.
|
||||||
* This transformation is useful for providing the DBU-to-micron conversion.
|
* This transformation is useful for providing the DBU-to-micron conversion.
|
||||||
|
*
|
||||||
|
* If "with_properties" is true, user properties are translated into values with tags corresponding
|
||||||
|
* to the property names.
|
||||||
*/
|
*/
|
||||||
RDB_PUBLIC void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape);
|
RDB_PUBLIC void create_item_from_shape (rdb::Database *db, rdb::id_type cell_id, rdb::id_type cat_id, const db::CplxTrans &trans, const db::Shape &shape, bool with_properties = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates RDB items from a region
|
* @brief Creates RDB items from a region
|
||||||
|
|
@ -146,7 +164,14 @@ RDB_PUBLIC_TEMPLATE void create_items_from_sequence (rdb::Database *db, rdb::id_
|
||||||
*
|
*
|
||||||
* Unknown types are converted to strings.
|
* Unknown types are converted to strings.
|
||||||
*/
|
*/
|
||||||
RDB_PUBLIC void add_item_value (rdb::Item *item, const tl::Variant &v, double dbu = 0.0);
|
RDB_PUBLIC ValueBase *add_item_value (rdb::Item *item, const tl::Variant &v, double dbu = 0.0, rdb::id_type tag_id = 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a value from a tl::Variant
|
||||||
|
*
|
||||||
|
* This version takes a db::CplxTrans for converting integer-unit geometry objects to micron-unit ones.
|
||||||
|
*/
|
||||||
|
RDB_PUBLIC ValueBase *add_item_value(rdb::Item *item, const tl::Variant &v, const db::CplxTrans &trans, rdb::id_type tag_id = 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue