Serialization of custom device classes

This commit is contained in:
Matthias Koefferlein 2021-07-04 19:14:37 +02:00
parent 3220bdf60d
commit ae6f77f45f
4 changed files with 108 additions and 5 deletions

View File

@ -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]
*

View File

@ -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);

View File

@ -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 ()) {

View File

@ -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