schematic vs schematic (SVS) not (LVS)

in manual, about LVS:

compare
This method (compare will extract the netlist (if not already done) and compare it against the schematic. 
It returns true on success and false otherwise, in case you like to take specific actions on success or failure. 

It seems the command "compare" is used to compare(layout, old.cir)
sometimes, after I modified my schematic, I want to compare the new schematic (new.cir) to an old schematic (old.cir).
So can the command "compare" compare two netlists rather than layout-vs-schematic?
for example,
compare(new.cir, old.cir)

Thanks
Hycmos

Comments

  • edited February 2020

    Hi,

    yes, that's possible. But not within the framework of LVS.

    LVS is just a wrapper around the scripting API, so you can basically code a script which does this.
    The problem is that there is no infrastructure for this application yet: no file format, no browser etc.
    The LVSDB format keeps a lot of information for layout back-annotation and probing which is
    not available in your case.

    A solution is either to tweak the LVS infrastructure (which can't be done without code changes
    at the core) or to rebuild a simple infrastructure for your purpose. The key element is the
    "NetlistCompareLogger" which is essentially a listener receiving events (success, mismatch)
    while the netlist compare happens.

    Here is a simple implementation taken from the unit tests. It will just print results as compare
    proceeds. You can basically tailor the output to your needs:

    # This class provides a receiver for netlist compare events
    class NetlistCompareTestLogger < RBA::GenericNetlistCompareLogger
    
      def initialize
        @texts = []
      end
    
      def out(text)
        @texts << text
      end
    
      def device_class_mismatch(a, b)
        out("device_class_mismatch " + dc2str(a) + " " + dc2str(b))
      end
    
      def begin_circuit(a, b)
        out("begin_circuit " + circuit2str(a) + " " + circuit2str(b))
      end
    
      def end_circuit(a, b, matching)
        out("end_circuit " + circuit2str(a) + " " + circuit2str(b) + " " + (matching ? "MATCH" : "NOMATCH"))
      end
    
      def circuit_skipped(a, b)
        out("circuit_skipped " + circuit2str(a) + " " + circuit2str(b))
      end
    
      def circuit_mismatch(a, b)
        out("circuit_mismatch " + circuit2str(a) + " " + circuit2str(b))
      end
    
      def match_nets(a, b)
        out("match_nets " + net2str(a) + " " + net2str(b))
      end
    
      def match_ambiguous_nets(a, b)
        out("match_ambiguous_nets " + net2str(a) + " " + net2str(b))
      end
    
      def net_mismatch(a, b)
        out("net_mismatch " + net2str(a) + " " + net2str(b))
      end
    
      def match_devices(a, b)
        out("match_devices " + device2str(a) + " " + device2str(b))
      end
    
      def device_mismatch(a, b)
        out("device_mismatch " + device2str(a) + " " + device2str(b))
      end
    
      def match_devices_with_different_parameters(a, b)
        out("match_devices_with_different_parameters " + device2str(a) + " " + device2str(b))
      end
    
      def match_devices_with_different_device_classes(a, b)
        out("match_devices_with_different_device_classes " + device2str(a) + " " + device2str(b))
      end
    
      def match_pins(a, b)
        out("match_pins " + pin2str(a) + " " + pin2str(b))
      end
    
      def pin_mismatch(a, b)
        out("pin_mismatch " + pin2str(a) + " " + pin2str(b))
      end
    
      def match_subcircuits(a, b)
        out("match_subcircuits " + subcircuit2str(a) + " " + subcircuit2str(b))
      end
    
      def subcircuit_mismatch(a, b)
        out("subcircuit_mismatch " + subcircuit2str(a) + " " + subcircuit2str(b))
      end
    
      def text
        return @texts.join("\n") + "\n"
      end
    
      def clear
        @texts = []
      end
    
      def dc2str(x) 
        return x ? x.name : "(null)"
      end
    
      def circuit2str(x) 
        return x ? x.name : "(null)"
      end
    
      def device2str(x) 
        return x ? x.expanded_name : "(null)"
      end
    
      def net2str(x) 
        return x ? x.expanded_name : "(null)"
      end
    
      def pin2str(x) 
        return x ? x.expanded_name : "(null)"
      end
    
      def subcircuit2str(x) 
        return x ? x.expanded_name : "(null)"
      end
    
    end
    
    
    # This is the actual compare step
    
    cir_path1 = ... # path to first Spice file
    cir_path2 = ... # path to second Spice file
    
    nl1 = RBA::Netlist::new
    nl1.read(cir_path1, RBA::NetlistSpiceReader::new)
    
    nl2 = RBA::Netlist::new
    nl2.read(cir_path2, RBA::NetlistSpiceReader::new)
    
    logger = NetlistCompareTestLogger::new
    comp = RBA::NetlistComparer::new(logger)
    # dump compare log
    puts comp.text
    

    Regards,

    Matthias

  • Sir,
    Thank you very much for your patience.
    I plan to study the code to understand the method.
    hope I can implement this work. <3

  • Good luck :)

    Please note I have added "puts comp.text" to dump the collected compare report.

    Matthias

  • get a script error:
    undefined method `text' for #-RBA::NetlistComparer:0x0000000030d94c18-

    can not run the line "puts comp.text".
    But I can see you defined the function text in class NetlistCompareTestLogger < RBA::GenericNetlistCompareLogger.

  • edited March 2020

    Sorry, please replace the actual compare code by this:

    # This is the actual compare step
    
    cir_path1 = ... # path to first Spice file
    cir_path2 = ... # path to second Spice file
    
    nl1 = RBA::Netlist::new
    nl1.read(cir_path1, RBA::NetlistSpiceReader::new)
    
    nl2 = RBA::Netlist::new
    nl2.read(cir_path2, RBA::NetlistSpiceReader::new)
    
    logger = NetlistCompareTestLogger::new
    comp = RBA::NetlistComparer::new(logger)
    comp.compare(nl1, nl2)
    # dump compare log
    puts logger.text
    

    (I cannot edit the code above as the editing period expired).

    The code is just a sketch ... there is a lot more to say about tweaking the compare step. Please study the methods provided by Netlist and NetlistComparer for various options that can be used for this purpose. SVS is a new application. Please don't expect it to work out of the box.

    Matthias

  • Hi @Matthias
    Do you have any way to ignore or set tolerance for parameter for SVS check?. two my netlists has a different width of device so it flag connection mismatch also. It should be show property mismatch only.

    Thank you,
    dai

  • Yes, that is basically possible. You can attach some criterion to a DeviceClass which tell the comparer whether devices are considered equal or not. If you skip a parameter in that definition it is not compared.

    See here for details and a code sample: https://www.klayout.de/doc-qt5/code/class_EqualDeviceParameters.html

    netlist is the first input netlist as I recall.

    Please note that such features may be subject to change. I focus on keeping LVS script stable, not the implementation details.

    Matthias

  • There is a "netgen" which performs any-to-any netlist compare.
    Not easy to find although it's part of the efabless / opencircuitdesign
    MAGIC-based toolchain (there are other "netgen" developments,
    newer and unrelated, which Bogart the search engine results). As
    I make it out, the results can be cryptic and not necessarily easy to
    get a graphical display, of. But people make it work on LSI / VLSI
    layouts from schematic and it seems netlist-source-agnostic.

    http://opencircuitdesign.com/netgen/

Sign In or Register to comment.