Automating OrCAD Netlist Comparison with Python
Building a CLI tool to diff PSTXNET netlists between design revisions, catching connectivity errors before they reach the PCB layout stage.
One of the most tedious parts of the schematic review process in OrCAD Capture is verifying that netlist changes between design revisions are intentional. When you’re working on a board with 2,000+ nets, manually comparing two PSTXNET.DAT files is not just impractical — it’s a recipe for missed errors.
The Problem
During my time working on high-pin-count Intel reference designs, I found myself repeatedly needing to answer a simple question: “What changed between rev A and rev B of this schematic?”
OrCAD Capture generates PSTXNET.DAT files during the netlist export process. These files contain the complete connectivity information for a design — every net, every pin, every component reference. But they’re flat text files with no built-in diff capability.
NET_NAME: DDR5_DQ0
NODE_NAME: U1.A3
NODE_NAME: R101.1
NODE_NAME: J1.B4
Comparing two of these files with a standard text diff tool (like diff or even VS Code’s built-in compare) produces noisy, hard-to-interpret results because the order of nodes within a net can change between exports even when the connectivity hasn’t actually changed.
The Solution
I built pstxnet-compare, a Python CLI tool that parses PSTXNET.DAT files into structured dictionaries keyed by net name, then performs a semantic comparison that ignores ordering differences within nets.
Parsing the Netlist
The parser is straightforward — it reads the file line by line, building a dictionary where each key is a net name and each value is a sorted set of node connections:
def parse_pstxnet(filepath: str) -> dict[str, set[str]]:
nets: dict[str, set[str]] = {}
current_net = None
with open(filepath, 'r') as f:
for line in f:
line = line.strip()
if line.startswith('NET_NAME:'):
current_net = line.split(':', 1)[1].strip()
nets[current_net] = set()
elif line.startswith('NODE_NAME:') and current_net:
node = line.split(':', 1)[1].strip()
nets[current_net].add(node)
return nets
Semantic Comparison
The comparison logic identifies four categories of changes:
- Added nets — nets present in the new revision but not the old
- Removed nets — nets present in the old revision but not the new
- Modified nets — nets that exist in both but have different pin connections
- Unchanged nets — nets that are identical (these get filtered from the report)
def compare_netlists(old: dict, new: dict) -> dict:
added = {k: new[k] for k in new if k not in old}
removed = {k: old[k] for k in old if k not in new}
modified = {}
for net in old:
if net in new and old[net] != new[net]:
modified[net] = {
'added_nodes': new[net] - old[net],
'removed_nodes': old[net] - new[net],
}
return {'added': added, 'removed': removed, 'modified': modified}
ANSI Color Output
The CLI uses ANSI escape codes to color-code the output in the terminal — green for added connections, red for removed ones, and yellow for modified nets. This makes it immediately obvious what changed at a glance:
GREEN = '\033[92m'
RED = '\033[91m'
YELLOW = '\033[93m'
RESET = '\033[0m'
def print_report(changes: dict) -> None:
for net, data in changes['modified'].items():
print(f"{YELLOW}~ {net}{RESET}")
for node in data['added_nodes']:
print(f" {GREEN}+ {node}{RESET}")
for node in data['removed_nodes']:
print(f" {RED}- {node}{RESET}")
Results
This tool cut our netlist review time from hours to minutes. Instead of eyeballing two massive text files, engineers on the team could run a single command and get a clean, color-coded report of exactly what changed.
$ pstxnet-compare rev_a/PSTXNET.DAT rev_b/PSTXNET.DAT
The tool has since been extended with a Tkinter GUI for engineers who prefer a graphical interface, and I’ve added support for exporting comparison reports to HTML and CSV formats.
Takeaways
- Parsing structured text files is a great entry point for EDA automation — netlists, BOMs, and DRC reports all follow predictable formats
- Semantic comparison beats text diffing when the underlying data has order-independent semantics
- Color-coded terminal output dramatically improves the usability of CLI tools for engineers who live in the terminal
- Python is the right tool for this kind of EDA glue work — fast enough for files with tens of thousands of lines, expressive enough to keep the code readable
Thanks for reading! If you found this useful, feel free to share.
More posts