Enhancement: added optional layer/datatype information to DRC/LVS 'name'

This commit is contained in:
Matthias Koefferlein 2024-06-16 19:33:24 +02:00
parent 24a9e6824a
commit 579da640ba
6 changed files with 86 additions and 12 deletions

View File

@ -1008,7 +1008,7 @@ std::string LayoutToNetlist::name (const ShapeCollection &coll) const
} }
} }
void LayoutToNetlist::register_layer (const ShapeCollection &collection, const std::string &n_in) unsigned int LayoutToNetlist::register_layer (const ShapeCollection &collection, const std::string &n_in)
{ {
if (m_region_by_original.find (tl::id_of (collection.get_delegate ())) != m_region_by_original.end ()) { if (m_region_by_original.find (tl::id_of (collection.get_delegate ())) != m_region_by_original.end ()) {
throw tl::Exception (tl::to_string (tr ("The layer is already registered"))); throw tl::Exception (tl::to_string (tr ("The layer is already registered")));
@ -1042,10 +1042,14 @@ void LayoutToNetlist::register_layer (const ShapeCollection &collection, const s
} }
unsigned int layer = dl.layer ();
m_region_by_original [tl::id_of (collection.get_delegate ())] = dl; m_region_by_original [tl::id_of (collection.get_delegate ())] = dl;
m_region_of_layer [dl.layer ()] = dl; m_region_of_layer [layer] = dl;
m_named_regions [n] = dl; m_named_regions [n] = dl;
m_name_of_layer [dl.layer ()] = n; m_name_of_layer [layer] = n;
return layer;
} }
db::DeepLayer LayoutToNetlist::deep_layer_of (const db::ShapeCollection &coll) const db::DeepLayer LayoutToNetlist::deep_layer_of (const db::ShapeCollection &coll) const

View File

@ -317,7 +317,7 @@ public:
* In addition to regions, text collections can be registered too. * In addition to regions, text collections can be registered too.
* Including texts in "connect" makes net names begin assigned from the text strings. * Including texts in "connect" makes net names begin assigned from the text strings.
*/ */
void register_layer (const ShapeCollection &collection, const std::string &name = std::string ()); unsigned int register_layer (const ShapeCollection &collection, const std::string &name = std::string ());
/** /**
* @brief Gets the name of the given collection * @brief Gets the name of the given collection

View File

@ -330,11 +330,16 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
gsi::method ("layer_name", (std::string (db::LayoutToNetlist::*) (const db::ShapeCollection &region) const) &db::LayoutToNetlist::name, gsi::arg ("l"), gsi::method ("layer_name", (std::string (db::LayoutToNetlist::*) (const db::ShapeCollection &region) const) &db::LayoutToNetlist::name, gsi::arg ("l"),
"@brief Gets the name of the given layer\n" "@brief Gets the name of the given layer\n"
) + ) +
gsi::method ("layer_index", (unsigned int (db::LayoutToNetlist::*) (const db::ShapeCollection &region) const) &db::LayoutToNetlist::layer_of<db::ShapeCollection>, gsi::arg ("l"),
"@brief Gets the layer index for the given data object\n"
"This method has been introduced in version 0.29.3.\n"
) +
gsi::method ("layer_name", (std::string (db::LayoutToNetlist::*) (unsigned int) const) &db::LayoutToNetlist::name, gsi::arg ("l"), gsi::method ("layer_name", (std::string (db::LayoutToNetlist::*) (unsigned int) const) &db::LayoutToNetlist::name, gsi::arg ("l"),
"@brief Gets the name of the given layer (by index)\n" "@brief Gets the name of the given layer (by index)\n"
) + ) +
gsi::method ("register", (void (db::LayoutToNetlist::*) (const db::ShapeCollection &collection, const std::string &)) &db::LayoutToNetlist::register_layer, gsi::arg ("l"), gsi::arg ("n", std::string ()), gsi::method ("register", (unsigned int (db::LayoutToNetlist::*) (const db::ShapeCollection &collection, const std::string &)) &db::LayoutToNetlist::register_layer, gsi::arg ("l"), gsi::arg ("n", std::string ()),
"@brief Names the given layer\n" "@brief Names the given layer\n"
"@return The index of the layer registered\n"
"'l' must be a \\Region or \\Texts object.\n" "'l' must be a \\Region or \\Texts object.\n"
"Flat regions or text collections must be registered with this function, before they can be used in \\connect. " "Flat regions or text collections must be registered with this function, before they can be used in \\connect. "
"Registering will copy the shapes into the LayoutToNetlist object in this step to enable " "Registering will copy the shapes into the LayoutToNetlist object in this step to enable "
@ -346,7 +351,7 @@ Class<db::LayoutToNetlist> decl_dbLayoutToNetlist ("db", "LayoutToNetlist",
"\n" "\n"
"If required, the system will assign a name automatically." "If required, the system will assign a name automatically."
"\n" "\n"
"This method has been generalized in version 0.27.\n" "This method has been generalized in version 0.27. Starting with version 0.29.3, the index of the layer is returned.\n"
) + ) +
gsi::method_ext ("layer_names", &l2n_layer_names, gsi::method_ext ("layer_names", &l2n_layer_names,
"@brief Returns a list of names of the layers kept inside the LayoutToNetlist object." "@brief Returns a list of names of the layers kept inside the LayoutToNetlist object."

View File

@ -299,6 +299,8 @@ module DRC
# @name name # @name name
# @brief Assigns a name to a layer # @brief Assigns a name to a layer
# @synopsis name(layer, name) # @synopsis name(layer, name)
# @synopsis name(layer, name, layer_number, datatype_number)
# @synopsis name(layer, name, layer_info)
# Layer names are listed in the LayoutToNetlist (L2N) or LVS database. They # Layer names are listed in the LayoutToNetlist (L2N) or LVS database. They
# are used to identify the layers, the net or device terminal geometries are # are used to identify the layers, the net or device terminal geometries are
# on. It is usual to have computed layers, so it is necessary to indicate the # on. It is usual to have computed layers, so it is necessary to indicate the
@ -325,6 +327,12 @@ module DRC
# #
# \name can only be used once on a layer and the layer names must be # \name can only be used once on a layer and the layer names must be
# unique (not taken by another layer). # unique (not taken by another layer).
#
# The layer/datatype or LayerInfo specification is optional and will
# be used to configure the internal layout. This information is also
# persisted inside database files. Specifying a layer/datatype information
# is useful, if a layer is not an original layer, but is to be restored
# to an actual layout layer later.
# %DRC% # %DRC%
# @name name_prefix # @name name_prefix
@ -332,13 +340,33 @@ module DRC
# @synopsis name_prefix(prefix) # @synopsis name_prefix(prefix)
# See \\name for details. The default prefix is "l". # See \\name for details. The default prefix is "l".
def name(l, name) def name(*args)
@engine._context("name") do @engine._context("name") do
if args.size < 2 || args.size > 4
raise("Two to four arguments expected (layer, name, [layer, datatype / layer properties])")
end
l = args[0]
l.is_a?(DRC::DRCLayer) || raise("First argument must be a layer") l.is_a?(DRC::DRCLayer) || raise("First argument must be a layer")
name = args[1]
(name.is_a?(String) && name != "") || raise("Second argument must be a non-empty string") (name.is_a?(String) && name != "") || raise("Second argument must be a non-empty string")
lp = args[2]
if lp
if !lp.is_a?(RBA::LayerInfo)
lnum = args[2]
dnum = args[3] || 0
lnum.is_a?(1.class) || raise("Layer argument needs to be a RBA::LayerInfo object or a layer number")
dnum.is_a?(1.class) || raise("Datatype argument needs to be an integer")
lp = RBA::LayerInfo::new(lnum, dnum)
elsif args[3]
raise("Three arguments are enough with RBA::LayerInfo")
end
end
id = l.data.data_id id = l.data.data_id
if @layers && @layers[id] if @layers && @layers[id]
@ -349,7 +377,7 @@ module DRC
return return
end end
self._register_layer(l.data, "name", name) self._register_layer(l.data, "name", name, lp)
end end
@ -828,7 +856,7 @@ module DRC
protected protected
def _register_layer(data, context, name = nil) def _register_layer(data, context, name = nil, lp = nil)
id = data.data_id id = data.data_id
ensure_data ensure_data
@ -846,7 +874,12 @@ module DRC
@layers[id] = [ data, name, context ] @layers[id] = [ data, name, context ]
# every layer gets registered and intra-layer connections are made # every layer gets registered and intra-layer connections are made
@l2n.register(data, name) index = @l2n.register(data, name)
# set the layer properties if requested
if lp
@l2n.internal_layout.set_info(index, lp)
end
end end

View File

@ -1911,3 +1911,35 @@ TEST(121_ShapesOfTerminal)
db::compare_layouts (_this, layout, au, db::NoNormalization); db::compare_layouts (_this, layout, au, db::NoNormalization);
} }
TEST(122_NamedLayers)
{
std::string rs = tl::testdata ();
rs += "/drc/drcSimpleTests_122.drc";
std::string input = tl::testdata ();
input += "/drc/drcSimpleTests_122.gds";
std::string au_output = tl::testdata ();
au_output += "/drc/drcSimpleTests_au122.l2n";
std::string output = this->tmp_file ("tmp.l2n");
{
// Set some variables
lym::Macro config;
config.set_text (tl::sprintf (
"$drc_test_source = '%s'\n"
"$drc_test_target = '%s'\n"
, input, output)
);
config.set_interpreter (lym::Macro::Ruby);
EXPECT_EQ (config.run (), 0);
}
lym::Macro drc;
drc.load_from (rs);
EXPECT_EQ (drc.run (), 0);
compare_text_files (output, au_output);
}

View File

@ -19,9 +19,9 @@ gate = active & poly
name(l1, "l1") name(l1, "l1")
name(l2, "l2") name(l2, "l2")
name(l3, "l3") name(l3, "l3")
name(sd, "sd") name(sd, "sd", 17, 0)
name(poly, "poly") name(poly, "poly")
name(gate, "gate") name(gate, "gate", RBA::LayerInfo::new(18, 0))
name(contact, "contact") name(contact, "contact")
mos_ex = RBA::DeviceExtractorMOS3Transistor::new("MOS") mos_ex = RBA::DeviceExtractorMOS3Transistor::new("MOS")