l2n dump format is leaner (device terminal shapes dropped from nets as they are contained in the device abstracts). Some refactoring.

This commit is contained in:
Matthias Koefferlein 2019-01-19 23:00:19 +01:00
parent 8213e71a79
commit a5e2cf58c3
12 changed files with 145 additions and 92 deletions

View File

@ -22,6 +22,7 @@
#include "dbDeviceModel.h"
#include "dbCircuit.h"
#include "dbNetlist.h"
namespace db
{
@ -71,11 +72,17 @@ void DeviceModel::set_netlist (Netlist *netlist)
void DeviceModel::set_name (const std::string &n)
{
m_name = n;
if (mp_netlist) {
mp_netlist->m_device_model_by_name.invalidate ();
}
}
void DeviceModel::set_cell_index (db::cell_index_type ci)
{
m_cell_index = ci;
if (mp_netlist) {
mp_netlist->m_device_model_by_cell_index.invalidate ();
}
}
size_t DeviceModel::cluster_id_for_terminal (size_t terminal_id) const

View File

@ -260,13 +260,9 @@ db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell
unsigned int layout_index = 0;
std::set<db::cell_index_type> device_cells;
if (! with_device_cells) {
const db::Layout &src_layout = m_dss.layout (layout_index);
for (db::Layout::const_iterator c = src_layout.begin (); c != src_layout.end (); ++c) {
if (db::NetlistDeviceExtractor::is_device_cell (src_layout, c->cell_index ())) {
device_cells.insert (c->cell_index ());
}
if (! with_device_cells && mp_netlist.get ()) {
for (db::Netlist::device_model_iterator i = mp_netlist->begin_device_models (); i != mp_netlist->end_device_models (); ++i) {
device_cells.insert (i->cell_index ());
}
}
@ -404,7 +400,7 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
if (cm == cmap.end ()) {
const char *name_prefix = 0;
if (db::NetlistDeviceExtractor::is_device_cell (*internal_layout (), subci)) {
if (mp_netlist->device_model_by_cell_index (subci)) {
name_prefix = device_cell_name_prefix;
} else {
name_prefix = cell_name_prefix;

View File

@ -149,7 +149,6 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n)
*mp_stream << "# Circuits are the hierarchical building blocks of the netlist." << endl;
for (db::Netlist::const_bottom_up_circuit_iterator i = nl->begin_bottom_up (); i != nl->end_bottom_up (); ++i) {
const db::Circuit *x = *i;
*mp_stream << endl << "# Circuit " << x->name () << endl;
*mp_stream << Keys::circuit_key << "(" << tl::to_word_or_quoted_string (x->name ()) << endl;
write (l2n, *x);
*mp_stream << ")" << endl;
@ -233,6 +232,10 @@ void std_writer_impl<Keys>::write (const db::PolygonRef *s, const db::ICplxTrans
template <class Keys>
void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n, const db::Net &net)
{
if (! l2n->netlist ()) {
throw tl::Exception (tl::to_string (tr ("Can't write annotated netlist before extraction has been done")));
}
const db::Layout *ly = l2n->internal_layout ();
const db::hier_clusters<db::PolygonRef> &clusters = l2n->net_clusters ();
const db::Circuit *circuit = net.circuit ();
@ -251,7 +254,7 @@ void std_writer_impl<Keys>::write (const db::LayoutToNetlist *l2n, const db::Net
// vanish in "purge" but the clusters will still be there we need to recursive into clusters from
// unknown cells.
db::cell_index_type ci = si.cell_index ();
if (ci != prev_ci && ci != cci && l2n->netlist ()->circuit_by_cell_index (ci)) {
if (ci != prev_ci && ci != cci && (l2n->netlist ()->circuit_by_cell_index (ci) || l2n->netlist ()->device_model_by_cell_index (ci))) {
si.skip_cell ();

View File

@ -33,26 +33,33 @@ namespace db
Netlist::Netlist ()
: m_valid_topology (false), m_lock_count (0),
m_circuit_by_name (this, &Netlist::begin_circuits, &Netlist::end_circuits),
m_circuit_by_cell_index (this, &Netlist::begin_circuits, &Netlist::end_circuits)
m_circuit_by_cell_index (this, &Netlist::begin_circuits, &Netlist::end_circuits),
m_device_model_by_name (this, &Netlist::begin_device_models, &Netlist::end_device_models),
m_device_model_by_cell_index (this, &Netlist::begin_device_models, &Netlist::end_device_models)
{
m_circuits.changed ().add (this, &Netlist::invalidate_topology);
m_circuits.changed ().add (this, &Netlist::circuits_changed);
m_device_models.changed ().add (this, &Netlist::device_models_changed);
}
Netlist::Netlist (const Netlist &other)
: gsi::ObjectBase (other), tl::Object (other), m_valid_topology (false), m_lock_count (0),
m_circuit_by_name (this, &Netlist::begin_circuits, &Netlist::end_circuits),
m_circuit_by_cell_index (this, &Netlist::begin_circuits, &Netlist::end_circuits)
m_circuit_by_cell_index (this, &Netlist::begin_circuits, &Netlist::end_circuits),
m_device_model_by_name (this, &Netlist::begin_device_models, &Netlist::end_device_models),
m_device_model_by_cell_index (this, &Netlist::begin_device_models, &Netlist::end_device_models)
{
operator= (other);
m_circuits.changed ().add (this, &Netlist::invalidate_topology);
m_circuits.changed ().add (this, &Netlist::circuits_changed);
m_device_models.changed ().add (this, &Netlist::device_models_changed);
}
Netlist::~Netlist ()
{
m_circuits.changed ().remove (this, &Netlist::invalidate_topology);
m_circuits.changed ().remove (this, &Netlist::circuits_changed);
m_device_models.changed ().remove (this, &Netlist::device_models_changed);
}
Netlist &Netlist::operator= (const Netlist &other)
@ -98,6 +105,12 @@ void Netlist::circuits_changed ()
m_circuit_by_name.invalidate ();
}
void Netlist::device_models_changed ()
{
m_device_model_by_cell_index.invalidate ();
m_device_model_by_name.invalidate ();
}
void Netlist::invalidate_topology ()
{
if (m_valid_topology) {

View File

@ -349,6 +349,46 @@ public:
return m_device_models.end ();
}
/**
* @brief Gets the device model with the given name
*
* If no device model with that name exists, null is returned.
*/
DeviceModel *device_model_by_name (const std::string &name)
{
return m_device_model_by_name.object_by (name);
}
/**
* @brief Gets the device model with the given name (const version)
*
* If no device model with that name exists, null is returned.
*/
const DeviceModel *device_model_by_name (const std::string &name) const
{
return m_device_model_by_name.object_by (name);
}
/**
* @brief Gets the device model with the given cell index
*
* If no device model with that cell index exists, null is returned.
*/
DeviceModel *device_model_by_cell_index (db::cell_index_type cell_index)
{
return m_device_model_by_cell_index.object_by (cell_index);
}
/**
* @brief Gets the device model with the given cell index (const version)
*
* If no device model with that cell index exists, null is returned.
*/
const DeviceModel *device_model_by_cell_index (db::cell_index_type cell_index) const
{
return m_device_model_by_cell_index.object_by (cell_index);
}
/**
* @brief Purge unused nets
*
@ -383,6 +423,7 @@ public:
private:
friend class Circuit;
friend class DeviceModel;
circuit_list m_circuits;
device_class_list m_device_classes;
@ -395,10 +436,13 @@ private:
size_t m_top_circuits;
object_by_attr<Netlist, Netlist::circuit_iterator, name_attribute<Circuit> > m_circuit_by_name;
object_by_attr<Netlist, Netlist::circuit_iterator, cell_index_attribute<Circuit> > m_circuit_by_cell_index;
object_by_attr<Netlist, Netlist::device_model_iterator, name_attribute<DeviceModel> > m_device_model_by_name;
object_by_attr<Netlist, Netlist::device_model_iterator, cell_index_attribute<DeviceModel> > m_device_model_by_cell_index;
void invalidate_topology ();
void validate_topology ();
void circuits_changed ();
void device_models_changed ();
const tl::vector<Circuit *> &child_circuits (Circuit *circuit);
const tl::vector<Circuit *> &parent_circuits (Circuit *circuit);

View File

@ -169,7 +169,7 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db:
for (std::set<db::cell_index_type>::const_iterator ci = called_cells.begin (); ci != called_cells.end (); ++ci) {
// skip device cells from previous extractions
if (is_device_cell (*ci)) {
if (m_netlist->device_model_by_cell_index (*ci)) {
continue;
}
@ -223,33 +223,6 @@ void NetlistDeviceExtractor::extract_without_initialize (db::Layout &layout, db:
}
}
bool NetlistDeviceExtractor::is_device_cell (const db::Layout &layout, db::cell_index_type ci)
{
db::properties_id_type pi = layout.cell (ci).prop_id ();
if (pi == 0) {
return false;
}
std::pair<bool, db::property_names_id_type> pn = layout.properties_repository ().get_id_of_name (db::NetlistDeviceExtractor::device_class_property_name ());
if (! pn.first) {
return false;
}
const db::PropertiesRepository::properties_set &ps = layout.properties_repository ().properties (pi);
for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) {
if (j->first == pn.second) {
return true;
}
}
return false;
}
bool NetlistDeviceExtractor::is_device_cell (db::cell_index_type ci) const
{
return is_device_cell (*mp_layout, ci);
}
void NetlistDeviceExtractor::push_new_devices ()
{
db::VCplxTrans dbu_inv = db::CplxTrans (mp_layout->dbu ()).inverted ();
@ -298,8 +271,6 @@ void NetlistDeviceExtractor::push_new_devices ()
ps.insert (std::make_pair (m_device_class_propname_id, tl::Variant (mp_device_class->name ())));
device_cell.prop_id (mp_layout->properties_repository ().properties_id (ps));
db::connected_clusters<db::PolygonRef> &cc = mp_clusters->clusters_per_cell (device_cell.cell_index ());
for (geometry_per_terminal_type::const_iterator t = d->second.begin (); t != d->second.end (); ++t) {
// Build a property set for the device terminal ID

View File

@ -234,11 +234,6 @@ public:
*/
static const tl::Variant &device_class_property_name ();
/**
* @brief Returns true, if the given cell is a device cell
*/
static bool is_device_cell (const db::Layout &layout, db::cell_index_type ci);
/**
* @brief Performs the extraction
*
@ -527,7 +522,6 @@ private:
void extract_without_initialize (db::Layout &layout, db::Cell &cell, hier_clusters_type &clusters, const std::vector<unsigned int> &layers);
void push_new_devices ();
bool is_device_cell (db::cell_index_type ci) const;
};
}

View File

@ -63,12 +63,6 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect
circuits.insert (std::make_pair (c->cell_index (), c.operator-> ()));
}
// reverse lookup for DeviceModel vs. cell index
std::map<db::cell_index_type, db::DeviceModel *> device_models;
for (db::Netlist::device_model_iterator dm = nl.begin_device_models (); dm != nl.end_device_models (); ++dm) {
device_models.insert (std::make_pair (dm->cell_index (), dm.operator-> ()));
}
std::map<db::cell_index_type, std::map<size_t, size_t> > pins_per_cluster_per_cell;
for (db::Layout::bottom_up_const_iterator cid = mp_layout->begin_bottom_up (); cid != mp_layout->end_bottom_up (); ++cid) {
@ -77,28 +71,11 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect
continue;
}
std::map<db::cell_index_type, db::DeviceModel *>::const_iterator dmc = device_models.find (*cid);
if (dmc != device_models.end ()) {
db::DeviceModel *dm = nl.device_model_by_cell_index (*cid);
if (dm) {
// make the terminal to cluster ID connections for the device model from the device cells
if (m_terminal_annot_name_id.first) {
for (connected_clusters_type::const_iterator dc = clusters.begin (); dc != clusters.end (); ++dc) {
for (local_cluster_type::attr_iterator a = dc->begin_attr (); a != dc->end_attr (); ++a) {
const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (*a);
for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) {
if (j->first == m_terminal_annot_name_id.second) {
dmc->second->set_cluster_id_for_terminal (j->second.to<size_t> (), dc->id ());
}
}
}
}
}
make_device_model_connections (dm, clusters);
continue;
}
// a cell makes a new circuit (or uses an existing one)
@ -151,6 +128,31 @@ NetlistExtractor::extract_nets (const db::DeepShapeStore &dss, const db::Connect
}
}
void
NetlistExtractor::make_device_model_connections (db::DeviceModel *dm, const connected_clusters_type &clusters)
{
// make the terminal to cluster ID connections for the device model from the device cells
if (m_terminal_annot_name_id.first) {
for (connected_clusters_type::const_iterator dc = clusters.begin (); dc != clusters.end (); ++dc) {
for (local_cluster_type::attr_iterator a = dc->begin_attr (); a != dc->end_attr (); ++a) {
const db::PropertiesRepository::properties_set &ps = mp_layout->properties_repository ().properties (*a);
for (db::PropertiesRepository::properties_set::const_iterator j = ps.begin (); j != ps.end (); ++j) {
if (j->first == m_terminal_annot_name_id.second) {
dm->set_cluster_id_for_terminal (j->second.to<size_t> (), dc->id ());
}
}
}
}
}
}
void NetlistExtractor::collect_labels (const connected_clusters_type &clusters,
size_t cid,
db::Net *net)

View File

@ -37,6 +37,7 @@ class Circuit;
class SubCircuit;
class Net;
class Device;
class DeviceModel;
/**
* @brief The Netlist Extractor
@ -151,6 +152,12 @@ private:
void collect_labels (const connected_clusters_type &clusters,
size_t cid,
db::Net *net);
/**
* @brief Makes the terminal to cluster ID connections of the device model
*/
void make_device_model_connections (db::DeviceModel *dm, const connected_clusters_type &clusters);
};
}

View File

@ -63,4 +63,27 @@ TEST(1_ReaderBasic)
tl::absolute_file_path (path),
tl::absolute_file_path (au_path)));
}
#if 0
std::string path = tmp_file ("tmp_l2nwriter_1.txt");
{
tl::OutputStream stream (path);
db::LayoutToNetlistStandardWriter writer (stream, false);
writer.write (&l2n);
}
std::string au_path = tl::combine_path (tl::combine_path (tl::combine_path (tl::testsrc (), "testdata"), "algo"), "l2n_writer_au.txt");
tl::InputStream is (path);
tl::InputStream is_au (au_path);
if (is.read_all () != is_au.read_all ()) {
_this->raise (tl::sprintf ("Compare failed - see\n actual: %s\n golden: %s",
tl::absolute_file_path (path),
tl::absolute_file_path (au_path)));
}
#endif
}

View File

@ -1047,10 +1047,19 @@ TEST(13_DeviceModel)
db::Netlist nl;
db::DeviceModel *dm = new db::DeviceModel (0, "name");
nl.add_device_model (dm);
EXPECT_EQ (dm->netlist () == &nl, true);
EXPECT_EQ (dm->device_class () == 0, true);
EXPECT_EQ (dm->name (), "name");
EXPECT_EQ (nl.device_model_by_name ("name") == dm, true);
EXPECT_EQ (nl.device_model_by_name ("name2") == 0, true);
EXPECT_EQ (nl.device_model_by_name ("does_not_exist") == 0, true);
dm->set_name ("name2");
EXPECT_EQ (dm->name (), "name2");
EXPECT_EQ (nl.device_model_by_name ("name") == 0, true);
EXPECT_EQ (nl.device_model_by_name ("name2") == dm, true);
EXPECT_EQ (nl.device_model_by_name ("does_not_exist") == 0, true);
dm->set_cluster_id_for_terminal (1, 17);
dm->set_cluster_id_for_terminal (0, 42);
@ -1058,10 +1067,10 @@ TEST(13_DeviceModel)
EXPECT_EQ (dm->cluster_id_for_terminal (1), size_t (17));
dm->set_cell_index (5);
EXPECT_EQ (nl.device_model_by_cell_index (5) == dm, true);
EXPECT_EQ (nl.device_model_by_cell_index (17) == 0, true);
EXPECT_EQ (dm->cell_index (), db::cell_index_type (5));
nl.add_device_model (dm);
EXPECT_EQ (dm->netlist () == &nl, true);
EXPECT_EQ (nl.begin_device_models () == nl.end_device_models (), false);
EXPECT_EQ (nl.begin_device_models ()->name (), "name2");

View File

@ -82,8 +82,6 @@ device(D$NMOS$1 NMOS
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
# Circuit INV2
circuit(INV2
# Nets with their geometries
@ -91,9 +89,7 @@ circuit(INV2
rect(poly -525 -250 -275 2250)
rect(poly -1700 1620 -400 1980)
rect(poly -525 -800 -275 800)
rect(poly -525 -475 -275 475)
rect(poly -525 2000 -275 3600)
rect(poly -525 2325 -275 3275)
rect(poly_lbl -801 1799 -799 1801)
rect(poly_cont -1630 1690 -1410 1910)
)
@ -101,9 +97,7 @@ circuit(INV2
rect(poly 275 -250 525 2250)
rect(poly 220 820 580 1180)
rect(poly 275 2000 525 3600)
rect(poly 275 2325 525 3275)
rect(poly 275 -800 525 800)
rect(poly 275 -475 525 475)
rect(diff_cont -910 2490 -690 2710)
rect(diff_cont -910 2890 -690 3110)
rect(diff_cont -910 -310 -690 -90)
@ -114,8 +108,6 @@ circuit(INV2
rect(metal1 -980 2420 -620 3180)
rect(metal1 -980 -380 -620 380)
rect(psd -1050 2325 -525 3275)
rect(psd -1050 2325 -525 3275)
rect(nsd -1050 -475 -525 475)
rect(nsd -1050 -475 -525 475)
)
net(OUT
@ -128,8 +120,6 @@ circuit(INV2
rect(metal1 620 -380 980 380)
rect(metal1_lbl 799 1799 801 1801)
rect(psd 525 2325 1050 3275)
rect(psd 525 2325 1050 3275)
rect(nsd 525 -475 1050 475)
rect(nsd 525 -475 1050 475)
)
net($4
@ -143,8 +133,6 @@ circuit(INV2
rect(via1 -125 75 125 325)
rect(metal2 -1400 -450 1400 450)
rect(nsd -275 -475 275 475)
rect(nsd -275 -475 275 475)
rect(nsd -275 -475 275 475)
)
net($5
rect(diff_cont -110 2490 110 2710)
@ -157,8 +145,6 @@ circuit(INV2
rect(via1 -125 2875 125 3125)
rect(metal2 -1400 2350 1400 3250)
rect(psd -275 2325 275 3275)
rect(psd -275 2325 275 3275)
rect(psd -275 2325 275 3275)
)
# Outgoing pins and their connections to nets
@ -211,8 +197,6 @@ circuit(INV2
)
)
# Circuit RINGO
circuit(RINGO
# Nets with their geometries