mirror of https://github.com/KLayout/klayout.git
WIP: specific device extractor and GSI binding.
This commit is contained in:
parent
ec7ab8e01d
commit
b512f628bc
|
|
@ -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") {
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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."
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue