diff --git a/src/db/db/dbNetlistDeviceExtractor.cc b/src/db/db/dbNetlistDeviceExtractor.cc index ad7aa001e..5664a0884 100644 --- a/src/db/db/dbNetlistDeviceExtractor.cc +++ b/src/db/db/dbNetlistDeviceExtractor.cc @@ -66,12 +66,13 @@ const tl::Variant &NetlistDeviceExtractor::terminal_property_name () void NetlistDeviceExtractor::initialize (db::Netlist *nl) { + m_layer_definitions.clear (); m_device_classes.clear (); m_device_name_index = 0; m_propname_id = 0; m_netlist.reset (nl); - create_device_classes (); + setup (); } static void insert_into_region (const db::PolygonRef &s, const db::ICplxTrans &tr, db::Region ®ion) @@ -79,25 +80,46 @@ static void insert_into_region (const db::PolygonRef &s, const db::ICplxTrans &t region.insert (s.obj ().transformed (tr * db::ICplxTrans (s.trans ()))); } -void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, const std::vector &deep_layers, db::Netlist *nl) +void NetlistDeviceExtractor::extract (db::DeepShapeStore &dss, const NetlistDeviceExtractor::input_layers &layer_map, db::Netlist *nl) { - db::Layout &layout = dss.layout (); - db::Cell &cell = dss.initial_cell (); + initialize (nl); std::vector layers; - layers.reserve (deep_layers.size ()); + layers.reserve (m_layer_definitions.size ()); + + for (layer_definitions::const_iterator ld = begin_layer_definitions (); ld != end_layer_definitions (); ++ld) { + + input_layers::const_iterator l = layer_map.find (ld->name); + if (l == layer_map.end ()) { + throw tl::Exception (tl::to_string (tr ("Missing input layer for device extraction: ")) + ld->name); + } + + tl_assert (l->second != 0); + db::DeepRegion *dr = dynamic_cast (l->second->delegate ()); + if (dr == 0) { + throw tl::Exception (tl::sprintf (tl::to_string (tr ("Invalid region passed to input layer '%s' for device extraction: must be of deep region kind")), ld->name)); + } + + if (&dr->deep_layer ().layout () != &dss.layout () || &dr->deep_layer ().initial_cell () != &dss.initial_cell ()) { + throw tl::Exception (tl::sprintf (tl::to_string (tr ("Invalid region passed to input layer '%s' for device extraction: not originating from the same source")), ld->name)); + } + + layers.push_back (dr->deep_layer ().layer ()); - for (std::vector::const_iterator dl = deep_layers.begin (); dl != deep_layers.end (); ++dl) { - tl_assert (&dl->layout () == &layout); - layers.push_back (dl->layer ()); } - extract (layout, cell, layers, nl); + extract_without_initialize (dss.layout (), dss.initial_cell (), layers, nl); } void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const std::vector &layers, db::Netlist *nl) { initialize (nl); + extract_without_initialize (layout, cell, layers, nl); +} + +void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db::Cell &cell, const std::vector &layers, db::Netlist *nl) +{ + tl_assert (layers.size () == m_layer_definitions.size ()); typedef db::PolygonRef shape_type; db::ShapeIterator::flags_type shape_iter_flags = db::ShapeIterator::Polygons; @@ -176,7 +198,7 @@ void NetlistDeviceExtractor::extract (db::Layout &layout, db::Cell &cell, const } } -void NetlistDeviceExtractor::create_device_classes () +void NetlistDeviceExtractor::setup () { // .. the default implementation does nothing .. } @@ -199,6 +221,11 @@ void NetlistDeviceExtractor::register_device_class (DeviceClass *device_class) m_device_classes.push_back (device_class); } +void NetlistDeviceExtractor::define_layer (const std::string &name, const std::string &description) +{ + m_layer_definitions.push_back (db::NetlistDeviceExtractorLayerDefinition (name, description, m_layer_definitions.size ())); +} + Device *NetlistDeviceExtractor::create_device (unsigned int device_class_index) { tl_assert (mp_circuit != 0); diff --git a/src/db/db/dbNetlistDeviceExtractor.h b/src/db/db/dbNetlistDeviceExtractor.h index 73430901e..5f4d458cf 100644 --- a/src/db/db/dbNetlistDeviceExtractor.h +++ b/src/db/db/dbNetlistDeviceExtractor.h @@ -145,6 +145,40 @@ private: std::string m_category_name, m_category_description; }; +/** + * @brief Specifies a single layer from the device extractor + */ +class DB_PUBLIC NetlistDeviceExtractorLayerDefinition +{ +public: + NetlistDeviceExtractorLayerDefinition () + : index (0) + { + // .. nothing yet .. + } + + NetlistDeviceExtractorLayerDefinition (const std::string &_name, const std::string &_description, size_t _index) + : name (_name), description (_description), index (_index) + { + // .. nothing yet .. + } + + /** + * @brief The formal name + */ + std::string name; + + /** + * @brief The human-readable description + */ + std::string description; + + /** + * @brief The index of the layer + */ + size_t index; +}; + /** * @brief Implements the device extraction for a specific setup * @@ -157,6 +191,9 @@ class DB_PUBLIC NetlistDeviceExtractor public: typedef std::list error_list; typedef error_list::const_iterator error_iterator; + typedef std::vector layer_definitions; + typedef layer_definitions::const_iterator layer_definitions_iterator; + typedef std::map input_layers; /** * @brief Default constructor @@ -202,9 +239,10 @@ public: * @brief Extracts the devices from a list of regions * * This method behaves identical to the other "extract" method, but accepts - * DeepShape layers for input. By definition, these already have the "PolygonRef" type. + * named regions for input. These regions need to be of deep region type and + * originate from the same layout than the DeepShapeStore. */ - void extract (DeepShapeStore &dss, const std::vector &layers, Netlist *netlist); + void extract (DeepShapeStore &dss, const input_layers &layers, Netlist *netlist); /** * @brief Gets the error iterator, begin @@ -230,14 +268,36 @@ public: return ! m_errors.empty (); } + /** + * @brief Gets the layer definition iterator, begin + */ + layer_definitions_iterator begin_layer_definitions () const + { + return m_layer_definitions.begin (); + } + + /** + * @brief Gets the layer definition iterator, end + */ + layer_definitions_iterator end_layer_definitions () const + { + return m_layer_definitions.end (); + } + protected: /** - * @brief Creates the device classes + * @brief Sets up the extractor + * + * This method is supposed to set up the device extractor. This involves two basic steps: + * defining the device classes and setting up the device layers. + * * At least one device class needs to be defined. Use "register_device_class" to register * the device classes you need. The first device class registered has device class index 0, * the further ones 1, 2, etc. + * + * The device layers need to be defined by calling "define_layer" once or several times. */ - virtual void create_device_classes (); + virtual void setup (); /** * @brief Gets the connectivity object used to extract the device geometry @@ -264,9 +324,20 @@ protected: * @brief Registers a device class * The device class object will become owned by the netlist and must not be deleted by * the caller. + * This method shall be used inside the implementation of "setup" to register + * the device classes. */ void register_device_class (DeviceClass *device_class); + /** + * @brief Defines a layer + * Each call will define one more layer for the device extraction. + * This method shall be used inside the implementation of "setip" to define + * the device layers. The actual geometries are later available to "extract_devices" + * in the order the layers are defined. + */ + void define_layer (const std::string &name, const std::string &description = std::string ()); + /** * @brief Creates a device * The device object returned can be configured by the caller, e.g. set parameters. @@ -366,6 +437,7 @@ private: db::cell_index_type m_cell_index; db::Circuit *mp_circuit; std::vector m_device_classes; + layer_definitions m_layer_definitions; std::vector m_layers; unsigned int m_device_name_index; error_list m_errors; @@ -375,6 +447,8 @@ private: * This method will produce the device classes required for the device extraction. */ void initialize (db::Netlist *nl); + + void extract_without_initialize (db::Layout &layout, db::Cell &cell, const std::vector &layers, db::Netlist *nl); }; } diff --git a/src/db/unit_tests/dbNetlistExtractorTests.cc b/src/db/unit_tests/dbNetlistExtractorTests.cc index 020d5b3fe..bbf7c72ab 100644 --- a/src/db/unit_tests/dbNetlistExtractorTests.cc +++ b/src/db/unit_tests/dbNetlistExtractorTests.cc @@ -57,8 +57,13 @@ public: } } - virtual void create_device_classes () + virtual void setup () { + define_layer ("PD", "P diffusion"); + define_layer ("ND", "N diffusion"); + define_layer ("G", "Gate"); + define_layer ("P", "Poly"); + db::DeviceClassMOS3Transistor *pmos_class = new db::DeviceClassMOS3Transistor (); pmos_class->set_name ("PMOS"); register_device_class (pmos_class); @@ -417,11 +422,11 @@ TEST(2_DeviceAndNetExtraction) // 21/0 -> Gate MOSFETExtractor ex (&ly); - std::vector dl; - dl.push_back (rpdiff); - dl.push_back (rndiff); - dl.push_back (rgate); - dl.push_back (rpoly); + db::NetlistDeviceExtractor::input_layers dl; + dl["PD"] = &rpdiff; + dl["ND"] = &rndiff; + dl["G"] = &rgate; + dl["P"] = &rpoly; ex.extract (dss, dl, &nl);