From 5dabd6093daf9158d5d1e9fb7df7e7464d40288c Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Tue, 23 Jul 2019 01:12:12 +0200 Subject: [PATCH] Provide new 'align' feature in LVS for automatic circuit flattening. --- scripts/extract_doc.rb | 73 ++++++++++--------- .../{make_drc_doc.sh => make_drc_lvs_doc.sh} | 0 src/lay/lay/doc/about/drc_ref_global.xml | 26 ++++--- src/lay/lay/doc/about/drc_ref_netter.xml | 11 +-- src/lay/lay/doc/about/lvs_ref_global.xml | 32 +++++++- src/lay/lay/doc/about/lvs_ref_netter.xml | 73 ++++++++++++++++++- src/lay/lay/doc/manual/lvs_intro.xml | 9 +-- src/lay/lay/doc/manual/lvs_tweaks.xml | 25 +++++++ src/lvs/lvs/templates/lvs.lym | 3 + src/lvs/unit_tests/lvsSimpleTests.cc | 6 ++ src/lvs/unit_tests/lvsTests.cc | 13 +++- 11 files changed, 203 insertions(+), 68 deletions(-) rename scripts/{make_drc_doc.sh => make_drc_lvs_doc.sh} (100%) diff --git a/scripts/extract_doc.rb b/scripts/extract_doc.rb index 9e01f759c..54e51bfb1 100755 --- a/scripts/extract_doc.rb +++ b/scripts/extract_doc.rb @@ -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 diff --git a/scripts/make_drc_doc.sh b/scripts/make_drc_lvs_doc.sh similarity index 100% rename from scripts/make_drc_doc.sh rename to scripts/make_drc_lvs_doc.sh diff --git a/src/lay/lay/doc/about/drc_ref_global.xml b/src/lay/lay/doc/about/drc_ref_global.xml index 2521e3296..07e837418 100644 --- a/src/lay/lay/doc/about/drc_ref_global.xml +++ b/src/lay/lay/doc/about/drc_ref_global.xml @@ -29,7 +29,7 @@ See Netter#antenna_check f
  • bjt3(name)
  • -Use this class with device_extract to specify extraction of a +Use this class with extract_devices to specify extraction of a bipolar junction transistor

    "bjt4" - Supplies the BJT4 transistor extractor class

    @@ -39,7 +39,7 @@ bipolar junction transistor
  • bjt4(name)
  • -Use this class with device_extract to specify extraction of a +Use this class with extract_devices to specify extraction of a bipolar junction transistor with a substrate terminal

    "box" - Creates a box object

    @@ -59,17 +59,17 @@ This function creates a box object. The arguments are the same than for the
  • capacitor(name, area_cap)
  • -Use this class with device_extract to specify extraction of a capacitor. +Use this class with extract_devices to specify extraction of a capacitor. The area_cap argument is the capacitance in Farad per square micrometer.

    "capacitor_with_bulk" - Supplies the capacitor extractor class that includes a bulk terminal

    Usage:

      -
    • capacitor_with_bulk(name)
    • +
    • capacitor_with_bulk(name, area_cap)

    -Use this class with device_extract to specify extraction of a capacitor +Use this class with extract_devices to specify extraction of a capacitor with a bulk terminal. The area_cap argument is the capacitance in Farad per square micrometer.

    @@ -192,7 +192,7 @@ Deep mode can be cancelled with tiles or fl
  • diode(name)
  • -Use this class with device_extract to specify extraction of a +Use this class with extract_devices to specify extraction of a planar diode

    "edge" - Creates an edge object

    @@ -396,7 +396,7 @@ filled with Layer#insert.
  • mos3(name)
  • -Use this class with device_extract to specify extraction of a +Use this class with extract_devices to specify extraction of a three-terminal MOS transistor

    "mos4" - Supplies the MOS4 transistor extractor class

    @@ -406,7 +406,7 @@ three-terminal MOS transistor
  • mos4(name)
  • -Use this class with device_extract to specify extraction of a +Use this class with extract_devices to specify extraction of a four-terminal MOS transistor

    "netlist" - Obtains the extracted netlist from the default Netter

    @@ -537,7 +537,7 @@ third parameter.

    Usage:

      -
    • report_netlist([ filename ])
    • +
    • report_netlist([ filename [, long ] ])

    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.

    "resistor" - Supplies the resistor extractor class

    @@ -555,17 +557,17 @@ will also be written to the given file.
  • resistor(name, sheet_rho)
  • -Use this class with device_extract to specify extraction of a resistor. +Use this class with extract_devices to specify extraction of a resistor. The sheet_rho value is the sheet resistance in ohms/square.

    "resistor_with_bulk" - Supplies the resistor extractor class that includes a bulk terminal

    Usage:

      -
    • resistor_with_bulk(name)
    • +
    • resistor_with_bulk(name, sheet_rho)

    -Use this class with device_extract to specify extraction of a resistor +Use this class with extract_devices to specify extraction of a resistor with a bulk terminal. The sheet_rho value is the sheet resistance in ohms/square.

    diff --git a/src/lay/lay/doc/about/drc_ref_netter.xml b/src/lay/lay/doc/about/drc_ref_netter.xml index 1fa008d21..4e56513b9 100644 --- a/src/lay/lay/doc/about/drc_ref_netter.xml +++ b/src/lay/lay/doc/about/drc_ref_netter.xml @@ -186,21 +186,16 @@ to shapes belonging to tie-down diodes.
  • connect_implicit(label_pattern)
  • -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.

    -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". -

    -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".

    "extract_devices" - Extracts devices based on the given extractor class, name and device layer selection

    diff --git a/src/lay/lay/doc/about/lvs_ref_global.xml b/src/lay/lay/doc/about/lvs_ref_global.xml index d99c2fb74..4ea1fa4fb 100644 --- a/src/lay/lay/doc/about/lvs_ref_global.xml +++ b/src/lay/lay/doc/about/lvs_ref_global.xml @@ -19,6 +19,15 @@ layers or specification of the layout source. For more details about the DRC functions see DRC::global.

    +

    "align" - Aligns the extracted netlist vs. the schematic by flattening circuits where required

    + +

    Usage:

    +
      +
    • align
    • +
    +

    +See Netter#align for a description of that function. +

    "compare" - Compares the extracted netlist vs. the schematic

    Usage:

    @@ -37,6 +46,24 @@ See
    Netter#compare for a descrip

    See Netter#equivalent_pins for a description of that function.

    +

    "max_branch_complexity" - Configures the maximum branch complexity for ambiguous net matching

    + +

    Usage:

    +
      +
    • max_branch_complexity(n)
    • +
    +

    +See Netter#max_branch_complexity for a description of that function. +

    +

    "max_depth" - Configures the maximum search depth for net match deduction

    + +

    Usage:

    +
      +
    • max_depth(n)
    • +
    +

    +See Netter#max_depth for a description of that function. +

    "max_res" - Ignores resistors with a resistance above a certain value

    Usage:

    @@ -68,13 +95,14 @@ See
    Netter for more details

    Usage:

      -
    • report_lvs([ filename ])
    • +
    • report_lvs([ filename [, long ] ])

    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.

    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 diff --git a/src/lay/lay/doc/about/lvs_ref_netter.xml b/src/lay/lay/doc/about/lvs_ref_netter.xml index 98a3cd859..604805c0c 100644 --- a/src/lay/lay/doc/about/lvs_ref_netter.xml +++ b/src/lay/lay/doc/about/lvs_ref_netter.xml @@ -43,6 +43,31 @@ end

    +

    "align" - Aligns the extracted netlist vs. the schematic

    + +

    Usage:

    +
      +
    • align
    • +
    +

    +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. +

    +This feature is in particular useful to remove structural cells +like device PCells, reuse blocks etc. +

    +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. +

    +"netlist.flatten_circuit(...)" or "schematic.flatten_circuit(...)" +are other (explicit) ways to flatten circuits. +

    +Please note that flattening circuits has some side effects such +as loss of details in the cross reference and net layout. +

    "compare" - Compares the extracted netlist vs. the schematic

    Usage:

    @@ -54,6 +79,9 @@ Before using this method, a schematic netlist has to be loaded with
    same_nets, same_circuits, same_device_classes and equivalent_pins.

    +The compare method will also modify the netlists in case of missing +corresponding circuits: the unpaired circuit will be flattened then. +

    This method will return true, if the netlists are equivalent and false otherwise.

    @@ -61,7 +89,7 @@ otherwise.

    Usage:

      -
    • equivalent_pins(circuit, pins ...)
    • +
    • equivalent_pins(circuit, pin ...)

    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):

    -netter.equivalent_pins("NAND2", "A", "B")
    +netter.equivalent_pins("NAND2", 0, 1)
     

    +The circuit argument is either a circuit name (a string) or a Circuit object +from the schematic netlist. +

    +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. +

    Before this method can be used, a schematic netlist needs to be loaded with schematic.

    @@ -86,6 +120,23 @@ Before this method can be used, a schematic netlist needs to be loaded with The LayoutVsSchematic object provides access to the internal details of the netter object.

    +

    "max_depth" - Configures the maximum search depth for net match deduction

    + +

    Usage:

    +
      +
    • max_depth(n)
    • +
    +

    +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. +

    "max_res" - Ignores resistors with a resistance above a certain value

    Usage:

    @@ -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.

    +One of the circuits may be nil. In this case, the corresponding +other circuit is mapped to "nothing", i.e. ignored. +

    Before this method can be used, a schematic netlist needs to be loaded with schematic.

    @@ -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.

    +One of the device classes may be nil. In this case, the corresponding +other device class is mapped to "nothing", i.e. ignored. +

    Before this method can be used, a schematic netlist needs to be loaded with schematic.

    @@ -145,7 +202,11 @@ Before this method can be used, a schematic netlist needs to be loaded with

    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. +

    +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. +

    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 schematic.

    -

    "schematic" - Reads the reference netlist

    +

    "schematic" - Gets, sets or reads the reference netlist

    Usage:

    • schematic(filename)
    • schematic(filename, reader)
    • schematic(netlist)
    • +
    • schematic

    +If no argument is given, the current schematic netlist is returned. nil is +returned if no schematic netlist is set yet. +

    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 NetlistReader object and allows detailed customization of the reader process. diff --git a/src/lay/lay/doc/manual/lvs_intro.xml b/src/lay/lay/doc/manual/lvs_intro.xml index 791254eb8..d3278dd8e 100644 --- a/src/lay/lay/doc/manual/lvs_intro.xml +++ b/src/lay/lay/doc/manual/lvs_intro.xml @@ -342,8 +342,7 @@ connect_global(nwell, "NWELL")

    schematic("inv.cir")

    - 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:

    compare
    @@ -357,7 +356,7 @@ connect_global(nwell, "NWELL") target_netlist("inv_extracted.cir", write_spice, "Extracted by KLayout")

    - 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:

    @@ -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.

    diff --git a/src/lay/lay/doc/manual/lvs_tweaks.xml b/src/lay/lay/doc/manual/lvs_tweaks.xml index 99c2a6d60..997104258 100644 --- a/src/lay/lay/doc/manual/lvs_tweaks.xml +++ b/src/lay/lay/doc/manual/lvs_tweaks.xml @@ -115,6 +115,31 @@ For example, "NMOS*" will flatten all circuits starting with "NMOS".

    +

    Automatic circuit flattening (netlist alignment)

    + +

    + Instead of flattening circuits explicitly, automatic flattening is provided through + the align method. +

    + +

    + 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. +

    + +

    + The "align" method will also flatten schematic circuits for which there is no + layout cell: +

    + +
    align
    +

    Black boxing (circuit abstraction)

    diff --git a/src/lvs/lvs/templates/lvs.lym b/src/lvs/lvs/templates/lvs.lym index 09e9ea06c..7b74b5643 100644 --- a/src/lvs/lvs/templates/lvs.lym +++ b/src/lvs/lvs/templates/lvs.lym @@ -101,6 +101,9 @@ connect_global(ptie, "SUBSTRATE") # Netlist normalization netlist.simplify +# Hierarchy alignment (flatten out unmatched cells) +align + # Netlist vs. netlist compare diff --git a/src/lvs/unit_tests/lvsSimpleTests.cc b/src/lvs/unit_tests/lvsSimpleTests.cc index 7e14387b5..f39253968 100644 --- a/src/lvs/unit_tests/lvsSimpleTests.cc +++ b/src/lvs/unit_tests/lvsSimpleTests.cc @@ -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"); +} + diff --git a/src/lvs/unit_tests/lvsTests.cc b/src/lvs/unit_tests/lvsTests.cc index d3ce9fa7c..d4fc23a89 100644 --- a/src/lvs/unit_tests/lvsTests.cc +++ b/src/lvs/unit_tests/lvsTests.cc @@ -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"); }