mirror of https://github.com/KLayout/klayout.git
WIP: combined devices and geometry/L2N DB representation. Yet to do: device cell transformation beyond vector?
This commit is contained in:
parent
9a361ee234
commit
db1e813635
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue