From ce61145f1c01c5adb51cb7e74e272b6e0958fbd7 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sun, 4 Jul 2021 17:05:17 +0200 Subject: [PATCH] More control over primary/secondary flag of parameters in device extraction - Spice reader will set primary flag for all (known) parameters read from a Spice netlist - "extract_devices" will return the device class object - primary/secondary flag can be set on device class objects through "enable_devices" --- src/db/db/dbDeviceClass.cc | 9 ++++ src/db/db/dbDeviceClass.h | 5 ++ src/db/db/dbNetlistDeviceExtractor.cc | 8 +-- src/db/db/dbNetlistDeviceExtractor.h | 12 ++++- src/db/db/dbNetlistSpiceReader.cc | 2 + src/db/db/gsiDeclDbNetlist.cc | 57 ++++++++++++++++++++ src/db/db/gsiDeclDbNetlistDeviceExtractor.cc | 13 ++++- src/drc/drc/built-in-macros/_drc_netter.rb | 5 ++ 8 files changed, 105 insertions(+), 6 deletions(-) diff --git a/src/db/db/dbDeviceClass.cc b/src/db/db/dbDeviceClass.cc index 389e81677..4ccf27c98 100644 --- a/src/db/db/dbDeviceClass.cc +++ b/src/db/db/dbDeviceClass.cc @@ -179,6 +179,15 @@ const DeviceParameterDefinition *DeviceClass::parameter_definition (size_t id) c } } +DeviceParameterDefinition *DeviceClass::parameter_definition_non_const (size_t id) +{ + if (id < m_parameter_definitions.size ()) { + return & m_parameter_definitions [id]; + } else { + return 0; + } +} + bool DeviceClass::has_parameter_with_name (const std::string &name) const { const std::vector &pd = parameter_definitions (); diff --git a/src/db/db/dbDeviceClass.h b/src/db/db/dbDeviceClass.h index 396a03fe4..01e8dc06e 100644 --- a/src/db/db/dbDeviceClass.h +++ b/src/db/db/dbDeviceClass.h @@ -508,6 +508,11 @@ public: */ const DeviceParameterDefinition *parameter_definition (size_t id) const; + /** + * @brief Gets the parameter definition from the ID (non-const version) + */ + DeviceParameterDefinition *parameter_definition_non_const (size_t id); + /** * @brief Returns true, if the device has a parameter with the given name */ diff --git a/src/db/db/dbNetlistDeviceExtractor.cc b/src/db/db/dbNetlistDeviceExtractor.cc index 7c97d1782..03129ea62 100644 --- a/src/db/db/dbNetlistDeviceExtractor.cc +++ b/src/db/db/dbNetlistDeviceExtractor.cc @@ -391,7 +391,7 @@ void NetlistDeviceExtractor::push_new_devices (const db::Vector &disp_cache) std::string cell_name = "D$" + mp_device_class->name (); db::Cell &device_cell = mp_layout->cell (mp_layout->add_cell (cell_name.c_str ())); - db::DeviceAbstract *dm = new db::DeviceAbstract (mp_device_class, mp_layout->cell_name (device_cell.cell_index ())); + db::DeviceAbstract *dm = new db::DeviceAbstract (mp_device_class.get (), mp_layout->cell_name (device_cell.cell_index ())); m_netlist->add_device_abstract (dm); dm->set_cell_index (device_cell.cell_index ()); @@ -487,7 +487,7 @@ void NetlistDeviceExtractor::register_device_class (DeviceClass *device_class) tl_assert (device_class != 0); tl_assert (m_netlist.get () != 0); - if (mp_device_class != 0) { + if (mp_device_class.get () != 0) { throw tl::Exception (tl::to_string (tr ("Device class already set"))); } if (m_name.empty ()) { @@ -526,12 +526,12 @@ const db::NetlistDeviceExtractorLayerDefinition &NetlistDeviceExtractor::define_ Device *NetlistDeviceExtractor::create_device () { - if (mp_device_class == 0) { + if (mp_device_class.get () == 0) { throw tl::Exception (tl::to_string (tr ("No device class registered"))); } tl_assert (mp_circuit != 0); - Device *device = new Device (mp_device_class); + Device *device = new Device (mp_device_class.get ()); mp_circuit->add_device (device); return device; } diff --git a/src/db/db/dbNetlistDeviceExtractor.h b/src/db/db/dbNetlistDeviceExtractor.h index c6cab89ae..7ee6d9f90 100644 --- a/src/db/db/dbNetlistDeviceExtractor.h +++ b/src/db/db/dbNetlistDeviceExtractor.h @@ -387,6 +387,16 @@ public: */ Device *create_device (); + /** + * @brief Gets the device class used during extraction + * + * This member is set in 'extract_devices' and holds the device class object used during extraction. + */ + DeviceClass *device_class () + { + return mp_device_class.get (); + } + /** * @brief Defines a device terminal in the layout (a region) */ @@ -535,7 +545,7 @@ private: const std::set *mp_breakout_cells; double m_device_scaling; db::Circuit *mp_circuit; - db::DeviceClass *mp_device_class; + tl::weak_ptr mp_device_class; std::string m_name; layer_definitions m_layer_definitions; std::vector m_layers; diff --git a/src/db/db/dbNetlistSpiceReader.cc b/src/db/db/dbNetlistSpiceReader.cc index 0f0fe8312..33b9f9202 100644 --- a/src/db/db/dbNetlistSpiceReader.cc +++ b/src/db/db/dbNetlistSpiceReader.cc @@ -625,6 +625,8 @@ bool NetlistSpiceReaderDelegate::element (db::Circuit *circuit, const std::strin std::map::const_iterator v = params.find (i->name ()); if (v != params.end ()) { device->set_parameter_value (i->id (), v->second / i->si_scaling ()); + // parameters read from the netlist are made primary so they are shown in the netlist browser + cls->parameter_definition_non_const (i->id ())->set_is_primary (true); } else if (i->id () == defp) { device->set_parameter_value (i->id (), value / i->si_scaling ()); } diff --git a/src/db/db/gsiDeclDbNetlist.cc b/src/db/db/gsiDeclDbNetlist.cc index be85f137f..7d677e5f2 100644 --- a/src/db/db/gsiDeclDbNetlist.cc +++ b/src/db/db/gsiDeclDbNetlist.cc @@ -927,6 +927,36 @@ static db::EqualDeviceParameters *get_equal_parameters (db::DeviceClass *cls) return dynamic_cast (cls->parameter_compare_delegate ()); } +static void enable_parameter (db::DeviceClass *cls, size_t id, bool en) +{ + db::DeviceParameterDefinition *pd = cls->parameter_definition_non_const (id); + if (pd) { + pd->set_is_primary (en); + } +} + +static void enable_parameter2 (db::DeviceClass *cls, const std::string &name, bool en) +{ + if (! cls->has_parameter_with_name (name)) { + return; + } + + size_t id = cls->parameter_id_for_name (name); + db::DeviceParameterDefinition *pd = cls->parameter_definition_non_const (id); + if (pd) { + pd->set_is_primary (en); + } +} + +static const db::DeviceParameterDefinition *parameter_definition2 (const db::DeviceClass *cls, const std::string &name) +{ + if (! cls->has_parameter_with_name (name)) { + return 0; + } else { + return cls->parameter_definition (cls->parameter_id_for_name (name)); + } +} + Class decl_dbDeviceClass ("db", "DeviceClass", gsi::method ("name", &db::DeviceClass::name, "@brief Gets the name of the device class." @@ -981,6 +1011,33 @@ Class decl_dbDeviceClass ("db", "DeviceClass", "Parameter definition IDs are used in some places to reference a specific parameter of a device. " "This method obtains the corresponding definition object." ) + + gsi::method_ext ("parameter_definition", ¶meter_definition2, gsi::arg ("parameter_name"), + "@brief Gets the parameter definition object for a given ID.\n" + "Parameter definition IDs are used in some places to reference a specific parameter of a device. " + "This method obtains the corresponding definition object." + "\n" + "This version accepts a parameter name.\n" + "\n" + "This method has been introduced in version 0.27.3.\n" + ) + + gsi::method_ext ("enable_parameter", &enable_parameter, gsi::arg ("parameter_id"), gsi::arg ("enable"), + "@brief Enables or disables a parameter.\n" + "Some parameters are 'secondary' parameters which are extracted but not handled in device compare and are not shown in the netlist browser. " + "For example, the 'W' parameter of the resistor is such a secondary parameter. This method allows turning a parameter in a primary one ('enable') or " + "into a secondary one ('disable').\n" + "\n" + "This method has been introduced in version 0.27.3.\n" + ) + + gsi::method_ext ("enable_parameter", &enable_parameter2, gsi::arg ("parameter_name"), gsi::arg ("enable"), + "@brief Enables or disables a parameter.\n" + "Some parameters are 'secondary' parameters which are extracted but not handled in device compare and are not shown in the netlist browser. " + "For example, the 'W' parameter of the resistor is such a secondary parameter. This method allows turning a parameter in a primary one ('enable') or " + "into a secondary one ('disable').\n" + "\n" + "This version accepts a parameter name.\n" + "\n" + "This method has been introduced in version 0.27.3.\n" + ) + gsi::method ("has_parameter?", &db::DeviceClass::has_parameter_with_name, gsi::arg ("name"), "@brief Returns true, if the device class has a parameter with the given name.\n" ) + diff --git a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc index 8ab83f4cf..24dc1fe2c 100644 --- a/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc +++ b/src/db/db/gsiDeclDbNetlistDeviceExtractor.cc @@ -214,6 +214,13 @@ Class decl_dbNetlistDeviceExtractor ("db", "DeviceEx gsi::method ("name", &db::NetlistDeviceExtractor::name, "@brief Gets the name of the device extractor and the device class." ) + + gsi::method ("device_class", &db::NetlistDeviceExtractor::device_class, + "@brief Gets the device class used during extraction\n" + "The attribute will hold the actual device class used in the device extraction. It " + "is valid only after 'extract_devices'.\n" + "\n" + "This method has been added in version 0.27.3.\n" + ) + gsi::iterator ("each_layer_definition", &db::NetlistDeviceExtractor::begin_layer_definitions, &db::NetlistDeviceExtractor::end_layer_definitions, "@brief Iterates over all layer definitions." ) + @@ -251,9 +258,13 @@ Class decl_GenericDeviceExtractor (decl_dbNetlistDeviceE "This method shall raise an error, if the input layer are not properly defined (e.g.\n" "too few etc.)\n" "\n" + "This is not a connectivity definition in the electrical sense, but defines the cluster of shapes " + "which generates a specific device. In this case, 'connectivity' means 'definition of shapes that need to touch to form the device'.\n" + "\n" "The 'layers' argument specifies the actual layer layouts for the logical device layers (see \\define_layer). " "The list of layers corresponds to the number of layers defined. Use the layer indexes from this list " - "to build the connectivity with \\Connectivity#connect." + "to build the connectivity with \\Connectivity#connect. Note, that in order to capture a connected cluster of shapes on the " + "same layer you'll need to include a self-connection like 'connectivity.connect(layers[0], layers[0])'." ) + gsi::callback ("extract_devices", &GenericDeviceExtractor::extract_devices, &GenericDeviceExtractor::cb_extract_devices, gsi::arg ("layer_geometry"), diff --git a/src/drc/drc/built-in-macros/_drc_netter.rb b/src/drc/drc/built-in-macros/_drc_netter.rb index 978e6c723..fe87ee25a 100644 --- a/src/drc/drc/built-in-macros/_drc_netter.rb +++ b/src/drc/drc/built-in-macros/_drc_netter.rb @@ -192,6 +192,9 @@ module DRC # # extract_devices(mos4("NMOS4"), { :SD => nsd, :G => gate, :P => poly, :W => bulk }) # @/code + # + # The return value of this method will be the device class of the devices + # generated in the extraction step (see \DeviceClass). def extract_devices(devex, layer_selection) @@ -215,6 +218,8 @@ module DRC end + devex.device_class + end # %DRC%