diff --git a/gplugins/klayout/netlist_spice_reader.py b/gplugins/klayout/netlist_spice_reader.py new file mode 100644 index 00000000..f524b208 --- /dev/null +++ b/gplugins/klayout/netlist_spice_reader.py @@ -0,0 +1,11 @@ +import klayout.db as kdb + + +class NoCommentReader(kdb.NetlistSpiceReaderDelegate): + """KLayout Spice reader without comments after $. This allows checking the netlist for HSPICE""" + + def parse_element(self, s: str, element: str) -> kdb.ParseElementData: + if "$" in s: + s = s.split("$")[0] # Don't take comments into account + parsed = super().parse_element(s, element) + return parsed diff --git a/gplugins/klayout/plot_nets.py b/gplugins/klayout/plot_nets.py index ac29ba9d..6ea21ad7 100644 --- a/gplugins/klayout/plot_nets.py +++ b/gplugins/klayout/plot_nets.py @@ -1,10 +1,12 @@ import itertools -from logging import warning from pathlib import Path import klayout.db as kdb import matplotlib.pyplot as plt import networkx as nx +from gdsfactory.config import logger + +from gplugins.klayout.netlist_spice_reader import NoCommentReader def _get_subcircuit_name(subcircuit: kdb.SubCircuit) -> str: @@ -81,11 +83,11 @@ def plot_nets( l2n.read(str(filepath)) netlist = l2n.netlist() case ".spice": - reader = kdb.NetlistSpiceReader() + reader = kdb.NetlistSpiceReader(NoCommentReader()) netlist = kdb.Netlist() netlist.read(str(filepath), reader) case _: - warning("Assuming file is KLayout native LayoutToNetlist file") + logger.warning("Assuming file is KLayout native LayoutToNetlist file") l2n = kdb.LayoutToNetlist() l2n.read(str(filepath)) netlist = l2n.netlist() diff --git a/gplugins/klayout/tests/test_netlist_spice_reader.py b/gplugins/klayout/tests/test_netlist_spice_reader.py new file mode 100644 index 00000000..a4f40204 --- /dev/null +++ b/gplugins/klayout/tests/test_netlist_spice_reader.py @@ -0,0 +1,25 @@ +import pytest + +from gplugins.klayout.netlist_spice_reader import NoCommentReader + + +@pytest.mark.parametrize( + "s,element,expected_name,expected_nets", + [ + ("1 2 POS", "X", "POS", {"1", "2"}), + ("2 3 NEG $ This is a comment", "X", "NEG", {"2", "3"}), + ( + "5 4 some_elem some_variable=1 $ This is a comment", + "X", + "some_elem", + {"5", "4"}, + ), + ], +) +def test_NoCommentReader( + s: str, element: str, expected_name: str, expected_nets: set[str] +) -> None: + reader = NoCommentReader() + parsed = reader.parse_element(s, element) + assert set(parsed.net_names) == expected_nets + assert parsed.model_name == expected_name.upper()