Tests and bug fixes for component maskshift implementation

This commit is contained in:
Matthias Koefferlein 2020-08-23 18:58:52 +02:00
parent cb1b3655e9
commit af2bfce051
7 changed files with 129 additions and 60 deletions

View File

@ -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 ();

View File

@ -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 &macro_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 &macro_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);
}
}

View File

@ -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 &macro_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 &macro_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)
{ }

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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

BIN
testdata/lefdef/masks-2/au.oas.gz vendored Normal file

Binary file not shown.