WIP: combined devices and geometry/L2N DB representation. Yet to do: device cell transformation beyond vector?

This commit is contained in:
Matthias Koefferlein 2019-05-09 01:07:54 +02:00
parent 9a361ee234
commit db1e813635
6 changed files with 196 additions and 41 deletions

View File

@ -189,17 +189,15 @@ void Device::set_parameter_value (const std::string &name, double v)
void Device::add_others_terminals (unsigned int this_terminal, db::Device *other, unsigned int other_terminal)
{
std::vector<OtherTerminalRef> &terminals = m_reconnected_terminals [this_terminal];
std::map<unsigned int, std::vector<OtherTerminalRef> >::const_iterator ot = other->m_reconnected_terminals.find (other_terminal);
if (ot == other->m_reconnected_terminals.end ()) {
return;
}
if (other->m_reconnected_terminals.empty ()) {
m_reconnected_terminals.insert (std::make_pair (this_terminal, ot->second));
terminals.push_back (OtherTerminalRef (other->device_abstract (), other->position () - position (), other_terminal));
} else {
std::vector<OtherTerminalRef> &terminals = m_reconnected_terminals [this_terminal];
size_t n = terminals.size ();
terminals.insert (terminals.end (), ot->second.begin (), ot->second.end ());
@ -212,10 +210,22 @@ void Device::add_others_terminals (unsigned int this_terminal, db::Device *other
}
}
void Device::init_terminal_routes ()
{
if (! device_class ()) {
return;
}
size_t n = device_class ()->terminal_definitions ().size ();
for (size_t i = 0; i < n; ++i) {
m_reconnected_terminals [i].push_back (OtherTerminalRef (device_abstract (), db::DVector (), i));
}
}
void Device::join_terminals (unsigned int this_terminal, db::Device *other, unsigned int other_terminal)
{
if (m_reconnected_terminals.empty ()) {
m_reconnected_terminals [this_terminal].push_back (OtherTerminalRef (device_abstract (), db::DVector (), this_terminal));
init_terminal_routes ();
}
other->connect_terminal (other_terminal, 0);
@ -227,6 +237,10 @@ void Device::reroute_terminal (unsigned int this_terminal, db::Device *other, un
{
// TODO: the internal connection is not represented currently ...
if (m_reconnected_terminals.empty ()) {
init_terminal_routes ();
}
if (! m_reconnected_terminals.empty ()) {
m_reconnected_terminals.erase (this_terminal);
}

View File

@ -280,6 +280,14 @@ public:
}
}
/**
* @brief Gets the map of reconnected terminals
*/
const std::map<unsigned int, std::vector<OtherTerminalRef> > &reconnected_terminals () const
{
return m_reconnected_terminals;
}
/**
* @brief Gets the set of other device abstracts
*
@ -291,6 +299,26 @@ public:
return m_other_abstracts;
}
/**
* @brief Gets the map of reconnected terminals (non-const version)
*
* NOTE: don't use this method to modify this container! It's provided for persistence implementation only.
*/
std::map<unsigned int, std::vector<OtherTerminalRef> > &reconnected_terminals ()
{
return m_reconnected_terminals;
}
/**
* @brief Gets the set of other device abstracts (non-const version)
*
* NOTE: don't use this method to modify this container! It's provided for persistence implementation only.
*/
std::vector<std::pair<const db::DeviceAbstract *, db::DVector> > &other_abstracts ()
{
return m_other_abstracts;
}
private:
friend class Circuit;
friend class Net;
@ -335,6 +363,7 @@ private:
void set_circuit (Circuit *circuit);
void add_others_terminals (unsigned int this_terminal, db::Device *other, unsigned int other_terminal);
void init_terminal_routes ();
};
}

View File

@ -69,11 +69,26 @@ namespace db
* A net declaration shall be there also if no geometry
* is present. The ID is a numerical shortcut for the net.
* pin(<name> <net-id>) - outgoing pin connection [short key: P]
* device(<name> <abstract> [device-def])
* device(<name> <abstract> [combined-device]* [terminal-route]* [device-def])
* - device with connections [short key: D]
* circuit(<name> [circuit-def]) - subcircuit with connections [short key: X]
*
* [combined-device]:
*
* device(<abstract> <dx> <dy>) - specifies an additional device component
* (for combined devices) with abstract <abstract>
* and offset dx, dy.
*
* [terminal-route]:
*
* connect(<device-index> <outer-terminal-name> <inner-terminal-name>)
* - connects the outer terminal with the terminal
* of the device component with <device-index>:
* 0 is the basic device, 1 the first combined
* device etc.
*
* [net-name]:
*
* name(<net-name>) - specify net name [short key: I]
*
* [geometry-def]:
@ -82,7 +97,9 @@ namespace db
* "*" for <x> or <y> means take previous
* rect(<layer> [coord] [coord]) - defines a rectangle [short key: R]
* coordinates are bottom/left and top/right
*
* [coord]
*
* <x> <y> - absolute coordinates
* (<x> <y>) - relative coordinates (reference is reset to 0,0
* for each net or terminal in device abstract)

View File

@ -309,7 +309,7 @@ void LayoutToNetlistStandardReader::do_read (db::LayoutToNetlist *l2n)
std::map<db::CellInstArray, std::list<Connections> >::const_iterator c = connections.find (i->cell_inst ());
if (c != connections.end ()) {
for (std::list<Connections>::const_iterator j = c->second.begin (); j != c->second.end (); ++j) {
l2n->net_clusters ().clusters_per_cell (ci).add_connection (j->from_cluster, db::ClusterInstance (j->to_cluster, i->cell_index (), i->complex_trans (), i->prop_id ()));
l2n->net_clusters ().clusters_per_cell (ci).add_connection (j->from_cluster, db::ClusterInstance (j->to_cluster, i->cell_index (), i->complex_trans () * db::ICplxTrans (j->offset), i->prop_id ()));
}
}
}
@ -486,6 +486,31 @@ LayoutToNetlistStandardReader::read_pin (db::LayoutToNetlist * /*l2n*/, db::Circ
circuit->connect_pin (pin.id (), net);
}
static size_t
terminal_id (const db::DeviceClass *device_class, const std::string &tname)
{
const std::vector<db::DeviceTerminalDefinition> &td = device_class->terminal_definitions ();
for (std::vector<db::DeviceTerminalDefinition>::const_iterator t = td.begin (); t != td.end (); ++t) {
if (t->name () == tname) {
return t->id ();
}
}
throw tl::Exception (tl::to_string (tr ("Not a valid terminal name: ")) + tname + tl::to_string (tr (" for device class: ")) + device_class->name ());
}
static db::DeviceAbstract *
device_model_by_name (db::Netlist *netlist, const std::string &dmname)
{
for (db::Netlist::device_abstract_iterator i = netlist->begin_device_abstracts (); i != netlist->end_device_abstracts (); ++i) {
if (i->name () == dmname) {
return i.operator-> ();
}
}
throw tl::Exception (tl::to_string (tr ("Not a valid device abstract name: ")) + dmname);
}
db::CellInstArray
LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circuit *circuit, std::list<Connections> &refs, std::map<unsigned int, Net *> &id2net)
{
@ -497,16 +522,7 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui
std::string dmname;
read_word_or_quoted (dmname);
db::DeviceAbstract *dm = 0;
for (db::Netlist::device_abstract_iterator i = l2n->netlist ()->begin_device_abstracts (); i != l2n->netlist ()->end_device_abstracts (); ++i) {
if (i->name () == dmname) {
dm = i.operator-> ();
}
}
if (! dm) {
throw tl::Exception (tl::to_string (tr ("Not a valid device abstract name: ")) + dmname);
}
db::DeviceAbstract *dm = device_model_by_name (l2n->netlist (), dmname);
db::Device *device = new db::Device ();
device->set_device_class (const_cast<db::DeviceClass *> (dm->device_class ()));
@ -515,6 +531,8 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui
circuit->add_device (device);
db::Coord x = 0, y = 0;
double dbu = l2n->internal_layout ()->dbu ();
db::VCplxTrans dbu_inv (1.0 / dbu);
while (br) {
@ -525,6 +543,44 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui
y = read_coord ();
br2.done ();
} else if (test (skeys::device_key) || test (lkeys::device_key)) {
std::string n;
Brace br2 (this);
read_word_or_quoted (n);
db::Coord dx = read_coord ();
db::Coord dy = read_coord ();
br2.done ();
device->other_abstracts ().push_back (std::make_pair (device_model_by_name (l2n->netlist (), n), db::DVector (dbu * dx, dbu * dy)));
} else if (test (skeys::connect_key) || test (lkeys::connect_key)) {
Brace br2 (this);
int device_comp_index = read_int ();
std::string touter, tinner;
read_word_or_quoted (touter);
read_word_or_quoted (tinner);
br2.done ();
if (device_comp_index < 0 || device_comp_index > int (device->other_abstracts ().size ())) {
throw tl::Exception (tl::to_string (tr ("Not a valid device component index: ")) + tl::to_string (device_comp_index));
}
size_t touter_id = terminal_id (dm->device_class (), touter);
size_t tinner_id = terminal_id (dm->device_class (), tinner);
const db::DeviceAbstract *da = device_comp_index > 0 ? device->other_abstracts () [device_comp_index - 1].first : dm;
db::DVector da_offset = device_comp_index > 0 ? device->other_abstracts () [device_comp_index - 1].second : db::DVector ();
device->reconnected_terminals () [touter_id].push_back (db::Device::OtherTerminalRef (da, da_offset, tinner_id));
} else if (test (skeys::terminal_key) || test (lkeys::terminal_key)) {
Brace br2 (this);
@ -533,18 +589,7 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui
unsigned int netid = (unsigned int) read_int ();
br2.done ();
size_t tid = std::numeric_limits<size_t>::max ();
const std::vector<db::DeviceTerminalDefinition> &td = dm->device_class ()->terminal_definitions ();
for (std::vector<db::DeviceTerminalDefinition>::const_iterator t = td.begin (); t != td.end (); ++t) {
if (t->name () == tname) {
tid = t->id ();
break;
}
}
if (tid == std::numeric_limits<size_t>::max ()) {
throw tl::Exception (tl::to_string (tr ("Not a valid terminal name: ")) + tname + tl::to_string (tr (" for device class: ")) + dm->device_class ()->name ());
}
size_t tid = terminal_id (dm->device_class (), tname);
db::Net *net = id2net [netid];
if (!net) {
@ -552,7 +597,15 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui
}
device->connect_terminal (tid, net);
refs.push_back (Connections (net->cluster_id (), dm->cluster_id_for_terminal (tid)));
const std::vector<db::Device::OtherTerminalRef> *tr = device->reconnected_terminals_for (tid);
if (tr) {
for (std::vector<db::Device::OtherTerminalRef>::const_iterator i = tr->begin (); i != tr->end (); ++i) {
refs.push_back (Connections (net->cluster_id (), i->device_abstract->cluster_id_for_terminal (i->other_terminal_id), dbu_inv * i->offset));
}
} else {
refs.push_back (Connections (net->cluster_id (), dm->cluster_id_for_terminal (tid), db::Vector ()));
}
} else if (test (skeys::param_key) || test (lkeys::param_key)) {
@ -586,16 +639,24 @@ LayoutToNetlistStandardReader::read_device (db::LayoutToNetlist *l2n, db::Circui
}
double dbu = l2n->internal_layout ()->dbu ();
device->set_position (db::DPoint (dbu * x, dbu * y));
br.done ();
// make device cell instance
db::CellInstArray inst (db::CellInst (dm->cell_index ()), db::Trans (db::Vector (x, y)));
db::Cell &ccell = l2n->internal_layout ()->cell (circuit->cell_index ());
// make device cell instances
db::CellInstArray inst (db::CellInst (dm->cell_index ()), db::Trans (db::Vector (x, y)));
ccell.insert (inst);
const std::vector<std::pair<const db::DeviceAbstract *, db::DVector> > &other_devices = device->other_abstracts ();
for (std::vector<std::pair<const db::DeviceAbstract *, db::DVector> >::const_iterator i = other_devices.begin (); i != other_devices.end (); ++i) {
db::CellInstArray other_inst (db::CellInst (i->first->cell_index ()), db::Trans (db::Vector (x, y) + dbu_inv * i->second));
ccell.insert (other_inst);
}
return inst;
}
@ -688,7 +749,7 @@ LayoutToNetlistStandardReader::read_subcircuit (db::LayoutToNetlist *l2n, db::Ci
subcircuit->connect_pin (sc_pin->id (), net);
db::Net *sc_net = circuit_ref->net_for_pin (sc_pin->id ());
if (sc_net) {
refs.push_back (Connections (net->cluster_id (), sc_net->cluster_id ()));
refs.push_back (Connections (net->cluster_id (), sc_net->cluster_id (), db::Vector ()));
}
} else {

View File

@ -74,11 +74,12 @@ private:
struct Connections
{
Connections (size_t _from_cluster, size_t _to_cluster)
: from_cluster (_from_cluster), to_cluster (_to_cluster)
Connections (size_t _from_cluster, size_t _to_cluster, const db::Vector &_offset)
: from_cluster (_from_cluster), to_cluster (_to_cluster), offset (_offset)
{ }
size_t from_cluster, to_cluster;
db::Vector offset;
};
tl::TextInputStream m_stream;

View File

@ -489,20 +489,53 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n, const db::Dev
{
const db::Layout *ly = l2n->internal_layout ();
double dbu = ly->dbu ();
db::VCplxTrans dbu_inv (1.0 / dbu);
tl_assert (device.device_class () != 0);
const std::vector<DeviceTerminalDefinition> &td = device.device_class ()->terminal_definitions ();
const std::vector<DeviceParameterDefinition> &pd = device.device_class ()->parameter_definitions ();
*mp_stream << indent1 << Keys::device_key << "(" << tl::to_word_or_quoted_string (device.expanded_name ());
tl_assert (device.device_abstract () != 0);
*mp_stream << " " << tl::to_word_or_quoted_string (device.device_abstract ()->name ()) << endl;
*mp_stream << indent2 << Keys::location_key << "(" << device.position ().x () / dbu << " " << device.position ().y () / dbu << ")" << endl;
std::map<std::pair<const db::DeviceAbstract *, db::Vector>, size_t> abstracts;
abstracts.insert (std::make_pair (std::make_pair (device.device_abstract (), db::Vector ()), 0));
const std::vector<std::pair<const db::DeviceAbstract *, db::DVector> > &other_abstracts = device.other_abstracts ();
for (std::vector<std::pair<const db::DeviceAbstract *, db::DVector> >::const_iterator a = other_abstracts.begin (); a != other_abstracts.end (); ++a) {
db::Vector pos = dbu_inv * a->second;
abstracts.insert (std::make_pair (std::make_pair (a->first, pos), a - other_abstracts.begin () + 1));
*mp_stream << " " << Keys::device_key << "(" << tl::to_word_or_quoted_string (a->first->name ()) << " " << pos.x () << " " << pos.y () << ")" << endl;
}
const std::map<unsigned int, std::vector<db::Device::OtherTerminalRef> > &reconnected_terminals = device.reconnected_terminals ();
for (std::map<unsigned int, std::vector<db::Device::OtherTerminalRef> >::const_iterator t = reconnected_terminals.begin (); t != reconnected_terminals.end (); ++t) {
for (std::vector<db::Device::OtherTerminalRef>::const_iterator c = t->second.begin (); c != t->second.end (); ++c) {
db::Vector pos = dbu_inv * c->offset;
std::map<std::pair<const db::DeviceAbstract *, db::Vector>, size_t>::const_iterator a = abstracts.find (std::make_pair (c->device_abstract, pos));
tl_assert (a != abstracts.end ());
*mp_stream << " " << Keys::connect_key << "(" << a->second << " " << tl::to_word_or_quoted_string (td [t->first].name ()) << " " << tl::to_word_or_quoted_string (td [c->other_terminal_id].name ()) << ")" << endl;
}
}
db::Point pos = dbu_inv * device.position ();
*mp_stream << indent2 << Keys::location_key << "(" << pos.x () << " " << pos.y () << ")" << endl;
const std::vector<DeviceParameterDefinition> &pd = device.device_class ()->parameter_definitions ();
for (std::vector<DeviceParameterDefinition>::const_iterator i = pd.begin (); i != pd.end (); ++i) {
*mp_stream << indent2 << Keys::param_key << "(" << tl::to_word_or_quoted_string (i->name ()) << " " << device.parameter_value (i->id ()) << ")" << endl;
}
const std::vector<DeviceTerminalDefinition> &td = device.device_class ()->terminal_definitions ();
for (std::vector<DeviceTerminalDefinition>::const_iterator i = td.begin (); i != td.end (); ++i) {
const db::Net *net = device.net_for_terminal (i->id ());
if (net) {