mirror of https://github.com/KLayout/klayout.git
Fixed DeviceClass assignment operator
This commit is contained in:
parent
4e0d8d92ef
commit
8f65ab099f
|
|
@ -120,11 +120,6 @@ public:
|
|||
|
||||
virtual bool less (const db::Device &a, const db::Device &b) const;
|
||||
|
||||
virtual DeviceParameterCompareDelegate *clone () const
|
||||
{
|
||||
return new PrimaryDeviceParametersAreEqual (*this);
|
||||
}
|
||||
|
||||
private:
|
||||
double m_relative;
|
||||
};
|
||||
|
|
@ -159,13 +154,13 @@ bool PrimaryDeviceParametersAreEqual::less (const db::Device &a, const db::Devic
|
|||
// DeviceClass class implementation
|
||||
|
||||
DeviceClass::DeviceClass ()
|
||||
: m_strict (false), mp_netlist (0)
|
||||
: m_strict (false), mp_netlist (0), m_supports_parallel_combination (false), m_supports_serial_combination (false)
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
DeviceClass::DeviceClass (const DeviceClass &other)
|
||||
: gsi::ObjectBase (other), tl::Object (other), tl::UniqueId (other), m_strict (false), mp_netlist (0)
|
||||
: gsi::ObjectBase (other), tl::Object (other), tl::UniqueId (other), m_strict (false), mp_netlist (0), m_supports_parallel_combination (false), m_supports_serial_combination (false)
|
||||
{
|
||||
operator= (other);
|
||||
}
|
||||
|
|
@ -173,12 +168,18 @@ DeviceClass::DeviceClass (const DeviceClass &other)
|
|||
DeviceClass &DeviceClass::operator= (const DeviceClass &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
|
||||
m_terminal_definitions = other.m_terminal_definitions;
|
||||
m_parameter_definitions = other.m_parameter_definitions;
|
||||
m_name = other.m_name;
|
||||
m_description = other.m_description;
|
||||
m_strict = other.m_strict;
|
||||
mp_pc_delegate.reset (const_cast<DeviceParameterCompareDelegate *> (other.mp_pc_delegate.get ()));
|
||||
mp_device_combiner.reset (const_cast<DeviceCombiner *> (other.mp_device_combiner.get ()));
|
||||
m_supports_serial_combination = other.m_supports_serial_combination;
|
||||
m_supports_parallel_combination = other.m_supports_parallel_combination;
|
||||
m_equivalent_terminal_ids = other.m_equivalent_terminal_ids;
|
||||
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,7 +295,6 @@ public:
|
|||
DeviceParameterCompareDelegate () { }
|
||||
virtual ~DeviceParameterCompareDelegate () { }
|
||||
|
||||
virtual DeviceParameterCompareDelegate *clone () const = 0;
|
||||
virtual bool less (const db::Device &a, const db::Device &b) const = 0;
|
||||
};
|
||||
|
||||
|
|
@ -315,11 +314,6 @@ public:
|
|||
|
||||
virtual bool less (const db::Device &a, const db::Device &b) const;
|
||||
|
||||
virtual DeviceParameterCompareDelegate *clone () const
|
||||
{
|
||||
return new EqualDeviceParameters (*this);
|
||||
}
|
||||
|
||||
EqualDeviceParameters &operator+= (const EqualDeviceParameters &other);
|
||||
|
||||
EqualDeviceParameters operator+ (const EqualDeviceParameters &other) const
|
||||
|
|
@ -344,15 +338,35 @@ public:
|
|||
|
||||
virtual bool less (const db::Device &a, const db::Device &b) const;
|
||||
|
||||
virtual DeviceParameterCompareDelegate *clone () const
|
||||
{
|
||||
return new AllDeviceParametersAreEqual (*this);
|
||||
}
|
||||
|
||||
private:
|
||||
double m_relative;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A device combiner
|
||||
*
|
||||
* The device combiner is a delegate that combines devices
|
||||
*/
|
||||
class DB_PUBLIC DeviceCombiner
|
||||
: public gsi::ObjectBase, public tl::Object
|
||||
{
|
||||
public:
|
||||
DeviceCombiner () { }
|
||||
virtual ~DeviceCombiner () { }
|
||||
|
||||
/**
|
||||
* @brief Combines two devices
|
||||
*
|
||||
* This method shall test, whether the two devices can be combined. Both devices
|
||||
* are guaranteed to share the same device class.
|
||||
* If they cannot be combined, this method shall do nothing and return false.
|
||||
* If they can be combined, this method shall reconnect the nets of the first
|
||||
* device and entirely disconnect the nets of the second device.
|
||||
* The second device will be deleted afterwards.
|
||||
*/
|
||||
virtual bool combine_devices (db::Device *a, db::Device *b) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A device class
|
||||
*
|
||||
|
|
@ -553,25 +567,57 @@ public:
|
|||
* device and entirely disconnect the nets of the second device.
|
||||
* The second device will be deleted afterwards.
|
||||
*/
|
||||
virtual bool combine_devices (db::Device * /*a*/, db::Device * /*b*/) const
|
||||
bool combine_devices (db::Device *a, db::Device *b) const
|
||||
{
|
||||
return false;
|
||||
return mp_device_combiner.get () ? mp_device_combiner->combine_devices (a, b) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the device class supports device combination in parallel mode
|
||||
*/
|
||||
virtual bool supports_parallel_combination () const
|
||||
bool supports_parallel_combination () const
|
||||
{
|
||||
return false;
|
||||
return m_supports_parallel_combination;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if the device class supports device combination in serial mode
|
||||
*/
|
||||
virtual bool supports_serial_combination () const
|
||||
bool supports_serial_combination () const
|
||||
{
|
||||
return false;
|
||||
return m_supports_serial_combination;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a value indicating that the class supports device combination in parallel mode
|
||||
*/
|
||||
void set_supports_parallel_combination (bool f)
|
||||
{
|
||||
m_supports_parallel_combination = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets a value indicating that the class supports device combination in serial mode
|
||||
*/
|
||||
void set_supports_serial_combination (bool f)
|
||||
{
|
||||
m_supports_serial_combination = f;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Marks two terminals as equivalent (swappable)
|
||||
*/
|
||||
void equivalent_terminal_id (size_t tid, size_t equiv_tid)
|
||||
{
|
||||
m_equivalent_terminal_ids.insert (std::make_pair (tid, equiv_tid));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears all equivalent terminal ids
|
||||
*/
|
||||
void clear_equivalent_terminal_ids ()
|
||||
{
|
||||
m_equivalent_terminal_ids.clear ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -580,9 +626,14 @@ public:
|
|||
* This method returns a "normalized" terminal ID. For example, for MOS
|
||||
* transistors where S and D can be exchanged, D will be mapped to S.
|
||||
*/
|
||||
virtual size_t normalize_terminal_id (size_t tid) const
|
||||
size_t normalize_terminal_id (size_t tid) const
|
||||
{
|
||||
return tid;
|
||||
std::map<size_t, size_t>::const_iterator ntid = m_equivalent_terminal_ids.find (tid);
|
||||
if (ntid != m_equivalent_terminal_ids.end ()) {
|
||||
return ntid->second;
|
||||
} else {
|
||||
return tid;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -643,6 +694,35 @@ public:
|
|||
return mp_pc_delegate.get ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Registers a device combiner
|
||||
*
|
||||
* The device class takes ownership of the combiner.
|
||||
*/
|
||||
void set_device_combiner (db::DeviceCombiner *combiner)
|
||||
{
|
||||
if (combiner) {
|
||||
combiner->keep (); // assume transfer of ownership for scripts
|
||||
}
|
||||
mp_device_combiner.reset (combiner);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the device combiner or null if no such delegate is registered
|
||||
*/
|
||||
const db::DeviceCombiner *device_combiner () const
|
||||
{
|
||||
return mp_device_combiner.get ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the device combiner or null if no such delegate is registered (non-const version)
|
||||
*/
|
||||
db::DeviceCombiner *device_combiner ()
|
||||
{
|
||||
return mp_device_combiner.get ();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate memory statistics
|
||||
*/
|
||||
|
|
@ -667,6 +747,10 @@ private:
|
|||
bool m_strict;
|
||||
db::Netlist *mp_netlist;
|
||||
tl::shared_ptr<db::DeviceParameterCompareDelegate> mp_pc_delegate;
|
||||
tl::shared_ptr<db::DeviceCombiner> mp_device_combiner;
|
||||
bool m_supports_parallel_combination;
|
||||
bool m_supports_serial_combination;
|
||||
std::map<size_t, size_t> m_equivalent_terminal_ids;
|
||||
|
||||
void set_netlist (db::Netlist *nl)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,58 +43,424 @@ static tl::RegisteredClass<db::DeviceClassTemplateBase> dct_bjt4 (new db::device
|
|||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassTwoTerminalDevice implementation
|
||||
|
||||
bool DeviceClassTwoTerminalDevice::combine_devices (Device *a, Device *b) const
|
||||
namespace
|
||||
{
|
||||
db::Net *na1 = a->net_for_terminal (0);
|
||||
db::Net *na2 = a->net_for_terminal (1);
|
||||
db::Net *nb1 = b->net_for_terminal (0);
|
||||
db::Net *nb2 = b->net_for_terminal (1);
|
||||
|
||||
if ((na1 == nb1 && na2 == nb2) || (na1 == nb2 && na2 == nb1)) {
|
||||
class TwoTerminalDeviceCombiner
|
||||
: public db::DeviceCombiner
|
||||
{
|
||||
public:
|
||||
bool combine_devices(db::Device *a, db::Device *b) const
|
||||
{
|
||||
db::Net *na1 = a->net_for_terminal (0);
|
||||
db::Net *na2 = a->net_for_terminal (1);
|
||||
db::Net *nb1 = b->net_for_terminal (0);
|
||||
db::Net *nb2 = b->net_for_terminal (1);
|
||||
|
||||
parallel (a, b);
|
||||
if ((na1 == nb1 && na2 == nb2) || (na1 == nb2 && na2 == nb1)) {
|
||||
|
||||
parallel (a, b);
|
||||
|
||||
if (na1 == nb1 && na2 == nb2) {
|
||||
a->join_terminals (0, b, 0);
|
||||
a->join_terminals (1, b, 1);
|
||||
} else {
|
||||
a->join_terminals (0, b, 1);
|
||||
a->join_terminals (1, b, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if ((na2 == nb1 || na2 == nb2) && na2->is_internal ()) {
|
||||
|
||||
// serial a(B) to b(A or B)
|
||||
serial (a, b);
|
||||
|
||||
if (na2 == nb1) {
|
||||
a->reroute_terminal (1, b, 0, 1);
|
||||
} else {
|
||||
a->reroute_terminal (1, b, 1, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if ((na1 == nb1 || na1 == nb2) && na1->is_internal ()) {
|
||||
|
||||
// serial a(A) to b(A or B)
|
||||
serial (a, b);
|
||||
|
||||
if (na1 == nb1) {
|
||||
a->reroute_terminal (0, b, 0, 1);
|
||||
} else {
|
||||
a->reroute_terminal (0, b, 1, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void parallel (Device *a, Device *b) const = 0;
|
||||
virtual void serial (Device *a, Device *b) const = 0;
|
||||
};
|
||||
|
||||
class ResistorDeviceCombiner
|
||||
: public TwoTerminalDeviceCombiner
|
||||
{
|
||||
public:
|
||||
void parallel (Device *a, Device *b) const
|
||||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb < 1e-10 ? 0.0 : va * vb / (va + vb));
|
||||
|
||||
// parallel width is sum of both, length is the one that gives the same value of resistance
|
||||
// R = 1/(1/R1 + 1/R2)
|
||||
// R = L/(W1+W2)
|
||||
// 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 dnom = (l2 * w1 + l1 * w2);
|
||||
if (fabs (dnom) > 1e-15) {
|
||||
a->set_parameter_value (1, (l1 * l2 * (w1 + w2)) / dnom);
|
||||
}
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
a->set_parameter_value (0, va + vb);
|
||||
|
||||
// parallel length is sum of both, width is the one that gives the same value of resistance
|
||||
// assuming same sheet rho
|
||||
// R = R1+R2
|
||||
// R = (L1+L2)/W
|
||||
// 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);
|
||||
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);
|
||||
a->set_parameter_value (3, aa + ab);
|
||||
|
||||
double pa = a->parameter_value (4);
|
||||
double pb = b->parameter_value (4);
|
||||
a->set_parameter_value (4, pa + pb);
|
||||
}
|
||||
};
|
||||
|
||||
class ResistorWithBulkDeviceCombiner
|
||||
: public ResistorDeviceCombiner
|
||||
{
|
||||
public:
|
||||
bool combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
db::Net *nab = a->net_for_terminal (2);
|
||||
db::Net *nbb = b->net_for_terminal (2);
|
||||
|
||||
if (nab == nbb && ResistorDeviceCombiner::combine_devices (a, b)) {
|
||||
a->join_terminals (2, b, 2);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CapacitorDeviceCombiner
|
||||
: public TwoTerminalDeviceCombiner
|
||||
{
|
||||
public:
|
||||
void serial (Device *a, Device *b) const
|
||||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb < 1e-10 ? 0.0 : va * vb / (va + vb));
|
||||
|
||||
// TODO: does this implementation make sense?
|
||||
double aa = a->parameter_value (1);
|
||||
double ab = b->parameter_value (1);
|
||||
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);
|
||||
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);
|
||||
a->set_parameter_value (0, va + vb);
|
||||
|
||||
double aa = a->parameter_value (1);
|
||||
double ab = b->parameter_value (1);
|
||||
a->set_parameter_value (1, aa + ab);
|
||||
|
||||
double pa = a->parameter_value (2);
|
||||
double pb = b->parameter_value (2);
|
||||
a->set_parameter_value (2, pa + pb);
|
||||
}
|
||||
};
|
||||
|
||||
class CapacitorWithBulkDeviceCombiner
|
||||
: public CapacitorDeviceCombiner
|
||||
{
|
||||
public:
|
||||
bool combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
db::Net *nab = a->net_for_terminal (2);
|
||||
db::Net *nbb = b->net_for_terminal (2);
|
||||
|
||||
if (nab == nbb && CapacitorDeviceCombiner::combine_devices (a, b)) {
|
||||
a->join_terminals (2, b, 2);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class InductorDeviceCombiner
|
||||
: public TwoTerminalDeviceCombiner
|
||||
{
|
||||
public:
|
||||
void parallel (Device *a, Device *b) const
|
||||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb < 1e-10 ? 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);
|
||||
a->set_parameter_value (0, va + vb);
|
||||
}
|
||||
};
|
||||
|
||||
class DiodeDeviceCombiner
|
||||
: public db::DeviceCombiner
|
||||
{
|
||||
public:
|
||||
bool combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
const db::Net *na1 = a->net_for_terminal (0);
|
||||
const db::Net *na2 = a->net_for_terminal (1);
|
||||
const db::Net *nb1 = b->net_for_terminal (0);
|
||||
const db::Net *nb2 = b->net_for_terminal (1);
|
||||
|
||||
// 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->join_terminals (0, b, 0);
|
||||
a->join_terminals (1, b, 1);
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
a->join_terminals (0, b, 1);
|
||||
a->join_terminals (1, b, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MOS3DeviceCombiner
|
||||
: public db::DeviceCombiner
|
||||
{
|
||||
public:
|
||||
bool combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
const db::Net *nas = a->net_for_terminal (0);
|
||||
const db::Net *nag = a->net_for_terminal (1);
|
||||
const db::Net *nad = a->net_for_terminal (2);
|
||||
const db::Net *nbs = b->net_for_terminal (0);
|
||||
const db::Net *nbg = b->net_for_terminal (1);
|
||||
const db::Net *nbd = b->net_for_terminal (2);
|
||||
|
||||
// parallel transistors can be combined into one
|
||||
if (((nas == nbs && nad == nbd) || (nas == nbd && nad == nbs)) && nag == nbg) {
|
||||
|
||||
// for combination the gate length must be identical
|
||||
if (fabs (a->parameter_value (0) - b->parameter_value (0)) < 1e-6) {
|
||||
|
||||
combine_parameters (a, b);
|
||||
|
||||
if (nas == nbs && nad == nbd) {
|
||||
a->join_terminals (0, b, 0);
|
||||
a->join_terminals (2, b, 2);
|
||||
} else {
|
||||
a->join_terminals (0, b, 2);
|
||||
a->join_terminals (2, b, 0);
|
||||
}
|
||||
|
||||
a->join_terminals (1, b, 1);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if ((na2 == nb1 || na2 == nb2) && na2->is_internal ()) {
|
||||
|
||||
// serial a(B) to b(A or B)
|
||||
serial (a, b);
|
||||
|
||||
if (na2 == nb1) {
|
||||
a->reroute_terminal (1, b, 0, 1);
|
||||
} else {
|
||||
a->reroute_terminal (1, b, 1, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else if ((na1 == nb1 || na1 == nb2) && na1->is_internal ()) {
|
||||
|
||||
// serial a(A) to b(A or B)
|
||||
serial (a, b);
|
||||
|
||||
if (na1 == nb1) {
|
||||
a->reroute_terminal (0, b, 0, 1);
|
||||
} else {
|
||||
a->reroute_terminal (0, b, 1, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
class MOS4DeviceCombiner
|
||||
: public MOS3DeviceCombiner
|
||||
{
|
||||
public:
|
||||
bool combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
const db::Net *nas = a->net_for_terminal (0);
|
||||
const db::Net *nag = a->net_for_terminal (1);
|
||||
const db::Net *nad = a->net_for_terminal (2);
|
||||
const db::Net *nab = a->net_for_terminal (3);
|
||||
const db::Net *nbs = b->net_for_terminal (0);
|
||||
const db::Net *nbg = b->net_for_terminal (1);
|
||||
const db::Net *nbd = b->net_for_terminal (2);
|
||||
const db::Net *nbb = b->net_for_terminal (3);
|
||||
|
||||
// parallel transistors can be combined into one
|
||||
if (((nas == nbs && nad == nbd) || (nas == nbd && nad == nbs)) && nag == nbg && nab == nbb) {
|
||||
|
||||
// for combination the gate length must be identical
|
||||
if (fabs (a->parameter_value (0) - b->parameter_value (0)) < 1e-6) {
|
||||
|
||||
combine_parameters (a, b);
|
||||
|
||||
if (nas == nbs && nad == nbd) {
|
||||
a->join_terminals (0, b, 0);
|
||||
a->join_terminals (2, b, 2);
|
||||
} else {
|
||||
a->join_terminals (0, b, 2);
|
||||
a->join_terminals (2, b, 0);
|
||||
}
|
||||
|
||||
a->join_terminals (1, b, 1);
|
||||
a->join_terminals (3, b, 3);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class BJT3DeviceCombiner
|
||||
: public db::DeviceCombiner
|
||||
{
|
||||
public:
|
||||
bool combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
const db::Net *nac = a->net_for_terminal (0);
|
||||
const db::Net *nab = a->net_for_terminal (1);
|
||||
const db::Net *nae = a->net_for_terminal (2);
|
||||
const db::Net *nbc = b->net_for_terminal (0);
|
||||
const db::Net *nbb = b->net_for_terminal (1);
|
||||
const db::Net *nbe = b->net_for_terminal (2);
|
||||
|
||||
// parallel transistors can be combined into one
|
||||
if (nac == nbc && nae == nbe && nab == nbb) {
|
||||
|
||||
combine_parameters (a, b);
|
||||
|
||||
a->join_terminals (0, b, 0);
|
||||
a->join_terminals (1, b, 1);
|
||||
a->join_terminals (2, b, 2);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
};
|
||||
|
||||
class BJT4DeviceCombiner
|
||||
: public BJT3DeviceCombiner
|
||||
{
|
||||
public:
|
||||
bool combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
const db::Net *nac = a->net_for_terminal (0);
|
||||
const db::Net *nab = a->net_for_terminal (1);
|
||||
const db::Net *nae = a->net_for_terminal (2);
|
||||
const db::Net *nas = a->net_for_terminal (3);
|
||||
const db::Net *nbc = b->net_for_terminal (0);
|
||||
const db::Net *nbb = b->net_for_terminal (1);
|
||||
const db::Net *nbe = b->net_for_terminal (2);
|
||||
const db::Net *nbs = b->net_for_terminal (3);
|
||||
|
||||
// parallel transistors can be combined into one
|
||||
if (nac == nbc && nae == nbe && nab == nbb && nas == nbs) {
|
||||
|
||||
combine_parameters (a, b);
|
||||
|
||||
a->join_terminals (0, b, 0);
|
||||
a->join_terminals (1, b, 1);
|
||||
a->join_terminals (2, b, 2);
|
||||
a->join_terminals (3, b, 3);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassResistor implementation
|
||||
|
|
@ -110,8 +476,13 @@ DB_PUBLIC size_t DeviceClassResistor::terminal_id_B = 1;
|
|||
|
||||
DeviceClassResistor::DeviceClassResistor ()
|
||||
{
|
||||
set_supports_serial_combination (true);
|
||||
set_supports_parallel_combination (true);
|
||||
set_device_combiner (new ResistorDeviceCombiner ());
|
||||
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("A", "Terminal A"));
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("B", "Terminal B"));
|
||||
equivalent_terminal_id (terminal_id_A, terminal_id_B);
|
||||
|
||||
add_parameter_definition (db::DeviceParameterDefinition ("R", "Resistance (Ohm)", 0.0));
|
||||
add_parameter_definition (db::DeviceParameterDefinition ("L", "Length (micrometer)", 0.0, false, 1e-6));
|
||||
|
|
@ -120,71 +491,6 @@ DeviceClassResistor::DeviceClassResistor ()
|
|||
add_parameter_definition (db::DeviceParameterDefinition ("P", "Perimeter (micrometer)", 0.0, false, 1e-6));
|
||||
}
|
||||
|
||||
void DeviceClassResistor::parallel (Device *a, Device *b) const
|
||||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb < 1e-10 ? 0.0 : va * vb / (va + vb));
|
||||
|
||||
// parallel width is sum of both, length is the one that gives the same value of resistance
|
||||
// R = 1/(1/R1 + 1/R2)
|
||||
// R = L/(W1+W2)
|
||||
// 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 dnom = (l2 * w1 + l1 * w2);
|
||||
if (fabs (dnom) > 1e-15) {
|
||||
a->set_parameter_value (1, (l1 * l2 * (w1 + w2)) / dnom);
|
||||
}
|
||||
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);
|
||||
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);
|
||||
a->set_parameter_value (4, pa + pb);
|
||||
}
|
||||
|
||||
void DeviceClassResistor::serial (Device *a, Device *b) const
|
||||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb);
|
||||
|
||||
// parallel length is sum of both, width is the one that gives the same value of resistance
|
||||
// assuming same sheet rho
|
||||
// R = R1+R2
|
||||
// R = (L1+L2)/W
|
||||
// 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);
|
||||
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);
|
||||
a->set_parameter_value (3, aa + ab);
|
||||
|
||||
double pa = a->parameter_value (4);
|
||||
double pb = b->parameter_value (4);
|
||||
a->set_parameter_value (4, pa + pb);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassResistorWithBulk implementation
|
||||
|
||||
|
|
@ -193,22 +499,10 @@ DB_PUBLIC size_t DeviceClassResistorWithBulk::terminal_id_W = 2;
|
|||
DeviceClassResistorWithBulk::DeviceClassResistorWithBulk ()
|
||||
: DeviceClassResistor ()
|
||||
{
|
||||
set_device_combiner (new ResistorWithBulkDeviceCombiner ());
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("W", "Terminal W (well, bulk)"));
|
||||
}
|
||||
|
||||
bool DeviceClassResistorWithBulk::combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
db::Net *nab = a->net_for_terminal (2);
|
||||
db::Net *nbb = b->net_for_terminal (2);
|
||||
|
||||
if (nab == nbb && DeviceClassResistor::combine_devices (a, b)) {
|
||||
a->join_terminals (2, b, 2);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassCapacitor implementation
|
||||
|
||||
|
|
@ -221,46 +515,19 @@ DB_PUBLIC size_t DeviceClassCapacitor::terminal_id_B = 1;
|
|||
|
||||
DeviceClassCapacitor::DeviceClassCapacitor ()
|
||||
{
|
||||
set_supports_serial_combination (true);
|
||||
set_supports_parallel_combination (true);
|
||||
set_device_combiner (new CapacitorDeviceCombiner ());
|
||||
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("A", "Terminal A"));
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("B", "Terminal B"));
|
||||
equivalent_terminal_id (terminal_id_A, terminal_id_B);
|
||||
|
||||
add_parameter_definition (db::DeviceParameterDefinition ("C", "Capacitance (Farad)", 0.0));
|
||||
add_parameter_definition (db::DeviceParameterDefinition ("A", "Area (square micrometer)", 0.0, false, 1e-12));
|
||||
add_parameter_definition (db::DeviceParameterDefinition ("P", "Perimeter (micrometer)", 0.0, false, 1e-6));
|
||||
}
|
||||
|
||||
void DeviceClassCapacitor::serial (Device *a, Device *b) const
|
||||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb < 1e-10 ? 0.0 : va * vb / (va + vb));
|
||||
|
||||
// TODO: does this implementation make sense?
|
||||
double aa = a->parameter_value (1);
|
||||
double ab = b->parameter_value (1);
|
||||
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);
|
||||
a->set_parameter_value (2, pa + pb);
|
||||
}
|
||||
|
||||
void DeviceClassCapacitor::parallel (Device *a, Device *b) const
|
||||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb);
|
||||
|
||||
double aa = a->parameter_value (1);
|
||||
double ab = b->parameter_value (1);
|
||||
a->set_parameter_value (1, aa + ab);
|
||||
|
||||
double pa = a->parameter_value (2);
|
||||
double pb = b->parameter_value (2);
|
||||
a->set_parameter_value (2, pa + pb);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassCapacitorWithBulk implementation
|
||||
|
||||
|
|
@ -269,22 +536,10 @@ DB_PUBLIC size_t DeviceClassCapacitorWithBulk::terminal_id_W = 2;
|
|||
DeviceClassCapacitorWithBulk::DeviceClassCapacitorWithBulk ()
|
||||
: DeviceClassCapacitor ()
|
||||
{
|
||||
set_device_combiner (new CapacitorWithBulkDeviceCombiner ());
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("W", "Terminal W (well, bulk)"));
|
||||
}
|
||||
|
||||
bool DeviceClassCapacitorWithBulk::combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
db::Net *nab = a->net_for_terminal (2);
|
||||
db::Net *nbb = b->net_for_terminal (2);
|
||||
|
||||
if (nab == nbb && DeviceClassCapacitor::combine_devices (a, b)) {
|
||||
a->join_terminals (2, b, 2);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassInductor implementation
|
||||
|
||||
|
|
@ -295,28 +550,19 @@ DB_PUBLIC size_t DeviceClassInductor::terminal_id_B = 1;
|
|||
|
||||
DeviceClassInductor::DeviceClassInductor ()
|
||||
{
|
||||
set_supports_serial_combination (true);
|
||||
set_supports_parallel_combination (true);
|
||||
set_device_combiner (new InductorDeviceCombiner ());
|
||||
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("A", "Terminal A"));
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("B", "Terminal B"));
|
||||
equivalent_terminal_id (terminal_id_A, terminal_id_B);
|
||||
|
||||
add_parameter_definition (db::DeviceParameterDefinition ("L", "Inductance (Henry)", 0.0));
|
||||
}
|
||||
|
||||
void DeviceClassInductor::parallel (Device *a, Device *b) const
|
||||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb < 1e-10 ? 0.0 : va * vb / (va + vb));
|
||||
}
|
||||
|
||||
void DeviceClassInductor::serial (Device *a, Device *b) const
|
||||
{
|
||||
double va = a->parameter_value (0);
|
||||
double vb = b->parameter_value (0);
|
||||
a->set_parameter_value (0, va + vb);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassInductor implementation
|
||||
// DeviceClassDiode implementation
|
||||
|
||||
DB_PUBLIC size_t DeviceClassDiode::param_id_A = 0;
|
||||
DB_PUBLIC size_t DeviceClassDiode::param_id_P = 1;
|
||||
|
|
@ -326,6 +572,9 @@ DB_PUBLIC size_t DeviceClassDiode::terminal_id_C = 1;
|
|||
|
||||
DeviceClassDiode::DeviceClassDiode ()
|
||||
{
|
||||
set_supports_parallel_combination (true);
|
||||
set_device_combiner (new DiodeDeviceCombiner ());
|
||||
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("A", "Anode"));
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("C", "Cathode"));
|
||||
|
||||
|
|
@ -333,29 +582,6 @@ DeviceClassDiode::DeviceClassDiode ()
|
|||
add_parameter_definition (db::DeviceParameterDefinition ("P", "Perimeter (micrometer)", 0.0, false, 1e-6));
|
||||
}
|
||||
|
||||
bool DeviceClassDiode::combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
const db::Net *na1 = a->net_for_terminal (0);
|
||||
const db::Net *na2 = a->net_for_terminal (1);
|
||||
const db::Net *nb1 = b->net_for_terminal (0);
|
||||
const db::Net *nb2 = b->net_for_terminal (1);
|
||||
|
||||
// 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->join_terminals (0, b, 0);
|
||||
a->join_terminals (1, b, 1);
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassMOS3Transistor implementation
|
||||
|
||||
|
|
@ -372,9 +598,13 @@ DB_PUBLIC size_t DeviceClassMOS3Transistor::terminal_id_D = 2;
|
|||
|
||||
DeviceClassMOS3Transistor::DeviceClassMOS3Transistor ()
|
||||
{
|
||||
set_supports_parallel_combination (true);
|
||||
set_device_combiner (new MOS3DeviceCombiner ());
|
||||
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("S", "Source"));
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("G", "Gate"));
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("D", "Drain"));
|
||||
equivalent_terminal_id (terminal_id_D, terminal_id_S);
|
||||
|
||||
add_parameter_definition (db::DeviceParameterDefinition ("L", "Gate length (micrometer)", 0.0, true, 1e-6));
|
||||
add_parameter_definition (db::DeviceParameterDefinition ("W", "Gate width (micrometer)", 0.0, true, 1e-6));
|
||||
|
|
@ -384,51 +614,6 @@ DeviceClassMOS3Transistor::DeviceClassMOS3Transistor ()
|
|||
add_parameter_definition (db::DeviceParameterDefinition ("PD", "Drain perimeter (micrometer)", 0.0, false, 1e-6));
|
||||
}
|
||||
|
||||
bool DeviceClassMOS3Transistor::combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
const db::Net *nas = a->net_for_terminal (0);
|
||||
const db::Net *nag = a->net_for_terminal (1);
|
||||
const db::Net *nad = a->net_for_terminal (2);
|
||||
const db::Net *nbs = b->net_for_terminal (0);
|
||||
const db::Net *nbg = b->net_for_terminal (1);
|
||||
const db::Net *nbd = b->net_for_terminal (2);
|
||||
|
||||
// parallel transistors can be combined into one
|
||||
if (((nas == nbs && nad == nbd) || (nas == nbd && nad == nbs)) && nag == nbg) {
|
||||
|
||||
// for combination the gate length must be identical
|
||||
if (fabs (a->parameter_value (0) - b->parameter_value (0)) < 1e-6) {
|
||||
|
||||
combine_parameters (a, b);
|
||||
|
||||
if (nas == nbs && nad == nbd) {
|
||||
a->join_terminals (0, b, 0);
|
||||
a->join_terminals (2, b, 2);
|
||||
} else {
|
||||
a->join_terminals (0, b, 2);
|
||||
a->join_terminals (2, b, 0);
|
||||
}
|
||||
|
||||
a->join_terminals (1, b, 1);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceClassMOS3Transistor::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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassMOS4Transistor implementation
|
||||
|
||||
|
|
@ -436,48 +621,10 @@ DB_PUBLIC size_t DeviceClassMOS4Transistor::terminal_id_B = 3;
|
|||
|
||||
DeviceClassMOS4Transistor::DeviceClassMOS4Transistor ()
|
||||
{
|
||||
set_device_combiner (new MOS4DeviceCombiner ());
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("B", "Bulk"));
|
||||
}
|
||||
|
||||
bool DeviceClassMOS4Transistor::combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
const db::Net *nas = a->net_for_terminal (0);
|
||||
const db::Net *nag = a->net_for_terminal (1);
|
||||
const db::Net *nad = a->net_for_terminal (2);
|
||||
const db::Net *nab = a->net_for_terminal (3);
|
||||
const db::Net *nbs = b->net_for_terminal (0);
|
||||
const db::Net *nbg = b->net_for_terminal (1);
|
||||
const db::Net *nbd = b->net_for_terminal (2);
|
||||
const db::Net *nbb = b->net_for_terminal (3);
|
||||
|
||||
// parallel transistors can be combined into one
|
||||
if (((nas == nbs && nad == nbd) || (nas == nbd && nad == nbs)) && nag == nbg && nab == nbb) {
|
||||
|
||||
// for combination the gate length must be identical
|
||||
if (fabs (a->parameter_value (0) - b->parameter_value (0)) < 1e-6) {
|
||||
|
||||
combine_parameters (a, b);
|
||||
|
||||
if (nas == nbs && nad == nbd) {
|
||||
a->join_terminals (0, b, 0);
|
||||
a->join_terminals (2, b, 2);
|
||||
} else {
|
||||
a->join_terminals (0, b, 2);
|
||||
a->join_terminals (2, b, 0);
|
||||
}
|
||||
|
||||
a->join_terminals (1, b, 1);
|
||||
a->join_terminals (3, b, 3);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassBJT3Transistor implementation
|
||||
|
||||
|
|
@ -495,6 +642,9 @@ DB_PUBLIC size_t DeviceClassBJT3Transistor::terminal_id_E = 2;
|
|||
|
||||
DeviceClassBJT3Transistor::DeviceClassBJT3Transistor ()
|
||||
{
|
||||
set_supports_parallel_combination (true);
|
||||
set_device_combiner (new BJT3DeviceCombiner ());
|
||||
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("C", "Collector"));
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("B", "Base"));
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("E", "Emitter"));
|
||||
|
|
@ -509,38 +659,6 @@ DeviceClassBJT3Transistor::DeviceClassBJT3Transistor ()
|
|||
add_parameter_definition (db::DeviceParameterDefinition ("NE", "Emitter count", 1.0, true));
|
||||
}
|
||||
|
||||
bool DeviceClassBJT3Transistor::combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
const db::Net *nac = a->net_for_terminal (0);
|
||||
const db::Net *nab = a->net_for_terminal (1);
|
||||
const db::Net *nae = a->net_for_terminal (2);
|
||||
const db::Net *nbc = b->net_for_terminal (0);
|
||||
const db::Net *nbb = b->net_for_terminal (1);
|
||||
const db::Net *nbe = b->net_for_terminal (2);
|
||||
|
||||
// parallel transistors can be combined into one
|
||||
if (nac == nbc && nae == nbe && nab == nbb) {
|
||||
|
||||
combine_parameters (a, b);
|
||||
|
||||
a->join_terminals (0, b, 0);
|
||||
a->join_terminals (1, b, 1);
|
||||
a->join_terminals (2, b, 2);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DeviceClassBJT3Transistor::combine_parameters (Device *a, Device *b) const
|
||||
{
|
||||
a->set_parameter_value (param_id_AE, a->parameter_value (param_id_AE) + b->parameter_value (param_id_AE));
|
||||
a->set_parameter_value (param_id_PE, a->parameter_value (param_id_PE) + b->parameter_value (param_id_PE));
|
||||
a->set_parameter_value (param_id_NE, a->parameter_value (param_id_NE) + b->parameter_value (param_id_NE));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// DeviceClassBJT4Transistor implementation
|
||||
|
||||
|
|
@ -548,35 +666,8 @@ DB_PUBLIC size_t DeviceClassBJT4Transistor::terminal_id_S = 3;
|
|||
|
||||
DeviceClassBJT4Transistor::DeviceClassBJT4Transistor ()
|
||||
{
|
||||
set_device_combiner (new BJT4DeviceCombiner ());
|
||||
add_terminal_definition (db::DeviceTerminalDefinition ("S", "Substrate"));
|
||||
}
|
||||
|
||||
bool DeviceClassBJT4Transistor::combine_devices (Device *a, Device *b) const
|
||||
{
|
||||
const db::Net *nac = a->net_for_terminal (0);
|
||||
const db::Net *nab = a->net_for_terminal (1);
|
||||
const db::Net *nae = a->net_for_terminal (2);
|
||||
const db::Net *nas = a->net_for_terminal (3);
|
||||
const db::Net *nbc = b->net_for_terminal (0);
|
||||
const db::Net *nbb = b->net_for_terminal (1);
|
||||
const db::Net *nbe = b->net_for_terminal (2);
|
||||
const db::Net *nbs = b->net_for_terminal (3);
|
||||
|
||||
// parallel transistors can be combined into one
|
||||
if (nac == nbc && nae == nbe && nab == nbb && nas == nbs) {
|
||||
|
||||
combine_parameters (a, b);
|
||||
|
||||
a->join_terminals (0, b, 0);
|
||||
a->join_terminals (1, b, 1);
|
||||
a->join_terminals (2, b, 2);
|
||||
a->join_terminals (3, b, 3);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,28 +29,13 @@
|
|||
namespace db
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A basic two-terminal device class
|
||||
*/
|
||||
class DB_PUBLIC DeviceClassTwoTerminalDevice
|
||||
: public db::DeviceClass
|
||||
{
|
||||
public:
|
||||
virtual bool combine_devices (Device *a, Device *b) const;
|
||||
|
||||
virtual void parallel (Device *a, Device *b) const = 0;
|
||||
virtual void serial (Device *a, Device *b) const = 0;
|
||||
virtual bool supports_parallel_combination () const { return true; }
|
||||
virtual bool supports_serial_combination () const { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A basic resistor device class
|
||||
* A resistor defines a single parameter, "R", which is the resistance in Ohm.
|
||||
* It defines two terminals, "A" and "B" for the two terminals.
|
||||
*/
|
||||
class DB_PUBLIC DeviceClassResistor
|
||||
: public db::DeviceClassTwoTerminalDevice
|
||||
: public db::DeviceClass
|
||||
{
|
||||
public:
|
||||
DeviceClassResistor ();
|
||||
|
|
@ -68,14 +53,6 @@ public:
|
|||
|
||||
static size_t terminal_id_A;
|
||||
static size_t terminal_id_B;
|
||||
|
||||
virtual void parallel (Device *a, Device *b) const;
|
||||
virtual void serial (Device *a, Device *b) const;
|
||||
|
||||
virtual size_t normalize_terminal_id (size_t id) const
|
||||
{
|
||||
return id == terminal_id_B ? terminal_id_A : id;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -95,8 +72,6 @@ public:
|
|||
}
|
||||
|
||||
static size_t terminal_id_W;
|
||||
|
||||
virtual bool combine_devices (Device *a, Device *b) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -105,7 +80,7 @@ public:
|
|||
* It defines two terminals, "A" and "B" for the two terminals.
|
||||
*/
|
||||
class DB_PUBLIC DeviceClassCapacitor
|
||||
: public db::DeviceClassTwoTerminalDevice
|
||||
: public db::DeviceClass
|
||||
{
|
||||
public:
|
||||
DeviceClassCapacitor ();
|
||||
|
|
@ -121,14 +96,6 @@ public:
|
|||
|
||||
static size_t terminal_id_A;
|
||||
static size_t terminal_id_B;
|
||||
|
||||
virtual void parallel (Device *a, Device *b) const;
|
||||
virtual void serial (Device *a, Device *b) const;
|
||||
|
||||
virtual size_t normalize_terminal_id (size_t id) const
|
||||
{
|
||||
return id == terminal_id_B ? terminal_id_A : id;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -148,8 +115,6 @@ public:
|
|||
}
|
||||
|
||||
static size_t terminal_id_W;
|
||||
|
||||
virtual bool combine_devices (Device *a, Device *b) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -158,7 +123,7 @@ public:
|
|||
* It defines two terminals, "A" and "B" for the two terminals.
|
||||
*/
|
||||
class DB_PUBLIC DeviceClassInductor
|
||||
: public db::DeviceClassTwoTerminalDevice
|
||||
: public db::DeviceClass
|
||||
{
|
||||
public:
|
||||
DeviceClassInductor ();
|
||||
|
|
@ -172,14 +137,6 @@ public:
|
|||
|
||||
static size_t terminal_id_A;
|
||||
static size_t terminal_id_B;
|
||||
|
||||
virtual void parallel (Device *a, Device *b) const;
|
||||
virtual void serial (Device *a, Device *b) const;
|
||||
|
||||
virtual size_t normalize_terminal_id (size_t id) const
|
||||
{
|
||||
return id == terminal_id_B ? terminal_id_A : id;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -204,9 +161,6 @@ public:
|
|||
{
|
||||
return new DeviceClassDiode (*this);
|
||||
}
|
||||
|
||||
virtual bool combine_devices (Device *a, Device *b) const;
|
||||
virtual bool supports_parallel_combination () const { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -237,14 +191,6 @@ public:
|
|||
return new DeviceClassMOS3Transistor (*this);
|
||||
}
|
||||
|
||||
virtual bool combine_devices (Device *a, Device *b) const;
|
||||
virtual bool supports_parallel_combination () const { return true; }
|
||||
|
||||
virtual size_t normalize_terminal_id (size_t tid) const
|
||||
{
|
||||
return tid == terminal_id_D ? terminal_id_S : tid;
|
||||
}
|
||||
|
||||
protected:
|
||||
void combine_parameters (Device *a, Device *b) const;
|
||||
};
|
||||
|
|
@ -266,13 +212,6 @@ public:
|
|||
{
|
||||
return new DeviceClassMOS4Transistor (*this);
|
||||
}
|
||||
|
||||
virtual size_t normalize_terminal_id (size_t tid) const
|
||||
{
|
||||
return tid == terminal_id_D ? terminal_id_S : tid;
|
||||
}
|
||||
|
||||
virtual bool combine_devices (Device *a, Device *b) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -303,12 +242,6 @@ public:
|
|||
{
|
||||
return new DeviceClassBJT3Transistor (*this);
|
||||
}
|
||||
|
||||
virtual bool combine_devices (Device *a, Device *b) const;
|
||||
virtual bool supports_parallel_combination () const { return true; }
|
||||
|
||||
protected:
|
||||
void combine_parameters (Device *a, Device *b) const;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -328,8 +261,6 @@ public:
|
|||
{
|
||||
return new DeviceClassBJT4Transistor (*this);
|
||||
}
|
||||
|
||||
virtual bool combine_devices (Device *a, Device *b) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -876,6 +876,31 @@ public:
|
|||
gsi::Callback cb_less;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A DeviceCombiner implementation that allows reimplementation of the virtual methods
|
||||
*/
|
||||
class GenericDeviceCombiner
|
||||
: public db::DeviceCombiner
|
||||
{
|
||||
public:
|
||||
GenericDeviceCombiner ()
|
||||
: db::DeviceCombiner ()
|
||||
{
|
||||
// .. nothing yet ..
|
||||
}
|
||||
|
||||
virtual bool combine_devices (db::Device *a, db::Device *b) const
|
||||
{
|
||||
if (cb_combine.can_issue ()) {
|
||||
return cb_combine.issue<db::DeviceCombiner, bool, db::Device *, db::Device *> (&db::DeviceCombiner::combine_devices, a, b);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
gsi::Callback cb_combine;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
db::EqualDeviceParameters *make_equal_dp (size_t param_id, double absolute, double relative)
|
||||
|
|
@ -942,6 +967,29 @@ Class<GenericDeviceParameterCompare> decl_GenericDeviceParameterCompare (decl_db
|
|||
"This class has been added in version 0.26. The 'equal' method has been dropped in 0.27.1 as it can be expressed as !less(a,b) && !less(b,a)."
|
||||
);
|
||||
|
||||
Class<GenericDeviceCombiner> decl_GenericDeviceCombiner ("db", "GenericDeviceCombiner",
|
||||
gsi::callback ("combine_devices", &GenericDeviceCombiner::combine_devices, &GenericDeviceCombiner::cb_combine, gsi::arg ("device_a"), gsi::arg ("device_b"),
|
||||
"@brief Combines two devices if possible.\n"
|
||||
"This method needs to test, whether the two devices can be combined. Both devices "
|
||||
"are guaranteed to share the same device class. "
|
||||
"If they cannot be combined, this method shall do nothing and return false. "
|
||||
"If they can be combined, this method shall reconnect the nets of the first "
|
||||
"device and entirely disconnect the nets of the second device. "
|
||||
"The second device will be deleted afterwards. "
|
||||
),
|
||||
"@brief A class implementing the combination of two devices (parallel or serial mode).\n"
|
||||
"Reimplement this class to provide a custom device combiner.\n"
|
||||
"Device combination requires 'supports_paralell_combination' or 'supports_serial_combination' to be set "
|
||||
"to true for the device class. In the netlist device combination step, the algorithm will try to identify "
|
||||
"devices which can be combined into single devices and use the combiner object to implement the actual "
|
||||
"joining of such devices.\n"
|
||||
"\n"
|
||||
"Attach this object to a device class with \\DeviceClass#combiner= to make the device "
|
||||
"class use this combiner.\n"
|
||||
"\n"
|
||||
"This class has been added in version 0.27.3."
|
||||
);
|
||||
|
||||
static tl::id_type id_of_device_class (const db::DeviceClass *cls)
|
||||
{
|
||||
return tl::id_of (cls);
|
||||
|
|
@ -957,6 +1005,16 @@ static db::EqualDeviceParameters *get_equal_parameters (db::DeviceClass *cls)
|
|||
return dynamic_cast<db::EqualDeviceParameters *> (cls->parameter_compare_delegate ());
|
||||
}
|
||||
|
||||
static void set_combiner (db::DeviceClass *cls, GenericDeviceCombiner *combiner)
|
||||
{
|
||||
cls->set_device_combiner (combiner);
|
||||
}
|
||||
|
||||
static GenericDeviceCombiner *get_combiner (db::DeviceClass *cls)
|
||||
{
|
||||
return dynamic_cast<GenericDeviceCombiner *> (cls->device_combiner ());
|
||||
}
|
||||
|
||||
static void enable_parameter (db::DeviceClass *cls, size_t id, bool en)
|
||||
{
|
||||
db::DeviceParameterDefinition *pd = cls->parameter_definition_non_const (id);
|
||||
|
|
@ -987,6 +1045,20 @@ static const db::DeviceParameterDefinition *parameter_definition2 (const db::Dev
|
|||
}
|
||||
}
|
||||
|
||||
static void dc_add_terminal_definition (db::DeviceClass *cls, db::DeviceTerminalDefinition *terminal_def)
|
||||
{
|
||||
if (terminal_def) {
|
||||
*terminal_def = cls->add_terminal_definition (*terminal_def);
|
||||
}
|
||||
}
|
||||
|
||||
static void dc_add_parameter_definition (db::DeviceClass *cls, db::DeviceParameterDefinition *parameter_def)
|
||||
{
|
||||
if (parameter_def) {
|
||||
*parameter_def = cls->add_parameter_definition (*parameter_def);
|
||||
}
|
||||
}
|
||||
|
||||
Class<db::DeviceClass> decl_dbDeviceClass ("db", "DeviceClass",
|
||||
gsi::method ("name", &db::DeviceClass::name,
|
||||
"@brief Gets the name of the device class."
|
||||
|
|
@ -1088,7 +1160,7 @@ Class<db::DeviceClass> decl_dbDeviceClass ("db", "DeviceClass",
|
|||
"@brief Gets the device parameter comparer for netlist verification or nil if no comparer is registered.\n"
|
||||
"See \\equal_parameters= for the setter.\n"
|
||||
"\n"
|
||||
"This getter has been introduced in version 0.26.4.\n"
|
||||
"This method has been moved from 'GenericDeviceClass' to 'DeviceClass' in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("equal_parameters=", &equal_parameters, gsi::arg ("comparer"),
|
||||
"@brief Specifies a device parameter comparer for netlist verification.\n"
|
||||
|
|
@ -1099,7 +1171,85 @@ Class<db::DeviceClass> decl_dbDeviceClass ("db", "DeviceClass",
|
|||
"\n"
|
||||
"You can assign nil for the parameter comparer to remove it.\n"
|
||||
"\n"
|
||||
"In special cases, you can even implement a custom compare scheme by deriving your own comparer from the \\GenericDeviceParameterCompare class."
|
||||
"In special cases, you can even implement a custom compare scheme by deriving your own comparer from the \\GenericDeviceParameterCompare class.\n"
|
||||
"\n"
|
||||
"This method has been moved from 'GenericDeviceClass' to 'DeviceClass' in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("add_terminal", &gsi::dc_add_terminal_definition, gsi::arg ("terminal_def"),
|
||||
"@brief Adds the given terminal definition to the device class\n"
|
||||
"This method will define a new terminal. The new terminal is added at the end of existing terminals. "
|
||||
"The terminal definition object passed as the argument is modified to contain the "
|
||||
"new ID of the terminal.\n"
|
||||
"\n"
|
||||
"The terminal is copied into the device class. Modifying the terminal object later "
|
||||
"does not have the effect of changing the terminal definition.\n"
|
||||
"\n"
|
||||
"This method has been moved from 'GenericDeviceClass' to 'DeviceClass' in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method ("clear_terminals", &db::DeviceClass::clear_terminal_definitions,
|
||||
"@brief Clears the list of terminals\n"
|
||||
"\n"
|
||||
"This method has been moved from 'GenericDeviceClass' to 'DeviceClass' in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("add_parameter", &gsi::dc_add_parameter_definition, gsi::arg ("parameter_def"),
|
||||
"@brief Adds the given parameter definition to the device class\n"
|
||||
"This method will define a new parameter. The new parameter is added at the end of existing parameters. "
|
||||
"The parameter definition object passed as the argument is modified to contain the "
|
||||
"new ID of the parameter."
|
||||
"\n"
|
||||
"The parameter is copied into the device class. Modifying the parameter object later "
|
||||
"does not have the effect of changing the parameter definition.\n"
|
||||
"\n"
|
||||
"This method has been moved from 'GenericDeviceClass' to 'DeviceClass' in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method ("clear_parameters", &db::DeviceClass::clear_parameter_definitions,
|
||||
"@brief Clears the list of parameters\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("combiner=", &set_combiner, gsi::arg ("combiner"),
|
||||
"@brief Specifies a device combiner (parallel or serial device combination).\n"
|
||||
"\n"
|
||||
"You can assign nil for the combiner to remove it.\n"
|
||||
"\n"
|
||||
"In special cases, you can even implement a custom combiner by deriving your own comparer from the \\GenericDeviceCombiner class.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method_ext ("combiner", &get_combiner,
|
||||
"@brief Gets a device combiner or nil if none is registered.\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method ("supports_parallel_combination=", &db::DeviceClass::set_supports_parallel_combination, gsi::arg ("f"),
|
||||
"@brief Specifies whether the device supports parallel device combination.\n"
|
||||
"Parallel device combination means that all terminals of two combination candidates are connected to the same nets. "
|
||||
"If the device does not support this combination mode, this predicate can be set to false. This will make the device "
|
||||
"extractor skip the combination test in parallel mode and improve performance somewhat.\n"
|
||||
"\n"
|
||||
"This method has been moved from 'GenericDeviceClass' to 'DeviceClass' in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method ("supports_serial_combination=", &db::DeviceClass::set_supports_serial_combination, gsi::arg ("f"),
|
||||
"@brief Specifies whether the device supports serial device combination.\n"
|
||||
"Serial device combination means that the devices are connected by internal nodes. "
|
||||
"If the device does not support this combination mode, this predicate can be set to false. This will make the device "
|
||||
"extractor skip the combination test in serial mode and improve performance somewhat.\n"
|
||||
"\n"
|
||||
"This method has been moved from 'GenericDeviceClass' to 'DeviceClass' in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method ("equivalent_terminal_id", &db::DeviceClass::equivalent_terminal_id, gsi::arg ("original_id"), gsi::arg ("equivalent_id"),
|
||||
"@brief Specifies a terminal to be equivalent to another.\n"
|
||||
"Use this method to specify two terminals to be exchangeable. For example to make S and D of a MOS transistor equivalent, "
|
||||
"call this method with S and D terminal IDs. In netlist matching, S will be translated to D and thus made equivalent to D.\n"
|
||||
"\n"
|
||||
"Note that terminal equivalence is not effective if the device class operates in strict mode (see \\DeviceClass#strict=).\n"
|
||||
"\n"
|
||||
"This method has been moved from 'GenericDeviceClass' to 'DeviceClass' in version 0.27.3.\n"
|
||||
) +
|
||||
gsi::method ("clear_equivalent_terminal_ids", &db::DeviceClass::clear_equivalent_terminal_ids,
|
||||
"@brief Clears all equivalent terminal ids\n"
|
||||
"\n"
|
||||
"This method has been added in version 0.27.3.\n"
|
||||
),
|
||||
"@brief A class describing a specific type of device.\n"
|
||||
"Device class objects live in the context of a \\Netlist object. After a "
|
||||
|
|
@ -1109,7 +1259,8 @@ Class<db::DeviceClass> decl_dbDeviceClass ("db", "DeviceClass",
|
|||
"\n"
|
||||
"The \\DeviceClass class is the base class for other device classes.\n"
|
||||
"\n"
|
||||
"This class has been added in version 0.26."
|
||||
"This class has been added in version 0.26. In version 0.27.3, the 'GenericDeviceClass' has been integrated with \\DeviceClass "
|
||||
"and the device class was made writeable in most respects. This enables manipulating built-in device classes."
|
||||
);
|
||||
|
||||
namespace {
|
||||
|
|
@ -1184,87 +1335,6 @@ private:
|
|||
|
||||
}
|
||||
|
||||
static void gdc_add_terminal_definition (GenericDeviceClass *cls, db::DeviceTerminalDefinition *terminal_def)
|
||||
{
|
||||
if (terminal_def) {
|
||||
*terminal_def = cls->add_terminal_definition (*terminal_def);
|
||||
}
|
||||
}
|
||||
|
||||
static void gdc_add_parameter_definition (GenericDeviceClass *cls, db::DeviceParameterDefinition *parameter_def)
|
||||
{
|
||||
if (parameter_def) {
|
||||
*parameter_def = cls->add_parameter_definition (*parameter_def);
|
||||
}
|
||||
}
|
||||
|
||||
Class<GenericDeviceClass> decl_GenericDeviceClass (decl_dbDeviceClass, "db", "GenericDeviceClass",
|
||||
gsi::method_ext ("add_terminal", &gsi::gdc_add_terminal_definition, gsi::arg ("terminal_def"),
|
||||
"@brief Adds the given terminal definition to the device class\n"
|
||||
"This method will define a new terminal. The new terminal is added at the end of existing terminals. "
|
||||
"The terminal definition object passed as the argument is modified to contain the "
|
||||
"new ID of the terminal.\n"
|
||||
"\n"
|
||||
"The terminal is copied into the device class. Modifying the terminal object later "
|
||||
"does not have the effect of changing the terminal definition."
|
||||
) +
|
||||
gsi::method ("clear_terminals", &GenericDeviceClass::clear_terminal_definitions,
|
||||
"@brief Clears the list of terminals\n"
|
||||
) +
|
||||
gsi::method_ext ("add_parameter", &gsi::gdc_add_parameter_definition, gsi::arg ("parameter_def"),
|
||||
"@brief Adds the given parameter definition to the device class\n"
|
||||
"This method will define a new parameter. The new parameter is added at the end of existing parameters. "
|
||||
"The parameter definition object passed as the argument is modified to contain the "
|
||||
"new ID of the parameter."
|
||||
"\n"
|
||||
"The parameter is copied into the device class. Modifying the parameter object later "
|
||||
"does not have the effect of changing the parameter definition."
|
||||
) +
|
||||
gsi::method ("clear_parameters", &GenericDeviceClass::clear_parameter_definitions,
|
||||
"@brief Clears the list of parameters\n"
|
||||
) +
|
||||
gsi::callback ("combine_devices", &GenericDeviceClass::combine_devices, &GenericDeviceClass::cb_combine_devices, gsi::arg ("a"), gsi::arg ("b"),
|
||||
"@brief Combines two devices.\n"
|
||||
"This method shall test, whether the two devices can be combined. Both devices "
|
||||
"are guaranteed to share the same device class (self). "
|
||||
"If they cannot be combined, this method shall do nothing and return false. "
|
||||
"If they can be combined, this method shall reconnect the nets of the first "
|
||||
"device and entirely disconnect the nets of the second device. "
|
||||
"It shall combine the parameters of both devices into the first. "
|
||||
"The second device will be deleted afterwards.\n"
|
||||
) +
|
||||
gsi::method ("supports_parallel_combination=", &GenericDeviceClass::set_supports_parallel_combination, gsi::arg ("f"),
|
||||
"@brief Specifies whether the device supports parallel device combination.\n"
|
||||
"Parallel device combination means that all terminals of two combination candidates are connected to the same nets. "
|
||||
"If the device does not support this combination mode, this predicate can be set to false. This will make the device "
|
||||
"extractor skip the combination test in parallel mode and improve performance somewhat."
|
||||
) +
|
||||
gsi::method ("supports_serial_combination=", &GenericDeviceClass::set_supports_serial_combination, gsi::arg ("f"),
|
||||
"@brief Specifies whether the device supports serial device combination.\n"
|
||||
"Serial device combination means that the devices are connected by internal nodes. "
|
||||
"If the device does not support this combination mode, this predicate can be set to false. This will make the device "
|
||||
"extractor skip the combination test in serial mode and improve performance somewhat."
|
||||
) +
|
||||
gsi::method ("equivalent_terminal_id", &GenericDeviceClass::equivalent_terminal_id, gsi::arg ("original_id"), gsi::arg ("equivalent_id"),
|
||||
"@brief Specifies a terminal to be equivalent to another.\n"
|
||||
"Use this method to specify two terminals to be exchangeable. For example to make S and D of a MOS transistor equivalent, "
|
||||
"call this method with S and D terminal IDs. In netlist matching, S will be translated to D and thus made equivalent to D.\n"
|
||||
"\n"
|
||||
"Note that terminal equivalence is not effective if the device class operates in strict mode (see \\DeviceClass#strict=)."
|
||||
),
|
||||
"@brief A generic device class\n"
|
||||
"This class allows building generic device classes. Specifically, terminals can be defined "
|
||||
"by adding terminal definitions. Terminal definitions should not be added dynamically. To create "
|
||||
"your own device, instantiate the \\GenericDeviceClass object, set name and description and "
|
||||
"specify the terminals. Then add this new device class to the \\Netlist object where it will live "
|
||||
"and be used to define device instances (\\Device objects).\n"
|
||||
"\n"
|
||||
"In addition, parameters can be defined which correspond to values stored inside the "
|
||||
"specific device instance (\\Device object)."
|
||||
"\n"
|
||||
"This class has been added in version 0.26."
|
||||
);
|
||||
|
||||
static db::Net *create_net (db::Circuit *c, const std::string &name)
|
||||
{
|
||||
db::Net *n = new db::Net ();
|
||||
|
|
|
|||
|
|
@ -124,13 +124,13 @@ class DBNetlist_TestClass < TestBase
|
|||
def test_2_NetlistBasicDeviceClass
|
||||
|
||||
nl = RBA::Netlist::new
|
||||
c = RBA::GenericDeviceClass::new
|
||||
c = RBA::DeviceClass::new
|
||||
nl.add(c)
|
||||
|
||||
c.name = "XYZ"
|
||||
assert_equal(c.name, "XYZ")
|
||||
|
||||
cc = RBA::GenericDeviceClass::new
|
||||
cc = RBA::DeviceClass::new
|
||||
|
||||
begin
|
||||
nl.remove(cc) # not in netlist yet
|
||||
|
|
@ -158,7 +158,7 @@ class DBNetlist_TestClass < TestBase
|
|||
nl.each_device_class { |i| names << i.name }
|
||||
assert_equal(names, [ c.name ])
|
||||
|
||||
cc = RBA::GenericDeviceClass::new
|
||||
cc = RBA::DeviceClass::new
|
||||
nl.add(cc)
|
||||
cc.name = "UVW"
|
||||
|
||||
|
|
@ -239,7 +239,7 @@ class DBNetlist_TestClass < TestBase
|
|||
|
||||
nl = RBA::Netlist::new
|
||||
|
||||
dc = RBA::GenericDeviceClass::new
|
||||
dc = RBA::DeviceClass::new
|
||||
nl.add(dc)
|
||||
assert_equal(dc.netlist.object_id, nl.object_id)
|
||||
dc.name = "DC"
|
||||
|
|
@ -576,11 +576,11 @@ class DBNetlist_TestClass < TestBase
|
|||
|
||||
end
|
||||
|
||||
def test_7_GenericDeviceClass
|
||||
def test_7_DeviceClass
|
||||
|
||||
nl = RBA::Netlist::new
|
||||
|
||||
dc = RBA::GenericDeviceClass::new
|
||||
dc = RBA::DeviceClass::new
|
||||
nl.add(dc)
|
||||
dc.name = "DC"
|
||||
assert_equal(dc.name, "DC")
|
||||
|
|
@ -758,7 +758,7 @@ class DBNetlist_TestClass < TestBase
|
|||
|
||||
nl = RBA::Netlist::new
|
||||
|
||||
dc = RBA::GenericDeviceClass::new
|
||||
dc = RBA::DeviceClass::new
|
||||
dc.name = "DC"
|
||||
nl.add(dc)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue