mirror of
https://github.com/KLayout/klayout.git
synced 2026-08-22 05:57:41 +02:00
WIP: further preparations for MASKSHIFT components.
This commit is contained in:
@@ -1028,13 +1028,13 @@ DEFImporter::read_vias (db::Layout & /*layout*/, db::Cell & /*design*/, double s
|
|||||||
|
|
||||||
db::Polygon poly;
|
db::Polygon poly;
|
||||||
read_polygon (poly, scale);
|
read_polygon (poly, scale);
|
||||||
geo_based_vg->add_polygon (ln, poly, mask);
|
geo_based_vg->add_polygon (ln, ViaGeometry, poly, mask, 0);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
db::Polygon poly;
|
db::Polygon poly;
|
||||||
read_rect (poly, scale);
|
read_rect (poly, scale);
|
||||||
geo_based_vg->add_polygon (ln, poly, mask);
|
geo_based_vg->add_polygon (ln, ViaGeometry, poly, mask, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1262,7 +1262,7 @@ DEFImporter::read_styles (double scale)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DEFImporter::read_components (std::list<std::pair<std::string, CellInstArray> > &instances, double scale)
|
DEFImporter::read_components (db::Layout &layout, std::list<std::pair<std::string, CellInstArray> > &instances, double scale)
|
||||||
{
|
{
|
||||||
while (test ("-")) {
|
while (test ("-")) {
|
||||||
|
|
||||||
@@ -1274,8 +1274,6 @@ DEFImporter::read_components (std::list<std::pair<std::string, CellInstArray> >
|
|||||||
bool is_placed = false;
|
bool is_placed = false;
|
||||||
std::string maskshift;
|
std::string maskshift;
|
||||||
|
|
||||||
std::pair<db::Cell *, db::Trans> ct = m_lef_importer.macro_by_name (model);
|
|
||||||
|
|
||||||
while (test ("+")) {
|
while (test ("+")) {
|
||||||
|
|
||||||
if (test ("PLACED") || test ("FIXED") || test ("COVER")) {
|
if (test ("PLACED") || test ("FIXED") || test ("COVER")) {
|
||||||
@@ -1303,12 +1301,22 @@ DEFImporter::read_components (std::list<std::pair<std::string, CellInstArray> >
|
|||||||
expect (";");
|
expect (";");
|
||||||
|
|
||||||
if (is_placed) {
|
if (is_placed) {
|
||||||
if (ct.first) {
|
|
||||||
db::CellInstArray inst (db::CellInst (ct.first->cell_index ()), db::Trans (ft.rot (), d) * ct.second);
|
std::map<std::string, MacroDesc>::const_iterator m = m_lef_importer.macros ().find (model);
|
||||||
instances.push_back (std::make_pair (inst_name, inst));
|
if (m == m_lef_importer.macros ().end ()) {
|
||||||
} else {
|
|
||||||
warn (tl::to_string (tr ("Macro not found in LEF file: ")) + model);
|
warn (tl::to_string (tr ("Macro not found in LEF file: ")) + model);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
std::pair<db::Cell *, db::Trans> ct = reader_state ()->macro_cell (model, layout, string2masks (maskshift), m->second, &m_lef_importer);
|
||||||
|
if (ct.first) {
|
||||||
|
db::CellInstArray inst (db::CellInst (ct.first->cell_index ()), db::Trans (ft.rot (), d) * ct.second);
|
||||||
|
instances.push_back (std::make_pair (inst_name, inst));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1491,7 +1499,7 @@ DEFImporter::do_read (db::Layout &layout)
|
|||||||
get_long ();
|
get_long ();
|
||||||
expect (";");
|
expect (";");
|
||||||
|
|
||||||
read_components (instances, scale);
|
read_components (layout, instances, scale);
|
||||||
|
|
||||||
expect ("END");
|
expect ("END");
|
||||||
expect ("COMPONENTS");
|
expect ("COMPONENTS");
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ private:
|
|||||||
void read_vias (db::Layout &layout, db::Cell &design, double scale);
|
void read_vias (db::Layout &layout, db::Cell &design, double scale);
|
||||||
void read_pins (db::Layout &layout, db::Cell &design, double scale);
|
void read_pins (db::Layout &layout, db::Cell &design, double scale);
|
||||||
void read_styles (double scale);
|
void read_styles (double scale);
|
||||||
void read_components (std::list<std::pair<std::string, db::CellInstArray> > &instances, double scale);
|
void read_components (Layout &layout, std::list<std::pair<std::string, db::CellInstArray> > &instances, double scale);
|
||||||
void read_single_net (std::string &nondefaultrule, db::Layout &layout, db::Cell &design, double scale, properties_id_type prop_id, bool specialnets);
|
void read_single_net (std::string &nondefaultrule, db::Layout &layout, db::Cell &design, double scale, properties_id_type prop_id, bool specialnets);
|
||||||
void produce_routing_geometry (db::Cell &design, const db::Polygon *style, unsigned int layer, properties_id_type prop_id, const std::vector<db::Point> &pts, const std::vector<std::pair<db::Coord, db::Coord> > &ext, std::pair<db::Coord, db::Coord> w);
|
void produce_routing_geometry (db::Cell &design, const db::Polygon *style, unsigned int layer, properties_id_type prop_id, const std::vector<db::Point> &pts, const std::vector<std::pair<db::Coord, db::Coord> > &ext, std::pair<db::Coord, db::Coord> w);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ static unsigned int hex_value (char c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<unsigned int> string2masks (const std::string &s)
|
std::vector<unsigned int> string2masks (const std::string &s)
|
||||||
{
|
{
|
||||||
std::vector<unsigned int> res;
|
std::vector<unsigned int> res;
|
||||||
res.reserve (s.size ());
|
res.reserve (s.size ());
|
||||||
@@ -100,6 +100,8 @@ static std::vector<unsigned int> string2masks (const std::string &s)
|
|||||||
res.push_back (hex_value (*cp));
|
res.push_back (hex_value (*cp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::reverse (res.begin (), res.end ());
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,7 +275,7 @@ GeometryBasedLayoutGenerator::mask_for (const std::string &ln, unsigned int m, c
|
|||||||
{
|
{
|
||||||
for (std::vector<std::string>::const_iterator l = m_maskshift_layers.begin (); l != m_maskshift_layers.end (); ++l) {
|
for (std::vector<std::string>::const_iterator l = m_maskshift_layers.begin (); l != m_maskshift_layers.end (); ++l) {
|
||||||
|
|
||||||
if (*l == ln) {
|
if (! l->empty () && *l == ln) {
|
||||||
|
|
||||||
unsigned int mm = mask (masks, (unsigned int) (l - m_maskshift_layers.begin ()));
|
unsigned int mm = mask (masks, (unsigned int) (l - m_maskshift_layers.begin ()));
|
||||||
|
|
||||||
@@ -295,35 +297,79 @@ GeometryBasedLayoutGenerator::mask_for (const std::string &ln, unsigned int m, c
|
|||||||
void
|
void
|
||||||
GeometryBasedLayoutGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm)
|
GeometryBasedLayoutGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm)
|
||||||
{
|
{
|
||||||
for (std::map <std::string, std::list<std::pair<unsigned int, db::Polygon> > >::const_iterator g = m_polygons.begin (); g != m_polygons.end (); ++g) {
|
for (std::map <std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, db::Shapes>::const_iterator g = m_shapes.begin (); g != m_shapes.end (); ++g) {
|
||||||
for (std::list<std::pair<unsigned int, db::Polygon> >::const_iterator i = g->second.begin (); i != g->second.end (); ++i) {
|
std::pair <bool, unsigned int> dl = reader.open_layer (layout, g->first.first, g->first.second.first, mask_for (g->first.first, g->first.second.second, masks, nm));
|
||||||
std::pair <bool, unsigned int> dl = reader.open_layer (layout, g->first, ViaGeometry, mask_for (g->first, i->first, masks, nm));
|
if (dl.first) {
|
||||||
if (dl.first) {
|
cell.shapes (dl.second).insert (g->second);
|
||||||
cell.shapes (dl.second).insert (i->second);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::map <std::string, std::list<std::pair<unsigned int, db::Box> > >::const_iterator g = m_boxes.begin (); g != m_boxes.end (); ++g) {
|
for (std::list<Via>::const_iterator v = m_vias.begin (); v != m_vias.end (); ++v) {
|
||||||
for (std::list<std::pair<unsigned int, db::Box> >::const_iterator i = g->second.begin (); i != g->second.end (); ++i) {
|
|
||||||
std::pair <bool, unsigned int> dl = reader.open_layer (layout, g->first, ViaGeometry, mask_for (g->first, i->first, masks, nm));
|
LEFDEFLayoutGenerator *g = reader.via_generator (v->name);
|
||||||
if (dl.first) {
|
if (! g) {
|
||||||
cell.shapes (dl.second).insert (i->second);
|
continue;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> msl = g->maskshift_layers ();
|
||||||
|
msl.resize (3, std::string ());
|
||||||
|
|
||||||
|
db::Cell *vc = reader.via_cell (v->name, layout,
|
||||||
|
mask_for (msl [0], v->bottom_mask, masks, nm),
|
||||||
|
mask_for (msl [1], v->cut_mask, masks, nm),
|
||||||
|
mask_for (msl [2], v->top_mask, masks, nm),
|
||||||
|
nm);
|
||||||
|
|
||||||
|
if (vc) {
|
||||||
|
cell.insert (db::CellInstArray (db::CellInst (vc->cell_index ()), v->trans));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Shape>
|
||||||
|
static db::Shape insert_shape (db::Shapes &shapes, const Shape &shape, db::properties_id_type prop_id)
|
||||||
|
{
|
||||||
|
if (prop_id == 0) {
|
||||||
|
return shapes.insert (shape);
|
||||||
|
} else {
|
||||||
|
return shapes.insert (db::object_with_properties<Shape> (shape, prop_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GeometryBasedLayoutGenerator::add_polygon (const std::string &ln, const db::Polygon &poly, unsigned int mask)
|
GeometryBasedLayoutGenerator::add_polygon (const std::string &ln, LayerPurpose purpose, const db::Polygon &poly, unsigned int mask, db::properties_id_type prop_id)
|
||||||
{
|
{
|
||||||
m_polygons [ln].push_back (std::make_pair (mask, poly));
|
insert_shape (m_shapes [std::make_pair (ln, std::make_pair (purpose, mask))], poly, prop_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GeometryBasedLayoutGenerator::add_box (const std::string &ln, const db::Box &box, unsigned int mask)
|
GeometryBasedLayoutGenerator::add_box (const std::string &ln, LayerPurpose purpose, const db::Box &box, unsigned int mask, db::properties_id_type prop_id)
|
||||||
{
|
{
|
||||||
m_boxes [ln].push_back (std::make_pair (mask, box));
|
insert_shape (m_shapes [std::make_pair (ln, std::make_pair (purpose, mask))], box, prop_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GeometryBasedLayoutGenerator::add_path (const std::string &ln, LayerPurpose purpose, const db::Path &path, unsigned int mask, db::properties_id_type prop_id)
|
||||||
|
{
|
||||||
|
insert_shape (m_shapes [std::make_pair (ln, std::make_pair (purpose, mask))], path, prop_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GeometryBasedLayoutGenerator::add_text (const std::string &ln, LayerPurpose purpose, const db::Text &text, unsigned int mask, db::properties_id_type prop_id)
|
||||||
|
{
|
||||||
|
insert_shape (m_shapes [std::make_pair (ln, std::make_pair (purpose, mask))], text, prop_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GeometryBasedLayoutGenerator::add_via (const std::string &vn, const db::Trans &trans, unsigned int bottom_mask, unsigned int cut_mask, unsigned int top_mask)
|
||||||
|
{
|
||||||
|
m_vias.push_back (Via ());
|
||||||
|
m_vias.back ().name = vn;
|
||||||
|
m_vias.back ().trans = trans;
|
||||||
|
m_vias.back ().bottom_mask = bottom_mask;
|
||||||
|
m_vias.back ().cut_mask = cut_mask;
|
||||||
|
m_vias.back ().top_mask = top_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
@@ -714,6 +760,12 @@ LEFDEFReaderState::~LEFDEFReaderState ()
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_via_generators.clear ();
|
m_via_generators.clear ();
|
||||||
|
|
||||||
|
for (std::map<std::string, LEFDEFLayoutGenerator *>::const_iterator i = m_macro_generators.begin (); i != m_macro_generators.end (); ++i) {
|
||||||
|
delete i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_macro_generators.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1196,6 +1248,17 @@ LEFDEFReaderState::register_via_cell (const std::string &vn, LEFDEFLayoutGenerat
|
|||||||
m_via_generators [vn] = generator;
|
m_via_generators [vn] = generator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LEFDEFLayoutGenerator *
|
||||||
|
LEFDEFReaderState::via_generator (const std::string &vn)
|
||||||
|
{
|
||||||
|
std::map<std::string, LEFDEFLayoutGenerator *>::const_iterator g = m_via_generators.find (vn);
|
||||||
|
if (g != m_via_generators.end ()) {
|
||||||
|
return g->second;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
db::Cell *
|
db::Cell *
|
||||||
LEFDEFReaderState::via_cell (const std::string &vn, db::Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm)
|
LEFDEFReaderState::via_cell (const std::string &vn, db::Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm)
|
||||||
{
|
{
|
||||||
@@ -1242,6 +1305,109 @@ LEFDEFReaderState::via_cell (const std::string &vn, db::Layout &layout, unsigned
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LEFDEFReaderState::register_macro_cell (const std::string &mn, LEFDEFLayoutGenerator *generator)
|
||||||
|
{
|
||||||
|
if (m_macro_generators.find (mn) != m_macro_generators.end ()) {
|
||||||
|
delete m_macro_generators [mn];
|
||||||
|
}
|
||||||
|
m_macro_generators [mn] = generator;
|
||||||
|
}
|
||||||
|
|
||||||
|
LEFDEFLayoutGenerator *
|
||||||
|
LEFDEFReaderState::macro_generator (const std::string &mn)
|
||||||
|
{
|
||||||
|
std::map<std::string, LEFDEFLayoutGenerator *>::const_iterator g = m_macro_generators.find (mn);
|
||||||
|
if (g != m_macro_generators.end ()) {
|
||||||
|
return g->second;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<db::Cell *, db::Trans>
|
||||||
|
LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std::vector<unsigned int> &masks, const MacroDesc ¯o_desc, const LEFDEFNumberOfMasks *nm)
|
||||||
|
{
|
||||||
|
MacroKey mk (mn, masks);
|
||||||
|
std::map<MacroKey, std::pair<db::Cell *, db::Trans> >::const_iterator i = m_macro_cells.find (mk);
|
||||||
|
if (i != m_macro_cells.end ()) {
|
||||||
|
tl_assert (! i->second.first || i->second.first->layout () == &layout);
|
||||||
|
return i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
db::Cell *cell = 0;
|
||||||
|
db::Trans tr;
|
||||||
|
|
||||||
|
std::map<std::string, LEFDEFLayoutGenerator *>::const_iterator g = m_macro_generators.find (mn);
|
||||||
|
if (g == m_macro_generators.end ()) {
|
||||||
|
return std::make_pair ((db::Cell *) 0, db::Trans ());
|
||||||
|
}
|
||||||
|
|
||||||
|
LEFDEFLayoutGenerator *mg = g->second;
|
||||||
|
|
||||||
|
if (! macro_desc.foreign_name.empty ()) {
|
||||||
|
|
||||||
|
db::cell_index_type ci;
|
||||||
|
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (macro_desc.foreign_name.c_str ());
|
||||||
|
if (c.first) {
|
||||||
|
ci = c.second;
|
||||||
|
} else {
|
||||||
|
ci = layout.add_cell (macro_desc.foreign_name.c_str ());
|
||||||
|
layout.cell (ci).set_ghost_cell (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
db::Cell *foreign_cell = &layout.cell (ci);
|
||||||
|
|
||||||
|
if (macro_desc.foreign_name != mn) {
|
||||||
|
|
||||||
|
// create an indirection for renaming the cell
|
||||||
|
cell = &layout.cell (layout.add_cell (mn.c_str ()));
|
||||||
|
cell->insert (db::CellInstArray (db::CellInst (foreign_cell->cell_index ()), db::Trans (db::Point () - macro_desc.origin) * macro_desc.foreign_trans));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// use FOREIGN cell instead of new one
|
||||||
|
cell = foreign_cell;
|
||||||
|
tr = db::Trans (db::Point () - macro_desc.origin) * macro_desc.foreign_trans;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (tech_comp ()->macro_resolution_mode () == 2) {
|
||||||
|
|
||||||
|
// create a ghost cell always
|
||||||
|
|
||||||
|
db::cell_index_type ci;
|
||||||
|
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (mn.c_str ());
|
||||||
|
if (c.first) {
|
||||||
|
ci = c.second;
|
||||||
|
} else {
|
||||||
|
ci = layout.add_cell (mn.c_str ());
|
||||||
|
layout.cell (ci).set_ghost_cell (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell = &layout.cell (ci);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// actually implement the real cell
|
||||||
|
|
||||||
|
std::string mask_suffix;
|
||||||
|
for (std::vector<unsigned int>::const_iterator m = masks.begin (); m != masks.end (); ++m) {
|
||||||
|
mask_suffix += "_";
|
||||||
|
mask_suffix += tl::to_string (*m);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string cn = mn + mask_suffix;
|
||||||
|
|
||||||
|
cell = &layout.cell (layout.add_cell (cn.c_str ()));
|
||||||
|
mg->create_cell (*this, layout, *cell, masks, nm);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
m_macro_cells [mk] = std::make_pair (cell, tr);
|
||||||
|
return std::make_pair (cell, tr);
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
// LEFDEFImporter implementation
|
// LEFDEFImporter implementation
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ namespace db
|
|||||||
{
|
{
|
||||||
|
|
||||||
class LEFDEFReaderState;
|
class LEFDEFReaderState;
|
||||||
|
struct MacroDesc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Correct a path relative to the stream and technology
|
* @brief Correct a path relative to the stream and technology
|
||||||
@@ -51,6 +52,11 @@ class LEFDEFReaderState;
|
|||||||
DB_PLUGIN_PUBLIC
|
DB_PLUGIN_PUBLIC
|
||||||
std::string correct_path (const std::string &fn, const db::Layout &layout, const std::string &base_path);
|
std::string correct_path (const std::string &fn, const db::Layout &layout, const std::string &base_path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convers a string to a MASKSHIFT index list
|
||||||
|
*/
|
||||||
|
std::vector<unsigned int> string2masks (const std::string &s);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generic base class of DXF reader exceptions
|
* @brief Generic base class of DXF reader exceptions
|
||||||
*/
|
*/
|
||||||
@@ -883,6 +889,7 @@ public:
|
|||||||
virtual ~LEFDEFLayoutGenerator () { }
|
virtual ~LEFDEFLayoutGenerator () { }
|
||||||
|
|
||||||
virtual void create_cell (LEFDEFReaderState &reader, db::Layout &layout, db::Cell &cell, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm) = 0;
|
virtual void create_cell (LEFDEFReaderState &reader, db::Layout &layout, db::Cell &cell, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm) = 0;
|
||||||
|
virtual std::vector<std::string> maskshift_layers () const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -896,6 +903,15 @@ public:
|
|||||||
|
|
||||||
virtual void create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm);
|
virtual void create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm);
|
||||||
|
|
||||||
|
virtual std::vector<std::string> maskshift_layers () const
|
||||||
|
{
|
||||||
|
std::vector<std::string> msl;
|
||||||
|
msl.push_back (m_bottom_layer);
|
||||||
|
msl.push_back (m_cut_layer);
|
||||||
|
msl.push_back (m_top_layer);
|
||||||
|
return msl;
|
||||||
|
}
|
||||||
|
|
||||||
void set_cutsize (const db::Vector &cutsize) { m_cutsize = cutsize; }
|
void set_cutsize (const db::Vector &cutsize) { m_cutsize = cutsize; }
|
||||||
void set_cutspacing (const db::Vector &cutspacing) { m_cutspacing = cutspacing; }
|
void set_cutspacing (const db::Vector &cutspacing) { m_cutspacing = cutspacing; }
|
||||||
void set_offset (const db::Point &offset) { m_offset = offset; }
|
void set_offset (const db::Point &offset) { m_offset = offset; }
|
||||||
@@ -931,12 +947,23 @@ class DB_PLUGIN_PUBLIC GeometryBasedLayoutGenerator
|
|||||||
: public LEFDEFLayoutGenerator
|
: public LEFDEFLayoutGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct Via {
|
||||||
|
Via () : bottom_mask (0), cut_mask (0), top_mask (0) { }
|
||||||
|
std::string name;
|
||||||
|
unsigned int bottom_mask, cut_mask, top_mask;
|
||||||
|
db::Trans trans;
|
||||||
|
};
|
||||||
|
|
||||||
GeometryBasedLayoutGenerator ();
|
GeometryBasedLayoutGenerator ();
|
||||||
|
|
||||||
virtual void create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *num_cut_masks);
|
virtual void create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *num_cut_masks);
|
||||||
|
virtual std::vector<std::string> maskshift_layers () const { return m_maskshift_layers; }
|
||||||
|
|
||||||
void add_polygon (const std::string &ln, const db::Polygon &poly, unsigned int mask);
|
void add_polygon (const std::string &ln, LayerPurpose purpose, const db::Polygon &poly, unsigned int mask, properties_id_type prop_id);
|
||||||
void add_box (const std::string &ln, const db::Box &box, unsigned int mask);
|
void add_box (const std::string &ln, LayerPurpose purpose, const db::Box &box, unsigned int mask, properties_id_type prop_id);
|
||||||
|
void add_path (const std::string &ln, LayerPurpose purpose, const db::Path &path, unsigned int mask, properties_id_type prop_id);
|
||||||
|
void add_via (const std::string &vn, const db::Trans &trans, unsigned int bottom_mask, unsigned int cut_mask, unsigned int top_mask);
|
||||||
|
void add_text (const std::string &ln, LayerPurpose purpose, const db::Text &text, unsigned int mask, db::properties_id_type prop_id);
|
||||||
|
|
||||||
void set_maskshift_layers (const std::vector<std::string> &ln) { m_maskshift_layers = ln; }
|
void set_maskshift_layers (const std::vector<std::string> &ln) { m_maskshift_layers = ln; }
|
||||||
|
|
||||||
@@ -949,8 +976,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map <std::string, std::list<std::pair<unsigned int, db::Polygon> > > m_polygons;
|
std::map <std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, db::Shapes> m_shapes;
|
||||||
std::map <std::string, std::list<std::pair<unsigned int, db::Box> > > m_boxes;
|
std::list<Via> m_vias;
|
||||||
std::vector<std::string> m_maskshift_layers;
|
std::vector<std::string> m_maskshift_layers;
|
||||||
|
|
||||||
unsigned int mask_for (const std::string &ln, unsigned int m, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm) const;
|
unsigned int mask_for (const std::string &ln, unsigned int m, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm) const;
|
||||||
@@ -1016,6 +1043,28 @@ public:
|
|||||||
*/
|
*/
|
||||||
db::Cell *via_cell (const std::string &vn, Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm);
|
db::Cell *via_cell (const std::string &vn, Layout &layout, unsigned int mask_bottom, unsigned int mask_cut, unsigned int mask_top, const LEFDEFNumberOfMasks *nm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the via generator for a given via name or 0 if there is no such generator
|
||||||
|
*/
|
||||||
|
LEFDEFLayoutGenerator *via_generator (const std::string &vn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers a macro generator for the macro with the given name
|
||||||
|
*
|
||||||
|
* The generator is capable of creating a macro for a specific mask configuration
|
||||||
|
*/
|
||||||
|
void register_macro_cell (const std::string &mn, LEFDEFLayoutGenerator *generator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the macro cell for the given macro name or 0 if no such maco is registered
|
||||||
|
*/
|
||||||
|
std::pair<db::Cell *, db::Trans> macro_cell (const std::string &mn, Layout &layout, const std::vector<unsigned int> &masks, const MacroDesc ¯o_desc, const LEFDEFNumberOfMasks *nm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the macro generator for a given macro name or 0 if there is no such generator
|
||||||
|
*/
|
||||||
|
LEFDEFLayoutGenerator *macro_generator (const std::string &mn);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the technology component pointer
|
* @brief Get the technology component pointer
|
||||||
*/
|
*/
|
||||||
@@ -1060,6 +1109,35 @@ private:
|
|||||||
unsigned int mask_bottom, mask_cut, mask_top;
|
unsigned int mask_bottom, mask_cut, mask_top;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A key for the via cache
|
||||||
|
*/
|
||||||
|
struct MacroKey
|
||||||
|
{
|
||||||
|
MacroKey (const std::string &n, const std::vector<unsigned int> &m)
|
||||||
|
: name (n), masks (m)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool operator== (const MacroKey &other) const
|
||||||
|
{
|
||||||
|
return name == other.name && masks == other.masks;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator< (const MacroKey &other) const
|
||||||
|
{
|
||||||
|
if (name != other.name) {
|
||||||
|
return name < other.name;
|
||||||
|
}
|
||||||
|
if (masks != other.masks) {
|
||||||
|
return masks < other.masks;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::vector<unsigned int> masks;
|
||||||
|
};
|
||||||
|
|
||||||
// no copying
|
// no copying
|
||||||
LEFDEFReaderState (const LEFDEFReaderState &);
|
LEFDEFReaderState (const LEFDEFReaderState &);
|
||||||
LEFDEFReaderState &operator= (const LEFDEFReaderState &);
|
LEFDEFReaderState &operator= (const LEFDEFReaderState &);
|
||||||
@@ -1070,9 +1148,11 @@ private:
|
|||||||
bool m_has_explicit_layer_mapping;
|
bool m_has_explicit_layer_mapping;
|
||||||
int m_laynum;
|
int m_laynum;
|
||||||
std::map<std::string, int> m_default_number;
|
std::map<std::string, int> m_default_number;
|
||||||
std::map<ViaKey, db::Cell *> m_via_cells;
|
|
||||||
const LEFDEFReaderOptions *mp_tech_comp;
|
const LEFDEFReaderOptions *mp_tech_comp;
|
||||||
|
std::map<ViaKey, db::Cell *> m_via_cells;
|
||||||
std::map<std::string, LEFDEFLayoutGenerator *> m_via_generators;
|
std::map<std::string, LEFDEFLayoutGenerator *> m_via_generators;
|
||||||
|
std::map<MacroKey, std::pair<db::Cell *, db::Trans> > m_macro_cells;
|
||||||
|
std::map<std::string, LEFDEFLayoutGenerator *> m_macro_generators;
|
||||||
|
|
||||||
std::pair <bool, unsigned int> open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
|
std::pair <bool, unsigned int> open_layer_uncached (db::Layout &layout, const std::string &name, LayerPurpose purpose, unsigned int mask);
|
||||||
void map_layer_explicit (const std::string &n, LayerPurpose purpose, const LayerProperties &lp, unsigned int layer, unsigned int mask);
|
void map_layer_explicit (const std::string &n, LayerPurpose purpose, const LayerProperties &lp, unsigned int layer, unsigned int mask);
|
||||||
@@ -1091,6 +1171,34 @@ struct DB_PLUGIN_PUBLIC ViaDesc
|
|||||||
std::string m1, m2;
|
std::string m1, m2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A structure describing a macro
|
||||||
|
*/
|
||||||
|
struct DB_PLUGIN_PUBLIC MacroDesc
|
||||||
|
{
|
||||||
|
MacroDesc () { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The name of the FOREIGN cell if present
|
||||||
|
*/
|
||||||
|
std::string foreign_name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The transformation of the FOREIGN cell
|
||||||
|
*/
|
||||||
|
db::Trans foreign_trans;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The origin
|
||||||
|
*/
|
||||||
|
db::Point origin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The bounding box
|
||||||
|
*/
|
||||||
|
db::Box bbox;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The LEF importer object
|
* @brief The LEF importer object
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -43,18 +43,7 @@ LEFImporter::~LEFImporter ()
|
|||||||
// .. nothing yet ..
|
// .. nothing yet ..
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Box
|
double
|
||||||
LEFImporter::macro_bbox_by_name (const std::string &name) const
|
|
||||||
{
|
|
||||||
std::map<std::string, db::Box>::const_iterator m = m_macro_bboxes_by_name.find (name);
|
|
||||||
if (m != m_macro_bboxes_by_name.end ()) {
|
|
||||||
return m->second;
|
|
||||||
} else {
|
|
||||||
return db::Box ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
LEFImporter::layer_ext (const std::string &layer, double def_ext) const
|
LEFImporter::layer_ext (const std::string &layer, double def_ext) const
|
||||||
{
|
{
|
||||||
std::map<std::string, double>::const_iterator l = m_default_ext.find (layer);
|
std::map<std::string, double>::const_iterator l = m_default_ext.find (layer);
|
||||||
@@ -105,19 +94,8 @@ LEFImporter::layer_width (const std::string &layer, const std::string &nondefaul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<db::Cell *, db::Trans>
|
|
||||||
LEFImporter::macro_by_name (const std::string &name) const
|
|
||||||
{
|
|
||||||
std::map<std::string, std::pair<db::Cell *, db::Trans> >::const_iterator m = m_macros_by_name.find (name);
|
|
||||||
if (m != m_macros_by_name.end ()) {
|
|
||||||
return m->second;
|
|
||||||
} else {
|
|
||||||
return std::make_pair ((db::Cell *) 0, db::Trans ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector <db::Trans>
|
std::vector <db::Trans>
|
||||||
LEFImporter::get_iteration (db::Layout &layout)
|
LEFImporter::get_iteration (double dbu)
|
||||||
{
|
{
|
||||||
test ("DO");
|
test ("DO");
|
||||||
long nx = get_long ();
|
long nx = get_long ();
|
||||||
@@ -131,7 +109,7 @@ LEFImporter::get_iteration (db::Layout &layout)
|
|||||||
std::vector <db::Trans> t;
|
std::vector <db::Trans> t;
|
||||||
for (long i = 0; i < nx; ++i) {
|
for (long i = 0; i < nx; ++i) {
|
||||||
for (long j = 0; j < ny; ++j) {
|
for (long j = 0; j < ny; ++j) {
|
||||||
t.push_back (db::Trans (db::Vector (db::DVector (dx * i / layout.dbu (), dy * j / layout.dbu ()))));
|
t.push_back (db::Trans (db::Vector (db::DVector (dx * i / dbu, dy * j / dbu))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
@@ -158,10 +136,9 @@ static db::Shape insert_shape (db::Cell &cell, unsigned int layer_id, const Shap
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose purpose, std::map<std::string, db::Box> *collect_bboxes, db::properties_id_type prop_id)
|
LEFImporter::read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, LayerPurpose purpose, std::map<std::string, db::Box> *collect_boxes_for_labels, db::properties_id_type prop_id)
|
||||||
{
|
{
|
||||||
std::string layer_name;
|
std::string layer_name;
|
||||||
double dbu = layout.dbu ();
|
|
||||||
double w = 0.0;
|
double w = 0.0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -201,12 +178,6 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
|||||||
mask = get_mask (get_long ());
|
mask = get_mask (get_long ());
|
||||||
}
|
}
|
||||||
|
|
||||||
int layer_id = -1;
|
|
||||||
std::pair <bool, unsigned int> dl = open_layer (layout, layer_name, purpose, mask);
|
|
||||||
if (dl.first) {
|
|
||||||
layer_id = int (dl.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iterate = test ("ITERATE");
|
bool iterate = test ("ITERATE");
|
||||||
|
|
||||||
while (! peek (";") && ! peek ("DO")) {
|
while (! peek (";") && ! peek ("DO")) {
|
||||||
@@ -221,20 +192,24 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
|||||||
db::Path p (points.begin (), points.end (), iw, iw / 2, iw / 2, false);
|
db::Path p (points.begin (), points.end (), iw, iw / 2, iw / 2, false);
|
||||||
|
|
||||||
if (iterate) {
|
if (iterate) {
|
||||||
std::vector<db::Trans> ti = get_iteration (layout);
|
|
||||||
if (layer_id >= 0) {
|
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
|
||||||
db::Shape s = insert_shape (cell, layer_id, p, *t, prop_id);
|
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||||
if (collect_bboxes) {
|
db::Path pt = p.transformed (*t);
|
||||||
collect_bboxes->insert (std::make_pair (layer_name, db::Box ())).first->second = s.bbox ();
|
lg->add_path (layer_name, purpose, pt, mask, prop_id);
|
||||||
}
|
if (collect_boxes_for_labels) {
|
||||||
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = pt.box ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (layer_id >= 0) {
|
|
||||||
db::Shape s = insert_shape (cell, layer_id, p, prop_id);
|
} else {
|
||||||
if (collect_bboxes) {
|
|
||||||
collect_bboxes->insert (std::make_pair (layer_name, db::Box ())).first->second = s.bbox ();
|
lg->add_path (layer_name, purpose, p, mask, prop_id);
|
||||||
|
if (collect_boxes_for_labels) {
|
||||||
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = p.box ();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expect (";");
|
expect (";");
|
||||||
@@ -248,12 +223,6 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
|||||||
mask = get_mask (get_long ());
|
mask = get_mask (get_long ());
|
||||||
}
|
}
|
||||||
|
|
||||||
int layer_id = -1;
|
|
||||||
std::pair <bool, unsigned int> dl = open_layer (layout, layer_name, purpose, mask);
|
|
||||||
if (dl.first) {
|
|
||||||
layer_id = int (dl.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iterate = test ("ITERATE");
|
bool iterate = test ("ITERATE");
|
||||||
|
|
||||||
while (! peek (";") && ! peek ("DO")) {
|
while (! peek (";") && ! peek ("DO")) {
|
||||||
@@ -268,20 +237,23 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
|||||||
p.assign_hull (points.begin (), points.end ());
|
p.assign_hull (points.begin (), points.end ());
|
||||||
|
|
||||||
if (iterate) {
|
if (iterate) {
|
||||||
std::vector<db::Trans> ti = get_iteration (layout);
|
|
||||||
if (layer_id >= 0) {
|
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||||
db::Shape s = insert_shape (cell, layer_id, p, *t, prop_id);
|
db::Polygon pt = p.transformed (*t);
|
||||||
if (collect_bboxes) {
|
lg->add_polygon (layer_name, purpose, pt, mask, prop_id);
|
||||||
collect_bboxes->insert (std::make_pair (layer_name, db::Box ())).first->second = s.bbox ();
|
if (collect_boxes_for_labels) {
|
||||||
}
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = pt.box ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (layer_id >= 0) {
|
|
||||||
db::Shape s = insert_shape (cell, layer_id, p, prop_id);
|
} else {
|
||||||
if (collect_bboxes) {
|
|
||||||
collect_bboxes->insert (std::make_pair (layer_name, db::Box ())).first->second = s.bbox ();
|
lg->add_polygon (layer_name, purpose, p, mask, prop_id);
|
||||||
|
if (collect_boxes_for_labels) {
|
||||||
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = p.box ();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expect (";");
|
expect (";");
|
||||||
@@ -295,39 +267,39 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
|||||||
mask = get_mask (get_long ());
|
mask = get_mask (get_long ());
|
||||||
}
|
}
|
||||||
|
|
||||||
int layer_id = -1;
|
|
||||||
std::pair <bool, unsigned int> dl = open_layer (layout, layer_name, purpose, mask);
|
|
||||||
if (dl.first) {
|
|
||||||
layer_id = int (dl.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iterate = test ("ITERATE");
|
bool iterate = test ("ITERATE");
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
|
||||||
test ("(");
|
test ("(");
|
||||||
double x = get_double ();
|
double x = get_double ();
|
||||||
double y = get_double ();
|
double y = get_double ();
|
||||||
points.push_back (db::Point (db::DPoint (x / dbu, y / dbu)));
|
points.push_back (db::Point (db::DPoint (x / dbu, y / dbu)));
|
||||||
test (")");
|
test (")");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db::Box b (points [0], points [1]);
|
db::Box b (points [0], points [1]);
|
||||||
|
|
||||||
if (iterate) {
|
if (iterate) {
|
||||||
std::vector<db::Trans> ti = get_iteration (layout);
|
|
||||||
if (layer_id >= 0) {
|
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
|
||||||
db::Shape s = insert_shape (cell, layer_id, b, *t, prop_id);
|
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||||
if (collect_bboxes) {
|
db::Box bt = b.transformed (*t);
|
||||||
collect_bboxes->insert (std::make_pair (layer_name, db::Box ())).first->second = s.bbox ();
|
lg->add_box (layer_name, purpose, bt, mask, prop_id);
|
||||||
}
|
if (collect_boxes_for_labels) {
|
||||||
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = bt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (layer_id >= 0) {
|
|
||||||
db::Shape s = insert_shape (cell, layer_id, b, prop_id);
|
} else {
|
||||||
if (collect_bboxes) {
|
|
||||||
collect_bboxes->insert (std::make_pair (layer_name, db::Box ())).first->second = s.bbox ();
|
lg->add_box (layer_name, purpose, b, mask, prop_id);
|
||||||
|
if (collect_boxes_for_labels) {
|
||||||
|
collect_boxes_for_labels->insert (std::make_pair (layer_name, db::Box ())).first->second = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expect (";");
|
expect (";");
|
||||||
@@ -348,12 +320,6 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
|||||||
unsigned int mask_cut = (mask / 10) % 10;
|
unsigned int mask_cut = (mask / 10) % 10;
|
||||||
unsigned int mask_top = (mask / 100) % 10;
|
unsigned int mask_top = (mask / 100) % 10;
|
||||||
|
|
||||||
int layer_id = -1;
|
|
||||||
std::pair <bool, unsigned int> dl = open_layer (layout, layer_name, purpose, mask);
|
|
||||||
if (dl.first) {
|
|
||||||
layer_id = int (dl.second);
|
|
||||||
}
|
|
||||||
|
|
||||||
double x = 0.0, y = 0.0;
|
double x = 0.0, y = 0.0;
|
||||||
if (test ("(")) {
|
if (test ("(")) {
|
||||||
x = get_double ();
|
x = get_double ();
|
||||||
@@ -366,20 +332,18 @@ LEFImporter::read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose p
|
|||||||
points.push_back (db::Vector (db::DVector (x / dbu, y / dbu)));
|
points.push_back (db::Vector (db::DVector (x / dbu, y / dbu)));
|
||||||
|
|
||||||
std::string vn = get ();
|
std::string vn = get ();
|
||||||
db::Cell *vc = reader_state ()->via_cell (vn, layout, mask_bottom, mask_cut, mask_top, this);
|
|
||||||
if (! vc) {
|
|
||||||
warn (tl::to_string (tr ("Unknown via: ")) + vn);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iterate) {
|
if (iterate) {
|
||||||
std::vector<db::Trans> ti = get_iteration (layout);
|
|
||||||
if (vc) {
|
std::vector<db::Trans> ti = get_iteration (dbu);
|
||||||
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
for (std::vector<db::Trans>::const_iterator t = ti.begin (); t != ti.end (); ++t) {
|
||||||
cell.insert (db::CellInstArray (db::CellInst (vc->cell_index ()), *t * db::Trans (points [0])));
|
lg->add_via (vn, *t * db::Trans (points [0]), mask_bottom, mask_cut, mask_top);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (vc) {
|
|
||||||
cell.insert (db::CellInstArray (db::CellInst (vc->cell_index ()), db::Trans (points [0])));
|
} else {
|
||||||
|
|
||||||
|
lg->add_via (vn, db::Trans (points [0]), mask_bottom, mask_cut, mask_top);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expect (";");
|
expect (";");
|
||||||
@@ -597,7 +561,7 @@ LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc
|
|||||||
db::Polygon p;
|
db::Polygon p;
|
||||||
p.assign_hull (points.begin (), points.end ());
|
p.assign_hull (points.begin (), points.end ());
|
||||||
|
|
||||||
lg->add_polygon (layer_name, p, mask);
|
lg->add_polygon (layer_name, ViaGeometry, p, mask, 0);
|
||||||
|
|
||||||
expect (";");
|
expect (";");
|
||||||
|
|
||||||
@@ -619,7 +583,7 @@ LEFImporter::read_viadef_by_geometry (GeometryBasedLayoutGenerator *lg, ViaDesc
|
|||||||
}
|
}
|
||||||
|
|
||||||
db::Box b (points [0], points [1]);
|
db::Box b (points [0], points [1]);
|
||||||
lg->add_box (layer_name, b, mask);
|
lg->add_box (layer_name, ViaGeometry, b, mask, 0);
|
||||||
|
|
||||||
expect (";");
|
expect (";");
|
||||||
|
|
||||||
@@ -823,14 +787,15 @@ LEFImporter::read_macro (Layout &layout)
|
|||||||
{
|
{
|
||||||
std::string mn = get ();
|
std::string mn = get ();
|
||||||
|
|
||||||
if (m_macros_by_name.find (mn) != m_macros_by_name.end ()) {
|
if (m_macros.find (mn) != m_macros.end ()) {
|
||||||
error (tl::to_string (tr ("Duplicate MACRO name: ")) + mn);
|
error (tl::to_string (tr ("Duplicate MACRO name: ")) + mn);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_cellname (mn);
|
set_cellname (mn);
|
||||||
|
|
||||||
db::Cell &cell = layout.cell (layout.add_cell ());
|
GeometryBasedLayoutGenerator *mg = new GeometryBasedLayoutGenerator ();
|
||||||
db::Cell *foreign_cell = 0;
|
reader_state ()->register_macro_cell (mn, mg);
|
||||||
|
|
||||||
db::Trans foreign_trans;
|
db::Trans foreign_trans;
|
||||||
std::string foreign_name;
|
std::string foreign_name;
|
||||||
|
|
||||||
@@ -892,14 +857,11 @@ LEFImporter::read_macro (Layout &layout)
|
|||||||
prop_id = layout.properties_repository ().properties_id (props);
|
prop_id = layout.properties_repository ().properties_id (props);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map <std::string, db::Box> bboxes;
|
std::map <std::string, db::Box> boxes_for_labels;
|
||||||
read_geometries (layout, cell, LEFPins, &bboxes, prop_id);
|
read_geometries (mg, layout.dbu (), LEFPins, &boxes_for_labels, prop_id);
|
||||||
|
|
||||||
for (std::map <std::string, db::Box>::const_iterator b = bboxes.begin (); b != bboxes.end (); ++b) {
|
for (std::map <std::string, db::Box>::const_iterator b = boxes_for_labels.begin (); b != boxes_for_labels.end (); ++b) {
|
||||||
std::pair <bool, unsigned int> dl = open_layer (layout, b->first, Label, 0);
|
mg->add_text (b->first, Label, db::Text (label.c_str (), db::Trans (b->second.center () - db::Point ())), 0, 0);
|
||||||
if (dl.first) {
|
|
||||||
cell.shapes (dl.second).insert (db::Text (label.c_str (), db::Trans (b->second.center () - db::Point ())));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expect ("END");
|
expect ("END");
|
||||||
@@ -915,10 +877,6 @@ LEFImporter::read_macro (Layout &layout)
|
|||||||
|
|
||||||
} else if (test ("FOREIGN")) {
|
} else if (test ("FOREIGN")) {
|
||||||
|
|
||||||
if (foreign_cell) {
|
|
||||||
error (tl::to_string (tr ("Duplicate FOREIGN definition")));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string cn = get ();
|
std::string cn = get ();
|
||||||
|
|
||||||
db::Point vec;
|
db::Point vec;
|
||||||
@@ -932,26 +890,24 @@ LEFImporter::read_macro (Layout &layout)
|
|||||||
|
|
||||||
if (options ().macro_resolution_mode () != 1) {
|
if (options ().macro_resolution_mode () != 1) {
|
||||||
|
|
||||||
db::cell_index_type ci;
|
if (! foreign_name.empty ()) {
|
||||||
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (cn.c_str ());
|
error (tl::to_string (tr ("Duplicate FOREIGN definition")));
|
||||||
if (c.first) {
|
|
||||||
ci = c.second;
|
|
||||||
} else {
|
|
||||||
ci = layout.add_cell (cn.c_str ());
|
|
||||||
layout.cell (ci).set_ghost_cell (true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreign_cell = &layout.cell (ci);
|
|
||||||
// What is the definition of the FOREIGN transformation?
|
// What is the definition of the FOREIGN transformation?
|
||||||
// Guessing: this transformation moves the lower-left origin to 0,0
|
// Guessing: this transformation moves the lower-left origin to 0,0
|
||||||
foreign_trans = db::Trans (db::Point () - vec) * db::Trans (ft);
|
foreign_trans = db::Trans (db::Point () - vec) * db::Trans (ft);
|
||||||
foreign_name = cn;
|
foreign_name = cn;
|
||||||
|
|
||||||
|
if (foreign_name != mn) {
|
||||||
|
warn (tl::to_string (tr ("FOREIGN name differs from MACRO name in macro: ")) + mn);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (test ("OBS")) {
|
} else if (test ("OBS")) {
|
||||||
|
|
||||||
read_geometries (layout, cell, Obstructions);
|
read_geometries (mg, layout.dbu (), Obstructions);
|
||||||
expect ("END");
|
expect ("END");
|
||||||
|
|
||||||
} else if (test ("FIXEDMASK")) {
|
} else if (test ("FIXEDMASK")) {
|
||||||
@@ -967,69 +923,14 @@ LEFImporter::read_macro (Layout &layout)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! foreign_cell) {
|
mg->add_box (std::string (), Outline, db::Box (-origin, -origin + size), 0, 0);
|
||||||
|
|
||||||
if (options ().macro_resolution_mode () != 2) {
|
MacroDesc macro_desc;
|
||||||
|
macro_desc.foreign_name = foreign_name;
|
||||||
// actually implement the real cell
|
macro_desc.foreign_trans = foreign_trans;
|
||||||
|
macro_desc.bbox = db::Box (-origin, -origin + size);
|
||||||
layout.rename_cell (cell.cell_index (), mn.c_str ());
|
macro_desc.origin = origin;
|
||||||
|
m_macros.insert (std::make_pair (mn, macro_desc));
|
||||||
std::pair <bool, unsigned int> dl = open_layer (layout, std::string (), Outline, 0);
|
|
||||||
if (dl.first) {
|
|
||||||
cell.shapes (dl.second).insert (db::Box (-origin, -origin + size));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&cell, db::Trans ())));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// macro resolution mode #2 (always create a MACRO reference, no LEF geometry)
|
|
||||||
|
|
||||||
db::cell_index_type ci;
|
|
||||||
std::pair<bool, db::cell_index_type> c = layout.cell_by_name (mn.c_str ());
|
|
||||||
if (c.first) {
|
|
||||||
ci = c.second;
|
|
||||||
} else {
|
|
||||||
ci = layout.add_cell (mn.c_str ());
|
|
||||||
layout.cell (ci).set_ghost_cell (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
layout.delete_cell (cell.cell_index ());
|
|
||||||
m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&layout.cell (ci), db::Trans ())));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (foreign_name != mn) {
|
|
||||||
|
|
||||||
warn (tl::to_string (tr ("FOREIGN name differs from MACRO name in macro: ")) + mn);
|
|
||||||
|
|
||||||
layout.rename_cell (cell.cell_index (), mn.c_str ());
|
|
||||||
|
|
||||||
// clear imported LEF geometry with a foreign cell, but provide a level of indirection so we have
|
|
||||||
// both the MACRO and the FOREIGN name
|
|
||||||
|
|
||||||
for (unsigned int l = 0; l < layout.layers (); ++l) {
|
|
||||||
if (layout.is_valid_layer (l)) {
|
|
||||||
cell.clear (l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cell.clear_insts ();
|
|
||||||
|
|
||||||
cell.insert (db::CellInstArray (db::CellInst (foreign_cell->cell_index ()), db::Trans (db::Point () - origin) * foreign_trans));
|
|
||||||
m_macros_by_name.insert (std::make_pair (mn, std::make_pair (&cell, db::Trans ())));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// use FOREIGN cell instead of new one
|
|
||||||
|
|
||||||
layout.delete_cell (cell.cell_index ());
|
|
||||||
m_macros_by_name.insert (std::make_pair (mn, std::make_pair (foreign_cell, db::Trans (db::Point () - origin) * foreign_trans)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
m_macro_bboxes_by_name.insert (std::make_pair (mn, db::Box (-origin, -origin + size)));
|
|
||||||
|
|
||||||
reset_cellname ();
|
reset_cellname ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,14 +57,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
~LEFImporter ();
|
~LEFImporter ();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the cell for a macro name
|
|
||||||
*
|
|
||||||
* Returns 0 if the name is not a valid macro name. Otherwise it returns the pointer
|
|
||||||
* to the corresponding db::Cell object.
|
|
||||||
*/
|
|
||||||
std::pair<db::Cell *, db::Trans> macro_by_name (const std::string ¯o_name) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the cell bbox for the given macro name
|
* @brief Get the cell bbox for the given macro name
|
||||||
*/
|
*/
|
||||||
@@ -126,6 +118,16 @@ public:
|
|||||||
return m_vias;
|
return m_vias;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the
|
||||||
|
*
|
||||||
|
* The map maps the macro name to the macro description.
|
||||||
|
*/
|
||||||
|
const std::map<std::string, MacroDesc> ¯os () const
|
||||||
|
{
|
||||||
|
return m_macros;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void do_read (db::Layout &layout);
|
void do_read (db::Layout &layout);
|
||||||
|
|
||||||
@@ -134,16 +136,13 @@ private:
|
|||||||
std::map<std::string, std::pair<double, double> > m_default_widths;
|
std::map<std::string, std::pair<double, double> > m_default_widths;
|
||||||
std::map<std::string, double> m_default_ext;
|
std::map<std::string, double> m_default_ext;
|
||||||
std::map<std::string, std::pair<double, double> > m_min_widths;
|
std::map<std::string, std::pair<double, double> > m_min_widths;
|
||||||
std::map<std::string, std::pair<db::Cell *, db::Trans> > m_macros_by_name;
|
std::map<std::string, MacroDesc> m_macros;
|
||||||
std::map<std::string, db::Box> m_macro_bboxes_by_name;
|
|
||||||
std::map<std::string, ViaDesc> m_vias;
|
std::map<std::string, ViaDesc> m_vias;
|
||||||
std::set<std::string> m_routing_layers, m_cut_layers;
|
std::set<std::string> m_routing_layers, m_cut_layers;
|
||||||
std::map<std::string, unsigned int> m_num_masks;
|
std::map<std::string, unsigned int> m_num_masks;
|
||||||
|
|
||||||
std::vector <db::Trans> get_iteration (db::Layout &layout);
|
std::vector <db::Trans> get_iteration (double dbu);
|
||||||
// @@@
|
void read_geometries (GeometryBasedLayoutGenerator *lg, double dbu, LayerPurpose purpose, std::map<std::string, db::Box> *collect_bboxes = 0, properties_id_type prop_id = 0);
|
||||||
void read_geometries (db::Layout &layout, db::Cell &cell, LayerPurpose purpose, std::map<std::string, db::Box> *collect_bboxes = 0, properties_id_type prop_id = 0);
|
|
||||||
// void read_geometries (GeometryBasedLayoutGenerator *lg, LayerPurpose purpose, std::map<std::string, db::Box> *collect_bboxes = 0, properties_id_type prop_id = 0);
|
|
||||||
void read_nondefaultrule (Layout &layout);
|
void read_nondefaultrule (Layout &layout);
|
||||||
void read_viadef (Layout &layout);
|
void read_viadef (Layout &layout);
|
||||||
void read_viadef_by_rule (RuleBasedViaGenerator *vg, ViaDesc &desc, const std::string &n, double dbu);
|
void read_viadef_by_rule (RuleBasedViaGenerator *vg, ViaDesc &desc, const std::string &n, double dbu);
|
||||||
|
|||||||
Reference in New Issue
Block a user