mirror of https://github.com/KLayout/klayout.git
Serialization of custom device classes
This commit is contained in:
parent
3220bdf60d
commit
ae6f77f45f
|
|
@ -58,7 +58,7 @@ namespace db
|
|||
* - connects the shapes of the layer with the given global
|
||||
* nets [short key: G]
|
||||
* circuit(<name> [circuit-def]) - circuit (cell) [short key: X]
|
||||
* class(<name> <template>) - a device class definition (template: RES,CAP,...) [short key: K]
|
||||
* class(<name> <template> [template-def]) - a device class definition (template: RES,CAP,...) [short key: K]
|
||||
* device(<name> <class> [device-abstract-def])
|
||||
* - device abstract [short key: D]
|
||||
*
|
||||
|
|
@ -127,8 +127,18 @@ namespace db
|
|||
* (<x> <y>) - relative coordinates (reference is reset to 0,0
|
||||
* for each net or terminal in device abstract)
|
||||
*
|
||||
* [template-def]:
|
||||
*
|
||||
* param(<name> <primary>? <default-value>*) - defines a template parameter [short key: E]
|
||||
* ('primary' is a value: 0 or 1)
|
||||
* terminal(<name>) - defines a terminal [short key: T]
|
||||
*
|
||||
* [device-abstract-def]:
|
||||
*
|
||||
* [device-abstract-terminal-def]*
|
||||
*
|
||||
* [device-abstract-terminal-def]:
|
||||
*
|
||||
* terminal(<terminal-name> [geometry-def]*)
|
||||
* - specifies the terminal geometry [short key: T]
|
||||
*
|
||||
|
|
|
|||
|
|
@ -236,10 +236,9 @@ void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::Layo
|
|||
std::string class_name, templ_name;
|
||||
read_word_or_quoted (class_name);
|
||||
read_word_or_quoted (templ_name);
|
||||
br.done ();
|
||||
|
||||
if (netlist->device_class_by_name (class_name) != 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Device class must be defined before being used in device")));
|
||||
throw tl::Exception (tl::to_string (tr ("Duplicate definition of device class: ")) + class_name);
|
||||
}
|
||||
|
||||
db::DeviceClassTemplateBase *dct = db::DeviceClassTemplateBase::template_by_name (templ_name);
|
||||
|
|
@ -251,6 +250,52 @@ void LayoutToNetlistStandardReader::read_netlist (db::Netlist *netlist, db::Layo
|
|||
dc->set_name (class_name);
|
||||
netlist->add_device_class (dc);
|
||||
|
||||
while (br) {
|
||||
|
||||
if (test (skeys::terminal_key) || test (lkeys::terminal_key)) {
|
||||
|
||||
Brace br (this);
|
||||
|
||||
std::string terminal_name;
|
||||
read_word_or_quoted (terminal_name);
|
||||
if (! dc->has_terminal_with_name (terminal_name)) {
|
||||
db::DeviceTerminalDefinition td;
|
||||
td.set_name (terminal_name);
|
||||
dc->add_terminal_definition (td);
|
||||
}
|
||||
|
||||
br.done ();
|
||||
|
||||
} else if (test (skeys::param_key) || test (lkeys::param_key)) {
|
||||
|
||||
Brace br (this);
|
||||
|
||||
std::string param_name;
|
||||
read_word_or_quoted (param_name);
|
||||
int primary = read_int ();
|
||||
int default_value = read_double ();
|
||||
if (! dc->has_parameter_with_name (param_name)) {
|
||||
db::DeviceParameterDefinition pd;
|
||||
pd.set_name (param_name);
|
||||
pd.set_is_primary (primary);
|
||||
pd.set_default_value (default_value);
|
||||
dc->add_parameter_definition (pd);
|
||||
} else {
|
||||
db::DeviceParameterDefinition *pd = dc->parameter_definition_non_const (dc->parameter_id_for_name (param_name));
|
||||
pd->set_default_value (default_value);
|
||||
pd->set_is_primary (primary);
|
||||
}
|
||||
|
||||
br.done ();
|
||||
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string (tr ("Invalid keyword")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
br.done ();
|
||||
|
||||
} else if (l2n && (test (skeys::connect_key) || test (lkeys::connect_key))) {
|
||||
|
||||
Brace br (this);
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include "dbLayoutToNetlist.h"
|
||||
#include "dbLayoutToNetlistFormatDefs.h"
|
||||
#include "dbPolygonTools.h"
|
||||
#include "tlMath.h"
|
||||
|
||||
namespace db
|
||||
{
|
||||
|
|
@ -113,6 +114,47 @@ void std_writer_impl<Keys>::write (const db::Netlist *netlist, const db::LayoutT
|
|||
}
|
||||
}
|
||||
|
||||
static bool same_parameter (const DeviceParameterDefinition &a, const DeviceParameterDefinition &b)
|
||||
{
|
||||
if (a.is_primary () != b.is_primary ()) {
|
||||
return false;
|
||||
}
|
||||
if (! tl::equal (a.default_value (), b.default_value ())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class Keys>
|
||||
void std_writer_impl<Keys>::write_device_class (const std::string &indent, const db::DeviceClass *cls, const std::string &temp_name, const db::DeviceClass *temp_class)
|
||||
{
|
||||
*mp_stream << indent << Keys::class_key << "(" << tl::to_word_or_quoted_string (cls->name ()) << " " << tl::to_word_or_quoted_string (temp_name);
|
||||
|
||||
bool any_def = false;
|
||||
|
||||
const std::vector<DeviceParameterDefinition> &pd = cls->parameter_definitions ();
|
||||
for (std::vector<DeviceParameterDefinition>::const_iterator p = pd.begin (); p != pd.end (); ++p) {
|
||||
if (! temp_class->has_parameter_with_name (p->name ()) || !same_parameter (*p, *temp_class->parameter_definition (temp_class->parameter_id_for_name (p->name ())))) {
|
||||
*mp_stream << endl << indent << indent1 << Keys::param_key << "(" << tl::to_word_or_quoted_string (p->name ()) << " " << tl::to_string (p->is_primary () ? 1 : 0) << " " << tl::to_string (p->default_value ()) << ")";
|
||||
any_def = true;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<DeviceTerminalDefinition> &td = cls->terminal_definitions ();
|
||||
for (std::vector<DeviceTerminalDefinition>::const_iterator t = td.begin (); t != td.end (); ++t) {
|
||||
if (! temp_class->has_terminal_with_name (t->name ())) {
|
||||
*mp_stream << endl << indent << indent1 << Keys::terminal_key << "(" << tl::to_word_or_quoted_string (t->name ()) << ")";
|
||||
any_def = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (any_def) {
|
||||
*mp_stream << endl << indent << ")" << endl;
|
||||
} else {
|
||||
*mp_stream << ")" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
template <class Keys>
|
||||
void std_writer_impl<Keys>::write (bool nested, std::map<const db::Circuit *, std::map<const db::Net *, unsigned int> > *net2id_per_circuit)
|
||||
{
|
||||
|
|
@ -203,9 +245,13 @@ void std_writer_impl<Keys>::write (bool nested, std::map<const db::Circuit *, st
|
|||
for (db::Netlist::const_device_class_iterator c = mp_netlist->begin_device_classes (); c != mp_netlist->end_device_classes (); ++c) {
|
||||
db::DeviceClassTemplateBase *temp = db::DeviceClassTemplateBase::is_a (c.operator-> ());
|
||||
if (temp) {
|
||||
*mp_stream << indent << Keys::class_key << "(" << tl::to_word_or_quoted_string (c->name ()) << " " << tl::to_word_or_quoted_string (temp->name ()) << ")" << endl;
|
||||
m_progress.set (mp_stream->pos ());
|
||||
std::unique_ptr<db::DeviceClass> temp_class (temp->create ());
|
||||
write_device_class (indent, c.operator-> (), temp->name (), temp_class.get ());
|
||||
} else {
|
||||
db::DeviceClass empty;
|
||||
write_device_class (indent, c.operator-> (), std::string (), &empty);
|
||||
}
|
||||
m_progress.set (mp_stream->pos ());
|
||||
}
|
||||
|
||||
if (mp_netlist->begin_device_abstracts () != mp_netlist->end_device_abstracts () && ! Keys::is_short ()) {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ namespace db
|
|||
class Circuit;
|
||||
class SubCircuit;
|
||||
class Device;
|
||||
class DeviceClass;
|
||||
class DeviceAbstract;
|
||||
class Net;
|
||||
class Netlist;
|
||||
|
|
@ -78,6 +79,7 @@ private:
|
|||
void write (const db::DeviceAbstract &device_abstract, const std::string &indent);
|
||||
void write (const db::NetShape *s, const db::ICplxTrans &tr, const std::string &lname, bool relative);
|
||||
void write (const db::DCplxTrans &trans);
|
||||
void write_device_class (const std::string &indent, const db::DeviceClass *cls, const std::string &name, const db::DeviceClass *temp_class);
|
||||
void reset_geometry_ref ();
|
||||
|
||||
// implementation of CircuitCallback
|
||||
|
|
|
|||
Loading…
Reference in New Issue