mirror of https://github.com/KLayout/klayout.git
Tests and bug fixes for component maskshift implementation
This commit is contained in:
parent
cb1b3655e9
commit
af2bfce051
|
|
@ -1313,7 +1313,7 @@ DEFImporter::read_components (db::Layout &layout, std::list<std::pair<std::strin
|
|||
|
||||
if (is_placed) {
|
||||
|
||||
std::pair<db::Cell *, db::Trans> ct = reader_state ()->macro_cell (model, layout, string2masks (maskshift), m->second, &m_lef_importer);
|
||||
std::pair<db::Cell *, db::Trans> ct = reader_state ()->macro_cell (model, layout, m_component_maskshift, 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));
|
||||
|
|
@ -1496,6 +1496,9 @@ DEFImporter::do_read (db::Layout &layout)
|
|||
m_component_maskshift.push_back (get ());
|
||||
}
|
||||
|
||||
// because we treat the layers bottom first ..
|
||||
std::reverse (m_component_maskshift.begin (), m_component_maskshift.end ());
|
||||
|
||||
} else if (test ("COMPONENTS")) {
|
||||
|
||||
get_long ();
|
||||
|
|
|
|||
|
|
@ -122,8 +122,11 @@ RuleBasedViaGenerator::RuleBasedViaGenerator ()
|
|||
{ }
|
||||
|
||||
void
|
||||
RuleBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm)
|
||||
RuleBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, db::Cell &cell, const std::vector<std::string> *maskshift_layers, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm)
|
||||
{
|
||||
// will not be used with an external maskshift layer stack
|
||||
tl_assert (maskshift_layers == 0);
|
||||
|
||||
unsigned int mask_bottom = mask (masks, 0), mask_cut = mask (masks, 1), mask_top = mask (masks, 2);
|
||||
|
||||
if (mask_bottom == 0) {
|
||||
|
|
@ -267,41 +270,61 @@ RuleBasedViaGenerator::create_cell (LEFDEFReaderState &reader, Layout &layout, d
|
|||
// GeometryBasedViaGenerator implementation
|
||||
|
||||
GeometryBasedLayoutGenerator::GeometryBasedLayoutGenerator ()
|
||||
: LEFDEFLayoutGenerator ()
|
||||
{ }
|
||||
: LEFDEFLayoutGenerator (), m_fixedmask (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
unsigned int
|
||||
GeometryBasedLayoutGenerator::mask_for (const std::string &ln, unsigned int m, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm) const
|
||||
GeometryBasedLayoutGenerator::get_maskshift (const std::string &ln, const std::vector<std::string> *msl, const std::vector<unsigned int> &masks)
|
||||
{
|
||||
for (std::vector<std::string>::const_iterator l = m_maskshift_layers.begin (); l != m_maskshift_layers.end (); ++l) {
|
||||
|
||||
if (! l->empty () && *l == ln) {
|
||||
|
||||
unsigned int mm = mask (masks, (unsigned int) (l - m_maskshift_layers.begin ()));
|
||||
|
||||
if (m == 0 || ! nm) {
|
||||
m = mm;
|
||||
} else if (mm > 0) {
|
||||
m = (m + mm - 2) % nm->number_of_masks (ln) + 1;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (! msl) {
|
||||
msl = &m_maskshift_layers;
|
||||
}
|
||||
|
||||
return m;
|
||||
for (std::vector<std::string>::const_iterator l = msl->begin (); l != msl->end (); ++l) {
|
||||
if (! l->empty () && *l == ln) {
|
||||
return mask (masks, (unsigned int) (l - msl->begin ()));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
GeometryBasedLayoutGenerator::mask_for (const std::string &ln, unsigned int m, unsigned int mshift, const LEFDEFNumberOfMasks *nm) const
|
||||
{
|
||||
// for FIXEDMASK we don't do any mask shifting
|
||||
if (m_fixedmask || m == 0 || mshift == 0 || !nm) {
|
||||
return m;
|
||||
} else {
|
||||
return (m + mshift - 2) % nm->number_of_masks (ln) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
GeometryBasedLayoutGenerator::combine_maskshifts (const std::string &ln, unsigned int mshift1, unsigned int mshift2, const LEFDEFNumberOfMasks *nm) const
|
||||
{
|
||||
if (mshift1 == 0 || mshift2 == 0) {
|
||||
return mshift1 + mshift2;
|
||||
} else {
|
||||
return (mshift1 + mshift2 - 2) % nm->number_of_masks (ln) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
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<std::string> *ext_msl, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm)
|
||||
{
|
||||
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) {
|
||||
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));
|
||||
|
||||
unsigned int mshift = get_maskshift (g->first.first, ext_msl, masks);
|
||||
unsigned int mask = mask_for (g->first.first, g->first.second.second, mshift, nm);
|
||||
|
||||
std::pair <bool, unsigned int> dl = reader.open_layer (layout, g->first.first, g->first.second.first, mask);
|
||||
if (dl.first) {
|
||||
cell.shapes (dl.second).insert (g->second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (std::list<Via>::const_iterator v = m_vias.begin (); v != m_vias.end (); ++v) {
|
||||
|
|
@ -314,10 +337,14 @@ GeometryBasedLayoutGenerator::create_cell (LEFDEFReaderState &reader, Layout &la
|
|||
std::vector<std::string> msl = g->maskshift_layers ();
|
||||
msl.resize (3, std::string ());
|
||||
|
||||
unsigned mshift_bottom = get_maskshift (msl [0], ext_msl, masks);
|
||||
unsigned mshift_cut = get_maskshift (msl [1], ext_msl, masks);
|
||||
unsigned mshift_top = get_maskshift (msl [2], ext_msl, masks);
|
||||
|
||||
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),
|
||||
combine_maskshifts (msl [0], v->bottom_mask, mshift_bottom, nm),
|
||||
combine_maskshifts (msl [1], v->cut_mask, mshift_cut, nm),
|
||||
combine_maskshifts (msl [2], v->top_mask, mshift_top, nm),
|
||||
nm);
|
||||
|
||||
if (vc) {
|
||||
|
|
@ -1292,7 +1319,7 @@ LEFDEFReaderState::via_cell (const std::string &vn, db::Layout &layout, unsigned
|
|||
masks.push_back (mask_cut);
|
||||
masks.push_back (mask_top);
|
||||
|
||||
vg->create_cell (*this, layout, *cell, masks, nm);
|
||||
vg->create_cell (*this, layout, *cell, 0, masks, nm);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -1326,9 +1353,22 @@ LEFDEFReaderState::macro_generator (const std::string &mn)
|
|||
}
|
||||
|
||||
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)
|
||||
LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std::vector<std::string> &maskshift_layers, const std::vector<unsigned int> &masks, const MacroDesc ¯o_desc, const LEFDEFNumberOfMasks *nm)
|
||||
{
|
||||
MacroKey mk (mn, masks);
|
||||
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;
|
||||
|
||||
MacroKey mk;
|
||||
if (mg->is_fixedmask ()) {
|
||||
mk = MacroKey (mn, std::vector<unsigned int> ());
|
||||
} else {
|
||||
mk = MacroKey (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);
|
||||
|
|
@ -1338,13 +1378,6 @@ LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std:
|
|||
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;
|
||||
|
|
@ -1392,15 +1425,22 @@ LEFDEFReaderState::macro_cell (const std::string &mn, Layout &layout, const std:
|
|||
// 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);
|
||||
if (! mg->is_fixedmask ()) {
|
||||
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);
|
||||
|
||||
if (mg->is_fixedmask ()) {
|
||||
mg->create_cell (*this, layout, *cell, 0, std::vector<unsigned int> (), nm);
|
||||
} else {
|
||||
mg->create_cell (*this, layout, *cell, &maskshift_layers, masks, nm);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -888,8 +888,9 @@ public:
|
|||
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<std::string> *maskshift_layers, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm) = 0;
|
||||
virtual std::vector<std::string> maskshift_layers () const = 0;
|
||||
virtual bool is_fixedmask () const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -901,7 +902,7 @@ class DB_PLUGIN_PUBLIC RuleBasedViaGenerator
|
|||
public:
|
||||
RuleBasedViaGenerator ();
|
||||
|
||||
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<std::string> *maskshift_layers, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm);
|
||||
|
||||
virtual std::vector<std::string> maskshift_layers () const
|
||||
{
|
||||
|
|
@ -912,6 +913,11 @@ public:
|
|||
return msl;
|
||||
}
|
||||
|
||||
virtual bool is_fixedmask () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void set_cutsize (const db::Vector &cutsize) { m_cutsize = cutsize; }
|
||||
void set_cutspacing (const db::Vector &cutspacing) { m_cutspacing = cutspacing; }
|
||||
void set_offset (const db::Point &offset) { m_offset = offset; }
|
||||
|
|
@ -947,17 +953,11 @@ class DB_PLUGIN_PUBLIC GeometryBasedLayoutGenerator
|
|||
: public LEFDEFLayoutGenerator
|
||||
{
|
||||
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 ();
|
||||
|
||||
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<std::string> *maskshift_layers, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *num_cut_masks);
|
||||
virtual std::vector<std::string> maskshift_layers () const { return m_maskshift_layers; }
|
||||
virtual bool is_fixedmask () const { return m_fixedmask; }
|
||||
|
||||
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, LayerPurpose purpose, const db::Box &box, unsigned int mask, properties_id_type prop_id);
|
||||
|
|
@ -975,12 +975,27 @@ public:
|
|||
m_maskshift_layers[l] = s;
|
||||
}
|
||||
|
||||
void set_fixedmask (bool f)
|
||||
{
|
||||
m_fixedmask = f;
|
||||
}
|
||||
|
||||
private:
|
||||
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;
|
||||
};
|
||||
|
||||
std::map <std::pair<std::string, std::pair<LayerPurpose, unsigned int> >, db::Shapes> m_shapes;
|
||||
std::list<Via> m_vias;
|
||||
std::vector<std::string> m_maskshift_layers;
|
||||
bool m_fixedmask;
|
||||
|
||||
unsigned int mask_for (const std::string &ln, unsigned int m, const std::vector<unsigned int> &masks, const LEFDEFNumberOfMasks *nm) const;
|
||||
unsigned int get_maskshift (const std::string &ln, const std::vector<std::string> *maskshift_layers, const std::vector<unsigned int> &masks);
|
||||
unsigned int mask_for (const std::string &ln, unsigned int m, unsigned int mshift, const LEFDEFNumberOfMasks *nm) const;
|
||||
unsigned int combine_maskshifts (const std::string &ln, unsigned int mshift1, unsigned int mshift2, const LEFDEFNumberOfMasks *nm) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1058,7 +1073,7 @@ public:
|
|||
/**
|
||||
* @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);
|
||||
std::pair<db::Cell *, db::Trans> macro_cell (const std::string &mn, Layout &layout, const std::vector<std::string> &maskshift_layers, 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
|
||||
|
|
@ -1114,6 +1129,9 @@ private:
|
|||
*/
|
||||
struct MacroKey
|
||||
{
|
||||
MacroKey ()
|
||||
{ }
|
||||
|
||||
MacroKey (const std::string &n, const std::vector<unsigned int> &m)
|
||||
: name (n), masks (m)
|
||||
{ }
|
||||
|
|
|
|||
|
|
@ -939,7 +939,7 @@ LEFImporter::read_macro (Layout &layout)
|
|||
|
||||
} else if (test ("FIXEDMASK")) {
|
||||
|
||||
// we do actually expect FIXEDMASK to be the case always.
|
||||
mg->set_fixedmask (true);
|
||||
expect (";");
|
||||
|
||||
} else {
|
||||
|
|
@ -1068,7 +1068,7 @@ void
|
|||
LEFImporter::finish_lef (db::Layout &layout)
|
||||
{
|
||||
for (std::map<std::string, MacroDesc>::const_iterator m = m_macros.begin (); m != m_macros.end (); ++m) {
|
||||
reader_state ()->macro_cell (m->first, layout, std::vector<unsigned int> (), m->second, this);
|
||||
reader_state ()->macro_cell (m->first, layout, std::vector<std::string> (), std::vector<unsigned int> (), m->second, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -541,6 +541,14 @@ TEST(114_lef_skips_end_library)
|
|||
run_test (_this, "lef-skips-end-library", "lef:in.lef+def:in.def", "au.oas", opt, false);
|
||||
}
|
||||
|
||||
TEST(115_componentmaskshift)
|
||||
{
|
||||
db::LEFDEFReaderOptions options = default_options ();
|
||||
options.set_map_file ("in.map");
|
||||
|
||||
run_test (_this, "masks-2", "lef:in_tech.lef+lef:in.lef+def:in.def", "au.oas.gz", options, false);
|
||||
}
|
||||
|
||||
TEST(200_lefdef_plugin)
|
||||
{
|
||||
db::Layout ly;
|
||||
|
|
|
|||
|
|
@ -1,25 +1,25 @@
|
|||
LAYER M0PO
|
||||
TYPE MASTERSLICE ;
|
||||
WIDTH 0.02 ;
|
||||
MASKS 2 ;
|
||||
MASK 2 ;
|
||||
END M0PO
|
||||
LAYER VIA0
|
||||
TYPE CUT ;
|
||||
MASKS 2 ;
|
||||
MASK 2 ;
|
||||
END VIA0
|
||||
LAYER M1
|
||||
TYPE MASTERSLICE ;
|
||||
WIDTH 0.024 ;
|
||||
MASKS 2 ;
|
||||
MASK 2 ;
|
||||
END M1
|
||||
LAYER VIA1
|
||||
TYPE CUT ;
|
||||
MASKS 2 ;
|
||||
MASK 2 ;
|
||||
END VIA1
|
||||
LAYER M2
|
||||
TYPE MASTERSLICE ;
|
||||
WIDTH 0.03 ;
|
||||
MASKS 2 ;
|
||||
MASK 2 ;
|
||||
END M2
|
||||
|
||||
VIA square
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue