Extension of the L2N/LVSDB format to support deleted terminals and parameters

Previously, when deleting parameters or terminals from device
definitions, these parameters or terminals re-appeared in the
netlist browser, because they were generated from the
template class (e.g. "A" and "B" from "RES").

An additional token is added that indicates whether to
remove all entries before adding new ones.

This feature is backward-compatible and LVSDB/L2N files have to
be generated from new KLayout versions to make use of that
feature.
This commit is contained in:
Matthias Koefferlein 2025-05-31 17:33:44 +02:00
parent 5173a2aad7
commit f2172d8e2a
3 changed files with 38 additions and 7 deletions

View File

@ -79,7 +79,10 @@ namespace db
* circuit(<name> [circuit-def]) - circuit (cell) [short key: X]
*
* [class]:
* class(<name> <template> [template-def]) - a device class definition (template: RES,CAP,...) [short key: K]
* class(<name> <template> <full-specs>? [template-def]) - a device class definition (template: RES,CAP,...) [short key: K]
* "fill_specs" is an optional value (0 or 1), indicating that all parameters and terminals
* are listed. For "1", the reader will remove all specs from the template before rebuilding
* them.
*
* [device]:
* device(<name> <class> [device-abstract-terminal|any]*)
@ -158,8 +161,8 @@ namespace db
* [template-param|template-terminal|any]*
*
* [template-param]:
* param(<name> <primary>? <default-value>*) - defines a template parameter [short key: E]
* ('primary' is a value: 0 or 1)
* param(<name> <primary> <default-value>) - defines a template parameter [short key: E]
* ('primary' is a value: 0 or 1, 'default_value' is a float)
*
* [template-terminal]:
* terminal(<name>) - defines a terminal [short key: T]

View File

@ -391,6 +391,9 @@ void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::Layo
read_word_or_quoted (class_name);
read_word_or_quoted (templ_name);
int full_specs = 0;
try_read_int (full_specs);
if (netlist->device_class_by_name (class_name) != 0) {
throw tl::Exception (tl::to_string (tr ("Duplicate definition of device class: ")) + class_name);
}
@ -407,6 +410,13 @@ void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::Layo
dc = dct->create ();
}
// start with tabula rasa on "full specs"
if (full_specs != 0) {
dc->clear_equivalent_terminal_ids ();
dc->clear_parameter_definitions ();
dc->clear_terminal_definitions ();
}
dc->set_name (class_name);
netlist->add_device_class (dc);

View File

@ -294,11 +294,29 @@ void std_writer_impl<Keys>::write_device_class (TokenizedOutput &stream, const d
TokenizedOutput out (stream, Keys::class_key);
out << tl::to_word_or_quoted_string (cls->name ()) << tl::to_word_or_quoted_string (temp_name);
// we need to issue all specs if some are deleted
bool full_specs = false;
const std::vector<DeviceParameterDefinition> &pd_temp = temp_class->parameter_definitions ();
for (auto p = pd_temp.begin (); p != pd_temp.end () && ! full_specs; ++p) {
full_specs = ! cls->has_parameter_with_name (p->name ());
}
const std::vector<DeviceTerminalDefinition> &td_temp = temp_class->terminal_definitions ();
for (auto t = td_temp.begin (); t != td_temp.end () && ! full_specs; ++t) {
full_specs = ! cls->has_terminal_with_name (t->name ());
}
// new token: indicates that all specs will be listed
if (full_specs) {
out << tl::to_string (1);
}
bool any_def = false;
const std::vector<DeviceParameterDefinition> &pd = cls->parameter_definitions ();
for (std::vector<DeviceParameterDefinition>::const_iterator p = pd.begin (); p != pd.end (); ++p) {
if (! temp_class->has_parameter_with_name (p->name ()) || !same_parameter (*p, *temp_class->parameter_definition (temp_class->parameter_id_for_name (p->name ())))) {
for (auto p = pd.begin (); p != pd.end (); ++p) {
if (full_specs || ! temp_class->has_parameter_with_name (p->name ()) || !same_parameter (*p, *temp_class->parameter_definition (temp_class->parameter_id_for_name (p->name ())))) {
if (! any_def) {
out << endl;
}
@ -308,8 +326,8 @@ void std_writer_impl<Keys>::write_device_class (TokenizedOutput &stream, const d
}
const std::vector<DeviceTerminalDefinition> &td = cls->terminal_definitions ();
for (std::vector<DeviceTerminalDefinition>::const_iterator t = td.begin (); t != td.end (); ++t) {
if (! temp_class->has_terminal_with_name (t->name ())) {
for (auto t = td.begin (); t != td.end (); ++t) {
if (full_specs || ! temp_class->has_terminal_with_name (t->name ())) {
if (! any_def) {
out << endl;
}