Provide new 'align' feature in LVS for automatic circuit flattening.

This commit is contained in:
Matthias Koefferlein 2019-07-23 01:12:12 +02:00
parent aff8212f2f
commit 5dabd6093d
11 changed files with 203 additions and 68 deletions

View File

@ -2,9 +2,10 @@
$script_call = $0 + " " + ARGV.join(" ")
$indir="src/drc/drc/built-in-macros"
$indirs = [ "src/drc/drc/built-in-macros", "src/lvs/lvs/built-in-macros" ]
$loc = "about"
$outfiles="src/lay/lay/doc"
$outfiles = "src/lay/lay/doc"
def create_ref(mod, s)
if s =~ /(.*)::(.*)#(.*)/
@ -262,53 +263,57 @@ collectors = {
"LVS" => Collector::new("lvs", "LVS Reference")
}
Dir.entries($indir).each do |p|
$indirs.each do |indir|
if p !~ /\.rb$/
next
end
Dir.entries(indir).each do |p|
infile = File.join($indir, p)
puts "Extracting doc from #{infile} .."
if p !~ /\.rb$/
next
end
File.open(infile, "r") do |file|
infile = File.join(indir, p)
puts "Extracting doc from #{infile} .."
block = []
collector = nil
line = 0
File.open(infile, "r") do |file|
file.each_line do |l|
block = []
collector = nil
line = 0
line += 1
file.each_line do |l|
begin
line += 1
l = unescape(l)
begin
if ! collector
collectors.each do |k,c|
if l =~ /^\s*#\s*%#{k}%/
collector = c
l = nil
block = []
break
l = unescape(l)
if ! collector
collectors.each do |k,c|
if l =~ /^\s*#\s*%#{k}%/
collector = c
l = nil
block = []
break
end
end
end
end
if l
if l =~ /^\s*#\s*(.*)\s*$/
collector && block.push($1)
elsif l =~ /^\s*$/
collector && collector.add_block(block)
collector = nil
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
puts ex.backtrace # @@@
exit 1
end
end

View File

@ -29,7 +29,7 @@ See <a href="/about/drc_ref_netter.xml#antenna_check">Netter#antenna_check</a> f
<li><tt>bjt3(name)</tt></li>
</ul>
<p>
Use this class with <a href="#device_extract">device_extract</a> to specify extraction of a
Use this class with <a href="#extract_devices">extract_devices</a> to specify extraction of a
bipolar junction transistor
</p>
<h2>"bjt4" - Supplies the BJT4 transistor extractor class</h2>
@ -39,7 +39,7 @@ bipolar junction transistor
<li><tt>bjt4(name)</tt></li>
</ul>
<p>
Use this class with <a href="#device_extract">device_extract</a> to specify extraction of a
Use this class with <a href="#extract_devices">extract_devices</a> to specify extraction of a
bipolar junction transistor with a substrate terminal
</p>
<h2>"box" - Creates a box object</h2>
@ -59,17 +59,17 @@ This function creates a box object. The arguments are the same than for the
<li><tt>capacitor(name, area_cap)</tt></li>
</ul>
<p>
Use this class with <a href="#device_extract">device_extract</a> to specify extraction of a capacitor.
Use this class with <a href="#extract_devices">extract_devices</a> to specify extraction of a capacitor.
The area_cap argument is the capacitance in Farad per square micrometer.
</p>
<h2>"capacitor_with_bulk" - Supplies the capacitor extractor class that includes a bulk terminal</h2>
<keyword name="capacitor_with_bulk"/>
<a name="capacitor_with_bulk"/><p>Usage:</p>
<ul>
<li><tt>capacitor_with_bulk(name)</tt></li>
<li><tt>capacitor_with_bulk(name, area_cap)</tt></li>
</ul>
<p>
Use this class with <a href="#device_extract">device_extract</a> to specify extraction of a capacitor
Use this class with <a href="#extract_devices">extract_devices</a> to specify extraction of a capacitor
with a bulk terminal.
The area_cap argument is the capacitance in Farad per square micrometer.
</p>
@ -192,7 +192,7 @@ Deep mode can be cancelled with <a href="#tiles">tiles</a> or <a href="#flat">fl
<li><tt>diode(name)</tt></li>
</ul>
<p>
Use this class with <a href="#device_extract">device_extract</a> to specify extraction of a
Use this class with <a href="#extract_devices">extract_devices</a> to specify extraction of a
planar diode
</p>
<h2>"edge" - Creates an edge object</h2>
@ -396,7 +396,7 @@ filled with <a href="/about/drc_ref_layer.xml#insert">Layer#insert</a>.
<li><tt>mos3(name)</tt></li>
</ul>
<p>
Use this class with <a href="#device_extract">device_extract</a> to specify extraction of a
Use this class with <a href="#extract_devices">extract_devices</a> to specify extraction of a
three-terminal MOS transistor
</p>
<h2>"mos4" - Supplies the MOS4 transistor extractor class</h2>
@ -406,7 +406,7 @@ three-terminal MOS transistor
<li><tt>mos4(name)</tt></li>
</ul>
<p>
Use this class with <a href="#device_extract">device_extract</a> to specify extraction of a
Use this class with <a href="#extract_devices">extract_devices</a> to specify extraction of a
four-terminal MOS transistor
</p>
<h2>"netlist" - Obtains the extracted netlist from the default <a href="#Netter">Netter</a></h2>
@ -537,7 +537,7 @@ third parameter.
<keyword name="report_netlist"/>
<a name="report_netlist"/><p>Usage:</p>
<ul>
<li><tt>report_netlist([ filename ])</tt></li>
<li><tt>report_netlist([ filename [, long ] ])</tt></li>
</ul>
<p>
This method applies to runsets creating a netlist through
@ -547,6 +547,8 @@ netlist plus the net and device shapes are turned into a
layout-to-netlist report (L2N database) and shown in the
netlist browser window. If a file name is given, the report
will also be written to the given file.
If a file name is given and "long" is true, a verbose
version of the L2N DB format will be used.
</p>
<h2>"resistor" - Supplies the resistor extractor class</h2>
<keyword name="resistor"/>
@ -555,17 +557,17 @@ will also be written to the given file.
<li><tt>resistor(name, sheet_rho)</tt></li>
</ul>
<p>
Use this class with <a href="#device_extract">device_extract</a> to specify extraction of a resistor.
Use this class with <a href="#extract_devices">extract_devices</a> to specify extraction of a resistor.
The sheet_rho value is the sheet resistance in ohms/square.
</p>
<h2>"resistor_with_bulk" - Supplies the resistor extractor class that includes a bulk terminal</h2>
<keyword name="resistor_with_bulk"/>
<a name="resistor_with_bulk"/><p>Usage:</p>
<ul>
<li><tt>resistor_with_bulk(name)</tt></li>
<li><tt>resistor_with_bulk(name, sheet_rho)</tt></li>
</ul>
<p>
Use this class with <a href="#device_extract">device_extract</a> to specify extraction of a resistor
Use this class with <a href="#extract_devices">extract_devices</a> to specify extraction of a resistor
with a bulk terminal.
The sheet_rho value is the sheet resistance in ohms/square.
</p>

View File

@ -186,21 +186,16 @@ to shapes belonging to tie-down diodes.
<li><tt>connect_implicit(label_pattern)</tt></li>
</ul>
<p>
Use this method to supply a glob pattern for labels which create implicit net connections
Use this method to supply label strings which create implicit net connections
on the top level circuit. This feature is useful to connect identically labelled nets
while a component isn't integrated yet. If the component is integrated, net may be connected
while a component isn't integrated yet. If the component is integrated, nets may be connected
on a higher hierarchy level - e.g. by a power mesh. Inside the component this net consists
of individual islands. To properly perform netlist extraction and comparison, these islands
need to be connected even though there isn't a physical connection. "connect_implicit" can
achive this if these islands are labelled with the same text on the top level of the
component.
</p><p>
Glob pattern are used which resemble shell file pattern: "*" is for all labels, "VDD"
for all "VDD" labels (pattern act case sensitive). "VDD*" is for all labels beginning
with "VDD" (still different labels will be connected to different nets!). "{VDD,VSS}"
is either "VDD" or "VSS".
</p><p>
The search pattern is applied on the next net extraction. The search pattern is cleared
The implicit connections are applied on the next net extraction and cleared
on "clear_connections".
</p>
<h2>"extract_devices" - Extracts devices based on the given extractor class, name and device layer selection</h2>

View File

@ -19,6 +19,15 @@ layers or specification of the layout source.
For more details about the DRC functions see <a href="/about/drc_ref_global.xml">DRC::global</a>.
</p>
<h2-index/>
<h2>"align" - Aligns the extracted netlist vs. the schematic by flattening circuits where required</h2>
<keyword name="align"/>
<a name="align"/><p>Usage:</p>
<ul>
<li><tt>align</tt></li>
</ul>
<p>
See <a href="/about/lvs_ref_netter.xml#align">Netter#align</a> for a description of that function.
</p>
<h2>"compare" - Compares the extracted netlist vs. the schematic</h2>
<keyword name="compare"/>
<a name="compare"/><p>Usage:</p>
@ -37,6 +46,24 @@ See <a href="/about/lvs_ref_netter.xml#compare">Netter#compare</a> for a descrip
<p>
See <a href="/about/lvs_ref_netter.xml#equivalent_pins">Netter#equivalent_pins</a> for a description of that function.
</p>
<h2>"max_branch_complexity" - Configures the maximum branch complexity for ambiguous net matching</h2>
<keyword name="max_branch_complexity"/>
<a name="max_branch_complexity"/><p>Usage:</p>
<ul>
<li><tt>max_branch_complexity(n)</tt></li>
</ul>
<p>
See <a href="/about/lvs_ref_netter.xml#max_branch_complexity">Netter#max_branch_complexity</a> for a description of that function.
</p>
<h2>"max_depth" - Configures the maximum search depth for net match deduction</h2>
<keyword name="max_depth"/>
<a name="max_depth"/><p>Usage:</p>
<ul>
<li><tt>max_depth(n)</tt></li>
</ul>
<p>
See <a href="/about/lvs_ref_netter.xml#max_depth">Netter#max_depth</a> for a description of that function.
</p>
<h2>"max_res" - Ignores resistors with a resistance above a certain value</h2>
<keyword name="max_res"/>
<a name="max_res"/><p>Usage:</p>
@ -68,13 +95,14 @@ See <a href="/about/lvs_ref_netter.xml">Netter</a> for more details
<keyword name="report_lvs"/>
<a name="report_lvs"/><p>Usage:</p>
<ul>
<li><tt>report_lvs([ filename ])</tt></li>
<li><tt>report_lvs([ filename [, long ] ])</tt></li>
</ul>
<p>
After the comparison step, the LVS database will be shown
in the netlist database browser in a cross-reference view.
If a filename is given, the LVS database is also written to
this file.
this file. If a file name is given and "long" is true, a
verbose version of the LVS DB format will be used.
</p><p>
If this method is called together with report_netlist and two files each, two
files can be generated - one for the extracted netlist (L2N database) and one for the

View File

@ -43,6 +43,31 @@ end
</pre>
</p>
<h2-index/>
<h2>"align" - Aligns the extracted netlist vs. the schematic</h2>
<keyword name="align"/>
<a name="align"/><p>Usage:</p>
<ul>
<li><tt>align</tt></li>
</ul>
<p>
The align method will modify the netlists in case of missing
corresponding circuits. It will flatten these circuits, thus
improving the equivalence between the netlists. Top level circuits
are not flattened.
</p><p>
This feature is in particular useful to remove structural cells
like device PCells, reuse blocks etc.
</p><p>
This method will also remove schematic circuits for which there is
no corresponding layout cell. In the extreme case of flat layout this
will result in a flat vs. flat compare.
</p><p>
"netlist.flatten_circuit(...)" or "schematic.flatten_circuit(...)"
are other (explicit) ways to flatten circuits.
</p><p>
Please note that flattening circuits has some side effects such
as loss of details in the cross reference and net layout.
</p>
<h2>"compare" - Compares the extracted netlist vs. the schematic</h2>
<keyword name="compare"/>
<a name="compare"/><p>Usage:</p>
@ -54,6 +79,9 @@ Before using this method, a schematic netlist has to be loaded with <a href="#sc
The compare can be configured in more details using <a href="#same_nets">same_nets</a>, <a href="#same_circuits">same_circuits</a>,
<a href="#same_device_classes">same_device_classes</a> and <a href="#equivalent_pins">equivalent_pins</a>.
</p><p>
The compare method will also modify the netlists in case of missing
corresponding circuits: the unpaired circuit will be flattened then.
</p><p>
This method will return true, if the netlists are equivalent and false
otherwise.
</p>
@ -61,7 +89,7 @@ otherwise.
<keyword name="equivalent_pins"/>
<a name="equivalent_pins"/><p>Usage:</p>
<ul>
<li><tt>equivalent_pins(circuit, pins ...)</tt></li>
<li><tt>equivalent_pins(circuit, pin ...)</tt></li>
</ul>
<p>
This method will mark the given pins as equivalent. This gives the compare algorithm
@ -70,9 +98,15 @@ is used to declare inputs from gates are equivalent where are are logically, but
physically (e.g. in a CMOS NAND gate):
</p><p>
<pre>
netter.equivalent_pins("NAND2", "A", "B")
netter.equivalent_pins("NAND2", 0, 1)
</pre>
</p><p>
The circuit argument is either a circuit name (a string) or a Circuit object
from the schematic netlist.
</p><p>
The pin arguments are zero-based pin numbers, where 0 is the first number, 1 the second etc.
If the netlist provides named pins, names can be used instead of numbers.
</p><p>
Before this method can be used, a schematic netlist needs to be loaded with
<a href="#schematic">schematic</a>.
</p>
@ -86,6 +120,23 @@ Before this method can be used, a schematic netlist needs to be loaded with
The <class_doc href="LayoutVsSchematic">LayoutVsSchematic</class_doc> object provides access to the internal details of
the netter object.
</p>
<h2>"max_depth" - Configures the maximum search depth for net match deduction</h2>
<keyword name="max_depth"/>
<a name="max_depth"/><p>Usage:</p>
<ul>
<li><tt>max_depth(n)</tt></li>
</ul>
<p>
The netlist compare algorithm works recursively: once a net
equivalence is established, additional matches are derived from
this equivalence. Such equivalences in turn are used to derive
new equivalences and so on. The maximum depth parameter configures
the number of recursions the algorithm performs before picking
the next net. With higher values for the depth, the algorithm
pursues this "deduction path" in greater depth while with
smaller values, the algorithm prefers picking nets in a random fashion
as the seeds for this deduction path. The default value is 8.
</p>
<h2>"max_res" - Ignores resistors with a resistance above a certain value</h2>
<keyword name="max_res"/>
<a name="max_res"/><p>Usage:</p>
@ -117,6 +168,9 @@ This method will force an equivalence between the two circuits.
By default, circuits are identified by name. If names are different, this
method allows establishing an explicit correspondence.
</p><p>
One of the circuits may be nil. In this case, the corresponding
other circuit is mapped to "nothing", i.e. ignored.
</p><p>
Before this method can be used, a schematic netlist needs to be loaded with
<a href="#schematic">schematic</a>.
</p>
@ -132,6 +186,9 @@ Device classes are also known as "models".
By default, device classes are identified by name. If names are different, this
method allows establishing an explicit correspondence.
</p><p>
One of the device classes may be nil. In this case, the corresponding
other device class is mapped to "nothing", i.e. ignored.
</p><p>
Before this method can be used, a schematic netlist needs to be loaded with
<a href="#schematic">schematic</a>.
</p>
@ -145,7 +202,11 @@ Before this method can be used, a schematic netlist needs to be loaded with
<p>
This method will force an equivalence between the net_a and net_b from circuit_a
and circuit_b (circuit in the three-argument form is for both circuit_a and circuit_b).
Circuit and nets are string giving a circuit and net by name.
</p><p>
In the four-argument form, the circuits can be either given by name or as Circuit
objects. In the three-argument form, the circuit has to be given by name.
Nets can be either given by name or as Net objects.
</p><p>
After using this function, the compare algorithm will consider these nets equivalent.
Use this method to provide hints for the comparer in cases which are difficult to
resolve otherwise.
@ -153,15 +214,19 @@ resolve otherwise.
Before this method can be used, a schematic netlist needs to be loaded with
<a href="#schematic">schematic</a>.
</p>
<h2>"schematic" - Reads the reference netlist</h2>
<h2>"schematic" - Gets, sets or reads the reference netlist</h2>
<keyword name="schematic"/>
<a name="schematic"/><p>Usage:</p>
<ul>
<li><tt>schematic(filename)</tt></li>
<li><tt>schematic(filename, reader)</tt></li>
<li><tt>schematic(netlist)</tt></li>
<li><tt>schematic</tt></li>
</ul>
<p>
If no argument is given, the current schematic netlist is returned. nil is
returned if no schematic netlist is set yet.
</p><p>
If a filename is given (first two forms), the netlist is read from the given file.
If no reader is provided, Spice format will be assumed. The reader object is a
<class_doc href="NetlistReader">NetlistReader</class_doc> object and allows detailed customization of the reader process.

View File

@ -342,8 +342,7 @@ connect_global(nwell, "NWELL")</pre>
<pre>schematic("inv.cir")</pre>
<p>
And with this we can trigger the compare step (this will implicitly trigger the netlist
extraction from the layout too):
Finally after having set this up, we can trigger the compare step:
</p>
<pre>compare</pre>
@ -357,7 +356,7 @@ connect_global(nwell, "NWELL")</pre>
target_netlist("inv_extracted.cir", write_spice, "Extracted by KLayout")</pre>
<p>
The extracted netlist is pretty much the same than the reference netlist, but
Since we have a LVS match, the extracted netlist is pretty much the same than the reference netlist, but
enhanced by some geometrical parameters such as source and drain area and
perimeter:
</p>
@ -390,8 +389,8 @@ M$2 2 1 4 6 NMOS L=0.25U W=0.9U AS=0.405P AD=0.405P PS=2.7U PD=2.7U
Tie-down diodes are contacts over active regions. The active regions are
implanted p+ on the substrate and n+ within the n well (the opposite implant
type of transistors). With this doping profile, the metal contact won't form
a Schottky barrier to the Silicon bulk and pretty much behave like an ohmic contact
(so in fact, the "diode" isn't a real diode in the sense of a rectifier).
a Schottky barrier to the Silicon bulk and behave like an ohmic contact.
So in fact, the "diode" isn't a real diode in the sense of a rectifier.
</p>
<p>

View File

@ -115,6 +115,31 @@
For example, "NMOS*" will flatten all circuits starting with "NMOS".
</p>
<h2>Automatic circuit flattening (netlist alignment)</h2>
<p>
Instead of flattening circuits explicitly, automatic flattening is provided through
the <a href="/about/lvs_ref_global.xml#align">align</a> method.
</p>
<p>
The "align" step is optional, hence useful: it will identify cells in the
layout without a corresponding schematic circuit and flatten them. "Flatten"
means their content is replicated inside their parent circuits and finally
the cell's corresponding circuit is removed. This is useful when the layout
contains structural cells: such cells are inserted not because the schematic
requires them as circuit building blocks, but because layout is easier to
create with these cells. Such cells can be PCells for devices or replication cells
which avoid duplicate layout work.
</p>
<p>
The "align" method will also flatten schematic circuits for which there is no
layout cell:
</p>
<pre>align</pre>
<h2>Black boxing (circuit abstraction)</h2>
<p>

View File

@ -101,6 +101,9 @@ connect_global(ptie, "SUBSTRATE")
# Netlist normalization
netlist.simplify
# Hierarchy alignment (flatten out unmatched cells)
align
# Netlist vs. netlist
compare
</text>

View File

@ -118,3 +118,9 @@ TEST(9_blackboxing)
{
run_test (_this, "ringo_simple_blackboxing", "ringo_for_blackboxing.gds");
}
TEST(10_simplification_with_align)
{
run_test (_this, "ringo_simple_simplification_with_align", "ringo_for_simplification.gds");
}

View File

@ -30,10 +30,10 @@
#include "lymMacro.h"
#include "tlFileUtils.h"
void run_test (tl::TestBase *_this, const std::string &suffix, const std::string &layout)
void run_test (tl::TestBase *_this, const std::string &lvs_rs, const std::string &suffix, const std::string &layout)
{
std::string rs = tl::testsrc ();
rs += "/testdata/lvs/" + suffix + ".lvs";
rs += "/testdata/lvs/" + lvs_rs;
std::string src = tl::testsrc ();
src += "/testdata/lvs/" + layout;
@ -100,5 +100,12 @@ void run_test (tl::TestBase *_this, const std::string &suffix, const std::string
TEST(1_full)
{
run_test (_this, "vexriscv", "vexriscv.oas.gz");
test_is_long_runner ();
run_test (_this, "vexriscv.lvs", "vexriscv", "vexriscv.oas.gz");
}
TEST(2_fullWithAlign)
{
test_is_long_runner ();
run_test (_this, "vexriscv_align.lvs", "vexriscv", "vexriscv.oas.gz");
}