diff --git a/samples/lvs/ringo.gds b/samples/lvs/ringo.gds
new file mode 100644
index 000000000..fa116f14d
Binary files /dev/null and b/samples/lvs/ringo.gds differ
diff --git a/samples/lvs/schematic.cir b/samples/lvs/schematic.cir
new file mode 100644
index 000000000..13d6d09f5
--- /dev/null
+++ b/samples/lvs/schematic.cir
@@ -0,0 +1,27 @@
+
+.SUBCKT RINGO VSS VDD FB ENABLE OUT
+X$1 VDD 1 VSS VDD FB ENABLE VSS ND2X1
+X$2 VDD 2 VSS VDD 1 VSS INVX1
+X$3 VDD 3 VSS VDD 2 VSS INVX1
+X$4 VDD 4 VSS VDD 3 VSS INVX1
+X$5 VDD 5 VSS VDD 4 VSS INVX1
+X$6 VDD 6 VSS VDD 5 VSS INVX1
+X$7 VDD 7 VSS VDD 6 VSS INVX1
+X$8 VDD 8 VSS VDD 7 VSS INVX1
+X$9 VDD 9 VSS VDD 8 VSS INVX1
+X$10 VDD 10 VSS VDD 9 VSS INVX1
+X$11 VDD FB VSS VDD 10 VSS INVX1
+X$12 VDD OUT VSS VDD FB VSS INVX1
+.ENDS RINGO
+
+.SUBCKT ND2X1 VDD OUT VSS NWELL B A BULK
+M$1 OUT A VDD NWELL PMOS L=0.25U W=1.5U
+M$2 VDD B OUT NWELL PMOS L=0.25U W=1.5U
+M$3 VSS A 1 BULK NMOS L=0.25U W=0.95U
+M$4 1 B OUT BULK NMOS L=0.25U W=0.95U
+.ENDS ND2X1
+
+.SUBCKT INVX1 VDD OUT VSS NWELL IN BULK
+M$1 VDD IN OUT NWELL PMOS L=0.25U W=1.5U
+M$2 VSS IN OUT BULK NMOS L=0.25U W=0.95U
+.ENDS INVX1
diff --git a/samples/lvs/tech.lyp b/samples/lvs/tech.lyp
new file mode 100644
index 000000000..2b5b553ca
--- /dev/null
+++ b/samples/lvs/tech.lyp
@@ -0,0 +1,303 @@
+
+
+
+ #c0c0c0
+ #c0c0c0
+ 0
+ 0
+ I9
+ I2
+ true
+ true
+ false
+ 2
+ false
+ false
+ 0
+ 1 - NWELL
+ 1/0@1
+
+
+ #c0c0c0
+ #c0c0c0
+ 48
+ 48
+ C0
+ I4
+ true
+ true
+ false
+ 1
+ false
+ false
+ 0
+ 3 - PPLUS
+ 3/0@1
+
+
+ #c0c0c0
+ #c0c0c0
+ 48
+ 48
+ C1
+ I4
+ true
+ true
+ false
+ 1
+ false
+ false
+ 0
+ 4 - NPLUS
+ 4/0@1
+
+
+ #ff0000
+ #ff9d9d
+ -64
+ -64
+ I3
+ I2
+ true
+ true
+ false
+ 2
+ false
+ false
+ 0
+ 2 - DIFF
+ 2/0@1
+
+
+ #91ff00
+ #91ff00
+ -48
+ -48
+ I8
+
+ true
+ true
+ false
+ 2
+ false
+ false
+ 0
+ 5 - POLY
+ 5/0@1
+
+
+ #008000
+ #808000
+ 0
+ 0
+ I3
+ I4
+ true
+ true
+ false
+ 1
+ false
+ false
+ 0
+ 6 - THICKOX
+ THICKOX 6/0@1
+
+
+ #805000
+ #805000
+ 0
+ 0
+ I3
+ I4
+ true
+ true
+ false
+ 1
+ false
+ false
+ 0
+ 7 - POLYRES
+ '7 - SALBL' 7/0@1
+
+
+ #ff00ff
+ #ffffff
+ 0
+ 0
+ I0
+
+ true
+ true
+ false
+ 2
+ false
+ true
+ 0
+ 8 - CONTACT
+ 8/0@1
+
+
+ #8000ff
+ #9580ff
+ 0
+ 0
+ I4
+
+ true
+ true
+ false
+ 2
+ false
+ false
+ 0
+ 9 - METAL1
+ 9/0@1
+
+
+ #e872ff
+ #e872ff
+ -48
+ -48
+ I1
+
+ true
+ true
+ false
+ 2
+ false
+ true
+ 0
+ 10 - VIA
+ 10/0@1
+
+
+ #0000ff
+ #8086ff
+ 0
+ 0
+ I8
+
+ true
+ true
+ false
+ 2
+ false
+ false
+ 0
+ 11 - METAL2
+ 11/0@1
+
+
+ #808080
+ #c0c0c0
+ 0
+ 128
+ I43
+
+ true
+ true
+ true
+ 1
+ false
+ false
+ 0
+ 12 - PAD
+ 12/0@1
+
+
+ #c0c0c0
+ #c0c0c0
+ 0
+ 0
+ I1
+ I4
+ true
+ true
+ false
+ 1
+ false
+ false
+ 0
+ 13 - BORDER
+ 13/0@1
+
+
+ #606060
+ #606060
+ 0
+ 0
+ I1
+ I2
+ true
+ true
+ false
+ 1
+ false
+ true
+ 0
+ 1000 - MARKING 1
+ 1000/0@1
+
+
+ #000000
+ #000000
+ 0
+ 0
+ I1
+ I2
+ true
+ true
+ false
+ 1
+ false
+ false
+ 0
+ 1001 - MARKING 2
+ 1001/0@1
+
+
+
+
+ ................
+ ...*............
+ ...*............
+ ...*............
+ *******.........
+ ...*............
+ ...*............
+ ...*............
+ ................
+ ...........*....
+ ...........*....
+ ...........*....
+ ........*******.
+ ...........*....
+ ...........*....
+ ...........*....
+
+ 1
+ custom plus
+
+
+
+ ................
+ ................
+ ................
+ ................
+ *******.........
+ ................
+ ................
+ ................
+ ................
+ ................
+ ................
+ ................
+ ........*******.
+ ................
+ ................
+ ................
+
+ 2
+
+
+
diff --git a/scripts/extract_doc.rb b/scripts/extract_doc.rb
index 8d8789958..9e01f759c 100755
--- a/scripts/extract_doc.rb
+++ b/scripts/extract_doc.rb
@@ -2,15 +2,21 @@
$script_call = $0 + " " + ARGV.join(" ")
-$key="%DRC%"
-$infile="src/drc/drc/built-in-macros/drc.lym"
-$loc = "about/drc_ref"
+$indir="src/drc/drc/built-in-macros"
+$loc = "about"
$outfiles="src/lay/lay/doc"
-$title="DRC Reference"
-def create_ref(s)
- if s =~ /(.*)#(.*)/
- "#{s}"
+def create_ref(mod, s)
+ if s =~ /(.*)::(.*)#(.*)/
+ "#{s}"
+ elsif s =~ /(.*)::(.*)/
+ "#{s}"
+ elsif s =~ /(.*)#(.*)/
+ if $2 != ""
+ "#{s}"
+ else
+ "#{$1}"
+ end
else
"#{s}"
end
@@ -20,11 +26,11 @@ def create_class_doc_ref(s)
"#{s}"
end
-def escape(s)
+def escape(mod, s)
s.gsub("&", "&").
gsub("<", "<").
gsub(">", ">").
- gsub(/\\([\w#]+)/) { create_ref($1) }.
+ gsub(/\\([\w:#]+)/) { create_ref(mod, $1) }.
gsub(/RBA::([\w#]+)/) { create_class_doc_ref($1) }
end
@@ -38,12 +44,14 @@ class DocItem
attr_accessor :synopsis
attr_accessor :name
attr_accessor :doc
+ attr_accessor :mod
- def initialize(block)
+ def initialize(mod, block)
@paragraphs = []
para = nil
self.synopsis = []
+ self.mod = mod
in_code = false
block.each do |b|
@@ -91,7 +99,7 @@ class DocItem
i > 0 && doc += "
\n"
p.each do |pp|
- doc += escape(pp).
+ doc += escape(self.mod, pp).
gsub(/\\@/, "&at;").
gsub(/\s*@code\s*/, "
").
gsub(/\s*@\/code\s*/, "").
@@ -113,13 +121,13 @@ end
class Scope < DocItem
- def initialize(block)
- super(block)
+ def initialize(mod, block)
+ super(mod, block)
@items = {}
end
- def add_doc_item(block)
- item = DocItem::new(block)
+ def add_doc_item(mod, block)
+ item = DocItem::new(mod, block)
@items[item.name] = item
end
@@ -137,8 +145,8 @@ class Scope < DocItem
HEAD
doc += "\n"
- doc += "" + escape(self.brief) + "\n"
- doc += "\n"
+ doc += "" + escape(self.mod, self.brief) + "\n"
+ doc += "\n"
doc += super_produce_doc
@@ -151,14 +159,14 @@ HEAD
item.name || raise("Missing @name for item #{item_key}")
item.brief || raise("Missing @brief for item #{item_key}")
- doc += "\"" + escape(item.name) + "\" - " + escape(item.brief) + "
\n"
- doc += "\n"
- doc += ""
+ doc += "\"" + escape(self.mod, item.name) + "\" - " + escape(self.mod, item.brief) + "
\n"
+ doc += "\n"
+ doc += ""
if ! item.synopsis.empty?
doc += "Usage:
\n"
doc += "\n"
item.synopsis.each do |s|
- doc += "- " + escape(s) + "
\n"
+ doc += "- " + escape(self.mod, s) + "
\n"
end
doc += "
\n"
end
@@ -177,17 +185,22 @@ end
class Collector
+ def initialize(mod, title)
+ @mod = mod
+ @title = title
+ end
+
def add_block(block)
if block.find { |l| l =~ /^@scope/ }
# is a scope block
@scopes ||= {}
- @current_scope = Scope::new(block)
+ @current_scope = Scope::new(@mod, block)
@scopes[@current_scope.name] = @current_scope
else
- @current_scope && @current_scope.add_doc_item(block)
+ @current_scope && @current_scope.add_doc_item(@mod, block)
end
end
@@ -196,7 +209,7 @@ class Collector
@scopes.keys.sort.each do |k|
suffix = k.downcase
- outfile = $outfiles + "/" + $loc + "_" + suffix + ".xml"
+ outfile = $outfiles + "/" + $loc + "/" + @mod + "_ref_" + suffix + ".xml"
File.open(outfile, "w") do |file|
file.write(@scopes[k].produce_doc)
puts "---> #{outfile} written."
@@ -207,7 +220,7 @@ class Collector
def produce_index
- outfile = $outfiles + "/" + $loc + ".xml"
+ outfile = $outfiles + "/" + $loc + "/" + @mod + "_ref.xml"
File.open(outfile, "w") do |file|
doc = <\n"
- doc += "#{escape($title)}\n"
- doc += "\n"
+ doc += "#{escape(@mod, @title)}\n"
+ doc += "\n"
doc += "\n"
@scopes.keys.sort.each do |k|
suffix = k.downcase
- doc += "\n"
+ doc += "\n"
end
doc += "\n"
@@ -244,36 +257,68 @@ HEAD
end
-collector = Collector::new
+collectors = {
+ "DRC" => Collector::new("drc", "DRC Reference"),
+ "LVS" => Collector::new("lvs", "LVS Reference")
+}
-File.open($infile, "r") do |file|
+Dir.entries($indir).each do |p|
- block = nil
- line = 0
+ if p !~ /\.rb$/
+ next
+ end
- file.each_line do |l|
+ infile = File.join($indir, p)
+ puts "Extracting doc from #{infile} .."
- line += 1
+ File.open(infile, "r") do |file|
- begin
- l = unescape(l)
- if l =~ /^\s*#\s*#{$key}/
- block = []
- elsif l =~ /^\s*#\s*(.*)\s*$/
- block && block.push($1)
- elsif l =~ /^\s*$/
- block && collector.add_block(block)
- block = nil
+ block = []
+ collector = nil
+ line = 0
+
+ file.each_line do |l|
+
+ line += 1
+
+ begin
+
+ l = unescape(l)
+
+ if ! collector
+ collectors.each do |k,c|
+ if l =~ /^\s*#\s*%#{k}%/
+ collector = c
+ l = nil
+ block = []
+ break
+ end
+ end
+ end
+
+ if l
+ if l =~ /^\s*#\s*(.*)\s*$/
+ collector && block.push($1)
+ elsif l =~ /^\s*$/
+ collector && collector.add_block(block)
+ collector = nil
+ end
+ end
+
+ rescue => ex
+ puts "ERROR in line #{line}:\n" + ex.to_s
+ puts ex.backtrace # @@@
+ exit 1
end
- rescue => ex
- puts "ERROR in line #{line}:\n" + ex.to_s
- exit 1
+
end
end
end
-collector.produce_doc
-collector.produce_index
+collectors.each do |k,collector|
+ collector.produce_doc
+ collector.produce_index
+end
diff --git a/src/ant/ant/RulerConfigPage4.ui b/src/ant/ant/RulerConfigPage4.ui
index 44bd546f2..9e3f13904 100644
--- a/src/ant/ant/RulerConfigPage4.ui
+++ b/src/ant/ant/RulerConfigPage4.ui
@@ -89,7 +89,7 @@
...
-
+
:/up.png:/up.png
@@ -103,7 +103,7 @@
...
-
+
:/add.png:/add.png
@@ -117,7 +117,7 @@
...
-
+
:/del.png:/del.png
@@ -131,7 +131,7 @@
...
-
+
:/down.png:/down.png
@@ -866,7 +866,7 @@
t_snap_cbx
-
+
diff --git a/src/db/db/db.pro b/src/db/db/db.pro
index 1556c253a..770575fd7 100644
--- a/src/db/db/db.pro
+++ b/src/db/db/db.pro
@@ -176,7 +176,14 @@ SOURCES = \
dbNetlistCompare.cc \
dbNetlistReader.cc \
dbNetlistSpiceReader.cc \
- gsiDeclDbNetlistCompare.cc
+ gsiDeclDbNetlistCompare.cc \
+ dbNetlistCrossReference.cc \
+ dbLayoutVsSchematicWriter.cc \
+ dbLayoutVsSchematicReader.cc \
+ dbLayoutVsSchematicFormatDefs.cc \
+ dbLayoutVsSchematic.cc \
+ gsiDeclDbNetlistCrossReference.cc \
+ gsiDeclDbLayoutVsSchematic.cc
HEADERS = \
dbArray.h \
@@ -317,7 +324,12 @@ HEADERS = \
gsiDeclDbHelpers.h \
dbNetlistCompare.h \
dbNetlistReader.h \
- dbNetlistSpiceReader.h
+ dbNetlistSpiceReader.h \
+ dbNetlistCrossReference.h \
+ dbLayoutVsSchematicWriter.h \
+ dbLayoutVsSchematicReader.h \
+ dbLayoutVsSchematicFormatDefs.h \
+ dbLayoutVsSchematic.h
!equals(HAVE_QT, "0") {
diff --git a/src/db/db/dbCellMapping.cc b/src/db/db/dbCellMapping.cc
index 7d29d5d13..0b10257b4 100644
--- a/src/db/db/dbCellMapping.cc
+++ b/src/db/db/dbCellMapping.cc
@@ -295,7 +295,7 @@ CellMapping::create_from_names (const db::Layout &layout_a, db::cell_index_type
}
std::vector
-CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /*cell_index_a*/, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set *exclude_cells)
+CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /*cell_index_a*/, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set *exclude_cells, const std::set *include_cells)
{
std::vector new_cells;
std::vector new_cells_b;
@@ -305,7 +305,9 @@ CellMapping::create_missing_mapping (db::Layout &layout_a, db::cell_index_type /
called_b.insert (cell_index_b);
for (std::set::const_iterator b = called_b.begin (); b != called_b.end (); ++b) {
- if (m_b2a_mapping.find (*b) == m_b2a_mapping.end () && (! exclude_cells || exclude_cells->find (*b) == exclude_cells->end ())) {
+ if (m_b2a_mapping.find (*b) == m_b2a_mapping.end ()
+ && (! exclude_cells || exclude_cells->find (*b) == exclude_cells->end ())
+ && (! include_cells || include_cells->find (*b) != include_cells->end ())) {
db::cell_index_type new_cell = layout_a.add_cell (layout_b.cell_name (*b));
new_cells.push_back (new_cell);
new_cells_b.push_back (*b);
diff --git a/src/db/db/dbCellMapping.h b/src/db/db/dbCellMapping.h
index 63740b1ca..858028659 100644
--- a/src/db/db/dbCellMapping.h
+++ b/src/db/db/dbCellMapping.h
@@ -190,9 +190,12 @@ public:
*
* If given, "exclude_cells" can specify a list of cells not to map.
*
+ * If given, "include_cells" can specify a list of cells which are included in the
+ * cell tree to create. Cells not in the "include_cells" list are ignored.
+ *
* The returned vector lists the new cells.
*/
- std::vector create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set *exclude_cells = 0);
+ std::vector create_missing_mapping (db::Layout &layout_a, db::cell_index_type cell_index_a, const db::Layout &layout_b, db::cell_index_type cell_index_b, const std::set *exclude_cells = 0, const std::set *include_cells = 0);
private:
void extract_unique (std::map >::const_iterator cand,
diff --git a/src/db/db/dbCircuit.cc b/src/db/db/dbCircuit.cc
index 2b5b6a09d..dd3c6dc03 100644
--- a/src/db/db/dbCircuit.cc
+++ b/src/db/db/dbCircuit.cc
@@ -22,6 +22,9 @@
#include "dbCircuit.h"
#include "dbNetlist.h"
+#include "dbLayout.h"
+
+#include
namespace db
{
@@ -30,7 +33,7 @@ namespace db
// Circuit class implementation
Circuit::Circuit ()
- : m_cell_index (0), mp_netlist (0),
+ : m_dont_purge (false), m_cell_index (0), mp_netlist (0),
m_device_by_id (this, &Circuit::begin_devices, &Circuit::end_devices),
m_subcircuit_by_id (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
m_net_by_cluster_id (this, &Circuit::begin_nets, &Circuit::end_nets),
@@ -44,8 +47,25 @@ Circuit::Circuit ()
m_subcircuits.changed ().add (this, &Circuit::subcircuits_changed);
}
+Circuit::Circuit (const db::Layout &layout, db::cell_index_type ci)
+ : m_name (layout.cell_name (ci)), m_dont_purge (false), m_cell_index (ci), mp_netlist (0),
+ m_device_by_id (this, &Circuit::begin_devices, &Circuit::end_devices),
+ m_subcircuit_by_id (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
+ m_net_by_cluster_id (this, &Circuit::begin_nets, &Circuit::end_nets),
+ m_device_by_name (this, &Circuit::begin_devices, &Circuit::end_devices),
+ m_subcircuit_by_name (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
+ m_net_by_name (this, &Circuit::begin_nets, &Circuit::end_nets),
+ m_index (0)
+{
+ m_devices.changed ().add (this, &Circuit::devices_changed);
+ m_nets.changed ().add (this, &Circuit::nets_changed);
+ m_subcircuits.changed ().add (this, &Circuit::subcircuits_changed);
+
+ set_boundary (db::DPolygon (db::CplxTrans (layout.dbu ()) * layout.cell (ci).bbox ()));
+}
+
Circuit::Circuit (const Circuit &other)
- : gsi::ObjectBase (other), tl::Object (other), m_cell_index (0), mp_netlist (0),
+ : gsi::ObjectBase (other), tl::Object (other), m_dont_purge (false), m_cell_index (0), mp_netlist (0),
m_device_by_id (this, &Circuit::begin_devices, &Circuit::end_devices),
m_subcircuit_by_id (this, &Circuit::begin_subcircuits, &Circuit::end_subcircuits),
m_net_by_cluster_id (this, &Circuit::begin_nets, &Circuit::end_nets),
@@ -80,6 +100,8 @@ Circuit &Circuit::operator= (const Circuit &other)
clear ();
m_name = other.m_name;
+ m_boundary = other.m_boundary;
+ m_dont_purge = other.m_dont_purge;
m_cell_index = other.m_cell_index;
m_pins = other.m_pins;
@@ -142,6 +164,13 @@ const Pin *Circuit::pin_by_id (size_t id) const
}
}
+void Circuit::rename_pin (size_t id, const std::string &name)
+{
+ if (id < m_pins.size ()) {
+ m_pins [id].set_name (name);
+ }
+}
+
const Pin *Circuit::pin_by_name (const std::string &name) const
{
for (Circuit::const_pin_iterator p = begin_pins (); p != end_pins (); ++p) {
@@ -181,6 +210,7 @@ void Circuit::clear ()
m_devices.clear ();
m_nets.clear ();
m_subcircuits.clear ();
+ m_boundary.clear ();
}
void Circuit::set_name (const std::string &name)
@@ -191,6 +221,16 @@ void Circuit::set_name (const std::string &name)
}
}
+void Circuit::set_boundary (const db::DPolygon &boundary)
+{
+ m_boundary = boundary;
+}
+
+void Circuit::set_dont_purge (bool dp)
+{
+ m_dont_purge = dp;
+}
+
void Circuit::set_cell_index (const db::cell_index_type ci)
{
m_cell_index = ci;
@@ -358,6 +398,7 @@ void Circuit::flatten_subcircuit (SubCircuit *subcircuit)
if (! d->name ().empty ()) {
device->set_name (subcircuit->expanded_name () + "." + d->name ());
}
+ device->set_trans (subcircuit->trans () * device->trans ());
add_device (device);
const std::vector &td = d->device_class ()->terminal_definitions ();
@@ -382,6 +423,7 @@ void Circuit::flatten_subcircuit (SubCircuit *subcircuit)
if (! new_subcircuit->name ().empty ()) {
new_subcircuit->set_name (subcircuit->expanded_name () + "." + new_subcircuit->name ());
}
+ new_subcircuit->set_trans (subcircuit->trans () * new_subcircuit->trans ());
add_subcircuit (new_subcircuit);
const db::Circuit *cr = sc->circuit_ref ();
@@ -422,11 +464,7 @@ void Circuit::translate_device_classes (const std::map &map)
{
for (device_iterator i = m_devices.begin (); i != m_devices.end (); ++i) {
- if (i->device_abstract ()) {
- std::map::const_iterator m = map.find (i->device_abstract ());
- tl_assert (m != map.end ());
- i->set_device_abstract (m->second);
- }
+ i->translate_device_abstracts (map);
}
}
@@ -438,6 +476,35 @@ void Circuit::set_pin_ref_for_pin (size_t pin_id, Net::pin_iterator iter)
m_pin_refs [pin_id] = iter;
}
+void Circuit::blank ()
+{
+ tl_assert (netlist () != 0);
+
+ std::set cs;
+ for (subcircuit_iterator i = m_subcircuits.begin (); i != m_subcircuits.end (); ++i) {
+ cs.insert (i->circuit_ref ());
+ }
+
+ // weak pointers are good because deleting a subcircuit might delete others ahead in
+ // this list:
+ std::list > called_circuits;
+ for (std::set::const_iterator c = cs.begin (); c != cs.end (); ++c) {
+ called_circuits.push_back (*c);
+ }
+
+ m_nets.clear ();
+ m_subcircuits.clear ();
+ m_devices.clear ();
+
+ for (std::list >::iterator c = called_circuits.begin (); c != called_circuits.end (); ++c) {
+ if (c->get () && ! (*c)->has_refs ()) {
+ netlist ()->purge_circuit (c->get ());
+ }
+ }
+
+ set_dont_purge (true);
+}
+
const Net *Circuit::net_for_pin (size_t pin_id) const
{
if (pin_id < m_pin_refs.size ()) {
@@ -534,6 +601,7 @@ bool Circuit::combine_parallel_devices (const db::DeviceClass &cls)
for (size_t i = 0; i < cl.size () - 1; ++i) {
for (size_t j = i + 1; j < cl.size (); ) {
if (cls.combine_devices (cl [i], cl [j])) {
+ cl [i]->join_device (cl [j]);
check_device_before_remove (this, cl [j]); // sanity check
delete cl [j];
cl.erase (cl.begin () + j);
@@ -623,6 +691,7 @@ bool Circuit::combine_serial_devices(const db::DeviceClass &cls)
// found a combination candidate
if (cls.combine_devices (dd.first, dd.second)) {
+ dd.first->join_device (dd.second);
check_device_before_remove (this, dd.second); // sanity check
delete dd.second;
any = true;
diff --git a/src/db/db/dbCircuit.h b/src/db/db/dbCircuit.h
index 042a3e144..3092fb6cd 100644
--- a/src/db/db/dbCircuit.h
+++ b/src/db/db/dbCircuit.h
@@ -30,6 +30,7 @@
#include "dbPin.h"
#include "dbSubCircuit.h"
#include "dbNetlistUtils.h"
+#include "dbPolygon.h"
#include "tlObject.h"
#include "tlObjectCollection.h"
@@ -40,6 +41,43 @@ namespace db
{
class Netlist;
+class Layout;
+
+/**
+ * @brief An iterator wrapper for the child and parent circuit iterator
+ */
+template
+struct DB_PUBLIC_TEMPLATE dereferencing_iterator
+ : public Iter
+{
+public:
+ typedef Value *pointer;
+ typedef Value &reference;
+ typedef typename Iter::difference_type difference_type;
+
+ dereferencing_iterator () { }
+ dereferencing_iterator (const dereferencing_iterator &d) : Iter (d) { }
+ dereferencing_iterator (const Iter &d) : Iter (d) { }
+ dereferencing_iterator &operator= (const dereferencing_iterator &d)
+ {
+ Iter::operator= (d);
+ return *this;
+ }
+
+ dereferencing_iterator operator+ (difference_type offset) const
+ {
+ return dereferencing_iterator (Iter::operator+ (offset));
+ }
+
+ dereferencing_iterator &operator+= (difference_type offset)
+ {
+ Iter::operator+= (offset);
+ return *this;
+ }
+
+ pointer operator-> () const { return Iter::operator* (); }
+ reference operator* () const { return *Iter::operator* (); }
+};
/**
* @brief A circuit
@@ -65,10 +103,10 @@ public:
typedef subcircuit_list::iterator subcircuit_iterator;
typedef tl::weak_collection::const_iterator const_refs_iterator;
typedef tl::weak_collection::iterator refs_iterator;
- typedef tl::vector::const_iterator child_circuit_iterator;
- typedef tl::vector::const_iterator const_child_circuit_iterator;
- typedef tl::vector::const_iterator parent_circuit_iterator;
- typedef tl::vector::const_iterator const_parent_circuit_iterator;
+ typedef dereferencing_iterator::const_iterator, Circuit> child_circuit_iterator;
+ typedef dereferencing_iterator::const_iterator, const Circuit> const_child_circuit_iterator;
+ typedef dereferencing_iterator::const_iterator, Circuit> parent_circuit_iterator;
+ typedef dereferencing_iterator::const_iterator, const Circuit> const_parent_circuit_iterator;
/**
* @brief Constructor
@@ -77,6 +115,13 @@ public:
*/
Circuit ();
+ /**
+ * @brief Constructor
+ *
+ * Creates a circuit corresponding to a layout cell
+ */
+ Circuit (const db::Layout &layout, db::cell_index_type ci);
+
/**
* @brief Copy constructor
*/
@@ -128,6 +173,33 @@ public:
return m_name;
}
+ /**
+ * @brief Sets the boundary
+ */
+ void set_boundary (const db::DPolygon &boundary);
+
+ /**
+ * @brief Gets the boundary
+ */
+ const db::DPolygon &boundary () const
+ {
+ return m_boundary;
+ }
+
+ /**
+ * @brief Sets or resets the "don't purge" flag
+ * This flag will prevent "purge" from deleting this circuit. It is set by "blank".
+ */
+ void set_dont_purge (bool dp);
+
+ /**
+ * @brief Gets or resets the "don't purge" flag
+ */
+ bool dont_purge () const
+ {
+ return m_dont_purge;
+ }
+
/**
* @brief The index of the circuit in the netlist
* CAUTION: this attribute is used for internal purposes and may not be valid always.
@@ -179,6 +251,23 @@ public:
return m_refs.begin ();
}
+ /**
+ * @brief Gets the references to this circuit (end, const version)
+ * This iterator will deliver all subcircuits referencing this circuit
+ */
+ const_refs_iterator end_refs () const
+ {
+ return m_refs.end ();
+ }
+
+ /**
+ * @brief Returns a value indicating whether the circuit has references
+ */
+ bool has_refs () const
+ {
+ return begin_refs () != end_refs ();
+ }
+
/**
* @brief Gets the child circuits iterator (begin)
* The child circuits are the circuits referenced by all subcircuits
@@ -225,15 +314,6 @@ public:
*/
const_parent_circuit_iterator end_parents () const;
- /**
- * @brief Gets the references to this circuit (end, const version)
- * This iterator will deliver all subcircuits referencing this circuit
- */
- const_refs_iterator end_refs () const
- {
- return m_refs.end ();
- }
-
/**
* @brief Clears the pins
*/
@@ -309,6 +389,14 @@ public:
*/
void remove_net (Net *net);
+ /**
+ * @brief Gets the number of nets
+ */
+ size_t net_count () const
+ {
+ return m_nets.size ();
+ }
+
/**
* @brief Begin iterator for the nets of the circuit (non-const version)
*/
@@ -393,6 +481,14 @@ public:
*/
void remove_device (Device *device);
+ /**
+ * @brief Gets the number of devices
+ */
+ size_t device_count () const
+ {
+ return m_devices.size ();
+ }
+
/**
* @brief Gets the device from a given ID (const version)
*
@@ -477,6 +573,14 @@ public:
*/
void remove_subcircuit (SubCircuit *subcircuit);
+ /**
+ * @brief Gets the number of subcircuits
+ */
+ size_t subcircuit_count () const
+ {
+ return m_subcircuits.size ();
+ }
+
/**
* @brief Gets the subcircuit from a given ID (const version)
*
@@ -574,6 +678,11 @@ public:
*/
void connect_pin (size_t pin_id, Net *net);
+ /**
+ * @brief Renames the pin with the given ID
+ */
+ void rename_pin (size_t pin_id, const std::string &name);
+
/**
* @brief Purge unused nets
*
@@ -598,6 +707,16 @@ public:
*/
void flatten_subcircuit (SubCircuit *subcircuit);
+ /**
+ * @brief Blanks out the circuit
+ *
+ * This will remove all innards of the circuit (nets, devices, subcircuits)
+ * and circuits which will itself are not longer be called after this.
+ * This operation will eventually leave a blackbox model of the circuit
+ * containing only pins.
+ */
+ void blank ();
+
private:
friend class Netlist;
friend class Net;
@@ -605,6 +724,8 @@ private:
friend class Device;
std::string m_name;
+ db::DPolygon m_boundary;
+ bool m_dont_purge;
db::cell_index_type m_cell_index;
net_list m_nets;
pin_list m_pins;
diff --git a/src/db/db/dbDeepRegion.cc b/src/db/db/dbDeepRegion.cc
index 1d2cd5673..149555c20 100644
--- a/src/db/db/dbDeepRegion.cc
+++ b/src/db/db/dbDeepRegion.cc
@@ -23,7 +23,6 @@
#include "dbDeepRegion.h"
#include "dbDeepShapeStore.h"
-#include "dbEmptyRegion.h"
#include "dbEmptyEdgePairs.h"
#include "dbRegion.h"
#include "dbRegionUtils.h"
@@ -462,10 +461,13 @@ DeepRegion::and_with (const Region &other) const
{
const DeepRegion *other_deep = dynamic_cast (other.delegate ());
- if (empty () || other.empty ()) {
+ if (empty ()) {
- // Nothing to do
- return new EmptyRegion ();
+ return clone ();
+
+ } else if (other.empty ()) {
+
+ return other.delegate ()->clone ();
} else if (! other_deep) {
@@ -483,14 +485,8 @@ DeepRegion::not_with (const Region &other) const
{
const DeepRegion *other_deep = dynamic_cast (other.delegate ());
- if (empty ()) {
+ if (empty () || other.empty ()) {
- // Nothing to do
- return new EmptyRegion ();
-
- } else if (other.empty ()) {
-
- // Nothing to do
return clone ();
} else if (! other_deep) {
@@ -1231,6 +1227,12 @@ DeepRegion::merged (bool min_coherence, unsigned int min_wc) const
RegionDelegate *
DeepRegion::sized (coord_type d, unsigned int mode) const
{
+ if (empty ()) {
+ // Nothing to do - NOTE: don't return EmptyRegion because we want to
+ // maintain "deepness"
+ return clone ();
+ }
+
ensure_merged_polygons_valid ();
db::Layout &layout = m_merged_polygons.layout ();
@@ -1299,6 +1301,12 @@ struct XYAnisotropyAndMagnificationReducer
RegionDelegate *
DeepRegion::sized (coord_type dx, coord_type dy, unsigned int mode) const
{
+ if (empty ()) {
+ // Nothing to do - NOTE: don't return EmptyRegion because we want to
+ // maintain "deepness"
+ return clone ();
+ }
+
if (dx == dy) {
return sized (dx, mode);
}
diff --git a/src/db/db/dbDeepShapeStore.cc b/src/db/db/dbDeepShapeStore.cc
index 1e0c1e96b..7fa787440 100644
--- a/src/db/db/dbDeepShapeStore.cc
+++ b/src/db/db/dbDeepShapeStore.cc
@@ -222,19 +222,11 @@ DeepLayer::check_dss () const
struct DeepShapeStore::LayoutHolder
{
LayoutHolder (const db::ICplxTrans &trans)
- : refs (0), layout (false), builder (&layout, trans), m_empty_layer (std::numeric_limits::max ())
+ : refs (0), layout (false), builder (&layout, trans)
{
// .. nothing yet ..
}
- unsigned int empty_layer () const
- {
- if (m_empty_layer == std::numeric_limits::max ()) {
- const_cast (this)->make_empty_layer ();
- }
- return m_empty_layer;
- }
-
void add_layer_ref (unsigned int layer)
{
layer_refs [layer] += 1;
@@ -255,15 +247,6 @@ struct DeepShapeStore::LayoutHolder
db::Layout layout;
db::HierarchyBuilder builder;
std::map layer_refs;
-
-private:
- unsigned int m_empty_layer;
-
- void make_empty_layer ()
- {
- m_empty_layer = layout.insert_layer ();
- layer_refs [m_empty_layer] += 1; // the empty layer is not deleted
- }
};
// ----------------------------------------------------------------------------------
@@ -514,6 +497,18 @@ void DeepShapeStore::make_layout (unsigned int layout_index, const db::Recursive
m_layout_map[std::make_pair (si, trans)] = layout_index;
}
+static unsigned int init_layer (db::Layout &layout, const db::RecursiveShapeIterator &si)
+{
+ unsigned int layer_index = layout.insert_layer ();
+
+ if (si.layout () && si.layer () < si.layout ()->layers ()) {
+ // try to preserve the layer properties
+ layout.set_properties (layer_index, si.layout ()->get_properties (si.layer ()));
+ }
+
+ return layer_index;
+}
+
DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator &si, double max_area_ratio, size_t max_vertex_count, const db::ICplxTrans &trans)
{
if (max_area_ratio == 0.0) {
@@ -528,7 +523,7 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
db::Layout &layout = m_layouts[layout_index]->layout;
db::HierarchyBuilder &builder = m_layouts[layout_index]->builder;
- unsigned int layer_index = layout.insert_layer ();
+ unsigned int layer_index = init_layer (layout, si);
builder.set_target_layer (layer_index);
// The chain of operators for producing clipped and reduced polygon references
@@ -540,6 +535,7 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
try {
tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy")));
+ db::LayoutLocker ll (&layout, true /*no update*/);
builder.set_shape_receiver (&clip);
db::RecursiveShapeIterator (si).push (& builder);
@@ -553,17 +549,6 @@ DeepLayer DeepShapeStore::create_polygon_layer (const db::RecursiveShapeIterator
return DeepLayer (this, layout_index, layer_index);
}
-DeepLayer DeepShapeStore::empty_layer (unsigned int layout_index) const
-{
- return DeepLayer (const_cast (this), layout_index, m_layouts[layout_index]->empty_layer ());
-}
-
-DeepLayer DeepShapeStore::empty_layer () const
-{
- require_singular ();
- return empty_layer (0);
-}
-
DeepLayer DeepShapeStore::create_custom_layer (const db::RecursiveShapeIterator &si, HierarchyBuilderShapeReceiver *pipe, const db::ICplxTrans &trans)
{
unsigned int layout_index = layout_for_iter (si, trans);
@@ -571,13 +556,14 @@ DeepLayer DeepShapeStore::create_custom_layer (const db::RecursiveShapeIterator
db::Layout &layout = m_layouts[layout_index]->layout;
db::HierarchyBuilder &builder = m_layouts[layout_index]->builder;
- unsigned int layer_index = layout.insert_layer ();
+ unsigned int layer_index = init_layer (layout, si);
builder.set_target_layer (layer_index);
// Build the working hierarchy from the recursive shape iterator
try {
tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy")));
+ db::LayoutLocker ll (&layout, true /*no update*/);
builder.set_shape_receiver (pipe);
db::RecursiveShapeIterator (si).push (& builder);
@@ -624,7 +610,7 @@ DeepLayer DeepShapeStore::create_edge_layer (const db::RecursiveShapeIterator &s
db::Layout &layout = m_layouts[layout_index]->layout;
db::HierarchyBuilder &builder = m_layouts[layout_index]->builder;
- unsigned int layer_index = layout.insert_layer ();
+ unsigned int layer_index = init_layer (layout, si);
builder.set_target_layer (layer_index);
// The chain of operators for producing edges
@@ -634,6 +620,7 @@ DeepLayer DeepShapeStore::create_edge_layer (const db::RecursiveShapeIterator &s
try {
tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy")));
+ db::LayoutLocker ll (&layout, true /*no update*/);
builder.set_shape_receiver (&refs);
db::RecursiveShapeIterator (si).push (& builder);
@@ -654,7 +641,7 @@ DeepLayer DeepShapeStore::create_edge_pair_layer (const db::RecursiveShapeIterat
db::Layout &layout = m_layouts[layout_index]->layout;
db::HierarchyBuilder &builder = m_layouts[layout_index]->builder;
- unsigned int layer_index = layout.insert_layer ();
+ unsigned int layer_index = init_layer (layout, si);
builder.set_target_layer (layer_index);
// The chain of operators for producing the edge pairs
@@ -664,6 +651,7 @@ DeepLayer DeepShapeStore::create_edge_pair_layer (const db::RecursiveShapeIterat
try {
tl::SelfTimer timer (tl::verbosity () >= 41, tl::to_string (tr ("Building working hierarchy")));
+ db::LayoutLocker ll (&layout, true /*no update*/);
builder.set_shape_receiver (&refs);
db::RecursiveShapeIterator (si).push (& builder);
@@ -697,7 +685,7 @@ DeepShapeStore::issue_variants (unsigned int layout_index, const std::map *excluded_cells)
+DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set *excluded_cells, const std::set *included_cells)
{
const db::Layout *source_layout = &m_layouts [layout_index]->layout;
if (source_layout->begin_top_down () == source_layout->end_top_cells ()) {
@@ -758,7 +746,7 @@ DeepShapeStore::cell_mapping_to_original (unsigned int layout_index, db::Layout
// Add new cells for the variants and (possible) devices which are cells added during the device
// extraction process
- cm->second.create_missing_mapping (*into_layout, into_cell, *source_layout, source_top, excluded_cells);
+ cm->second.create_missing_mapping (*into_layout, into_cell, *source_layout, source_top, excluded_cells, included_cells);
}
diff --git a/src/db/db/dbDeepShapeStore.h b/src/db/db/dbDeepShapeStore.h
index 2246e8a18..79c5c7495 100644
--- a/src/db/db/dbDeepShapeStore.h
+++ b/src/db/db/dbDeepShapeStore.h
@@ -343,19 +343,6 @@ public:
*/
DeepLayer create_copy (const DeepLayer &source, HierarchyBuilderShapeReceiver *pipe);
- /**
- * @brief Gets the empty working layer
- *
- * This method will deliver an empty layer for the given layout index. CAUTION: don't modify this layer as it may
- * be reused.
- */
- DeepLayer empty_layer (unsigned int layout_index) const;
-
- /**
- * @brief Gets the empty working layer for the singular layout
- */
- DeepLayer empty_layer () const;
-
/**
* @brief Inserts the deep layer's shapes into some target layout
*/
@@ -375,9 +362,11 @@ public:
* "layout_index" is the layout to return to it's original. "into_layout" is the original layout, "into_cell"
* the original cell.
*
- * "excluded_cells" - if not 0 - will exclude the given cells (and flatten them).
+ * "excluded_cells" - if not 0 - will exclude the given cells
+ *
+ * "included_cells" - if not 0 - will only include the given cells in the cell mapping
*/
- const db::CellMapping &cell_mapping_to_original (unsigned int layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set *excluded_cells = 0);
+ const db::CellMapping &cell_mapping_to_original (unsigned int layout_index, db::Layout *into_layout, db::cell_index_type into_cell, const std::set *excluded_cells = 0, const std::set *included_cells = 0);
/**
* @brief Create cell variants from the given variant collector
diff --git a/src/db/db/dbDevice.cc b/src/db/db/dbDevice.cc
index e803cec08..ca950ad2e 100644
--- a/src/db/db/dbDevice.cc
+++ b/src/db/db/dbDevice.cc
@@ -67,7 +67,7 @@ Device &Device::operator= (const Device &other)
{
if (this != &other) {
m_name = other.m_name;
- m_position = other.m_position;
+ m_trans = other.m_trans;
m_parameters = other.m_parameters;
mp_device_class = other.mp_device_class;
mp_device_abstract = other.mp_device_abstract;
@@ -97,9 +97,9 @@ void Device::set_name (const std::string &n)
}
}
-void Device::set_position (const db::DPoint &pt)
+void Device::set_trans (const db::DCplxTrans &tr)
{
- m_position = pt;
+ m_trans = tr;
}
void Device::set_terminal_ref_for_terminal (size_t terminal_id, Net::terminal_iterator iter)
@@ -187,4 +187,103 @@ 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 &terminals = m_reconnected_terminals [this_terminal];
+
+ std::map >::const_iterator ot = other->m_reconnected_terminals.find (other_terminal);
+ if (ot == other->m_reconnected_terminals.end ()) {
+
+ terminals.push_back (DeviceReconnectedTerminal (other_abstracts ().size () + 1, other_terminal));
+
+ } else {
+
+ size_t n = terminals.size ();
+ terminals.insert (terminals.end (), ot->second.begin (), ot->second.end ());
+
+ while (n < terminals.size ()) {
+ terminals [n].device_index += other_abstracts ().size () + 1;
+ ++n;
+ }
+
+ }
+}
+
+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 (DeviceReconnectedTerminal (0, i));
+ }
+}
+
+void Device::join_terminals (unsigned int this_terminal, db::Device *other, unsigned int other_terminal)
+{
+ if (m_reconnected_terminals.empty ()) {
+ init_terminal_routes ();
+ }
+
+ other->connect_terminal (other_terminal, 0);
+
+ add_others_terminals (this_terminal, other, other_terminal);
+}
+
+void Device::reroute_terminal (unsigned int this_terminal, db::Device *other, unsigned int from_other_terminal, unsigned int other_terminal)
+{
+ // 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);
+ }
+
+ add_others_terminals (this_terminal, other, other_terminal);
+
+ connect_terminal (this_terminal, other->net_for_terminal (other_terminal));
+
+ other->connect_terminal (from_other_terminal, 0);
+ other->connect_terminal (other_terminal, 0);
+}
+
+void Device::join_device (db::Device *other)
+{
+ db::DCplxTrans d = trans ().inverted () * other->trans ();
+
+ m_other_abstracts.reserve (m_other_abstracts.size () + 1 + other->m_other_abstracts.size ());
+
+ m_other_abstracts.push_back (db::DeviceAbstractRef (other->device_abstract (), d));
+
+ for (std::vector::const_iterator a = other->m_other_abstracts.begin (); a != other->m_other_abstracts.end (); ++a) {
+ m_other_abstracts.push_back (*a);
+ m_other_abstracts.back ().trans = d * m_other_abstracts.back ().trans;
+ }
+}
+
+static db::DeviceAbstract *map_da (const std::map &map, const db::DeviceAbstract *da)
+{
+ if (! da) {
+ return 0;
+ } else {
+ std::map::const_iterator m = map.find (da);
+ tl_assert (m != map.end ());
+ return m->second;
+ }
+}
+
+void Device::translate_device_abstracts (const std::map &map)
+{
+ set_device_abstract (map_da (map, device_abstract ()));
+
+ for (std::vector::iterator a = m_other_abstracts.begin (); a != m_other_abstracts.end (); ++a) {
+ a->device_abstract = map_da (map, a->device_abstract);
+ }
+}
+
}
diff --git a/src/db/db/dbDevice.h b/src/db/db/dbDevice.h
index 5b12d25d5..7e6b8af3e 100644
--- a/src/db/db/dbDevice.h
+++ b/src/db/db/dbDevice.h
@@ -26,6 +26,8 @@
#include "dbCommon.h"
#include "dbNet.h"
#include "dbPoint.h"
+#include "dbVector.h"
+#include "dbTrans.h"
#include "tlObject.h"
@@ -38,6 +40,51 @@ class Circuit;
class DeviceClass;
class DeviceAbstract;
+/**
+ * @brief A structure describing a terminal reference into another device abstract
+ */
+struct DeviceReconnectedTerminal
+{
+ DeviceReconnectedTerminal (size_t _device_index, unsigned int _other_terminal_id)
+ : device_index (_device_index), other_terminal_id (_other_terminal_id)
+ {
+ // .. nothing yet ..
+ }
+
+ DeviceReconnectedTerminal ()
+ : device_index (0), other_terminal_id (0)
+ {
+ // .. nothing yet ..
+ }
+
+ size_t device_index;
+ unsigned int other_terminal_id;
+};
+
+/**
+ * @brief A structure describing a reference to another device abstract
+ *
+ * This structure is used within Device to reference more than the standard
+ * device abstract.
+ */
+struct DeviceAbstractRef
+{
+ DeviceAbstractRef (const db::DeviceAbstract *_device_abstract, const db::DCplxTrans &_trans)
+ : device_abstract (_device_abstract), trans (_trans)
+ {
+ // .. nothing yet ..
+ }
+
+ DeviceAbstractRef ()
+ : device_abstract (0), trans ()
+ {
+ // .. nothing yet ..
+ }
+
+ const db::DeviceAbstract *device_abstract;
+ db::DCplxTrans trans;
+};
+
/**
* @brief An actual device
*
@@ -166,19 +213,19 @@ public:
/**
* @brief Sets the device position
- * The device position should be the center of the recognition shape or something similar.
+ * The device position should be the center and orientation of the recognition shape or something similar.
* Giving the device a position allows combining multiple devices with the same
* relative geometry into a single cell.
- * The position has to be given in micrometer units.
+ * The transformation has to be given in micrometer units.
*/
- void set_position (const db::DPoint &pos);
+ void set_trans (const db::DCplxTrans &tr);
/**
* @brief Gets the device position
*/
- const db::DPoint &position () const
+ const db::DCplxTrans &trans () const
{
- return m_position;
+ return m_trans;
}
/**
@@ -228,6 +275,80 @@ public:
*/
void set_parameter_value (const std::string &name, double v);
+ /**
+ * @brief Used for device combination: join terminals with other device
+ */
+ void join_terminals (unsigned int this_terminal, db::Device *other, unsigned int other_terminal);
+
+ /**
+ * @brief Used for device combination: reroute terminal to other device
+ *
+ * This will disconnect "this_terminal" from the device and make a connection to
+ * "other_terminal" of the "other" device instead.
+ *
+ * An internal connection between "this_terminal" and "from_other_terminal" is
+ * implied.
+ */
+ void reroute_terminal (unsigned int this_terminal, db::Device *other, unsigned int from_other_terminal, unsigned int other_terminal);
+
+ /**
+ * @brief Gets the set of other terminal references
+ *
+ * This method will return 0 if the device isn't a combined device or the given terminal
+ * is not connector to a different abstract.
+ *
+ * The returned vector (if any) is a complete list of terminals connected to the given
+ * logical device terminal.
+ */
+ const std::vector *reconnected_terminals_for (unsigned int this_terminal) const
+ {
+ std::map >::const_iterator t = m_reconnected_terminals.find (this_terminal);
+ if (t != m_reconnected_terminals.end ()) {
+ return & t->second;
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * @brief Gets the map of reconnected terminals
+ */
+ const std::map > &reconnected_terminals () const
+ {
+ return m_reconnected_terminals;
+ }
+
+ /**
+ * @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 > &reconnected_terminals ()
+ {
+ return m_reconnected_terminals;
+ }
+
+ /**
+ * @brief Gets the set of other device abstracts
+ *
+ * This list does not include the intrinsic original abstract of the device.
+ * This vector is non-empty if this device is a combined one.
+ */
+ const std::vector &other_abstracts () const
+ {
+ return m_other_abstracts;
+ }
+
+ /**
+ * @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 &other_abstracts ()
+ {
+ return m_other_abstracts;
+ }
+
private:
friend class Circuit;
friend class Net;
@@ -235,11 +356,23 @@ private:
DeviceClass *mp_device_class;
DeviceAbstract *mp_device_abstract;
std::string m_name;
- db::DPoint m_position;
+ db::DCplxTrans m_trans;
std::vector m_terminal_refs;
std::vector m_parameters;
size_t m_id;
Circuit *mp_circuit;
+ std::vector m_other_abstracts;
+ std::map > m_reconnected_terminals;
+
+ /**
+ * @brief Translates the device abstracts
+ */
+ void translate_device_abstracts (const std::map &map);
+
+ /**
+ * @brief Joins this device with another
+ */
+ void join_device (db::Device *other);
/**
* @brief Sets the terminal reference for a specific terminal
@@ -258,6 +391,9 @@ private:
* @brief Sets the circuit
*/
void set_circuit (Circuit *circuit);
+
+ void add_others_terminals (unsigned int this_terminal, db::Device *other, unsigned int other_terminal);
+ void init_terminal_routes ();
};
}
diff --git a/src/db/db/dbDeviceClass.cc b/src/db/db/dbDeviceClass.cc
index b42ddfcd0..322885071 100644
--- a/src/db/db/dbDeviceClass.cc
+++ b/src/db/db/dbDeviceClass.cc
@@ -22,6 +22,7 @@
#include "dbDeviceClass.h"
#include "dbDevice.h"
+#include "tlClassRegistry.h"
namespace db
{
@@ -273,4 +274,29 @@ bool DeviceClass::equal (const db::Device &a, const db::Device &b)
}
}
+// --------------------------------------------------------------------------------
+// DeviceClassTemplateBase class implementation
+
+DeviceClassTemplateBase *
+DeviceClassTemplateBase::template_by_name (const std::string &name)
+{
+ for (tl::Registrar::iterator i = tl::Registrar::begin (); i != tl::Registrar::end (); ++i) {
+ if (i->name () == name) {
+ return i.operator-> ();
+ }
+ }
+ return 0;
+}
+
+DeviceClassTemplateBase *
+DeviceClassTemplateBase::is_a (const db::DeviceClass *dc)
+{
+ for (tl::Registrar::iterator i = tl::Registrar::begin (); i != tl::Registrar::end (); ++i) {
+ if (i->is_of (dc)) {
+ return i.operator-> ();
+ }
+ }
+ return 0;
+}
+
}
diff --git a/src/db/db/dbDeviceClass.h b/src/db/db/dbDeviceClass.h
index 6b0388a79..bb433ea92 100644
--- a/src/db/db/dbDeviceClass.h
+++ b/src/db/db/dbDeviceClass.h
@@ -124,7 +124,7 @@ public:
* @brief Creates an empty device parameter definition
*/
DeviceParameterDefinition ()
- : m_name (), m_description (), m_default_value (0.0), m_id (0), m_is_primary (true)
+ : m_name (), m_description (), m_default_value (0.0), m_id (0), m_is_primary (true), m_si_scaling (1.0)
{
// .. nothing yet ..
}
@@ -132,8 +132,8 @@ public:
/**
* @brief Creates a device parameter definition with the given name and description
*/
- DeviceParameterDefinition (const std::string &name, const std::string &description, double default_value = 0.0, bool is_primary = true)
- : m_name (name), m_description (description), m_default_value (default_value), m_id (0), m_is_primary (is_primary)
+ DeviceParameterDefinition (const std::string &name, const std::string &description, double default_value = 0.0, bool is_primary = true, double si_scaling = 1.0)
+ : m_name (name), m_description (description), m_default_value (default_value), m_id (0), m_is_primary (is_primary), m_si_scaling (si_scaling)
{
// .. nothing yet ..
}
@@ -178,6 +178,17 @@ public:
return m_default_value;
}
+ /**
+ * @brief Gets the SI unit scaling factor
+ *
+ * Some parameters are given in micrometers for example. This
+ * scaling factor gives the translation to SI units (1e-6 for micrometers).
+ */
+ double si_scaling () const
+ {
+ return m_si_scaling;
+ }
+
/**
* @brief Sets the parameter description
*/
@@ -220,6 +231,7 @@ private:
double m_default_value;
size_t m_id;
bool m_is_primary;
+ double m_si_scaling;
void set_id (size_t id)
{
@@ -536,6 +548,74 @@ private:
}
};
+/**
+ * @brief A device class template
+ *
+ * This is a registered class which provides a device class template.
+ * The built-in classes serve as templates and registering a template
+ * allows regenerating the class from an abstract description (template
+ * name).
+ *
+ * NOTE: device classes derived from one of the built-in classes
+ * cannot be distinguished from pure built-in classes. Entirely
+ * customized classes are treated as "non-template based" (i.e.
+ * "is_a" returns 0).
+ */
+class DB_PUBLIC DeviceClassTemplateBase
+{
+public:
+ DeviceClassTemplateBase (const std::string &name)
+ : m_name (name)
+ {
+ // .. nothing yet ..
+ }
+
+ virtual ~DeviceClassTemplateBase () { }
+
+ const std::string &name () const
+ {
+ return m_name;
+ }
+
+ virtual bool is_of (const db::DeviceClass *) const = 0;
+ virtual DeviceClass *create () const = 0;
+
+ static DeviceClassTemplateBase *template_by_name (const std::string &name);
+ static DeviceClassTemplateBase *is_a (const db::DeviceClass *dc);
+
+private:
+ std::string m_name;
+
+ DeviceClassTemplateBase (const DeviceClassTemplateBase &);
+ DeviceClassTemplateBase &operator= (const DeviceClassTemplateBase &);
+};
+
+template
+class DB_PUBLIC_TEMPLATE device_class_template
+ : public DeviceClassTemplateBase
+{
+public:
+ device_class_template (const std::string &name)
+ : DeviceClassTemplateBase (name)
+ {
+ // .. nothing yet ..
+ }
+
+ virtual bool is_of (const db::DeviceClass *dc) const
+ {
+ return dynamic_cast (dc) != 0;
+ }
+
+ virtual DeviceClass *create () const
+ {
+ return new T ();
+ }
+
+private:
+ device_class_template (const device_class_template &);
+ device_class_template &operator= (const device_class_template &);
+};
+
}
#endif
diff --git a/src/db/db/dbHierNetworkProcessor.cc b/src/db/db/dbHierNetworkProcessor.cc
index 593f031c2..2005b010c 100644
--- a/src/db/db/dbHierNetworkProcessor.cc
+++ b/src/db/db/dbHierNetworkProcessor.cc
@@ -145,6 +145,12 @@ Connectivity::global_net_id (const std::string &gn)
return id;
}
+size_t
+Connectivity::global_nets () const
+{
+ return m_global_net_names.size ();
+}
+
Connectivity::layer_iterator
Connectivity::begin_layers () const
{
@@ -1270,6 +1276,11 @@ private:
for (db::CellInstArray::iterator ii2 = i2.begin_touching (ib1.transformed (t2i), mp_layout); ! ii2.at_end (); ++ii2) {
db::ICplxTrans tt2 = t2 * i2.complex_trans (*ii2);
+ if (i1.cell_index () == i2.cell_index () && tt1 == tt2) {
+ // skip interactions between identical instances (duplicate instance removal)
+ continue;
+ }
+
box_type ib2 = bb2.transformed (tt2);
box_type common12 = ib1 & ib2 & common;
@@ -1653,6 +1664,8 @@ hier_clusters::make_path (const db::Layout &layout, const db::Cell &cell, siz
connected_clusters &child_cc = clusters_per_cell (p->inst_cell_index ());
if (child_cc.is_root (id)) {
+ std::set > seen; // to avoid duplicate connections
+
const db::Cell &child_cell = layout.cell (p->inst_cell_index ());
for (db::Cell::parent_inst_iterator pi = child_cell.begin_parent_insts (); ! pi.at_end (); ++pi) {
@@ -1662,7 +1675,7 @@ hier_clusters::make_path (const db::Layout &layout, const db::Cell &cell, siz
for (db::CellInstArray::iterator pii = child_inst.begin (); ! pii.at_end (); ++pii) {
ClusterInstance ci2 (id, child_inst.cell_index (), child_inst.complex_trans (*pii), child_inst.prop_id ());
- if (cell.cell_index () != pi->parent_cell_index () || ci != ci2) {
+ if ((cell.cell_index () != pi->parent_cell_index () || ci != ci2) && seen.find (std::make_pair (pi->parent_cell_index (), ci2)) == seen.end ()) {
size_t id_dummy;
@@ -1676,6 +1689,7 @@ hier_clusters::make_path (const db::Layout &layout, const db::Cell &cell, siz
}
parent_cc.add_connection (id_dummy, ci2);
+ seen.insert (std::make_pair (pi->parent_cell_index (), ci2));
}
@@ -1709,6 +1723,8 @@ hier_clusters::make_path (const db::Layout &layout, const db::Cell &cell, siz
connected_clusters &child_cc = clusters_per_cell (p->inst_cell_index ());
if (child_cc.is_root (id)) {
+ std::set > seen; // to avoid duplicate connections
+
const db::Cell &child_cell = layout.cell (p->inst_cell_index ());
for (db::Cell::parent_inst_iterator pi = child_cell.begin_parent_insts (); ! pi.at_end (); ++pi) {
@@ -1717,22 +1733,27 @@ hier_clusters::make_path (const db::Layout &layout, const db::Cell &cell, siz
connected_clusters &parent_cc = clusters_per_cell (pi->parent_cell_index ());
for (db::CellInstArray::iterator pii = child_inst.begin (); ! pii.at_end (); ++pii) {
- size_t id_dummy;
-
- const typename db::local_cluster::global_nets &gn = child_cc.cluster_by_id (id).get_global_nets ();
- if (gn.empty ()) {
- id_dummy = parent_cc.insert_dummy ();
- } else {
- local_cluster *lc = parent_cc.insert ();
- lc->set_global_nets (gn);
- id_dummy = lc->id ();
- }
-
ClusterInstance ci2 (id, child_inst.cell_index (), child_inst.complex_trans (*pii), child_inst.prop_id ());
- parent_cc.add_connection (id_dummy, ci2);
+ if (seen.find (std::make_pair (pi->parent_cell_index (), ci2)) == seen.end ()) {
+
+ size_t id_dummy;
+
+ const typename db::local_cluster::global_nets &gn = child_cc.cluster_by_id (id).get_global_nets ();
+ if (gn.empty ()) {
+ id_dummy = parent_cc.insert_dummy ();
+ } else {
+ local_cluster *lc = parent_cc.insert ();
+ lc->set_global_nets (gn);
+ id_dummy = lc->id ();
+ }
+
+ parent_cc.add_connection (id_dummy, ci2);
+ seen.insert (std::make_pair (pi->parent_cell_index (), ci2));
+
+ if (pci == pi->parent_cell_index () && ci == ci2) {
+ id_new = id_dummy;
+ }
- if (pci == pi->parent_cell_index () && ci == ci2) {
- id_new = id_dummy;
}
}
@@ -1821,7 +1842,7 @@ hier_clusters::build_local_cluster (const db::Layout &layout, const db::Cell
tl::SelfTimer timer (tl::verbosity () > m_base_verbosity + 20, msg);
connected_clusters &local = m_per_cell_clusters [cell.cell_index ()];
- local.build_clusters (cell, shape_flags, conn, attr_equivalence, tl::verbosity () >= m_base_verbosity + 30);
+ local.build_clusters (cell, shape_flags, conn, attr_equivalence, true);
}
template
@@ -1950,8 +1971,7 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c
static std::string desc = tl::to_string (tr ("Instance to instance treatment"));
tl::SelfTimer timer (tl::verbosity () > m_base_verbosity + 30, desc);
- bool report_progress = tl::verbosity () >= m_base_verbosity + 30;
- db::box_scanner bs (report_progress, desc);
+ db::box_scanner bs (true, desc);
for (std::vector::const_iterator inst = inst_storage.begin (); inst != inst_storage.end (); ++inst) {
bs.insert (inst.operator-> (), 0);
@@ -1969,8 +1989,7 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c
static std::string desc = tl::to_string (tr ("Local to instance treatment"));
tl::SelfTimer timer (tl::verbosity () > m_base_verbosity + 30, desc);
- bool report_progress = tl::verbosity () >= m_base_verbosity + 30;
- db::box_scanner2, unsigned int, db::Instance, unsigned int> bs2 (report_progress, desc);
+ db::box_scanner2, unsigned int, db::Instance, unsigned int> bs2 (true, desc);
for (typename connected_clusters::const_iterator c = local.begin (); c != local.end (); ++c) {
@@ -2025,8 +2044,9 @@ hier_clusters::build_hier_connections (cell_clusters_box_converter &cbc, c
// insert the global nets from here
for (typename db::connected_clusters::const_iterator cl = local.begin (); cl != local.end (); ++cl) {
- if (! cl->get_global_nets ().empty ()) {
- global_net_clusters.add (cl->get_global_nets (), db::ClusterInstance (cl->id ()));
+ const typename db::local_cluster::global_nets &gn = cl->get_global_nets ();
+ if (! gn.empty ()) {
+ global_net_clusters.add (gn, db::ClusterInstance (cl->id ()));
}
}
@@ -2153,6 +2173,10 @@ template
recursive_cluster_shape_iterator::recursive_cluster_shape_iterator (const hier_clusters &hc, unsigned int layer, db::cell_index_type ci, typename local_cluster::id_type id)
: mp_hc (&hc), m_layer (layer), m_id (id)
{
+ if (id == 0) {
+ return;
+ }
+
down (ci, id, db::ICplxTrans ());
while (m_shape_iter.at_end () && ! m_conn_iter_stack.empty ()) {
diff --git a/src/db/db/dbHierNetworkProcessor.h b/src/db/db/dbHierNetworkProcessor.h
index 5d14a904a..112648e9c 100644
--- a/src/db/db/dbHierNetworkProcessor.h
+++ b/src/db/db/dbHierNetworkProcessor.h
@@ -131,6 +131,11 @@ public:
*/
size_t global_net_id (const std::string &gn);
+ /**
+ * @brief Gets the number of global nets (it's also the max ID + 1)
+ */
+ size_t global_nets () const;
+
/**
* @brief Begin iterator for the layers involved
*/
diff --git a/src/db/db/dbLayout.h b/src/db/db/dbLayout.h
index 08e06fb1a..27724cf78 100644
--- a/src/db/db/dbLayout.h
+++ b/src/db/db/dbLayout.h
@@ -1562,6 +1562,17 @@ public:
}
}
+ /**
+ * @brief Cancel the "in changes" state (see "start_changes")
+ * This version does not force an update
+ */
+ void end_changes_no_update ()
+ {
+ if (m_invalid > 0) {
+ --m_invalid;
+ }
+ }
+
/**
* @brief Tell if the layout object is under construction
*
@@ -1763,8 +1774,8 @@ mem_stat (MemStatistics *stat, MemStatistics::purpose_t purpose, int cat, const
class DB_PUBLIC LayoutLocker
{
public:
- explicit LayoutLocker (db::Layout *layout = 0)
- : mp_layout (layout)
+ explicit LayoutLocker (db::Layout *layout = 0, bool no_update = false)
+ : mp_layout (layout), m_no_update (no_update)
{
if (mp_layout) {
mp_layout->start_changes ();
@@ -1773,13 +1784,11 @@ public:
~LayoutLocker ()
{
- if (mp_layout) {
- mp_layout->end_changes ();
- }
+ set (0, false);
}
LayoutLocker (const LayoutLocker &other)
- : mp_layout (other.mp_layout)
+ : mp_layout (other.mp_layout), m_no_update (other.m_no_update)
{
if (mp_layout) {
mp_layout->start_changes ();
@@ -1792,20 +1801,30 @@ public:
return *this;
}
- if (mp_layout) {
- mp_layout->end_changes ();
- }
- mp_layout = other.mp_layout;
- if (mp_layout) {
- mp_layout->start_changes ();
- }
-
+ set (other.mp_layout, other.m_no_update);
return *this;
}
private:
-
db::Layout *mp_layout;
+ bool m_no_update;
+
+ void set (db::Layout *layout, bool no_update)
+ {
+ if (mp_layout) {
+ if (m_no_update) {
+ mp_layout->end_changes_no_update ();
+ } else {
+ mp_layout->end_changes ();
+ }
+ }
+ mp_layout = layout;
+ m_no_update = no_update;
+ if (mp_layout) {
+ mp_layout->start_changes ();
+ }
+ }
+
};
}
diff --git a/src/db/db/dbLayoutToNetlist.cc b/src/db/db/dbLayoutToNetlist.cc
index b9bb376ca..4e339c96e 100644
--- a/src/db/db/dbLayoutToNetlist.cc
+++ b/src/db/db/dbLayoutToNetlist.cc
@@ -26,6 +26,11 @@
#include "dbDeepRegion.h"
#include "dbShapeRepository.h"
#include "dbCellMapping.h"
+#include "dbLayoutToNetlistWriter.h"
+#include "dbLayoutToNetlistReader.h"
+#include "dbLayoutVsSchematic.h"
+#include "dbLayoutToNetlistFormatDefs.h"
+#include "dbLayoutVsSchematicFormatDefs.h"
namespace db
{
@@ -87,6 +92,14 @@ LayoutToNetlist::~LayoutToNetlist ()
m_net_clusters.clear ();
}
+void LayoutToNetlist::keep_dss ()
+{
+ if (mp_dss.get () && ! mp_internal_dss.get ()) {
+ mp_dss->keep ();
+ mp_internal_dss.reset (mp_dss.get ());
+ }
+}
+
void LayoutToNetlist::init ()
{
dss ().set_text_enlargement (1);
@@ -155,7 +168,9 @@ db::Region *LayoutToNetlist::make_text_layer (unsigned int layer_index, const st
si.shape_flags (db::ShapeIterator::Texts);
std::auto_ptr region (new db::Region (si, dss ()));
- register_layer (*region, n);
+ if (! n.empty ()) {
+ register_layer (*region, n);
+ }
return region.release ();
}
@@ -166,7 +181,9 @@ db::Region *LayoutToNetlist::make_polygon_layer (unsigned int layer_index, const
si.shape_flags (db::ShapeIterator::Paths | db::ShapeIterator::Polygons | db::ShapeIterator::Boxes);
std::auto_ptr region (new db::Region (si, dss ()));
- register_layer (*region, n);
+ if (! n.empty ()) {
+ register_layer (*region, n);
+ }
return region.release ();
}
@@ -188,7 +205,7 @@ void LayoutToNetlist::connect (const db::Region &l)
}
if (! is_persisted (l)) {
- throw (tl::Exception (tl::to_string (tr ("Only named layers can be used in intra-layer connectivity for netlist extraction"))));
+ register_layer (l, make_new_name ());
}
// we need to keep a reference, so we can safely delete the region
@@ -204,10 +221,10 @@ void LayoutToNetlist::connect (const db::Region &a, const db::Region &b)
throw tl::Exception (tl::to_string (tr ("The netlist has already been extracted")));
}
if (! is_persisted (a)) {
- throw (tl::Exception (tl::to_string (tr ("Only named layers can be used in inter-layer connectivity (first layer) for netlist extraction"))));
+ register_layer (a, make_new_name ());
}
if (! is_persisted (b)) {
- throw (tl::Exception (tl::to_string (tr ("Only named layers can be used in inter-layer connectivity (second layer) for netlist extraction"))));
+ register_layer (b, make_new_name ());
}
// we need to keep a reference, so we can safely delete the region
@@ -225,7 +242,7 @@ size_t LayoutToNetlist::connect_global (const db::Region &l, const std::string &
throw tl::Exception (tl::to_string (tr ("The netlist has already been extracted")));
}
if (! is_persisted (l)) {
- throw (tl::Exception (tl::to_string (tr ("Only named layers can be used in global connectivity for netlist extraction"))));
+ register_layer (l, make_new_name ());
}
// we need to keep a reference, so we can safely delete the region
@@ -320,11 +337,7 @@ void LayoutToNetlist::register_layer (const db::Region ®ion, const std::strin
db::DeepRegion *delegate = dynamic_cast (region.delegate());
if (! delegate) {
- if (region.empty ()) {
- dl = dss ().empty_layer (m_layout_index);
- } else {
- dl = dss ().create_from_flat (region, true);
- }
+ dl = dss ().create_from_flat (region, true);
} else {
@@ -343,6 +356,29 @@ void LayoutToNetlist::register_layer (const db::Region ®ion, const std::strin
m_name_of_layer [dl.layer ()] = n;
}
+std::string LayoutToNetlist::make_new_name (const std::string &stem)
+{
+ int m = std::numeric_limits::max () / 2 + 1;
+ int n = m;
+
+ std::string name;
+ while (m > 0) {
+
+ m /= 2;
+
+ name = stem;
+ name += std::string ("$");
+ name += tl::to_string (n - m);
+
+ if (m_named_regions.find (name) == m_named_regions.end ()) {
+ n -= m;
+ }
+
+ }
+
+ return name;
+}
+
std::string LayoutToNetlist::name (const db::Region ®ion) const
{
std::map::const_iterator n = m_name_of_layer.find (layer_of (region));
@@ -396,9 +432,6 @@ db::DeepLayer LayoutToNetlist::deep_layer_of (const db::Region ®ion) const
std::pair lff = dss ().layer_for_flat (region);
if (lff.first) {
return lff.second;
- } else if (region.empty ()) {
- // provide a substitute empty layer for empty
- return dss ().empty_layer (m_layout_index);
} else {
throw (tl::Exception (tl::to_string (tr ("Non-hierarchical layers cannot be used in netlist extraction"))));
}
@@ -413,7 +446,7 @@ unsigned int LayoutToNetlist::layer_of (const db::Region ®ion) const
return deep_layer_of (region).layer ();
}
-db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell &cell, bool with_device_cells)
+db::CellMapping LayoutToNetlist::make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector *nets, bool with_device_cells)
{
std::set device_cells;
if (! with_device_cells && mp_netlist.get ()) {
@@ -422,7 +455,31 @@ db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell
}
}
- return dss ().cell_mapping_to_original (m_layout_index, &layout, cell.cell_index (), &device_cells);
+ std::set net_cells;
+ if (nets) {
+ // Compute the "included cell" list for cell_mapping_to_original: these are all cells which
+ // are required to represent the net hierarchically.
+ for (std::vector::const_iterator n = nets->begin (); n != nets->end (); ++n) {
+ const db::Net *net = *n;
+ db::cell_index_type net_cell = net->circuit ()->cell_index ();
+ if (net_cells.find (net_cell) == net_cells.end ()) {
+ net_cells.insert (net_cell);
+ internal_layout()->cell (net_cell).collect_caller_cells (net_cells);
+ }
+ }
+ }
+
+ return dss ().cell_mapping_to_original (m_layout_index, &layout, cell.cell_index (), &device_cells, nets ? &net_cells : 0);
+}
+
+db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector &nets, bool with_device_cells)
+{
+ return make_cell_mapping_into (layout, cell, &nets, with_device_cells);
+}
+
+db::CellMapping LayoutToNetlist::cell_mapping_into (db::Layout &layout, db::Cell &cell, bool with_device_cells)
+{
+ return make_cell_mapping_into (layout, cell, 0, with_device_cells);
}
db::CellMapping LayoutToNetlist::const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell)
@@ -436,6 +493,36 @@ db::CellMapping LayoutToNetlist::const_cell_mapping_into (const db::Layout &layo
return cm;
}
+std::map
+LayoutToNetlist::create_layermap (db::Layout &target_layout, int ln) const
+{
+ std::map lm;
+ if (! internal_layout ()) {
+ return lm;
+ }
+
+ const db::Layout &source_layout = *internal_layout ();
+
+ std::set layers_to_copy;
+ const db::Connectivity &conn = connectivity ();
+ for (db::Connectivity::layer_iterator layer = conn.begin_layers (); layer != conn.end_layers (); ++layer) {
+ layers_to_copy.insert (*layer);
+ }
+
+ for (std::set::const_iterator l = layers_to_copy.begin (); l != layers_to_copy.end (); ++l) {
+ const db::LayerProperties &lp = source_layout.get_properties (*l);
+ unsigned int tl;
+ if (! lp.is_null ()) {
+ tl = target_layout.insert_layer (lp);
+ } else {
+ tl = target_layout.insert_layer (db::LayerProperties (ln++, 0, name (*l)));
+ }
+ lm.insert (std::make_pair (tl, const_cast (this)->layer_by_index (*l)));
+ }
+
+ return lm;
+}
+
db::Netlist *LayoutToNetlist::netlist () const
{
return mp_netlist.get ();
@@ -455,13 +542,13 @@ namespace
}
template
-static bool deliver_shape (const db::PolygonRef &, StopOnFirst, const Tr &)
+static bool deliver_shape (const db::PolygonRef &, StopOnFirst, const Tr &, db::properties_id_type)
{
return false;
}
template
-static bool deliver_shape (const db::PolygonRef &pr, db::Region ®ion, const Tr &tr)
+static bool deliver_shape (const db::PolygonRef &pr, db::Region ®ion, const Tr &tr, db::properties_id_type /*propid*/)
{
if (pr.obj ().is_box ()) {
region.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr));
@@ -472,76 +559,102 @@ static bool deliver_shape (const db::PolygonRef &pr, db::Region ®ion, const T
}
template
-static bool deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const Tr &tr)
+static bool deliver_shape (const db::PolygonRef &pr, db::Shapes &shapes, const Tr &tr, db::properties_id_type propid)
{
if (pr.obj ().is_box ()) {
- shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr));
+ if (propid) {
+ shapes.insert (db::BoxWithProperties (pr.obj ().box ().transformed (pr.trans ()).transformed (tr), propid));
+ } else {
+ shapes.insert (pr.obj ().box ().transformed (pr.trans ()).transformed (tr));
+ }
} else {
db::Layout *layout = shapes.layout ();
if (layout) {
- shapes.insert (db::PolygonRef (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ()));
+ db::PolygonRef polygon_ref (pr.obj ().transformed (pr.trans ()).transformed (tr), layout->shape_repository ());
+ if (propid) {
+ shapes.insert (db::PolygonRefWithProperties (polygon_ref, propid));
+ } else {
+ shapes.insert (polygon_ref);
+ }
} else {
- shapes.insert (pr.obj ().transformed (pr.trans ()).transformed (tr));
+ db::Polygon polygon (pr.obj ().transformed (pr.trans ()).transformed (tr));
+ if (propid) {
+ shapes.insert (db::PolygonWithProperties (polygon, propid));
+ } else {
+ shapes.insert (polygon);
+ }
}
}
return true;
}
-template
-static bool deliver_shapes_of_net_recursive (const db::Netlist * /*nl*/, const db::hier_clusters &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, const db::ICplxTrans &tr, To &to)
+template
+static bool deliver_shapes_of_net_recursive (const db::Netlist * /*nl*/, const db::hier_clusters &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, const db::ICplxTrans &tr, To &to, db::properties_id_type propid)
{
// deliver the net shapes
- for (db::recursive_cluster_shape_iterator rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) {
- if (! deliver_shape (*rci, to, tr * rci.trans ())) {
+ for (db::recursive_cluster_shape_iterator rci (clusters, layer_id, ci, cid); !rci.at_end (); ++rci) {
+ if (! deliver_shape (*rci, to, tr * rci.trans (), propid)) {
return false;
}
}
return true;
}
-template
-static bool deliver_shapes_of_net_nonrecursive (const db::Netlist *nl, const db::hier_clusters &clusters, db::cell_index_type ci, size_t cid, unsigned int layer_id, const db::ICplxTrans &tr, To &to)
+template
+static bool deliver_shapes_of_net (bool recursive, const db::Netlist *nl, const db::hier_clusters &clusters, db::cell_index_type ci, size_t cid, const std::map &lmap, const db::ICplxTrans &tr, db::properties_id_type propid)
{
- // NOTE: this scheme will deliver the shapes from the cell, including (!)
- // subcells that are purged
+ // shortcut
+ if (lmap.empty ()) {
+ return true;
+ }
- db::cell_index_type prev_ci = ci;
+ const db::connected_clusters &cc = clusters.clusters_per_cell (ci);
+ const db::local_cluster &lc = cc.cluster_by_id (cid);
- // deliver the net shapes
- for (db::recursive_cluster_shape_iterator rci (clusters, layer_id, ci, cid); !rci.at_end (); ) {
-
- db::cell_index_type cci = rci.cell_index ();
- if (cci != prev_ci && cci != ci && (! nl || nl->circuit_by_cell_index (cci) || nl->device_abstract_by_cell_index (cci))) {
-
- rci.skip_cell ();
-
- } else {
-
- if (! deliver_shape (*rci, to, tr * rci.trans ())) {
+ for (typename std::map::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
+ for (typename db::local_cluster::shape_iterator s = lc.begin (l->first); ! s.at_end (); ++s) {
+ if (! deliver_shape (*s, *l->second, tr, propid)) {
return false;
}
- prev_ci = cci;
-
- ++rci;
-
}
+ }
+
+ const typename db::connected_clusters::connections_type &conn = cc.connections_for_cluster (cid);
+ for (typename db::connected_clusters::connections_type::const_iterator c = conn.begin (); c != conn.end (); ) {
+
+ db::cell_index_type cci = c->inst_cell_index ();
+ if (! recursive && (! nl || nl->circuit_by_cell_index (cci) || nl->device_abstract_by_cell_index (cci))) {
+ // skip this cell in non-recursive mode (and all following instances of the same cell too)
+ typename db::connected_clusters::connections_type::const_iterator cc = c;
+ while (++cc != conn.end ()) {
+ if (cc->inst_cell_index () != cci) {
+ break;
+ }
+ }
+ c = cc;
+ continue;
+ }
+
+ if (! deliver_shapes_of_net (recursive, nl, clusters, cci, c->id (), lmap, tr * c->inst_trans (), propid)) {
+ return false;
+ }
+ ++c;
}
return true;
}
-void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to) const
+void LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, db::properties_id_type propid) const
{
unsigned int lid = layer_of (of_layer);
const db::Circuit *circuit = net.circuit ();
tl_assert (circuit != 0);
- if (! recursive) {
- deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), to);
- } else {
- deliver_shapes_of_net_recursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), to);
- }
+ std::map lmap;
+ lmap [lid] = &to;
+
+ deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), propid);
}
db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive) const
@@ -551,27 +664,25 @@ db::Region *LayoutToNetlist::shapes_of_net (const db::Net &net, const db::Region
tl_assert (circuit != 0);
std::auto_ptr res (new db::Region ());
+ std::map lmap;
+ lmap [lid] = res.get ();
- if (! recursive) {
- deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), *res);
- } else {
- deliver_shapes_of_net_recursive (mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lid, db::ICplxTrans (), *res);
- }
+ deliver_shapes_of_net (recursive, mp_netlist.get (), m_net_clusters, circuit->cell_index (), net.cluster_id (), lmap, db::ICplxTrans (), 0);
return res.release ();
}
void
-LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map, db::cell_index_type> &cmap, const db::ICplxTrans &tr) const
+LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const db::ICplxTrans &tr) const
{
const db::Circuit *circuit = net.circuit ();
tl_assert (circuit != 0);
- build_net_rec (circuit->cell_index (), net.cluster_id (), target, target_cell, lmap, &net, net_cell_name_prefix, cell_name_prefix, device_cell_name_prefix, cmap, tr);
+ build_net_rec (circuit->cell_index (), net.cluster_id (), target, target_cell, lmap, &net, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, tr);
}
void
-LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &tc, const std::map &lmap, const db::Net *net, const char *net_cell_name_prefix, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix, std::map, db::cell_index_type> &cmap, const db::ICplxTrans &tr) const
+LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &tc, const std::map &lmap, const db::Net *net, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const db::ICplxTrans &tr) const
{
db::Cell *target_cell = &tc;
@@ -582,14 +693,15 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
bool any_connections = circuit_cell_name_prefix && ! ccl.connections_for_cluster (cid).empty ();
if (! any_connections) {
- bool consider_cell = any_connections;
- for (std::map::const_iterator l = lmap.begin (); l != lmap.end () && !consider_cell; ++l) {
+ StopOnFirst sof;
+ std::map sof_lmap;
+ for (std::map::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) {
- StopOnFirst sof;
- consider_cell = !deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, sof);
+ sof_lmap.insert (std::make_pair (layer_of (*l->second), &sof));
}
}
+ bool consider_cell = ! deliver_shapes_of_net (hier_mode == BNH_Flatten, mp_netlist.get (), m_net_clusters, ci, cid, sof_lmap, tr, 0);
if (! consider_cell) {
// shortcut if cell is empty -> no net cell will be produced
return;
@@ -604,13 +716,16 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
}
+ std::map target_lmap;
for (std::map::const_iterator l = lmap.begin (); l != lmap.end (); ++l) {
if (l->second) {
- deliver_shapes_of_net_nonrecursive (mp_netlist.get (), m_net_clusters, ci, cid, layer_of (*l->second), tr, target_cell->shapes (l->first));
+ target_lmap.insert (std::make_pair (layer_of (*l->second), &target_cell->shapes (l->first)));
}
}
- if (! circuit_cell_name_prefix && ! device_cell_name_prefix) {
+ deliver_shapes_of_net (hier_mode == BNH_Flatten, mp_netlist.get (), m_net_clusters, ci, cid, target_lmap, tr, netname_propid);
+
+ if (hier_mode != BNH_SubcircuitCells && ! device_cell_name_prefix) {
return;
}
@@ -627,8 +742,10 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
db::cell_index_type subci = c->inst_cell_index ();
size_t subcid = c->id ();
- std::map, db::cell_index_type>::const_iterator cm = cmap.find (std::make_pair (subci, subcid));
- if (cm == cmap.end ()) {
+ CellReuseTableKey cmap_key (subci, netname_propid, subcid);
+
+ cell_reuse_table_type::const_iterator cm = reuse_table.find (cmap_key);
+ if (cm == reuse_table.end ()) {
const char *name_prefix = 0;
if (mp_netlist->device_abstract_by_cell_index (subci)) {
@@ -642,12 +759,12 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
std::string cell_name = internal_layout ()->cell_name (subci);
db::cell_index_type target_ci = target.add_cell ((std::string (name_prefix) + cell_name).c_str ());
- cm = cmap.insert (std::make_pair (std::make_pair (subci, subcid), target_ci)).first;
+ cm = reuse_table.insert (std::make_pair (cmap_key, target_ci)).first;
- build_net_rec (subci, subcid, target, target.cell (target_ci), lmap, 0, 0, circuit_cell_name_prefix, device_cell_name_prefix, cmap, tr_mag);
+ build_net_rec (subci, subcid, target, target.cell (target_ci), lmap, 0, 0, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, reuse_table, tr_mag);
} else {
- cm = cmap.insert (std::make_pair (std::make_pair (subci, subcid), std::numeric_limits::max ())).first;
+ cm = reuse_table.insert (std::make_pair (cmap_key, std::numeric_limits::max ())).first;
}
}
@@ -661,57 +778,113 @@ LayoutToNetlist::build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &
}
}
-void
-LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix) const
+db::properties_id_type
+LayoutToNetlist::make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const
{
- if (! m_netlist_extracted) {
- throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
+ if (! netname_prop.is_nil ()) {
+
+ db::property_names_id_type name_propnameid = ly.properties_repository ().prop_name_id (netname_prop);
+ db::PropertiesRepository::properties_set propset;
+ propset.insert (std::make_pair (name_propnameid, tl::Variant (net.expanded_name ())));
+
+ return ly.properties_repository ().properties_id (propset);
+
+ } else {
+ return 0;
}
-
- std::map, db::cell_index_type> cell_map;
-
- double mag = internal_layout ()->dbu () / target.dbu ();
- build_net_rec (net, target, target_cell, lmap, 0, cell_name_prefix, device_cell_name_prefix, cell_map, db::ICplxTrans (mag));
}
void
-LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const char *net_cell_name_prefix, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
+LayoutToNetlist::build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const
{
if (! m_netlist_extracted) {
throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
}
- std::map, db::cell_index_type> cell_map;
+ cell_reuse_table_type cell_reuse_table;
+
double mag = internal_layout ()->dbu () / target.dbu ();
+ db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, net);
+ build_net_rec (net, target, target_cell, lmap, 0, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, cell_reuse_table, db::ICplxTrans (mag));
+}
+
+void
+LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
+{
+ build_nets (0, cmap, target, lmap, net_cell_name_prefix, netname_prop, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix);
+}
+
+void
+LayoutToNetlist::build_net_rec (const db::Net &net, db::Layout &target, db::cell_index_type circuit_cell, const db::CellMapping &cmap, const std::map &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const
+{
+ if (! cmap.has_mapping (circuit_cell)) {
+
+ const db::Cell &cc = internal_layout ()->cell (circuit_cell);
+
+ for (db::Cell::parent_inst_iterator p = cc.begin_parent_insts (); ! p.at_end (); ++p) {
+
+ db::CellInstArray ci = p->child_inst ().cell_inst ();
+ for (db::CellInstArray::iterator ia = ci.begin (); ! ia.at_end(); ++ia) {
+
+ db::ICplxTrans tr_parent = ci.complex_trans (*ia) * tr;
+ build_net_rec (net, target, p->parent_cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, tr_parent);
+
+ }
+
+ }
+
+ } else {
+
+ double mag = internal_layout ()->dbu () / target.dbu ();
+
+ db::cell_index_type target_ci = cmap.cell_mapping (circuit_cell);
+ build_net_rec (net, target, target.cell (target_ci), lmap, net_cell_name_prefix, netname_propid, hier_mode, cell_name_prefix, device_cell_name_prefix, reuse_table, db::ICplxTrans (mag) * tr);
+
+ }
+}
+
+void
+LayoutToNetlist::build_nets (const std::vector *nets, const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const
+{
+ if (! m_netlist_extracted) {
+ throw tl::Exception (tl::to_string (tr ("The netlist has not been extracted yet")));
+ }
+
+ std::set net_set;
+ if (nets) {
+ net_set.insert (nets->begin (), nets->end ());
+ }
+
+ cell_reuse_table_type cell_reuse_table;
+
const db::Netlist *netlist = mp_netlist.get ();
for (db::Netlist::const_circuit_iterator c = netlist->begin_circuits (); c != netlist->end_circuits (); ++c) {
- if (! cmap.has_mapping (c->cell_index ())) {
- continue;
- }
-
bool is_top_circuit = c->begin_parents () == c->end_parents ();
- db::cell_index_type target_ci = cmap.cell_mapping (c->cell_index ());
-
for (db::Circuit::const_net_iterator n = c->begin_nets (); n != c->end_nets (); ++n) {
- // exlude local nets in recursive mode
- if (circuit_cell_name_prefix && ! is_top_circuit && n->pin_count () > 0) {
+ // exlude local nets in recursive mode except if they are explicitly selected
+ if (! nets && hier_mode != BNH_Disconnected && ! is_top_circuit && n->pin_count () > 0) {
continue;
}
- build_net_rec (*n, target, target.cell (target_ci), lmap, net_cell_name_prefix, circuit_cell_name_prefix, device_cell_name_prefix, cell_map, db::ICplxTrans (mag));
+ if (! nets || net_set.find (n.operator-> ()) != net_set.end ()) {
+ db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, *n);
+ build_net_rec (*n, target, c->cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, db::ICplxTrans ());
+ }
}
- if (circuit_cell_name_prefix) {
+ if (hier_mode != BNH_Disconnected && ! nets) {
- // with recursive nets we skip nets in subcircuits which are connected upwards. This means, nets will
+ // With recursive nets we skip nets in subcircuits which are connected upwards. This means, nets will
// get lost if there is no connection to this pin from the outside. Hence we need to deliver nets from
// subcircuits as part of the circuit which calls the subcircuit - but NOT in a subcircuit cell, because
// this will just apply to nets from certain instances. But the net cell name will be formed as "subcircuit:net"
+ //
+ // In explicit selection mode we don't care about this as nets are explicitly taken or not.
const db::Circuit &circuit = *c;
for (db::Circuit::const_subcircuit_iterator sc = circuit.begin_subcircuits (); sc != circuit.end_subcircuits (); ++sc) {
@@ -725,13 +898,15 @@ LayoutToNetlist::build_all_nets (const db::CellMapping &cmap, db::Layout &target
if (n) {
double dbu = target.dbu ();
- db::ICplxTrans tr = db::ICplxTrans (mag) * (db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu));
+ db::ICplxTrans tr = db::CplxTrans (dbu).inverted () * subcircuit.trans () * db::CplxTrans (dbu);
+
+ db::properties_id_type netname_propid = make_netname_propid (target, netname_prop, *n);
if (net_cell_name_prefix) {
std::string ncn = std::string (net_cell_name_prefix) + subcircuit.expanded_name () + ":";
- build_net_rec (*n, target, target.cell (target_ci), lmap, ncn.c_str (), circuit_cell_name_prefix, device_cell_name_prefix, cell_map, tr);
+ build_net_rec (*n, target, c->cell_index (), cmap, lmap, ncn.c_str (), netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, tr);
} else {
- build_net_rec (*n, target, target.cell (target_ci), lmap, net_cell_name_prefix, circuit_cell_name_prefix, device_cell_name_prefix, cell_map, tr);
+ build_net_rec (*n, target, c->cell_index (), cmap, lmap, net_cell_name_prefix, netname_propid, hier_mode, circuit_cell_name_prefix, device_cell_name_prefix, cell_reuse_table, tr);
}
}
@@ -893,8 +1068,8 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, const db::Reg
db::Region rgate, rmetal;
- deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (gate), db::ICplxTrans (), rgate);
- deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (metal), db::ICplxTrans (), rmetal);
+ deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (gate), db::ICplxTrans (), rgate, 0);
+ deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (metal), db::ICplxTrans (), rmetal, 0);
double agate = rgate.area () * dbu * dbu;
double ametal = rmetal.area () * dbu * dbu;
@@ -905,7 +1080,7 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, const db::Reg
for (std::vector >::const_iterator d = diodes.begin (); d != diodes.end () && ! skip; ++d) {
db::Region rdiode;
- deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (*d->first), db::ICplxTrans (), rdiode);
+ deliver_shapes_of_net_recursive (0, m_net_clusters, *cid, *c, layer_of (*d->first), db::ICplxTrans (), rdiode, 0);
if (fabs (d->second) < db::epsilon) {
if (rdiode.area () > 0) {
@@ -939,4 +1114,46 @@ db::Region LayoutToNetlist::antenna_check (const db::Region &gate, const db::Reg
return db::Region (new db::DeepRegion (dl));
}
+
+void db::LayoutToNetlist::save (const std::string &path, bool short_format)
+{
+ tl::OutputStream stream (path);
+ db::LayoutToNetlistStandardWriter writer (stream, short_format);
+ set_filename (path);
+ writer.write (this);
+}
+
+void db::LayoutToNetlist::load (const std::string &path)
+{
+ tl::InputStream stream (path);
+ db::LayoutToNetlistStandardReader reader (stream);
+ set_filename (path);
+ set_name (stream.filename ());
+ reader.read (this);
+}
+
+db::LayoutToNetlist *db::LayoutToNetlist::create_from_file (const std::string &path)
+{
+ std::auto_ptr db;
+
+ // TODO: generic concept to detect format
+ std::string first_line;
+ {
+ tl::InputStream stream (path);
+ tl::TextInputStream text_stream (stream);
+ first_line = text_stream.get_line ();
+ }
+
+ if (first_line.find (db::lvs_std_format::keys::lvs_magic_string) == 0) {
+ db::LayoutVsSchematic *lvs_db = new db::LayoutVsSchematic ();
+ db.reset (lvs_db);
+ lvs_db->load (path);
+ } else {
+ db.reset (new db::LayoutToNetlist ());
+ db->load (path);
+ }
+
+ return db.release ();
+}
+
}
diff --git a/src/db/db/dbLayoutToNetlist.h b/src/db/db/dbLayoutToNetlist.h
index 5003deb03..cb5485a8b 100644
--- a/src/db/db/dbLayoutToNetlist.h
+++ b/src/db/db/dbLayoutToNetlist.h
@@ -20,8 +20,8 @@
*/
-#ifndef _HDR_dbLayout2Netlist
-#define _HDR_dbLayout2Netlist
+#ifndef _HDR_dbLayoutToNetlist
+#define _HDR_dbLayoutToNetlist
#include "dbCommon.h"
#include "dbCellMapping.h"
@@ -114,6 +114,78 @@ public:
*/
~LayoutToNetlist ();
+ /**
+ * @brief Makes the extractor take over ownership over the DSS when it was created with an external DSS
+ */
+ void keep_dss ();
+
+ /**
+ * @brief Gets the database description
+ */
+ const std::string &description () const
+ {
+ return m_description;
+ }
+
+ /**
+ * @brief Sets the database description
+ */
+ void set_description (const std::string &description)
+ {
+ m_description = description;
+ }
+
+ /**
+ * @brief Gets the original file
+ *
+ * The original file describes what original file the netlist database
+ * was derived from.
+ */
+ const std::string &original_file () const
+ {
+ return m_original_file;
+ }
+
+ /**
+ * @brief Sets the database original file
+ */
+ void set_original_file (const std::string &original_file)
+ {
+ m_original_file = original_file;
+ }
+
+ /**
+ * @brief Gets the database name
+ */
+ const std::string &name () const
+ {
+ return m_name;
+ }
+
+ /**
+ * @brief Sets the database name
+ */
+ void set_name (const std::string &name)
+ {
+ m_name = name;
+ }
+
+ /**
+ * @brief Gets the file name
+ */
+ const std::string &filename () const
+ {
+ return m_filename;
+ }
+
+ /**
+ * @brief Sets the file name
+ */
+ void set_filename (const std::string &filename)
+ {
+ m_filename = filename;
+ }
+
/**
* @brief Sets the number of threads to use for operations which support multiple threads
*/
@@ -154,8 +226,7 @@ public:
* (see below) enhances readability of backannotated information
* if layers are involved. Use this method to attach a name to a region
* derived by boolean operations for example.
- * Named regions are persisted inside the LayoutToNetlist object. Only
- * named regions can be put into "connect".
+ * Named regions are persisted inside the LayoutToNetlist object.
*/
void register_layer (const db::Region ®ion, const std::string &name);
@@ -264,21 +335,18 @@ public:
* a derived layer. Certain limitations apply. It's safe to use
* boolean operations for deriving layers. Other operations are applicable as long as they are
* capable of delivering hierarchical layers.
- * Regions put into "connect" need to be named.
*/
void connect (const db::Region &l);
/**
* @brief Defines an inter-layer connection for the given layers.
* The conditions mentioned with intra-layer "connect" apply for this method too.
- * Regions put into "connect" need to be named.
*/
void connect (const db::Region &a, const db::Region &b);
/**
* @brief Connects the given layer with a global net with the given name
* Returns the global net ID
- * Regions put into "connect" need to be named.
*/
size_t connect_global (const db::Region &l, const std::string &gn);
@@ -372,13 +440,31 @@ public:
*/
db::CellMapping cell_mapping_into (db::Layout &layout, db::Cell &cell, bool with_device_cells = false);
+ /**
+ * @brief Creates a cell mapping for copying shapes from the internal layout to the given target layout for a given list of nets
+ * This version will only create cells which are required to represent the given nets.
+ * If 'with_device_cells' is true, cells will be produced for devices. These are cells not corresponding to circuits, so they are disabled normally.
+ * Use this option, if you want to access device terminal shapes per device.
+ * CAUTION: This function may create new cells in "layout".
+ */
+ db::CellMapping cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector &nets, bool with_device_cells = false);
+
/**
* @brief Creates a cell mapping for copying shapes from the internal layout to the given target layout.
* This version will not create new cells in the target layout.
- * If the required cells do not exist there yet, flatting will happen.
+ * If the required cells do not exist there yet, flattening will happen.
*/
db::CellMapping const_cell_mapping_into (const db::Layout &layout, const db::Cell &cell);
+ /**
+ * @brief Creates a layer mapping for build_nets etc.
+ * This method will create new layers inside the target layout corresponding to the
+ * original layers as kept inside the LayoutToNetlist database.
+ * It will return a layer mapping table suitable for use with build_all_nets, build_nets etc.
+ * Layers without original layer information will be given layer numbers ln, ln+1 etc.
+ */
+ std::map create_layermap (db::Layout &target_layout, int ln) const;
+
/**
* @brief gets the netlist extracted (0 if no extraction happened yet)
*/
@@ -428,32 +514,64 @@ public:
*
* This methods returns a new'd Region. It's the responsibility of the caller
* to delete this object.
+ *
+ * propid is an optional properties ID which is attached to the shapes if not 0.
*/
- void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to) const;
+ void shapes_of_net (const db::Net &net, const db::Region &of_layer, bool recursive, db::Shapes &to, properties_id_type propid = 0) const;
+
+ /**
+ * @brief An enum describing the way the net hierarchy is mapped
+ */
+ enum BuildNetHierarchyMode
+ {
+ /**
+ * @brief Flatten the net
+ * Collects all shapes of a net and puts that into the net cell or circuit cell
+ */
+ BNH_Flatten = 0,
+ /**
+ * @brief Build a net hierarchy adding cells for each subcircuit on the net
+ * Uses the circuit_cell_prefix to build the subcircuit cell names
+ */
+ BNH_SubcircuitCells = 1,
+ /**
+ * @brief No hierarchy
+ * Just output the shapes of the net belonging to the circuit cell.
+ * Connections are not indicated!
+ */
+ BNH_Disconnected = 2
+ };
/**
* @brief Builds a net representation in the given layout and cell
*
- * This method has two modes: recursive and top-level mode. In recursive mode,
- * it will create a proper hierarchy below the given target cell to hold all subcircuits the
- * net connects to. It will copy the net's parts from this subcircuits into these cells.
+ * This method puts the shapes of a net into the given target cell using a variety of options
+ * to represent the net name and the hierarchy of the net.
*
- * In top-level mode, only the shapes from the net inside it's circuit are copied to
- * the given target cell. No other cells are created.
+ * If the netname_prop name is not nil, a property with the given name is created and assigned
+ * the net name.
*
- * Recursive mode is picked when a cell name prefix is given. The new cells will be
- * named like cell_name_prefix + circuit name.
+ * Net hierarchy is covered in three ways:
+ * * No connection indicated (hier_mode == BNH_Disconnected: the net shapes are simply put into their
+ * respective circuits. The connections are not indicated.
+ * * Subnet hierarchy (hier_mode == BNH_SubcircuitCells): for each root net, a full hierarchy is built
+ * to accommodate the subnets (see build_net in recursive mode).
+ * * Flat (hier_mode == BNH_Flatten): each net is flattened and put into the circuit it
+ * belongs to.
*
* If a device cell name prefix is given, cells will be produced for each device abstract
- * using a name like device_cell_name_prefix + device name.
+ * using a name like device_cell_name_prefix + device name. Otherwise the device shapes are
+ * treated as part of the net.
*
* @param target The target layout
* @param target_cell The target cell
* @param lmap Target layer indexes (keys) and net regions (values)
+ * @param hier_mode See description of this method
+ * @param netname_prop An (optional) property name to which to attach the net name
* @param cell_name_prefix Chooses recursive mode if non-null
* @param device_cell_name_prefix See above
*/
- void build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *cell_name_prefix, const char *device_cell_name_prefix) const;
+ void build_net (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix) const;
/**
* @brief Builds a full hierarchical representation of the nets
@@ -462,28 +580,42 @@ public:
* object to determine the target cell (create them with "cell_mapping_into" or "const_cell_mapping_into").
* If no mapping is requested, the specific circuit it skipped.
*
- * The method has two net annotation modes:
- * * No annotation (net_cell_name_prefix == 0): the shapes will be put into the target cell simply
+ * The method has three net annotation modes:
+ * * No annotation (net_cell_name_prefix == 0 and netname_prop == nil): the shapes will be put
+ * into the target cell simply
+ * * Net name property (net_cell_name_prefix == 0 and netname_prop != nil): the shapes will be
+ * annotated with a property named with netname_prop and containing the net name string.
* * Individual subcells per net (net_cell_name_prefix != 0): for each net, a subcell is created
* and the net shapes will be put there (name of the subcell = net_cell_name_prefix + net name).
+ * (this mode can be combined with netname_prop too).
*
- * In addition, net hierarchy is covered in two ways:
- * * No connection indicated (circuit_cell_name_prefix == 0: the net shapes are simply put into their
+ * In addition, net hierarchy is covered in three ways:
+ * * No connection indicated (hier_mode == BNH_Disconnected: the net shapes are simply put into their
* respective circuits. The connections are not indicated.
- * * Subnet hierarchy (circuit_cell_name_prefix != 0): for each root net, a full hierarchy is built
+ * * Subnet hierarchy (hier_mode == BNH_SubcircuitCells): for each root net, a full hierarchy is built
* to accommodate the subnets (see build_net in recursive mode).
+ * * Flat (hier_mode == BNH_Flatten): each net is flattened and put into the circuit it
+ * belongs to.
*
* If a device cell name prefix is given, cells will be produced for each device abstract
- * using a name like device_cell_name_prefix + device name.
+ * using a name like device_cell_name_prefix + device name. Otherwise the device shapes are
+ * treated as part of the net.
*
* @param cmap The mapping of internal layout to target layout for the circuit mapping
* @param target The target layout
* @param lmap Target layer indexes (keys) and net regions (values)
+ * @param hier_mode See description of this method
+ * @param netname_prop An (optional) property name to which to attach the net name
* @param circuit_cell_name_prefix See method description
* @param net_cell_name_prefix See method description
* @param device_cell_name_prefix See above
*/
- void build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const char *net_cell_name_prefix, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
+ void build_all_nets (const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
+
+ /**
+ * @brief Like build_all_nets, but with the ability to select some nets
+ */
+ void build_nets (const std::vector *nets, const db::CellMapping &cmap, db::Layout &target, const std::map &lmap, const char *net_cell_name_prefix, const tl::Variant &netname_prop, BuildNetHierarchyMode hier_mode, const char *circuit_cell_name_prefix, const char *device_cell_name_prefix) const;
/**
* @brief Finds the net by probing a specific location on the given layer
@@ -531,11 +663,42 @@ public:
*/
db::Region antenna_check (const db::Region &gate, const db::Region &metal, double ratio, const std::vector > &diodes = std::vector > ());
+ /**
+ * @brief Saves the database to the given path
+ *
+ * Currently, the internal format will be used. If "short_format" is true, the short version
+ * of the format is used.
+ *
+ * This is a convenience method. The low-level functionality is the LayoutToNetlistWriter.
+ */
+ void save (const std::string &path, bool short_format);
+
+ /**
+ * @brief Loads the database from the given path
+ *
+ * This is a convenience method. The low-level functionality is the LayoutToNetlistReader.
+ */
+ void load (const std::string &path);
+
+ /**
+ * @brief Creates a LayoutToNetlist object from a file
+ *
+ * This method analyses the file and will create a LayoutToNetlist object
+ * or one of a derived class (specifically LayoutVsSchematic).
+ *
+ * The returned object is new'd one and must be deleted by the caller.
+ */
+ static db::LayoutToNetlist *create_from_file (const std::string &path);
+
private:
// no copying
LayoutToNetlist (const db::LayoutToNetlist &other);
LayoutToNetlist &operator= (const db::LayoutToNetlist &other);
+ std::string m_description;
+ std::string m_name;
+ std::string m_original_file;
+ std::string m_filename;
db::RecursiveShapeIterator m_iter;
std::auto_ptr mp_internal_dss;
tl::weak_ptr mp_dss;
@@ -550,12 +713,45 @@ private:
bool m_is_flat;
db::DeepLayer m_dummy_layer;
+ struct CellReuseTableKey
+ {
+ CellReuseTableKey (db::cell_index_type _cell_index, db::properties_id_type _netname_propid, size_t _cluster_id)
+ : cell_index (_cell_index), netname_propid (_netname_propid), cluster_id (_cluster_id)
+ {
+ // .. nothing yet ..
+ }
+
+ bool operator< (const CellReuseTableKey &other) const
+ {
+ if (cell_index != other.cell_index) {
+ return cell_index < other.cell_index;
+ }
+ if (netname_propid != other.netname_propid) {
+ return netname_propid < other.netname_propid;
+ }
+ if (cluster_id != other.cluster_id) {
+ return cluster_id < other.cluster_id;
+ }
+ return false;
+ }
+
+ db::cell_index_type cell_index;
+ db::properties_id_type netname_propid;
+ size_t cluster_id;
+ };
+
+ typedef std::map cell_reuse_table_type;
+
void init ();
size_t search_net (const db::ICplxTrans &trans, const db::Cell *cell, const db::local_cluster &test_cluster, std::vector &rev_inst_path);
- void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map, db::cell_index_type> &cmap, const ICplxTrans &tr) const;
- void build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const Net *net, const char *net_cell_name_prefix, const char *cell_name_prefix, const char *device_cell_name_prefix, std::map, db::cell_index_type> &cmap, const ICplxTrans &tr) const;
+ void build_net_rec (const db::Net &net, db::Layout &target, cell_index_type circuit_cell, const db::CellMapping &cmap, const std::map &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
+ void build_net_rec (const db::Net &net, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
+ void build_net_rec (db::cell_index_type ci, size_t cid, db::Layout &target, db::Cell &target_cell, const std::map &lmap, const Net *net, const char *net_cell_name_prefix, db::properties_id_type netname_propid, BuildNetHierarchyMode hier_mode, const char *cell_name_prefix, const char *device_cell_name_prefix, cell_reuse_table_type &reuse_table, const ICplxTrans &tr) const;
db::DeepLayer deep_layer_of (const db::Region ®ion) const;
void ensure_layout () const;
+ std::string make_new_name (const std::string &stem = std::string ());
+ db::properties_id_type make_netname_propid (db::Layout &ly, const tl::Variant &netname_prop, const db::Net &net) const;
+ db::CellMapping make_cell_mapping_into (db::Layout &layout, db::Cell &cell, const std::vector *nets, bool with_device_cells);
};
}
diff --git a/src/db/db/dbLayoutToNetlistFormatDefs.cc b/src/db/db/dbLayoutToNetlistFormatDefs.cc
index 3a00f45e0..eabcaa83a 100644
--- a/src/db/db/dbLayoutToNetlistFormatDefs.cc
+++ b/src/db/db/dbLayoutToNetlistFormatDefs.cc
@@ -27,49 +27,57 @@ namespace db
namespace l2n_std_format
{
- template<> DB_PUBLIC const std::string keys::version_key ("version");
- template<> DB_PUBLIC const std::string keys::description_key ("description");
- template<> DB_PUBLIC const std::string keys::top_key ("top");
- template<> DB_PUBLIC const std::string keys::unit_key ("unit");
- template<> DB_PUBLIC const std::string keys::layer_key ("layer");
- template<> DB_PUBLIC const std::string keys::connect_key ("connect");
- template<> DB_PUBLIC const std::string keys::global_key ("global");
- template<> DB_PUBLIC const std::string keys::circuit_key ("circuit");
- template<> DB_PUBLIC const std::string keys::net_key ("net");
- template<> DB_PUBLIC const std::string keys::name_key ("name");
- template<> DB_PUBLIC const std::string keys::device_key ("device");
- template<> DB_PUBLIC const std::string keys::polygon_key ("polygon");
- template<> DB_PUBLIC const std::string keys::rect_key ("rect");
- template<> DB_PUBLIC const std::string keys::terminal_key ("terminal");
- template<> DB_PUBLIC const std::string keys::abstract_key ("abstract");
- template<> DB_PUBLIC const std::string keys::param_key ("param");
- template<> DB_PUBLIC const std::string keys::location_key ("location");
- template<> DB_PUBLIC const std::string keys::rotation_key ("rotation");
- template<> DB_PUBLIC const std::string keys::mirror_key ("mirror");
- template<> DB_PUBLIC const std::string keys::scale_key ("scale");
- template<> DB_PUBLIC const std::string keys::pin_key ("pin");
+ const char *l2n_magic_string_cstr = "#%l2n-klayout";
- template<> DB_PUBLIC const std::string keys::version_key ("V");
- template<> DB_PUBLIC const std::string keys::description_key ("B");
- template<> DB_PUBLIC const std::string keys::top_key ("W");
- template<> DB_PUBLIC const std::string keys::unit_key ("U");
- template<> DB_PUBLIC const std::string keys::layer_key ("L");
- template<> DB_PUBLIC const std::string keys::connect_key ("C");
- template<> DB_PUBLIC const std::string keys::global_key ("G");
- template<> DB_PUBLIC const std::string keys::circuit_key ("X");
- template<> DB_PUBLIC const std::string keys::net_key ("N");
- template<> DB_PUBLIC const std::string keys::name_key ("I");
- template<> DB_PUBLIC const std::string keys::device_key ("D");
- template<> DB_PUBLIC const std::string keys::polygon_key ("Q");
- template<> DB_PUBLIC const std::string keys::rect_key ("R");
- template<> DB_PUBLIC const std::string keys::terminal_key ("T");
- template<> DB_PUBLIC const std::string keys::abstract_key ("A");
- template<> DB_PUBLIC const std::string keys::param_key ("E");
- template<> DB_PUBLIC const std::string keys::location_key ("Y");
- template<> DB_PUBLIC const std::string keys::rotation_key ("O");
- template<> DB_PUBLIC const std::string keys::mirror_key ("M");
- template<> DB_PUBLIC const std::string keys::scale_key ("S");
- template<> DB_PUBLIC const std::string keys::pin_key ("P");
+ DB_PUBLIC std::string LongKeys::l2n_magic_string (l2n_magic_string_cstr);
+ DB_PUBLIC std::string ShortKeys::l2n_magic_string (l2n_magic_string_cstr);
+
+ DB_PUBLIC std::string LongKeys::version_key ("version");
+ DB_PUBLIC std::string LongKeys::description_key ("description");
+ DB_PUBLIC std::string LongKeys::top_key ("top");
+ DB_PUBLIC std::string LongKeys::unit_key ("unit");
+ DB_PUBLIC std::string LongKeys::layer_key ("layer");
+ DB_PUBLIC std::string LongKeys::class_key ("class");
+ DB_PUBLIC std::string LongKeys::connect_key ("connect");
+ DB_PUBLIC std::string LongKeys::global_key ("global");
+ DB_PUBLIC std::string LongKeys::circuit_key ("circuit");
+ DB_PUBLIC std::string LongKeys::net_key ("net");
+ DB_PUBLIC std::string LongKeys::name_key ("name");
+ DB_PUBLIC std::string LongKeys::device_key ("device");
+ DB_PUBLIC std::string LongKeys::polygon_key ("polygon");
+ DB_PUBLIC std::string LongKeys::rect_key ("rect");
+ DB_PUBLIC std::string LongKeys::terminal_key ("terminal");
+ DB_PUBLIC std::string LongKeys::abstract_key ("abstract");
+ DB_PUBLIC std::string LongKeys::param_key ("param");
+ DB_PUBLIC std::string LongKeys::location_key ("location");
+ DB_PUBLIC std::string LongKeys::rotation_key ("rotation");
+ DB_PUBLIC std::string LongKeys::mirror_key ("mirror");
+ DB_PUBLIC std::string LongKeys::scale_key ("scale");
+ DB_PUBLIC std::string LongKeys::pin_key ("pin");
+
+ // A, B, C, D, E, G, I, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y
+ DB_PUBLIC std::string ShortKeys::version_key ("V");
+ DB_PUBLIC std::string ShortKeys::description_key ("B");
+ DB_PUBLIC std::string ShortKeys::top_key ("W");
+ DB_PUBLIC std::string ShortKeys::unit_key ("U");
+ DB_PUBLIC std::string ShortKeys::layer_key ("L");
+ DB_PUBLIC std::string ShortKeys::class_key ("K");
+ DB_PUBLIC std::string ShortKeys::connect_key ("C");
+ DB_PUBLIC std::string ShortKeys::global_key ("G");
+ DB_PUBLIC std::string ShortKeys::circuit_key ("X");
+ DB_PUBLIC std::string ShortKeys::net_key ("N");
+ DB_PUBLIC std::string ShortKeys::name_key ("I");
+ DB_PUBLIC std::string ShortKeys::device_key ("D");
+ DB_PUBLIC std::string ShortKeys::polygon_key ("Q");
+ DB_PUBLIC std::string ShortKeys::rect_key ("R");
+ DB_PUBLIC std::string ShortKeys::terminal_key ("T");
+ DB_PUBLIC std::string ShortKeys::abstract_key ("A");
+ DB_PUBLIC std::string ShortKeys::param_key ("E");
+ DB_PUBLIC std::string ShortKeys::location_key ("Y");
+ DB_PUBLIC std::string ShortKeys::rotation_key ("O");
+ DB_PUBLIC std::string ShortKeys::mirror_key ("M");
+ DB_PUBLIC std::string ShortKeys::scale_key ("S");
+ DB_PUBLIC std::string ShortKeys::pin_key ("P");
}
}
diff --git a/src/db/db/dbLayoutToNetlistFormatDefs.h b/src/db/db/dbLayoutToNetlistFormatDefs.h
index 8bb38dbec..8d70abcbc 100644
--- a/src/db/db/dbLayoutToNetlistFormatDefs.h
+++ b/src/db/db/dbLayoutToNetlistFormatDefs.h
@@ -52,35 +52,69 @@ namespace db
* description() - an arbitrary description text [short key: B]
* unit() - specifies the database unit [short key: U]
* top() - specifies the name of the top circuit [short key: W]
- * layer() - define a layer [short key: L]
+ * layer( ?) - define a layer [short key: L]
* connect( ...) - connects layer1 with the following layers [short key: C]
* global( ...)
* - connects the shapes of the layer with the given global
* nets [short key: G]
* circuit( [circuit-def]) - circuit (cell) [short key: X]
+ * class(