Added the new feature: 'flag_missing_ports'

This commit is contained in:
Matthias Koefferlein 2025-05-24 22:33:18 +02:00
parent 7b865451ee
commit 094e11897a
11 changed files with 574 additions and 1 deletions

View File

@ -25,6 +25,7 @@
#include "dbLayoutVsSchematic.h"
#include "dbLayoutVsSchematicWriter.h"
#include "dbLayoutVsSchematicReader.h"
#include "dbNetlistCompareUtils.h"
namespace db
{
@ -86,6 +87,43 @@ db::NetlistCrossReference *LayoutVsSchematic::make_cross_ref ()
return mp_cross_ref.get ();
}
bool
LayoutVsSchematic::flag_missing_ports (const db::Circuit *circuit)
{
if (! mp_cross_ref.get ()) {
return false;
}
db::NetlistCrossReference::PerCircuitData *pcd = const_cast<db::NetlistCrossReference::PerCircuitData *> (mp_cross_ref->per_circuit_data_for (std::make_pair (circuit, circuit)));
if (! pcd) {
return false;
}
bool error = false;
for (auto n = pcd->nets.begin (); n != pcd->nets.end (); ++n) {
const db::Net *schem = n->pair.second;
const db::Net *layout = n->pair.first;
if (schem && layout && schem->begin_pins () != schem->end_pins ()) {
if (db::name_compare (layout, schem) != 0) {
std::string msg = tl::sprintf (tl::to_string (tr ("Port mismatch '%s' vs. '%s'")), layout->expanded_name (), schem->expanded_name ());
db::LogEntryData entry (db::Error, msg);
pcd->log_entries.push_back (entry);
error = true;
}
}
}
return !error;
}
void LayoutVsSchematic::save (const std::string &path, bool short_format)
{

View File

@ -144,6 +144,22 @@ public:
*/
db::NetlistCrossReference *make_cross_ref ();
/**
* @brief Checks top-level port names
*
* This method checks that every top-level pin has a corresponding
* schematic pin and their names are equivalent. This verifies that
* all pins are labelles properly.
*
* Errors are placed in the log file. The return values indicates
* if there are no errors.
*
* The circuit is either a schematic or layout circuit.
*
* See issue #2055.
*/
bool flag_missing_ports (const db::Circuit *circuit);
/**
* @brief Saves the database to the given path
*

View File

@ -110,6 +110,18 @@ Class<db::LayoutVsSchematic> decl_dbLayoutVsSchematic (decl_dbLayoutToNetlist, "
"\n"
"See \\NetlistCrossReference for more details.\n"
) +
gsi::method ("flag_missing_ports", &db::LayoutVsSchematic::flag_missing_ports, gsi::arg ("circuit"),
"@brief Flags inconsistent port labels in the given circuit\n"
"@param circuit Either a layout or schematic circuit\n"
"@return True, if no errors were found\n"
"This method will check all schematic nets which have pins and tests whether the corresponding layout net "
"has the same name. This way, it is checked if the pins are properly labelled.\n"
"\n"
"The method must be called after the compare step was successful. Error messages will be added "
"to the log entries. If an error occured or the cross reference is not value, 'false' is returned.\n"
"\n"
"This method was introduced in version 0.30.2."
) +
gsi::method_ext ("write_l2n", &save_l2n, gsi::arg ("path"), gsi::arg ("short_format", false),
"@brief Writes the \\LayoutToNetlist part of the object to a file.\n"
"This method employs the native format of KLayout.\n"

View File

@ -225,9 +225,16 @@ module LVS
# @synopsis lvs_data
# See \Netter#lvs_data for a description of that function.
# %LVS%
# @name flag_missing_ports
# @brief Checks if all top level ports are properly labelled
# @synopsis flag_missing_ports
# See \Netter#flag_missing_ports for a description of that function.
%w(schematic compare split_gates join_symmetric_nets tolerance ignore_parameter enable_parameter disable_parameter
blank_circuit align same_nets same_nets! same_circuits same_device_classes equivalent_pins
min_caps max_res max_depth max_branch_complexity consider_net_names lvs_data no_lvs_hints).each do |f|
min_caps max_res max_depth max_branch_complexity consider_net_names lvs_data no_lvs_hints
flag_missing_ports).each do |f|
eval <<"CODE"
def #{f}(*args)
_netter.#{f}(*args)

View File

@ -530,6 +530,33 @@ CODE
@comparer_config << lambda { |comparer| comparer.with_log = false }
end
# %LVS%
# @name flag_missing_ports
# @brief Flags inconsistently labelled or missing ports in the current top circuit
# @synopsis flag_missing_ports
# This method must be called after "compare" was executed successfully and will
# report errors if pins in the current top circuit's schematic are not labelled
# correspondingly in the layout. This prevents swapping of port labels or
# pads.
#
# @code
# success = compare
# success && flag_missing_ports
# @/code
#
# Note that in order to use this method, the top circuit from the schematic netlist
# needs to have pins. This may not be always the case - for example, if the top
# level circuit is not a subcircuit in a Spice netlist.
def flag_missing_ports
lvs_data.netlist || raise("Netlist not extracted yet")
lvs_data.xref || raise("Compare step was not executed yet")
lvs_data.flag_missing_ports(lvs_data.netlist.top_circuit)
end
# %LVS%
# @name same_nets
# @brief Establishes an equivalence between the nets

View File

@ -357,3 +357,8 @@ TEST(62_LayerNames)
run_test (_this, "layer_names", "layer_names.gds", false, true, "TOP");
}
TEST(63_FlagMissingPorts)
{
run_test (_this, "flag_missing_ports", "flag_missing_ports.gds", false, true, "TOP");
}

23
testdata/lvs/flag_missing_ports.cir vendored Normal file
View File

@ -0,0 +1,23 @@
* Extracted by KLayout
* cell ND2X1
* pin VSS
* pin VDD
* pin b
* pin X
* pin SUBSTRATE
.SUBCKT ND2X1 1 3 5 6 7
* net 1 VSS
* net 3 VDD
* net 5 b
* net 6 X
* net 7 SUBSTRATE
* device instance $1 r0 *1 0.85,5.8 PMOS
M$1 1 6 2 4 PMOS L=0.25U W=1.5U AS=0.6375P AD=0.3375P PS=3.85U PD=1.95U
* device instance $2 r0 *1 1.55,5.8 PMOS
M$2 2 5 1 4 PMOS L=0.25U W=1.5U AS=0.3375P AD=0.6375P PS=1.95U PD=3.85U
* device instance $3 r0 *1 0.85,2.135 NMOS
M$3 8 6 3 7 NMOS L=0.25U W=0.95U AS=0.40375P AD=0.21375P PS=2.75U PD=1.4U
* device instance $4 r0 *1 1.55,2.135 NMOS
M$4 2 5 8 7 NMOS L=0.25U W=0.95U AS=0.21375P AD=0.40375P PS=1.4U PD=2.75U
.ENDS ND2X1

BIN
testdata/lvs/flag_missing_ports.gds vendored Normal file

Binary file not shown.

76
testdata/lvs/flag_missing_ports.lvs vendored Normal file
View File

@ -0,0 +1,76 @@
source($lvs_test_source, "ND2X1")
report_lvs($lvs_test_target_lvsdb, true)
target_netlist($lvs_test_target_cir, write_spice, "Extracted by KLayout")
schematic("flag_missing_ports.sch")
deep
# Drawing layers
nwell = input(1, 0)
active = input(2, 0)
pplus = input(3, 0)
nplus = input(4, 0)
poly = input(5, 0)
contact = input(8, 0)
metal1 = input(9, 0)
via1 = input(10, 0)
metal2 = input(11, 0)
# Bulk layer for terminal provisioning
bulk = polygon_layer
# Computed layers
active_in_nwell = active & nwell
pactive = active_in_nwell & pplus
pgate = pactive & poly
psd = pactive - pgate
ntie = active_in_nwell & nplus
active_outside_nwell = active - nwell
nactive = active_outside_nwell & nplus
ngate = nactive & poly
nsd = nactive - ngate
ptie = active_outside_nwell & pplus
# Device extraction
# PMOS transistor device extraction
extract_devices(mos4("PMOS"), { "SD" => psd, "G" => pgate, "W" => nwell,
"tS" => psd, "tD" => psd, "tG" => poly, "tW" => nwell })
# NMOS transistor device extraction
extract_devices(mos4("NMOS"), { "SD" => nsd, "G" => ngate, "W" => bulk,
"tS" => nsd, "tD" => nsd, "tG" => poly, "tW" => bulk })
# Define connectivity for netlist extraction
# Inter-layer
connect(psd, contact)
connect(nsd, contact)
connect(poly, contact)
connect(ntie, contact)
connect(nwell, ntie)
connect(ptie, contact)
connect(contact, metal1)
connect(metal1, via1)
connect(via1, metal2)
# Global
connect_global(bulk, "SUBSTRATE")
connect_global(ptie, "SUBSTRATE")
# Compare section
netlist.simplify
compare
flag_missing_ports

362
testdata/lvs/flag_missing_ports.lvsdb vendored Normal file
View File

@ -0,0 +1,362 @@
#%lvsdb-klayout
# Layout
layout(
top(ND2X1)
unit(0.001)
# Layer section
# This section lists the mask layers (drawing or derived) and their connections.
# Mask layers
layer(l3 '1/0')
layer(l4 '5/0')
layer(l8 '8/0')
layer(l11 '9/0')
layer(l12)
layer(l13)
layer(l7)
layer(l2)
layer(l9)
layer(l6)
layer(l10)
# Mask layer connectivity
connect(l3 l3 l9)
connect(l4 l4 l8)
connect(l8 l4 l8 l11 l2 l9 l6 l10)
connect(l11 l8 l11 l12)
connect(l12 l11 l12 l13)
connect(l13 l12 l13)
connect(l7 l7)
connect(l2 l8 l2)
connect(l9 l3 l8 l9)
connect(l6 l8 l6)
connect(l10 l8 l10)
# Global nets and connectivity
global(l7 SUBSTRATE)
global(l10 SUBSTRATE)
# Device class section
class(PMOS MOS4)
class(NMOS MOS4)
# Device abstracts section
# Device abstracts list the pin shapes of the devices.
device(D$PMOS PMOS
terminal(S
rect(l2 (-550 -750) (425 1500))
)
terminal(G
rect(l4 (-125 -750) (250 1500))
)
terminal(D
rect(l2 (125 -750) (450 1500))
)
terminal(B
rect(l3 (-125 -750) (250 1500))
)
)
device(D$PMOS$1 PMOS
terminal(S
rect(l2 (-575 -750) (450 1500))
)
terminal(G
rect(l4 (-125 -750) (250 1500))
)
terminal(D
rect(l2 (125 -750) (425 1500))
)
terminal(B
rect(l3 (-125 -750) (250 1500))
)
)
device(D$NMOS NMOS
terminal(S
rect(l6 (-550 -475) (425 950))
)
terminal(G
rect(l4 (-125 -475) (250 950))
)
terminal(D
rect(l6 (125 -475) (450 950))
)
terminal(B
rect(l7 (-125 -475) (250 950))
)
)
device(D$NMOS$1 NMOS
terminal(S
rect(l6 (-575 -475) (450 950))
)
terminal(G
rect(l4 (-125 -475) (250 950))
)
terminal(D
rect(l6 (125 -475) (425 950))
)
terminal(B
rect(l7 (-125 -475) (250 950))
)
)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(ND2X1
# Circuit boundary
rect((-100 400) (2600 7600))
# Nets with their geometries
net(1 name(VSS)
rect(l8 (1110 5160) (180 180))
rect(l8 (-180 920) (180 180))
rect(l8 (-180 -730) (180 180))
rect(l11 (-240 -790) (300 1700))
rect(l11 (-1350 0) (2400 800))
rect(l11 (-1150 -400) (0 0))
rect(l2 (-275 -2150) (425 1500))
rect(l2 (-400 -1500) (425 1500))
)
net(2
rect(l8 (1810 1770) (180 180))
rect(l8 (-180 370) (180 180))
rect(l8 (-1580 3760) (180 180))
rect(l8 (-180 -730) (180 180))
rect(l8 (-180 -730) (180 180))
rect(l8 (1220 920) (180 180))
rect(l8 (-180 -1280) (180 180))
rect(l8 (-180 370) (180 180))
polygon(l11 (-240 -4180) (0 1390) (490 0) (0 -300) (-190 0) (0 -1090))
rect(l11 (-110 1390) (300 1400))
polygon(l11 (-1890 0) (0 600) (300 0) (0 -300) (1590 0) (0 -300))
rect(l11 (-1890 600) (300 1400))
rect(l11 (1100 -1700) (300 300))
rect(l11 (-300 0) (300 1400))
rect(l2 (-1750 -1450) (425 1500))
rect(l2 (950 -1500) (425 1500))
rect(l6 (-425 -4890) (425 950))
)
net(3 name(VDD)
rect(l8 (410 1770) (180 180))
rect(l8 (-180 370) (180 180))
rect(l11 (-240 -1300) (300 1360))
rect(l11 (-650 -2160) (2400 800))
rect(l11 (-1150 -400) (0 0))
rect(l6 (-950 860) (425 950))
)
net(4
rect(l3 (-100 4500) (2600 3500))
)
net(5 name(b)
rect(l4 (1425 2860) (250 1940))
rect(l4 (-345 -950) (300 300))
rect(l4 (-205 650) (250 2000))
rect(l4 (-250 -2000) (250 2000))
rect(l4 (-250 -5390) (250 1450))
rect(l8 (-285 1050) (180 180))
rect(l11 (-70 -90) (0 0))
rect(l11 (-170 -150) (300 300))
)
net(6 name(X)
rect(l4 (725 2860) (250 1940))
rect(l4 (-325 -1850) (300 300))
rect(l4 (-225 1550) (250 2000))
rect(l4 (-250 -2000) (250 2000))
rect(l4 (-250 -5390) (250 1450))
rect(l8 (-265 150) (180 180))
rect(l11 (-90 -90) (0 0))
rect(l11 (-150 -150) (300 300))
)
net(7 name(SUBSTRATE))
net(8
rect(l6 (975 1660) (425 950))
rect(l6 (-400 -950) (425 950))
)
# Outgoing pins and their connections to nets
pin(1 name(VSS))
pin(3 name(VDD))
pin(5 name(b))
pin(6 name(X))
pin(7 name(SUBSTRATE))
# Devices and their connections
device(1 D$PMOS
location(850 5800)
param(L 0.25)
param(W 1.5)
param(AS 0.6375)
param(AD 0.3375)
param(PS 3.85)
param(PD 1.95)
terminal(S 2)
terminal(G 6)
terminal(D 1)
terminal(B 4)
)
device(2 D$PMOS$1
location(1550 5800)
param(L 0.25)
param(W 1.5)
param(AS 0.3375)
param(AD 0.6375)
param(PS 1.95)
param(PD 3.85)
terminal(S 1)
terminal(G 5)
terminal(D 2)
terminal(B 4)
)
device(3 D$NMOS
location(850 2135)
param(L 0.25)
param(W 0.95)
param(AS 0.40375)
param(AD 0.21375)
param(PS 2.75)
param(PD 1.4)
terminal(S 3)
terminal(G 6)
terminal(D 8)
terminal(B 7)
)
device(4 D$NMOS$1
location(1550 2135)
param(L 0.25)
param(W 0.95)
param(AS 0.21375)
param(AD 0.40375)
param(PS 1.4)
param(PD 2.75)
terminal(S 8)
terminal(G 5)
terminal(D 2)
terminal(B 7)
)
)
)
# Reference netlist
reference(
# Device class section
class(PMOS MOS4)
class(NMOS MOS4)
# Circuit section
# Circuits are the hierarchical building blocks of the netlist.
circuit(ND2X1
# Nets
net(1 name(VDD))
net(2 name(OUT))
net(3 name(VSS))
net(4 name(NWELL))
net(5 name(B))
net(6 name(A))
net(7 name(BULK))
net(8 name('1'))
# Outgoing pins and their connections to nets
pin(1 name(VDD))
pin(2 name(OUT))
pin(3 name(VSS))
pin(4 name(NWELL))
pin(5 name(B))
pin(6 name(A))
pin(7 name(BULK))
# Devices and their connections
device(1 PMOS
name($1)
param(L 0.25)
param(W 1.5)
param(AS 0)
param(AD 0)
param(PS 0)
param(PD 0)
terminal(S 1)
terminal(G 6)
terminal(D 2)
terminal(B 4)
)
device(2 PMOS
name($2)
param(L 0.25)
param(W 1.5)
param(AS 0)
param(AD 0)
param(PS 0)
param(PD 0)
terminal(S 1)
terminal(G 5)
terminal(D 2)
terminal(B 4)
)
device(3 NMOS
name($3)
param(L 0.25)
param(W 0.95)
param(AS 0)
param(AD 0)
param(PS 0)
param(PD 0)
terminal(S 3)
terminal(G 6)
terminal(D 8)
terminal(B 7)
)
device(4 NMOS
name($4)
param(L 0.25)
param(W 0.95)
param(AS 0)
param(AD 0)
param(PS 0)
param(PD 0)
terminal(S 8)
terminal(G 5)
terminal(D 2)
terminal(B 7)
)
)
)
# Cross reference
xref(
circuit(ND2X1 ND2X1 match
log(
entry(error description('Port mismatch \'$4\' vs. \'NWELL\''))
entry(error description('Port mismatch \'$2\' vs. \'OUT\''))
entry(error description('Port mismatch \'SUBSTRATE\' vs. \'BULK\''))
entry(error description('Port mismatch \'VDD\' vs. \'VSS\''))
entry(error description('Port mismatch \'VSS\' vs. \'VDD\''))
entry(error description('Port mismatch \'X\' vs. \'A\''))
)
xref(
net(8 8 match)
net(4 4 match)
net(2 2 match)
net(7 7 match)
net(3 3 match)
net(1 1 match)
net(6 6 match)
net(5 5 match)
pin(() 3 match)
pin(() 1 match)
pin(4 6 match)
pin(1 2 match)
pin(0 0 match)
pin(3 5 match)
pin(2 4 match)
device(3 3 match)
device(4 4 match)
device(1 1 match)
device(2 2 match)
)
)
)

7
testdata/lvs/flag_missing_ports.sch vendored Normal file
View File

@ -0,0 +1,7 @@
.SUBCKT ND2X1 VDD OUT VSS NWELL B A BULK
M$1 OUT A VDD NWELL PMOS L=0.25U W=1.5U
M$2 OUT B VDD NWELL PMOS L=0.25U W=1.5U
M$3 1 A VSS BULK NMOS L=0.25U W=0.95U
M$4 OUT B 1 BULK NMOS L=0.25U W=0.95U
.ENDS ND2X1