From 19ded2d784b6b84ad7c9c80c379c4f2c8d282af4 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Thu, 21 May 2026 00:05:57 +0200 Subject: [PATCH] WIP --- src/db/db/dbDevice.cc | 21 ++- src/db/db/dbDevice.h | 19 ++- src/db/db/dbDeviceClass.cc | 42 ++++-- src/db/db/dbDeviceClass.h | 21 ++- src/db/db/dbLayoutToNetlistFormatDefs.cc | 8 ++ src/db/db/dbLayoutToNetlistFormatDefs.h | 23 ++- src/db/db/dbLayoutToNetlistReader.cc | 163 ++++++++++++++++++---- src/db/db/dbLayoutToNetlistReader.h | 2 + src/db/db/dbLayoutToNetlistWriter.cc | 27 +++- src/db/db/dbNetlistCompareUtils.cc | 4 +- src/db/db/dbNetlistDeviceClasses.cc | 94 ++++++------- src/db/db/dbNetlistDeviceExtractor.h | 2 +- src/db/db/dbNetlistSpiceReaderDelegate.cc | 7 +- src/db/db/dbNetlistSpiceWriter.cc | 3 +- src/db/db/gsiDeclDbNetlist.cc | 9 +- src/db/unit_tests/dbNetlistTests.cc | 20 +-- src/layui/layui/layNetlistBrowserModel.cc | 16 ++- 17 files changed, 356 insertions(+), 125 deletions(-) diff --git a/src/db/db/dbDevice.cc b/src/db/db/dbDevice.cc index 4e4b36e16..b889e26e8 100644 --- a/src/db/db/dbDevice.cc +++ b/src/db/db/dbDevice.cc @@ -163,7 +163,7 @@ void Device::connect_terminal (size_t terminal_id, Net *net) } } -double Device::parameter_value (size_t param_id) const +const tl::Variant &Device::parameter_value (size_t param_id) const { if (m_parameters.size () > param_id) { return m_parameters [param_id]; @@ -173,10 +173,11 @@ double Device::parameter_value (size_t param_id) const return pd->default_value (); } } - return 0.0; + static tl::Variant dummy_value (0.0); + return dummy_value; } -void Device::set_parameter_value (size_t param_id, double v) +void Device::set_parameter_value (size_t param_id, const tl::Variant &v) { if (m_parameters.size () <= param_id) { @@ -198,18 +199,26 @@ void Device::set_parameter_value (size_t param_id, double v) m_parameters [param_id] = v; } -double Device::parameter_value (const std::string &name) const +const tl::Variant &Device::parameter_value (const std::string &name) const { - return device_class () ? parameter_value (device_class ()->parameter_id_for_name (name)) : 0.0; + static tl::Variant dummy_value (0.0); + return device_class () ? parameter_value (device_class ()->parameter_id_for_name (name)) : dummy_value; } -void Device::set_parameter_value (const std::string &name, double v) +void Device::set_parameter_value (const std::string &name, const tl::Variant &v) { if (device_class ()) { set_parameter_value (device_class ()->parameter_id_for_name (name), v); } } +void Device::set_parameter_value_create (const std::string &name, const tl::Variant &v, bool primary, const tl::Variant &def_value) +{ + if (device_class ()) { + set_parameter_value (device_class ()->parameter_id_for_name_create (name, primary, def_value), v); + } +} + void Device::add_others_terminals (unsigned int this_terminal, db::Device *other, unsigned int other_terminal) { std::vector &terminals = m_reconnected_terminals [this_terminal]; diff --git a/src/db/db/dbDevice.h b/src/db/db/dbDevice.h index bf7e4dd32..47056f7a4 100644 --- a/src/db/db/dbDevice.h +++ b/src/db/db/dbDevice.h @@ -283,24 +283,33 @@ public: /** * @brief Gets the value for the parameter with the given ID */ - double parameter_value (size_t param_id) const; + const tl::Variant ¶meter_value (size_t param_id) const; /** * @brief Sets the value for the parameter with the given ID */ - void set_parameter_value (size_t param_id, double v); + void set_parameter_value (size_t param_id, const tl::Variant &v); /** * @brief Gets the value for the parameter with the given name * If the name is not valid, an exception is thrown. */ - double parameter_value (const std::string &name) const; + const tl::Variant ¶meter_value (const std::string &name) const; /** * @brief Sets the value for the parameter with the given name * If the name is not valid, an exception is thrown. */ - void set_parameter_value (const std::string &name, double v); + void set_parameter_value (const std::string &name, const tl::Variant &v); + + /** + * @brief Sets the value for the parameter with the given name + * + * If the name is not valid, the parameter is created with the given primary + * flag and default value. The default value also defines the type of the + * parameter. + */ + void set_parameter_value_create (const std::string &name, const tl::Variant &v, bool primary, const tl::Variant &def_value); /** * @brief Used for device combination: join terminals with other device @@ -402,7 +411,7 @@ private: std::string m_name; db::DCplxTrans m_trans; std::vector m_terminal_refs; - std::vector m_parameters; + std::vector m_parameters; size_t m_id; Circuit *mp_circuit; std::vector m_other_abstracts; diff --git a/src/db/db/dbDeviceClass.cc b/src/db/db/dbDeviceClass.cc index 8aeec11d0..c2bd5eb0b 100644 --- a/src/db/db/dbDeviceClass.cc +++ b/src/db/db/dbDeviceClass.cc @@ -121,9 +121,17 @@ std::string EqualDeviceParameters::to_string () const bool EqualDeviceParameters::less (const db::Device &a, const db::Device &b) const { for (std::vector > >::const_iterator c = m_compare_set.begin (); c != m_compare_set.end (); ++c) { - int cmp = compare_parameters (a.parameter_value (c->first), b.parameter_value (c->first), c->second.first, c->second.second); - if (cmp != 0) { - return cmp < 0; + const tl::Variant &va = a.parameter_value (c->first); + const tl::Variant &vb = b.parameter_value (c->first); + if (va.is_double () && vb.is_double ()) { + int cmp = compare_parameters (va.to_double (), vb.to_double (), c->second.first, c->second.second); + if (cmp != 0) { + return cmp < 0; + } + } else { + if (va != vb) { + return va < vb; + } } } @@ -137,9 +145,17 @@ bool EqualDeviceParameters::less (const db::Device &a, const db::Device &b) cons const std::vector &pd = primary_device_class (a, b)->parameter_definitions (); for (std::vector::const_iterator p = pd.begin (); p != pd.end (); ++p) { if (p->is_primary () && seen.find (p->id ()) == seen.end ()) { - int cmp = compare_parameters (a.parameter_value (p->id ()), b.parameter_value (p->id ())); - if (cmp != 0) { - return cmp < 0; + const tl::Variant &va = a.parameter_value (p->id ()); + const tl::Variant &vb = b.parameter_value (p->id ()); + if (va.is_double () && vb.is_double ()) { + int cmp = compare_parameters (va.to_double (), vb.to_double ()); + if (cmp != 0) { + return cmp < 0; + } + } else { + if (va != vb) { + return va < vb; + } } } } @@ -168,9 +184,17 @@ bool AllDeviceParametersAreEqual::less (const db::Device &a, const db::Device &b { const std::vector ¶meters = a.device_class ()->parameter_definitions (); for (std::vector::const_iterator c = parameters.begin (); c != parameters.end (); ++c) { - int cmp = compare_parameters (a.parameter_value (c->id ()), b.parameter_value (c->id ()), 0.0, m_relative); - if (cmp != 0) { - return cmp < 0; + const tl::Variant &va = a.parameter_value (c->id ()); + const tl::Variant &vb = b.parameter_value (c->id ()); + if (va.is_double () && vb.is_double ()) { + int cmp = compare_parameters (va.to_double (), vb.to_double (), 0.0, m_relative); + if (cmp != 0) { + return cmp < 0; + } + } else { + if (va != vb) { + return va < vb; + } } } diff --git a/src/db/db/dbDeviceClass.h b/src/db/db/dbDeviceClass.h index 51f26ecc7..d92501c44 100644 --- a/src/db/db/dbDeviceClass.h +++ b/src/db/db/dbDeviceClass.h @@ -154,7 +154,7 @@ public: /** * @brief Creates a device parameter definition with the given name and description */ - DeviceParameterDefinition (const std::string &name, const std::string &description, double default_value = 0.0, bool is_primary = true, double si_scaling = 1.0, double geo_scaling = 0.0) + DeviceParameterDefinition (const std::string &name, const std::string &description, tl::Variant default_value = tl::Variant (0.0), bool is_primary = true, double si_scaling = 1.0, double geo_scaling = 0.0) : m_name (name), m_description (description), m_default_value (default_value), m_id (0), m_is_primary (is_primary), m_si_scaling (si_scaling), m_geo_scaling (geo_scaling) { // .. nothing yet .. @@ -234,7 +234,7 @@ public: /** * @brief Gets the parameter default value */ - double default_value () const + const tl::Variant &default_value () const { return m_default_value; } @@ -242,7 +242,7 @@ public: /** * @brief Sets the parameter default value */ - void set_default_value (double d) + void set_default_value (const tl::Variant &d) { m_default_value = d; } @@ -291,7 +291,7 @@ private: friend class DeviceClass; std::string m_name, m_description; - double m_default_value; + tl::Variant m_default_value; size_t m_id; bool m_is_primary; double m_si_scaling; @@ -578,6 +578,19 @@ public: */ size_t parameter_id_for_name (const std::string &name) const; + /** + * @brief Returns the parameter ID for the parameter with the given name + * + * A new parameter definition is created, if the parameter does not exist yes. + * + * @param name The name of the parameter + * @param primary The primary flag of the new parameter, if it does not exist yet + * @param default_value The default value of the new parameter, if it does not exist yet + * + * The default value also declares the type. + */ + size_t parameter_id_for_name_create (const std::string &name, bool primary, const tl::Variant &default_value) const; + /** * @brief Returns true, if the device has a terminal with the given name */ diff --git a/src/db/db/dbLayoutToNetlistFormatDefs.cc b/src/db/db/dbLayoutToNetlistFormatDefs.cc index 03aa0afbd..87f5451a1 100644 --- a/src/db/db/dbLayoutToNetlistFormatDefs.cc +++ b/src/db/db/dbLayoutToNetlistFormatDefs.cc @@ -53,6 +53,10 @@ namespace l2n_std_format DB_PUBLIC std::string LongKeys::terminal_key ("terminal"); DB_PUBLIC std::string LongKeys::abstract_key ("abstract"); DB_PUBLIC std::string LongKeys::param_key ("param"); + DB_PUBLIC std::string LongKeys::param_int_key ("param-int"); + DB_PUBLIC std::string LongKeys::param_string_key ("param-string"); + DB_PUBLIC std::string LongKeys::param_var_key ("param-var"); + DB_PUBLIC std::string LongKeys::param_nil_key ("param-nil"); DB_PUBLIC std::string LongKeys::location_key ("location"); DB_PUBLIC std::string LongKeys::rotation_key ("rotation"); DB_PUBLIC std::string LongKeys::mirror_key ("mirror"); @@ -88,6 +92,10 @@ namespace l2n_std_format DB_PUBLIC std::string ShortKeys::terminal_key ("T"); DB_PUBLIC std::string ShortKeys::abstract_key ("A"); DB_PUBLIC std::string ShortKeys::param_key ("E"); + DB_PUBLIC std::string ShortKeys::param_int_key ("EI"); + DB_PUBLIC std::string ShortKeys::param_string_key ("ES"); + DB_PUBLIC std::string ShortKeys::param_var_key ("EV"); + DB_PUBLIC std::string ShortKeys::param_nil_key ("EN"); DB_PUBLIC std::string ShortKeys::location_key ("Y"); DB_PUBLIC std::string ShortKeys::rotation_key ("O"); DB_PUBLIC std::string ShortKeys::mirror_key ("M"); diff --git a/src/db/db/dbLayoutToNetlistFormatDefs.h b/src/db/db/dbLayoutToNetlistFormatDefs.h index 3909bb779..55da0c13a 100644 --- a/src/db/db/dbLayoutToNetlistFormatDefs.h +++ b/src/db/db/dbLayoutToNetlistFormatDefs.h @@ -163,6 +163,15 @@ namespace db * [template-param]: * param( ) - defines a template parameter [short key: E] * ('primary' is a value: 0 or 1, 'default_value' is a float) + * param-int( ) - defines a template parameter [short key: EI] + * ('primary' is a value: 0 or 1, 'default_value' is an int) + * param-string( ) - defines a template parameter [short key: ES] + * ('primary' is a value: 0 or 1, 'default_value' is a string) + * param-var( ) - defines a template parameter [short key: EV] + * ('primary' is a value: 0 or 1, 'default_value' is a string encoding the default + * value in KLayout variant notation) + * param-nil( ) - defines a template parameter [short key: EN] + * ('primary' is a value: 0 or 1) * * [template-terminal]: * terminal() - defines a terminal [short key: T] @@ -172,7 +181,11 @@ namespace db * - specifies the terminal geometry [short key: T] * * [param]: - * param( ) - defines a parameter [short key: E] + * param( ) - defines a parameter with a default value [short key: E] + * param-int( ) - defines a parameter with an int value [short key: EI] + * param-nil() - defines a parameter with a nil value [short key: EN] + * param-string( ) - defines a parameter with a string value [short key: ES] + * param-var( ) - defines a parameter with a variant value [short key: EV] * * [device-terminal]: * terminal( ) @@ -246,6 +259,10 @@ namespace l2n_std_format static std::string terminal_key; static std::string abstract_key; static std::string param_key; + static std::string param_int_key; + static std::string param_string_key; + static std::string param_var_key; + static std::string param_nil_key; static std::string location_key; static std::string rotation_key; static std::string mirror_key; @@ -287,6 +304,10 @@ namespace l2n_std_format static std::string terminal_key; static std::string abstract_key; static std::string param_key; + static std::string param_int_key; + static std::string param_string_key; + static std::string param_var_key; + static std::string param_nil_key; static std::string location_key; static std::string rotation_key; static std::string mirror_key; diff --git a/src/db/db/dbLayoutToNetlistReader.cc b/src/db/db/dbLayoutToNetlistReader.cc index 2a62e55ef..8ce32e6d6 100644 --- a/src/db/db/dbLayoutToNetlistReader.cc +++ b/src/db/db/dbLayoutToNetlistReader.cc @@ -104,6 +104,21 @@ LayoutToNetlistStandardReader::try_read_int (int &i) return m_ex.try_read (i); } +long +LayoutToNetlistStandardReader::read_long () +{ + long i = 0; + m_ex.read (i); + return i; +} + +bool +LayoutToNetlistStandardReader::try_read_long (long &i) +{ + i = 0; + return m_ex.try_read (i); +} + db::Coord LayoutToNetlistStandardReader::read_coord () { @@ -322,6 +337,21 @@ static db::Region &layer_by_name (db::LayoutToNetlist *l2n, const std::string &n return *l; } +static void make_parameter (db::DeviceClass *dc, const std::string ¶m_name, bool primary, const tl::Variant &default_value) +{ + if (! dc->has_parameter_with_name (param_name)) { + db::DeviceParameterDefinition pd; + pd.set_name (param_name); + pd.set_is_primary (primary); + pd.set_default_value (default_value); + dc->add_parameter_definition (pd); + } else { + db::DeviceParameterDefinition *pd = dc->parameter_definition_non_const (dc->parameter_id_for_name (param_name)); + pd->set_default_value (default_value); + pd->set_is_primary (primary); + } +} + void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::LayoutToNetlist *l2n, LayoutToNetlistStandardReader::Brace *nested, std::map *map_per_circuit) { m_dbu = 0.001; @@ -459,17 +489,62 @@ void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::Layo read_word_or_quoted (param_name); int primary = read_int (); double default_value = read_double (); - if (! dc->has_parameter_with_name (param_name)) { - db::DeviceParameterDefinition pd; - pd.set_name (param_name); - pd.set_is_primary (primary); - pd.set_default_value (default_value); - dc->add_parameter_definition (pd); - } else { - db::DeviceParameterDefinition *pd = dc->parameter_definition_non_const (dc->parameter_id_for_name (param_name)); - pd->set_default_value (default_value); - pd->set_is_primary (primary); - } + make_parameter (dc, param_name, primary, default_value); + + br.done (); + + } else if (test (skeys::param_int_key) || test (lkeys::param_int_key)) { + + Brace br (this); + + std::string param_name; + read_word_or_quoted (param_name); + int primary = read_int (); + int default_value = read_int (); + make_parameter (dc, param_name, primary, default_value); + + br.done (); + + } else if (test (skeys::param_string_key) || test (lkeys::param_string_key)) { + + Brace br (this); + + std::string param_name; + read_word_or_quoted (param_name); + int primary = read_int (); + std::string default_value; + read_word_or_quoted (default_value); + make_parameter (dc, param_name, primary, default_value); + + br.done (); + + } else if (test (skeys::param_var_key) || test (lkeys::param_var_key)) { + + Brace br (this); + + std::string param_name; + read_word_or_quoted (param_name); + + int primary = read_int (); + + std::string default_value_str; + read_word_or_quoted (default_value_str); + tl::Variant default_value; + tl::Extractor ex (default_value_str.c_str ()); + ex.read (default_value); + + make_parameter (dc, param_name, primary, default_value); + + br.done (); + + } else if (test (skeys::param_nil_key) || test (lkeys::param_nil_key)) { + + Brace br (this); + + std::string param_name; + read_word_or_quoted (param_name); + int primary = read_int (); + make_parameter (dc, param_name, primary, tl::Variant ()); br.done (); @@ -1052,24 +1127,58 @@ LayoutToNetlistStandardReader::read_device (db::Netlist *netlist, db::LayoutToNe double value = read_double (); br2.done (); - size_t pid = std::numeric_limits::max (); - const std::vector &pd = dm.second->parameter_definitions (); - for (std::vector::const_iterator p = pd.begin (); p != pd.end (); ++p) { - if (p->name () == pname) { - pid = p->id (); - break; - } - } - - // if no parameter with this name exists, create one - if (pid == std::numeric_limits::max ()) { - // TODO: this should only happen for generic devices - db::DeviceClass *dc = const_cast (dm.second); - pid = dc->add_parameter_definition (db::DeviceParameterDefinition (pname, std::string ())).id (); - } - + size_t pid = dm.second->parameter_id_for_name_create (pname, false, 0.0); device->set_parameter_value (pid, value); + } else if (test (skeys::param_int_key) || test (lkeys::param_int_key)) { + + Brace br2 (this); + std::string pname; + read_word_or_quoted (pname); + long value = read_long (); + br2.done (); + + size_t pid = dm.second->parameter_id_for_name_create (pname, false, long (0)); + device->set_parameter_value (pid, value); + + } else if (test (skeys::param_string_key) || test (lkeys::param_string_key)) { + + Brace br2 (this); + std::string pname; + read_word_or_quoted (pname); + std::string value; + read_word_or_quoted (value); + br2.done (); + + size_t pid = dm.second->parameter_id_for_name_create (pname, false, std::string ()); + device->set_parameter_value (pid, value); + + } else if (test (skeys::param_var_key) || test (lkeys::param_var_key)) { + + Brace br2 (this); + std::string pname; + read_word_or_quoted (pname); + std::string value_str; + read_word_or_quoted (value_str); + br2.done (); + + tl::Variant value; + tl::Extractor ex (value_str.c_str ()); + ex.read (value); + + size_t pid = dm.second->parameter_id_for_name_create (pname, false, tl::Variant ()); + device->set_parameter_value (pid, value); + + } else if (test (skeys::param_nil_key) || test (lkeys::param_nil_key)) { + + Brace br2 (this); + std::string pname; + read_word_or_quoted (pname); + br2.done (); + + size_t pid = dm.second->parameter_id_for_name_create (pname, false, tl::Variant ()); + device->set_parameter_value (pid, tl::Variant ()); + } else if (at_end ()) { throw tl::Exception (tl::to_string (tr ("Unexpected end of file inside device definition (location, scale, mirror, rotation, param or terminal expected)"))); } else { diff --git a/src/db/db/dbLayoutToNetlistReader.h b/src/db/db/dbLayoutToNetlistReader.h index 358af95ea..f9c307157 100644 --- a/src/db/db/dbLayoutToNetlistReader.h +++ b/src/db/db/dbLayoutToNetlistReader.h @@ -136,6 +136,8 @@ protected: void read_word_or_quoted (std::string &s); int read_int (); bool try_read_int (int &i); + long read_long (); + bool try_read_long (long &i); db::Coord read_coord (); double read_double (); bool at_end (); diff --git a/src/db/db/dbLayoutToNetlistWriter.cc b/src/db/db/dbLayoutToNetlistWriter.cc index 67e71fdc9..33a353e3e 100644 --- a/src/db/db/dbLayoutToNetlistWriter.cc +++ b/src/db/db/dbLayoutToNetlistWriter.cc @@ -324,7 +324,18 @@ void std_writer_impl::write_device_class (TokenizedOutput &stream, const d if (! any_def) { out << endl; } - TokenizedOutput (out, Keys::param_key) << tl::to_word_or_quoted_string (p->name ()) << tl::to_string (p->is_primary () ? 1 : 0) << tl::to_string (p->default_value ()); + const tl::Variant &def = p->default_value (); + if (def.is_double ()) { + TokenizedOutput (out, Keys::param_key) << tl::to_word_or_quoted_string (p->name ()) << tl::to_string (p->is_primary () ? 1 : 0) << def.to_string (); + } else if (def.is_long () || def.is_ulong ()) { + TokenizedOutput (out, Keys::param_int_key) << tl::to_word_or_quoted_string (p->name ()) << tl::to_string (p->is_primary () ? 1 : 0) << def.to_string (); + } else if (def.is_a_string ()) { + TokenizedOutput (out, Keys::param_string_key) << tl::to_word_or_quoted_string (p->name ()) << tl::to_string (p->is_primary () ? 1 : 0) << tl::to_quoted_string (def.to_string ()); + } else if (def.is_nil ()) { + TokenizedOutput (out, Keys::param_nil_key) << tl::to_word_or_quoted_string (p->name ()) << tl::to_string (p->is_primary () ? 1 : 0); + } else { + TokenizedOutput (out, Keys::param_var_key) << tl::to_word_or_quoted_string (p->name ()) << tl::to_string (p->is_primary () ? 1 : 0) << tl::to_quoted_string (def.to_parsable_string ()); + } any_def = true; } } @@ -906,7 +917,19 @@ void std_writer_impl::write (TokenizedOutput &stream, const db::Device &de } for (std::vector::const_iterator i = pd.begin (); i != pd.end (); ++i) { - TokenizedOutput (out, Keys::param_key) << tl::to_word_or_quoted_string (i->name ()) << tl::sprintf ("%.12g", device.parameter_value (i->id ())); + + const tl::Variant &value = device.parameter_value (i->id ()); + if (value.is_double ()) { + TokenizedOutput (out, Keys::param_key) << tl::to_word_or_quoted_string (i->name ()) << value.to_string (); + } else if (value.is_long () || value.is_ulong ()) { + TokenizedOutput (out, Keys::param_int_key) << tl::to_word_or_quoted_string (i->name ()) << value.to_string (); + } else if (value.is_a_string ()) { + TokenizedOutput (out, Keys::param_string_key) << tl::to_word_or_quoted_string (i->name ()) << tl::to_quoted_string (value.to_string ()); + } else if (value.is_nil ()) { + TokenizedOutput (out, Keys::param_nil_key) << tl::to_word_or_quoted_string (i->name ()); + } else { + TokenizedOutput (out, Keys::param_var_key) << tl::to_word_or_quoted_string (i->name ()) << tl::to_quoted_string (value.to_parsable_string ()); + } } for (std::vector::const_iterator i = td.begin (); i != td.end (); ++i) { diff --git a/src/db/db/dbNetlistCompareUtils.cc b/src/db/db/dbNetlistCompareUtils.cc index 88663faee..ece5d7316 100644 --- a/src/db/db/dbNetlistCompareUtils.cc +++ b/src/db/db/dbNetlistCompareUtils.cc @@ -326,11 +326,11 @@ DeviceFilter::filter (const db::Device *device) const const db::DeviceClassCapacitor *cap = dynamic_cast (device->device_class ()); if (res) { - if (m_res_threshold > 0.0 && device->parameter_value (db::DeviceClassResistor::param_id_R) > m_res_threshold) { + if (m_res_threshold > 0.0 && device->parameter_value (db::DeviceClassResistor::param_id_R).to_double () > m_res_threshold) { return false; } } else if (cap) { - if (m_cap_threshold > 0.0 && device->parameter_value (db::DeviceClassCapacitor::param_id_C) < m_cap_threshold) { + if (m_cap_threshold > 0.0 && device->parameter_value (db::DeviceClassCapacitor::param_id_C).to_double () < m_cap_threshold) { return false; } } diff --git a/src/db/db/dbNetlistDeviceClasses.cc b/src/db/db/dbNetlistDeviceClasses.cc index e13c93fbc..437aa4e32 100644 --- a/src/db/db/dbNetlistDeviceClasses.cc +++ b/src/db/db/dbNetlistDeviceClasses.cc @@ -114,8 +114,8 @@ class ResistorDeviceCombiner public: void parallel (Device *a, Device *b) const { - double va = a->parameter_value (0); - double vb = b->parameter_value (0); + double va = a->parameter_value (0).to_double (); + double vb = b->parameter_value (0).to_double (); a->set_parameter_value (0, va + vb < 1e-30 ? 0.0 : va * vb / (va + vb)); // parallel width is sum of both, length is the one that gives the same value of resistance @@ -124,10 +124,10 @@ public: // R1 = L1/W1 // R2 = L2/W2 // -> L = (L1*L2*(W1+W2))/(L2*W1+L1*W2)) - double l1 = a->parameter_value (1); - double w1 = a->parameter_value (2); - double l2 = b->parameter_value (1); - double w2 = b->parameter_value (2); + double l1 = a->parameter_value (1).to_double (); + double w1 = a->parameter_value (2).to_double (); + double l2 = b->parameter_value (1).to_double (); + double w2 = b->parameter_value (2).to_double (); double dnom = (l2 * w1 + l1 * w2); if (fabs (dnom) > 1e-15) { a->set_parameter_value (1, (l1 * l2 * (w1 + w2)) / dnom); @@ -135,20 +135,20 @@ public: a->set_parameter_value (2, w1 + w2); // TODO: does this implementation make sense? (area) - double aa = a->parameter_value (3); - double ab = b->parameter_value (3); + double aa = a->parameter_value (3).to_double (); + double ab = b->parameter_value (3).to_double (); a->set_parameter_value (3, aa + ab); // TODO: does this implementation make sense? (perimeter) - double pa = a->parameter_value (4); - double pb = b->parameter_value (4); + double pa = a->parameter_value (4).to_double (); + double pb = b->parameter_value (4).to_double (); a->set_parameter_value (4, pa + pb); } void serial (Device *a, Device *b) const { - double va = a->parameter_value (0); - double vb = b->parameter_value (0); + double va = a->parameter_value (0).to_double (); + double vb = b->parameter_value (0).to_double (); a->set_parameter_value (0, va + vb); // parallel length is sum of both, width is the one that gives the same value of resistance @@ -158,22 +158,22 @@ public: // R1 = L1/W1 // R2 = L2/W2 // -> W = ((L1+L2)*W1*W2)/(W1*L2+W2*L1) - double l1 = a->parameter_value (1); - double w1 = a->parameter_value (2); - double l2 = b->parameter_value (1); - double w2 = b->parameter_value (2); + double l1 = a->parameter_value (1).to_double (); + double w1 = a->parameter_value (2).to_double (); + double l2 = b->parameter_value (1).to_double (); + double w2 = b->parameter_value (2).to_double (); a->set_parameter_value (1, l1 + l2); double dnom = (l2 * w1 + l1 * w2); if (fabs (dnom) > 1e-15) { a->set_parameter_value (2, (w1 * w2 * (l1 + l2)) / dnom); } - double aa = a->parameter_value (3); - double ab = b->parameter_value (3); + double aa = a->parameter_value (3).to_double (); + double ab = b->parameter_value (3).to_double (); a->set_parameter_value (3, aa + ab); - double pa = a->parameter_value (4); - double pb = b->parameter_value (4); + double pa = a->parameter_value (4).to_double (); + double pb = b->parameter_value (4).to_double (); a->set_parameter_value (4, pa + pb); } }; @@ -202,33 +202,33 @@ class CapacitorDeviceCombiner public: void serial (Device *a, Device *b) const { - double va = a->parameter_value (0); - double vb = b->parameter_value (0); + double va = a->parameter_value (0).to_double (); + double vb = b->parameter_value (0).to_double (); a->set_parameter_value (0, va + vb < 1e-30 ? 0.0 : va * vb / (va + vb)); // TODO: does this implementation make sense? - double aa = a->parameter_value (1); - double ab = b->parameter_value (1); + double aa = a->parameter_value (1).to_double (); + double ab = b->parameter_value (1).to_double (); a->set_parameter_value (1, aa + ab); // TODO: does this implementation make sense? - double pa = a->parameter_value (2); - double pb = b->parameter_value (2); + double pa = a->parameter_value (2).to_double (); + double pb = b->parameter_value (2).to_double (); a->set_parameter_value (2, pa + pb); } void parallel (Device *a, Device *b) const { - double va = a->parameter_value (0); - double vb = b->parameter_value (0); + double va = a->parameter_value (0).to_double (); + double vb = b->parameter_value (0).to_double (); a->set_parameter_value (0, va + vb); - double aa = a->parameter_value (1); - double ab = b->parameter_value (1); + double aa = a->parameter_value (1).to_double (); + double ab = b->parameter_value (1).to_double (); a->set_parameter_value (1, aa + ab); - double pa = a->parameter_value (2); - double pb = b->parameter_value (2); + double pa = a->parameter_value (2).to_double (); + double pb = b->parameter_value (2).to_double (); a->set_parameter_value (2, pa + pb); } }; @@ -257,15 +257,15 @@ class InductorDeviceCombiner public: void parallel (Device *a, Device *b) const { - double va = a->parameter_value (0); - double vb = b->parameter_value (0); + double va = a->parameter_value (0).to_double (); + double vb = b->parameter_value (0).to_double (); a->set_parameter_value (0, va + vb < 1e-30 ? 0.0 : va * vb / (va + vb)); } void serial (Device *a, Device *b) const { - double va = a->parameter_value (0); - double vb = b->parameter_value (0); + double va = a->parameter_value (0).to_double (); + double vb = b->parameter_value (0).to_double (); a->set_parameter_value (0, va + vb); } }; @@ -284,8 +284,8 @@ public: // only parallel diodes can be combined and their areas will add if (na1 == nb1 && na2 == nb2) { - a->set_parameter_value (0, a->parameter_value (0) + b->parameter_value (0)); - a->set_parameter_value (1, a->parameter_value (1) + b->parameter_value (1)); + a->set_parameter_value (0, a->parameter_value (0).to_double () + b->parameter_value (0).to_double ()); + a->set_parameter_value (1, a->parameter_value (1).to_double () + b->parameter_value (1).to_double ()); a->join_terminals (0, b, 0); a->join_terminals (1, b, 1); @@ -340,11 +340,11 @@ public: void combine_parameters (Device *a, Device *b) const { - a->set_parameter_value (1, a->parameter_value (1) + b->parameter_value (1)); - a->set_parameter_value (2, a->parameter_value (2) + b->parameter_value (2)); - a->set_parameter_value (3, a->parameter_value (3) + b->parameter_value (3)); - a->set_parameter_value (4, a->parameter_value (4) + b->parameter_value (4)); - a->set_parameter_value (5, a->parameter_value (5) + b->parameter_value (5)); + a->set_parameter_value (1, a->parameter_value (1).to_double () + b->parameter_value (1).to_double ()); + a->set_parameter_value (2, a->parameter_value (2).to_double () + b->parameter_value (2).to_double ()); + a->set_parameter_value (3, a->parameter_value (3).to_double () + b->parameter_value (3).to_double ()); + a->set_parameter_value (4, a->parameter_value (4).to_double () + b->parameter_value (4).to_double ()); + a->set_parameter_value (5, a->parameter_value (5).to_double () + b->parameter_value (5).to_double ()); } }; @@ -423,9 +423,9 @@ public: void combine_parameters (Device *a, Device *b) const { - a->set_parameter_value (DeviceClassBJT3Transistor::param_id_AE, a->parameter_value (DeviceClassBJT3Transistor::param_id_AE) + b->parameter_value (DeviceClassBJT3Transistor::param_id_AE)); - a->set_parameter_value (DeviceClassBJT3Transistor::param_id_PE, a->parameter_value (DeviceClassBJT3Transistor::param_id_PE) + b->parameter_value (DeviceClassBJT3Transistor::param_id_PE)); - a->set_parameter_value (DeviceClassBJT3Transistor::param_id_NE, a->parameter_value (DeviceClassBJT3Transistor::param_id_NE) + b->parameter_value (DeviceClassBJT3Transistor::param_id_NE)); + a->set_parameter_value (DeviceClassBJT3Transistor::param_id_AE, a->parameter_value (DeviceClassBJT3Transistor::param_id_AE).to_double () + b->parameter_value (DeviceClassBJT3Transistor::param_id_AE).to_double ()); + a->set_parameter_value (DeviceClassBJT3Transistor::param_id_PE, a->parameter_value (DeviceClassBJT3Transistor::param_id_PE).to_double () + b->parameter_value (DeviceClassBJT3Transistor::param_id_PE).to_double ()); + a->set_parameter_value (DeviceClassBJT3Transistor::param_id_NE, a->parameter_value (DeviceClassBJT3Transistor::param_id_NE).to_double () + b->parameter_value (DeviceClassBJT3Transistor::param_id_NE).to_double ()); } }; @@ -639,7 +639,7 @@ DeviceClassMOS3Transistor::is_drain_terminal (size_t tid) const bool DeviceClassMOS3Transistor::lengths_are_identical (const db::Device *a, const db::Device *b) { - return (fabs (a->parameter_value (DeviceClassMOS3Transistor::param_id_L) - b->parameter_value (DeviceClassMOS3Transistor::param_id_L)) < 1e-6); + return (fabs (a->parameter_value (DeviceClassMOS3Transistor::param_id_L).to_double () - b->parameter_value (DeviceClassMOS3Transistor::param_id_L).to_double ()) < 1e-6); } bool diff --git a/src/db/db/dbNetlistDeviceExtractor.h b/src/db/db/dbNetlistDeviceExtractor.h index 8fda8cdaf..3da7e5489 100644 --- a/src/db/db/dbNetlistDeviceExtractor.h +++ b/src/db/db/dbNetlistDeviceExtractor.h @@ -460,7 +460,7 @@ private: } std::map > > geometry; - std::map parameters; + std::map parameters; }; typedef std::map > geometry_per_layer_type; diff --git a/src/db/db/dbNetlistSpiceReaderDelegate.cc b/src/db/db/dbNetlistSpiceReaderDelegate.cc index d23a203c5..81b396efe 100644 --- a/src/db/db/dbNetlistSpiceReaderDelegate.cc +++ b/src/db/db/dbNetlistSpiceReaderDelegate.cc @@ -587,8 +587,11 @@ NetlistSpiceReaderDelegate::apply_parameter_scaling (db::Device *device) const const std::vector &pd = device->device_class ()->parameter_definitions (); for (auto i = pd.begin (); i != pd.end (); ++i) { - double pv = device->parameter_value (i->id ()); - device->set_parameter_value (i->id (), pv / i->si_scaling () * pow (m_options.scale, i->geo_scaling_exponent ())); + const tl::Variant &pv = device->parameter_value (i->id ()); + // @@@ only in case of double??? + if (pv.is_double ()) { + device->set_parameter_value (i->id (), pv.to_double () / i->si_scaling () * pow (m_options.scale, i->geo_scaling_exponent ())); + } } } diff --git a/src/db/db/dbNetlistSpiceWriter.cc b/src/db/db/dbNetlistSpiceWriter.cc index 6f190c6d4..8e8df95db 100644 --- a/src/db/db/dbNetlistSpiceWriter.cc +++ b/src/db/db/dbNetlistSpiceWriter.cc @@ -231,12 +231,13 @@ std::string NetlistSpiceWriterDelegate::format_params (const db::Device &dev, si double sis = i->si_scaling (); os << " " << i->name () << "="; // for compatibility + // @@@ other parameter types!!! if (fabs (sis * 1e6 - 1.0) < 1e-10) { os << tl::to_string (dev.parameter_value (i->id ())) << "U"; } else if (fabs (sis * 1e12 - 1.0) < 1e-10) { os << tl::to_string (dev.parameter_value (i->id ())) << "P"; } else { - os << tl::to_string (dev.parameter_value (i->id ()) * sis); + os << tl::to_string (dev.parameter_value (i->id ()).to_double () * sis); } } } diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index b297e004b..a89c85747 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -432,17 +432,18 @@ Class decl_dbDevice (decl_dbNetlistObject, "db", "Device", "@brief Disconnects the given terminal from any net.\n" "This version accepts a terminal name. If the name is not a valid terminal name, an exception is raised." ) + - gsi::method ("parameter", (double (db::Device::*) (size_t) const) &db::Device::parameter_value, gsi::arg ("param_id"), + gsi::method ("parameter", (const tl::Variant &(db::Device::*) (size_t) const) &db::Device::parameter_value, gsi::arg ("param_id"), "@brief Gets the parameter value for the given parameter ID." ) + - gsi::method ("set_parameter", (void (db::Device::*) (size_t, double)) &db::Device::set_parameter_value, gsi::arg ("param_id"), gsi::arg ("value"), + gsi::method ("set_parameter", (void (db::Device::*) (size_t, const tl::Variant &)) &db::Device::set_parameter_value, gsi::arg ("param_id"), gsi::arg ("value"), "@brief Sets the parameter value for the given parameter ID." ) + - gsi::method ("parameter", (double (db::Device::*) (const std::string &) const) &db::Device::parameter_value, gsi::arg ("param_name"), + gsi::method ("parameter", (const tl::Variant &(db::Device::*) (const std::string &) const) &db::Device::parameter_value, gsi::arg ("param_name"), "@brief Gets the parameter value for the given parameter name.\n" "If the parameter name is not valid, an exception is thrown." ) + - gsi::method ("set_parameter", (void (db::Device::*) (const std::string &, double)) &db::Device::set_parameter_value, gsi::arg ("param_name"), gsi::arg ("value"), + // @@@ set_parameter_create!!! + gsi::method ("set_parameter", (void (db::Device::*) (const std::string &, const tl::Variant &)) &db::Device::set_parameter_value, gsi::arg ("param_name"), gsi::arg ("value"), "@brief Sets the parameter value for the given parameter name.\n" "If the parameter name is not valid, an exception is thrown." ), diff --git a/src/db/unit_tests/dbNetlistTests.cc b/src/db/unit_tests/dbNetlistTests.cc index 7bf6aee55..6e45dead7 100644 --- a/src/db/unit_tests/dbNetlistTests.cc +++ b/src/db/unit_tests/dbNetlistTests.cc @@ -507,20 +507,20 @@ TEST(4_CircuitDevices) EXPECT_EQ (c->device_by_name (d2a->name ()) == d2a, true); EXPECT_EQ (c->device_by_name ("doesnt_exist") == 0, true); - EXPECT_EQ (d1->parameter_value (0), 1.0); - EXPECT_EQ (d1->parameter_value (1), 2.0); - EXPECT_EQ (d2a->parameter_value (0), 2.0); - EXPECT_EQ (d2a->parameter_value (1), 1.0); + EXPECT_EQ (d1->parameter_value (0).to_double (), 1.0); + EXPECT_EQ (d1->parameter_value (1).to_double (), 2.0); + EXPECT_EQ (d2a->parameter_value (0).to_double (), 2.0); + EXPECT_EQ (d2a->parameter_value (1).to_double (), 1.0); d1->set_parameter_value (1, 1.5); - EXPECT_EQ (d1->parameter_value (0), 1.0); - EXPECT_EQ (d1->parameter_value (1), 1.5); + EXPECT_EQ (d1->parameter_value (0).to_double (), 1.0); + EXPECT_EQ (d1->parameter_value (1).to_double (), 1.5); d1->set_parameter_value (0, 0.5); - EXPECT_EQ (d1->parameter_value (0), 0.5); - EXPECT_EQ (d1->parameter_value (1), 1.5); + EXPECT_EQ (d1->parameter_value (0).to_double (), 0.5); + EXPECT_EQ (d1->parameter_value (1).to_double (), 1.5); d2a->set_parameter_value (0, -1.0); - EXPECT_EQ (d2a->parameter_value (0), -1.0); - EXPECT_EQ (d2a->parameter_value (1), 1.0); + EXPECT_EQ (d2a->parameter_value (0).to_double (), -1.0); + EXPECT_EQ (d2a->parameter_value (1).to_double (), 1.0); EXPECT_EQ (netlist2 (*c), "c:\n" diff --git a/src/layui/layui/layNetlistBrowserModel.cc b/src/layui/layui/layNetlistBrowserModel.cc index e61c7b35c..03ae31400 100644 --- a/src/layui/layui/layNetlistBrowserModel.cc +++ b/src/layui/layui/layNetlistBrowserModel.cc @@ -262,6 +262,16 @@ std::string formatted_value (double v) } } +static +std::string formatted_value (const tl::Variant &v) +{ + if (v.is_double ()) { + return formatted_value (v.to_double ()); + } else { + return v.to_string (); + } +} + static std::string device_parameter_string (const db::Device *device) { @@ -277,7 +287,6 @@ std::string device_parameter_string (const db::Device *device) for (std::vector::const_iterator p = pd.begin (); p != pd.end (); ++p) { if (p->is_primary ()) { - double v = device->parameter_value (p->id ()); if (first) { s += " ["; } else { @@ -285,7 +294,7 @@ std::string device_parameter_string (const db::Device *device) } s += p->name (); s += "="; - s += formatted_value (v); + s += formatted_value (device->parameter_value (p->id ())); term = "]"; first = false; } @@ -294,8 +303,7 @@ std::string device_parameter_string (const db::Device *device) bool first_sec = true; for (std::vector::const_iterator p = pd.begin (); p != pd.end (); ++p) { - double v = device->parameter_value (p->id ()); - std::string vs = formatted_value (v); + std::string vs = formatted_value (device->parameter_value (p->id ())); std::string vs_def = formatted_value (p->default_value ()); if (! p->is_primary () && vs != vs_def) { if (first) {