WIP: specific device extractor and GSI binding.

This commit is contained in:
Matthias Koefferlein 2018-12-30 14:54:59 +01:00
parent ec7ab8e01d
commit b512f628bc
5 changed files with 268 additions and 99 deletions

View File

@ -150,7 +150,8 @@ SOURCES = \
dbNetlistExtractor.cc \
gsiDeclDbNetlistDeviceClasses.cc \
gsiDeclDbNetlistDeviceExtractor.cc \
gsiDeclDbHierNetworkProcessor.cc
gsiDeclDbHierNetworkProcessor.cc \
dbNetlistDeviceExtractorClasses.cc
HEADERS = \
dbArray.h \
@ -264,7 +265,8 @@ HEADERS = \
dbNetlist.h \
dbNetlistDeviceClasses.h \
dbNetlistDeviceExtractor.h \
dbNetlistExtractor.h
dbNetlistExtractor.h \
dbNetlistDeviceExtractorClasses.h
!equals(HAVE_QT, "0") {

View File

@ -0,0 +1,128 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2018 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "dbNetlistDeviceExtractorClasses.h"
#include "dbNetlistDeviceClasses.h"
// ---------------------------------------------------------------------------------
// NetlistDeviceExtractorMOS3Transistor implementation
namespace db
{
NetlistDeviceExtractorMOS3Transistor::NetlistDeviceExtractorMOS3Transistor (const std::string &name)
: db::NetlistDeviceExtractor (name)
{
// .. nothing yet ..
}
void NetlistDeviceExtractorMOS3Transistor::setup ()
{
define_layer ("SD", "Source/drain diffusion");
define_layer ("G", "Gate");
define_layer ("P", "Poly");
register_device_class (new db::DeviceClassMOS3Transistor ());
}
db::Connectivity NetlistDeviceExtractorMOS3Transistor::get_connectivity (const db::Layout & /*layout*/, const std::vector<unsigned int> &layers) const
{
tl_assert (layers.size () == 3);
unsigned int diff = layers [0];
unsigned int gate = layers [1];
// not used for device recognition: poly (2), but used for producing the gate terminals
// The layer definition is diff, gate
db::Connectivity conn;
// collect all connected diffusion shapes
conn.connect (diff, diff);
// collect all connected gate shapes
conn.connect (gate, gate);
// connect gate with diff to detect gate/diffusion boundary
conn.connect (diff, gate);
return conn;
}
void NetlistDeviceExtractorMOS3Transistor::extract_devices (const std::vector<db::Region> &layer_geometry)
{
const db::Region &rdiff = layer_geometry [0];
const db::Region &rgates = layer_geometry [1];
for (db::Region::const_iterator p = rgates.begin_merged (); !p.at_end (); ++p) {
db::Region rgate (*p);
db::Region rdiff2gate = rdiff.selected_interacting (rgate);
if (rdiff2gate.empty ()) {
error (tl::to_string (tr ("Gate shape touches no diffusion - ignored")), *p);
} else {
unsigned int terminal_geometry_index = 0;
unsigned int gate_geometry_index = 2;
if (rdiff2gate.size () != 2) {
error (tl::sprintf (tl::to_string (tr ("Expected two polygons on diff interacting one gate shape (found %d) - gate shape ignored")), int (rdiff2gate.size ())), *p);
continue;
}
db::Edges edges (rgate.edges () & rdiff2gate.edges ());
if (edges.size () != 2) {
error (tl::sprintf (tl::to_string (tr ("Expected two edges interacting gate/diff (found %d) - width and length may be incorrect")), int (edges.size ())), *p);
continue;
}
if (! p->is_box ()) {
error (tl::to_string (tr ("Gate shape is not a box - width and length may be incorrect")), *p);
}
db::Device *device = create_device ();
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, dbu () * edges.length () * 0.5);
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, dbu () * (p->perimeter () - edges.length ()) * 0.5);
int diff_index = 0;
for (db::Region::const_iterator d = rdiff2gate.begin (); !d.at_end () && diff_index < 2; ++d, ++diff_index) {
// count the number of gate shapes attached to this shape and distribute the area of the
// diffusion region to the number of gates
int n = rgates.selected_interacting (db::Region (*d)).size ();
tl_assert (n > 0);
device->set_parameter_value (diff_index == 0 ? db::DeviceClassMOS3Transistor::param_id_AS : db::DeviceClassMOS3Transistor::param_id_AD, dbu () * dbu () * d->area () / double (n));
define_terminal (device, diff_index == 0 ? db::DeviceClassMOS3Transistor::terminal_id_S : db::DeviceClassMOS3Transistor::terminal_id_D, terminal_geometry_index, *d);
}
define_terminal (device, db::DeviceClassMOS3Transistor::terminal_id_G, gate_geometry_index, *p);
// output the device for debugging
device_out (device, rdiff2gate, rgate);
}
}
}
}

View File

@ -0,0 +1,81 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2018 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _HDR_dbNetlistDeviceExtractorClasses
#define _HDR_dbNetlistDeviceExtractorClasses
#include "dbNetlistDeviceExtractor.h"
namespace db
{
/**
* @brief A device extractor for a three-terminal MOS transistor
*
* This class supplies the generic extractor for a MOS device.
* The device is defined by two basic input layers: the diffusion area
* (source and drain) and the gate area. It requires a third layer
* (poly) to put the gate terminals on. The separation between poly
* and allows separating the device recognition layer (gate) from the
* conductive layer.
*
* The device class produced by this extractor is DeviceClassMOS3Transistor.
* The extractor extracts the four parameters of this class: L, W, AS and AD.
*
* The diffusion area is distributed on the number of gates connecting to
* the particular source or drain area.
*/
class DB_PUBLIC NetlistDeviceExtractorMOS3Transistor
: public db::NetlistDeviceExtractor
{
public:
NetlistDeviceExtractorMOS3Transistor (const std::string &name);
virtual void setup ();
virtual db::Connectivity get_connectivity (const db::Layout &layout, const std::vector<unsigned int> &layers) const;
virtual void extract_devices (const std::vector<db::Region> &layer_geometry);
protected:
/**
* @brief A cappback when the device is produced
* This callback is provided as a debugging port
*/
virtual void device_out (const db::Device * /*device*/, const db::Region & /*diff*/, const db::Region & /*gate*/)
{
// .. no specific implementation ..
}
};
}
namespace tl
{
template<> struct tl::type_traits<db::NetlistDeviceExtractorMOS3Transistor> : public tl::type_traits<void>
{
typedef tl::false_tag has_copy_constructor;
typedef tl::false_tag has_default_constructor;
};
}
#endif

View File

@ -22,6 +22,7 @@
#include "gsiDecl.h"
#include "dbNetlistDeviceExtractor.h"
#include "dbNetlistDeviceExtractorClasses.h"
namespace {
@ -212,16 +213,32 @@ Class<db::NetlistDeviceExtractorLayerDefinition> decl_dbNetlistDeviceExtractorLa
"This class has been introduced in version 0.26."
);
Class<NetlistDeviceExtractorImpl> decl_dbNetlistDeviceExtractor ("db", "NetlistDeviceExtractorImpl",
gsi::method ("name", &NetlistDeviceExtractorImpl::name,
Class<db::NetlistDeviceExtractor> decl_dbNetlistDeviceExtractor ("db", "DeviceExtractorBase",
gsi::method ("name", &db::NetlistDeviceExtractor::name,
"@brief Gets the name of the device extractor and the device class."
) +
gsi::iterator ("each_layer_definition", &db::NetlistDeviceExtractor::begin_layer_definitions, &db::NetlistDeviceExtractor::end_layer_definitions,
"@brief Iterates over all layer definitions."
) +
gsi::iterator ("each_error", &db::NetlistDeviceExtractor::begin_errors, &db::NetlistDeviceExtractor::end_errors,
"@brief Iterates over all errors collected in the device extractor."
),
"@brief The base class for all device extractors.\n"
"This is an abstract base class for device extractors. See \\NetlistDeviceExtractor for a generic "
"class which you can reimplement to supply your own customized device extractor. "
"In many cases using one of the preconfigured specific device extractors may be useful already and "
"it's not required to implement a custom one. For an example about a preconfigured device extractor see "
"\\DeviceExtractorMOS3Transistor.\n"
"\n"
"This class cannot and should not be instantiated explicitly. Use one of the subclasses instead.\n"
"\n"
"This class has been introduced in version 0.26."
);
Class<NetlistDeviceExtractorImpl> decl_NetlistDeviceExtractorImpl (decl_dbNetlistDeviceExtractor, "db", "DeviceExtractor",
gsi::method ("name=", &NetlistDeviceExtractorImpl::set_name,
"@brief Sets the name of the device extractor and the device class."
) +
gsi::iterator ("each_layer_definition", &NetlistDeviceExtractorImpl::begin_layer_definitions, &NetlistDeviceExtractorImpl::end_layer_definitions,
"@brief Iterates over all layer definitions."
) +
gsi::callback ("setup", &NetlistDeviceExtractorImpl::setup, &NetlistDeviceExtractorImpl::cb_setup,
"@brief Sets up the extractor.\n"
"This method is supposed to set up the device extractor. This involves three basic steps:\n"
@ -368,4 +385,34 @@ Class<NetlistDeviceExtractorImpl> decl_dbNetlistDeviceExtractor ("db", "NetlistD
"This class has been introduced in version 0.26."
);
db::NetlistDeviceExtractorMOS3Transistor *make_mos3_extractor (const std::string &name)
{
return new db::NetlistDeviceExtractorMOS3Transistor (name);
}
Class<db::NetlistDeviceExtractorMOS3Transistor> decl_NetlistDeviceExtractorMOS3Transistor (decl_dbNetlistDeviceExtractor, "db", "DeviceExtractorMOS3Transistor",
gsi::constructor ("new", &make_mos3_extractor, gsi::arg ("name"),
"@brief Creates a new device extractor with the given name."
),
"@brief A device extractor for a three-terminal MOS transistor\n"
"\n"
"This class supplies the generic extractor for a MOS device.\n"
"The device is defined by two basic input layers: the diffusion area\n"
"(source and drain) and the gate area. It requires a third layer\n"
"(poly) to put the gate terminals on. The separation between poly\n"
"and allows separating the device recognition layer (gate) from the\n"
"conductive layer.\n"
"\n"
"The device class produced by this extractor is \\DeviceClassMOS3Transistor.\n"
"The extractor extracts the four parameters of this class: L, W, AS and AD.\n"
"\n"
"The diffusion area is distributed on the number of gates connecting to\n"
"the particular source or drain area.\n"
"\n"
"This class is a closed one and methods cannot be reimplemented. To reimplement "
"specific methods, see \\DeviceExtractor.\n"
"\n"
"This class has been introduced in version 0.26."
);
}

View File

@ -21,7 +21,7 @@
*/
#include "dbNetlistDeviceExtractor.h"
#include "dbNetlistDeviceExtractorClasses.h"
#include "dbNetlistExtractor.h"
#include "dbNetlistDeviceClasses.h"
#include "dbLayout.h"
@ -59,11 +59,11 @@ static std::string device_name (const db::Device &device)
}
class MOSFETExtractor
: public db::NetlistDeviceExtractor
: public db::NetlistDeviceExtractorMOS3Transistor
{
public:
MOSFETExtractor (const std::string &name, db::Layout *debug_out)
: db::NetlistDeviceExtractor (name), mp_debug_out (debug_out), m_ldiff (0), m_lgate (0)
: db::NetlistDeviceExtractorMOS3Transistor (name), mp_debug_out (debug_out), m_ldiff (0), m_lgate (0)
{
if (mp_debug_out) {
m_ldiff = mp_debug_out->insert_layer (db::LayerProperties (100, 0));
@ -71,95 +71,6 @@ public:
}
}
virtual void setup ()
{
define_layer ("SD", "Source/drain diffusion");
define_layer ("G", "Gate");
define_layer ("P", "Poly");
register_device_class (new db::DeviceClassMOS3Transistor ());
}
virtual db::Connectivity get_connectivity (const db::Layout & /*layout*/, const std::vector<unsigned int> &layers) const
{
tl_assert (layers.size () == 3);
unsigned int diff = layers [0];
unsigned int gate = layers [1];
// not used for device recognition: poly (2), but used for producing the gate terminals
// The layer definition is diff, gate
db::Connectivity conn;
// collect all connected diffusion shapes
conn.connect (diff, diff);
// collect all connected gate shapes
conn.connect (gate, gate);
// connect gate with diff to detect gate/diffusion boundary
conn.connect (diff, gate);
return conn;
}
virtual void extract_devices (const std::vector<db::Region> &layer_geometry)
{
const db::Region &rdiff = layer_geometry [0];
const db::Region &rgates = layer_geometry [1];
for (db::Region::const_iterator p = rgates.begin_merged (); !p.at_end (); ++p) {
db::Region rgate (*p);
db::Region rdiff2gate = rdiff.selected_interacting (rgate);
if (rdiff2gate.empty ()) {
error (tl::to_string (tr ("Gate shape touches no diffusion - ignored")), *p);
} else {
unsigned int terminal_geometry_index = 0;
unsigned int gate_geometry_index = 2;
if (rdiff2gate.size () != 2) {
error (tl::sprintf (tl::to_string (tr ("Expected two polygons on diff interacting one gate shape (found %d) - gate shape ignored")), int (rdiff2gate.size ())), *p);
continue;
}
db::Edges edges (rgate.edges () & rdiff2gate.edges ());
if (edges.size () != 2) {
error (tl::sprintf (tl::to_string (tr ("Expected two edges interacting gate/diff (found %d) - width and length may be incorrect")), int (edges.size ())), *p);
continue;
}
if (! p->is_box ()) {
error (tl::to_string (tr ("Gate shape is not a box - width and length may be incorrect")), *p);
}
db::Device *device = create_device ();
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_W, dbu () * edges.length () * 0.5);
device->set_parameter_value (db::DeviceClassMOS3Transistor::param_id_L, dbu () * (p->perimeter () - edges.length ()) * 0.5);
int diff_index = 0;
for (db::Region::const_iterator d = rdiff2gate.begin (); !d.at_end () && diff_index < 2; ++d, ++diff_index) {
// count the number of gate shapes attached to this shape and distribute the area of the
// diffusion region to the number of gates
int n = rgates.selected_interacting (db::Region (*d)).size ();
tl_assert (n > 0);
device->set_parameter_value (diff_index == 0 ? db::DeviceClassMOS3Transistor::param_id_AS : db::DeviceClassMOS3Transistor::param_id_AD, dbu () * dbu () * d->area () / double (n));
define_terminal (device, diff_index == 0 ? db::DeviceClassMOS3Transistor::terminal_id_S : db::DeviceClassMOS3Transistor::terminal_id_D, terminal_geometry_index, *d);
}
define_terminal (device, db::DeviceClassMOS3Transistor::terminal_id_G, gate_geometry_index, *p);
// output the device for debugging
device_out (device, rdiff2gate, rgate);
}
}
}
private:
db::Layout *mp_debug_out;
unsigned int m_ldiff, m_lgate;