mirror of https://github.com/KLayout/klayout.git
WIP: added documentation to LVS script.
This commit is contained in:
parent
a8f8ca0d7d
commit
ed41af9b4b
|
|
@ -13,21 +13,6 @@ module DRC
|
|||
# as global functions too where they act on a default incarnation
|
||||
# of the netter. Usually it's not required to instantiate a Netter
|
||||
# object, but it serves as a container for this functionality.
|
||||
|
||||
# %LVS%
|
||||
# @scope
|
||||
# @name Netter
|
||||
# @brief LVS Reference: Netter object
|
||||
# The Netter object provides services related to network extraction
|
||||
# from a layout plus comparison against a reference netlist.
|
||||
# Similar to the DRC netter (which lacks the compare ability), the
|
||||
# relevant method of this object are available as global functions too
|
||||
# where they act on a default incarnation. Usually it's not required
|
||||
# to instantiate a Netter object explicitly.
|
||||
#
|
||||
# An individual netter object can be created, if the netter results
|
||||
# need to be kept for multiple extractions. If you really need
|
||||
# a Netter object, use the global \netter function:
|
||||
#
|
||||
# @code
|
||||
# # create a new Netter object:
|
||||
|
|
@ -394,11 +379,11 @@ module DRC
|
|||
def ensure_data
|
||||
if !@l2n
|
||||
@layers = {}
|
||||
make_data
|
||||
_make_data
|
||||
end
|
||||
end
|
||||
|
||||
def make_data
|
||||
def _make_data
|
||||
|
||||
if @engine._dss
|
||||
@engine._dss.is_singular? || raise("The DRC script features more than one or no layout source - network extraction cannot be performed in such configurations")
|
||||
|
|
|
|||
|
|
@ -66,7 +66,56 @@ module LVS
|
|||
@output_lvsdb_file = filename
|
||||
end
|
||||
|
||||
# ...
|
||||
# %DRC%
|
||||
# @name schematic
|
||||
# @brief Reads the reference netlist
|
||||
# @synopsis schematic(filename)
|
||||
# @synopsis schematic(filename, reader)
|
||||
# @synopsis schematic(netlist)
|
||||
# See \Netter#schematic for a description of that function.
|
||||
|
||||
# %DRC%
|
||||
# @name compare
|
||||
# @brief Compares the extracted netlist vs. the schematic
|
||||
# @synopsis compare
|
||||
# See \Netter#compare for a description of that function.
|
||||
|
||||
# %DRC%
|
||||
# @name same_nets
|
||||
# @brief Establishes an equivalence between the nets
|
||||
# @synopsis same_nets(circuit, net_a, net_b)
|
||||
# @synopsis same_nets(circuit_a, net_a, circuit_b, net_b)
|
||||
# See \Netter#same_nets for a description of that function.
|
||||
|
||||
# %DRC%
|
||||
# @name same_circuits
|
||||
# @brief Establishes an equivalence between the circuits
|
||||
# @synopsis same_circuits(circuit_a, circuit_b)
|
||||
# See \Netter#same_circuits for a description of that function.
|
||||
|
||||
# %DRC%
|
||||
# @name same_device_classes
|
||||
# @brief Establishes an equivalence between the device_classes
|
||||
# @synopsis same_device_classes(class_a, class_b)
|
||||
# See \Netter#same_device_classes for a description of that function.
|
||||
|
||||
# %DRC%
|
||||
# @name equivalent_pins
|
||||
# @brief Marks pins as equivalent
|
||||
# @synopsis equivalent_pins(circuit, pins ...)
|
||||
# See \Netter#equivalen_pins for a description of that function.
|
||||
|
||||
# %LVS%
|
||||
# @name min_caps
|
||||
# @brief Ignores capacitors with a capacitance below a certain value
|
||||
# @synopsis min_caps(threshold)
|
||||
# See \Netter#min_caps for a description of that function.
|
||||
|
||||
# %LVS%
|
||||
# @name max_res
|
||||
# @brief Ignores resistors with a resistance above a certain value
|
||||
# @synopsis max_res(threshold)
|
||||
# See \Netter#max_res for a description of that function.
|
||||
|
||||
%w(schematic compare same_nets same_circuits same_device_classes equivalent_pins min_caps max_res max_depth max_branch_complexity).each do |f|
|
||||
eval <<"CODE"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,17 @@ module LVS
|
|||
# relevant method of this object are available as global functions too
|
||||
# where they act on a default incarnation. Usually it's not required
|
||||
# to instantiate a Netter object explicitly.
|
||||
#
|
||||
# An individual netter object can be created, if the netter results
|
||||
# need to be kept for multiple extractions or when different configurations
|
||||
# need to be used in the same script. If you really want
|
||||
# a Netter object, use the global \netter function:
|
||||
# The Netter object provides services related to network extraction
|
||||
# from a layout plus comparison against a reference netlist.
|
||||
# Similar to the DRC netter (which lacks the compare ability), the
|
||||
# relevant method of this object are available as global functions too
|
||||
# where they act on a default incarnation. Usually it's not required
|
||||
# to instantiate a Netter object explicitly.
|
||||
#
|
||||
# An individual netter object can be created, if the netter results
|
||||
# need to be kept for multiple extractions. If you really need
|
||||
|
|
@ -24,11 +35,23 @@ module LVS
|
|||
# @code
|
||||
# # create a new Netter object:
|
||||
# nx = netter
|
||||
#
|
||||
# # build connectivity
|
||||
# nx.connect(poly, contact)
|
||||
# ...
|
||||
# @/code
|
||||
#
|
||||
# # read the reference netlist
|
||||
# nx.schematic("reference.cir")
|
||||
#
|
||||
# # configure the netlist compare
|
||||
# nx.same_circuits("A", "B")
|
||||
# ...
|
||||
#
|
||||
# # runs the compare
|
||||
# if ! nx.compare
|
||||
# puts("no equivalence!")
|
||||
# end
|
||||
# @/code
|
||||
|
||||
class LVSNetter < DRCNetter
|
||||
|
||||
|
|
@ -36,7 +59,7 @@ module LVS
|
|||
super
|
||||
end
|
||||
|
||||
def make_data
|
||||
def _make_data
|
||||
|
||||
if @engine._dss
|
||||
@engine._dss.is_singular? || raise("The LVS script features more than one or no layout source - network extraction cannot be performed in such configurations")
|
||||
|
|
@ -51,6 +74,13 @@ module LVS
|
|||
|
||||
end
|
||||
|
||||
# %LVS%
|
||||
# @name lvs_data
|
||||
# @brief Gets the internal RBA::LayoutVsSchematic object
|
||||
# @synopsis lvs_data
|
||||
# The RBA::LayoutVsSchematic object provides access to the internal details of
|
||||
# the netter object.
|
||||
|
||||
def lvs_data
|
||||
l2n_data
|
||||
@lvs
|
||||
|
|
@ -67,6 +97,17 @@ module LVS
|
|||
data
|
||||
end
|
||||
|
||||
# %LVS%
|
||||
# @name compare
|
||||
# @brief Compares the extracted netlist vs. the schematic
|
||||
# @synopsis compare
|
||||
# Before using this method, a schematic netlist has to be loaded with \schematic.
|
||||
# The compare can be configured in more details using \same_nets, \same_circuits,
|
||||
# \same_device_classes and \equivalent_pins.
|
||||
#
|
||||
# This method will return true, if the netlists are equivalent and false
|
||||
# otherwise.
|
||||
|
||||
def compare
|
||||
@lvs.compare(@comparer)
|
||||
end
|
||||
|
|
@ -80,6 +121,21 @@ module LVS
|
|||
|
||||
end
|
||||
|
||||
# %LVS%
|
||||
# @name same_nets
|
||||
# @brief Establishes an equivalence between the nets
|
||||
# @synopsis same_nets(circuit, net_a, net_b)
|
||||
# @synopsis same_nets(circuit_a, net_a, circuit_b, net_b)
|
||||
# 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.
|
||||
# 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.
|
||||
#
|
||||
# Before this method can be used, a schematic netlist needs to be loaded with
|
||||
# \schematic.
|
||||
|
||||
def same_nets(*args)
|
||||
|
||||
pins.each do |a|
|
||||
|
|
@ -111,6 +167,17 @@ module LVS
|
|||
|
||||
end
|
||||
|
||||
# %LVS%
|
||||
# @name same_circuits
|
||||
# @brief Establishes an equivalence between the circuits
|
||||
# @synopsis same_circuits(circuit_a, circuit_b)
|
||||
# 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.
|
||||
#
|
||||
# Before this method can be used, a schematic netlist needs to be loaded with
|
||||
# \schematic.
|
||||
|
||||
def same_circuits(a, b)
|
||||
|
||||
a.is_a?(String) || b.is_a?(String) || raise("Both arguments of 'same_circuits' need to be strings")
|
||||
|
|
@ -124,6 +191,18 @@ module LVS
|
|||
|
||||
end
|
||||
|
||||
# %LVS%
|
||||
# @name same_device_classes
|
||||
# @brief Establishes an equivalence between the device classes
|
||||
# @synopsis same_device_classes(class_a, class_b)
|
||||
# This method will force an equivalence between the two device classes.
|
||||
# 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.
|
||||
#
|
||||
# Before this method can be used, a schematic netlist needs to be loaded with
|
||||
# \schematic.
|
||||
|
||||
def same_device_classes(a, b)
|
||||
|
||||
a.is_a?(String) || b.is_a?(String) || raise("Both arguments of 'same_device_classes' need to be strings")
|
||||
|
|
@ -137,6 +216,22 @@ module LVS
|
|||
|
||||
end
|
||||
|
||||
# %LVS%
|
||||
# @name equivalent_pins
|
||||
# @brief Marks pins as equivalent
|
||||
# @synopsis equivalent_pins(circuit, pins ...)
|
||||
# This method will mark the given pins as equivalent. This gives the compare algorithm
|
||||
# more degrees of freedom when establishing net correspondence. Typically this method
|
||||
# is used to declare inputs from gates are equivalent where are are logically, but not
|
||||
# physically (e.g. in a CMOS NAND gate):
|
||||
#
|
||||
# @code
|
||||
# netter.equivalent_pins("NAND2", "A", "B")
|
||||
# @/code
|
||||
#
|
||||
# Before this method can be used, a schematic netlist needs to be loaded with
|
||||
# \schematic.
|
||||
|
||||
def equivalent_pins(circuit, *pins)
|
||||
|
||||
circuit.is_a?(String) || raise("Circuit arguments of 'equivalent_pins' needs to be a string")
|
||||
|
|
@ -157,31 +252,64 @@ module LVS
|
|||
|
||||
end
|
||||
|
||||
def schematic(filename, reader = nil)
|
||||
# %LVS%
|
||||
# @name schematic
|
||||
# @brief Reads the reference netlist
|
||||
# @synopsis schematic(filename)
|
||||
# @synopsis schematic(filename, reader)
|
||||
# @synopsis schematic(netlist)
|
||||
# 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
|
||||
# RBA::NetlistReader object and allows detailed customization of the reader process.
|
||||
#
|
||||
# Alternatively, a RBA::Netlist object can be given which is obtained from any other
|
||||
# source.
|
||||
|
||||
def schematic(schematic, reader = nil)
|
||||
|
||||
filename.is_a?(String) || raise("First argument must be string in 'schematic'")
|
||||
|
||||
if reader
|
||||
reader.is_a?(RBA::NetlistReader) || raise("Second argument must be netlist reader object in 'schematic'")
|
||||
if schematic.is_a?(RBA::Netlist)
|
||||
lvs_data.reference = netlist
|
||||
else
|
||||
reader = RBA::NetlistSpiceReader::new
|
||||
|
||||
schematic.is_a?(String) || raise("First argument must be string or netlist in 'schematic'")
|
||||
|
||||
if reader
|
||||
reader.is_a?(RBA::NetlistReader) || raise("Second argument must be netlist reader object in 'schematic'")
|
||||
else
|
||||
reader = RBA::NetlistSpiceReader::new
|
||||
end
|
||||
|
||||
netlist_file = @engine._make_path(schematic)
|
||||
@engine.info("Reading netlist: #{netlist_file} ..")
|
||||
|
||||
netlist = RBA::Netlist::new
|
||||
netlist.read(netlist_file, reader)
|
||||
|
||||
lvs_data.reference = netlist
|
||||
|
||||
end
|
||||
|
||||
netlist_file = @engine._make_path(filename)
|
||||
@engine.info("Reading netlist: #{netlist_file} ..")
|
||||
|
||||
netlist = RBA::Netlist::new
|
||||
netlist.read(netlist_file, reader)
|
||||
|
||||
lvs_data.reference = netlist
|
||||
|
||||
end
|
||||
|
||||
# %LVS%
|
||||
# @name min_caps
|
||||
# @brief Ignores capacitors with a capacitance below a certain value
|
||||
# @synopsis min_caps(threshold)
|
||||
# After using this method, the netlist compare will ignore capacitance devices
|
||||
# with a capacitance values below the given threshold (in Farad).
|
||||
|
||||
def min_caps(value)
|
||||
lvs_data
|
||||
@comparer.min_capacitance = value.to_f
|
||||
end
|
||||
|
||||
# %LVS%
|
||||
# @name max_res
|
||||
# @brief Ignores resistors with a resistance above a certain value
|
||||
# @synopsis max_res(threshold)
|
||||
# After using this method, the netlist compare will ignore resistor devices
|
||||
# with a resistance value above the given threshold (in Farad).
|
||||
|
||||
def max_res(value)
|
||||
lvs_data
|
||||
@comparer.max_resistance = value.to_f
|
||||
|
|
|
|||
Loading…
Reference in New Issue