COP API Reference
COP (Controllability Observability Program) - Probabilistic testability analysis using Bayesian networks for reconvergent fanout correlation modeling.
Overview
The COP module provides probability-based testability metrics:
- C1: Probability that a signal is 1 (controllability to 1)
- C0: Probability that a signal is 0 (controllability to 0, equals 1 - C1)
- Obs: Probability that a signal fault is observable at primary outputs
- Testability: Combined metric (C1 × Obs) indicating ease of testing
Main Entry Point
run_cop()
Main function for COP analysis with integrated reconvergence detection.
from opentestability.core.cop import run_cop
run_cop(
input_filename,
output_filename,
json_flag=False,
reconvergence_algorithm='auto',
reconvergence_data=None,
auto_parallel=True,
max_workers=4
)
Parameters:
input_filename(str): Name of parsed netlist fileoutput_filename(str): Name of output filejson_flag(bool): Whether to generate JSON output (default: False)reconvergence_algorithm(str): Algorithm for reconvergence detection'auto': Automatic selection (default)'simple': Simplified algorithm (O(n² log n), 98% accuracy)'basic': Basic algorithm (O(n²))'advanced': Complete algorithm (O(n³))None: Disable reconvergence handling
reconvergence_data(dict): Pre-computed reconvergence data (optional)auto_parallel(bool): Enable automatic parallel for large circuits (default: True)max_workers(int): Maximum parallel workers (default: 4)
Returns:
str: Path to generated text output file
Example:
from opentestability.core.cop import run_cop
# Basic usage
run_cop('circuit.txt', 'cop_results.txt')
# With reconvergence and JSON output
run_cop('circuit.txt', 'cop_results.txt',
json_flag=True,
reconvergence_algorithm='simple')
# Large circuit with parallel processing
run_cop('large_design.txt', 'results.txt',
reconvergence_algorithm='auto',
auto_parallel=True,
max_workers=8)
Controllability Module
build_controllability()
Compute C1 (probability of signal being 1) for all signals using forward propagation.
from opentestability.core.cop.controllability import build_controllability
C1 = build_controllability(nets, primary_inputs, gates, max_iterations=10000)
Parameters:
nets(List[str]): List of all signal names in circuitprimary_inputs(List[str]): List of primary input signal namesgates(List[Tuple]): List of gate tuples (gate_type, output_signal, [input_signals])max_iterations(int): Maximum iterations for convergence (default: 10000)
Returns:
Dict[str, float]: Dictionary mapping signal names to C1 probabilities
Algorithm:
- Initialize primary inputs to C1 = 0.5 (random test patterns)
- Initialize other signals to None (uncomputed)
- Iteratively compute gate outputs when inputs are ready
- Continue until convergence or max iterations reached
Example:
nets = ['a', 'b', 'n1', 'z']
inputs = ['a', 'b']
gates = [
('AND2X1', 'n1', ['a', 'b']),
('INVX1', 'z', ['n1'])
]
C1 = build_controllability(nets, inputs, gates)
print(f"Signal z has C1 = {C1['z']:.4f}")
get_controllability_metrics()
Package controllability metrics for output.
from opentestability.core.cop.controllability import get_controllability_metrics
metrics = get_controllability_metrics(C1)
Returns:
{
'signal_name': {
'c1': 0.5, # Probability signal is 1
'c0': 0.5 # Probability signal is 0
}
}
Gate Logic Module
Probabilistic transfer functions for various gate types.
calculate_gate_c1()
Main dispatcher for calculating C1 of any gate type.
from opentestability.core.cop.gate_logic import calculate_gate_c1
output_c1 = calculate_gate_c1(gate_type, input_c1_list)
Parameters:
gate_type(str): Gate type (e.g., ‘AND2X1’, ‘NAND’, ‘OR’, ‘XOR’)input_c1_list(List[float]): List of input C1 probabilities
Returns:
float: Probability that output is 1
Supported Gates:
- INV, NOT, BUF
- AND, NAND (multi-input)
- OR, NOR (multi-input)
- XOR, XNOR (multi-input)
- AOI, OAI (approximate)
Example:
# 2-input AND gate with inputs at 0.5 probability
c1_out = calculate_gate_c1('AND2X1', [0.5, 0.5])
# Result: 0.25 (0.5 × 0.5)
Individual Gate Functions
calculate_inv_c1()
Inverter: out.C1 = 1.0 - in.C1
c1_out = calculate_inv_c1(input_c1)
calculate_and_c1()
AND gate: out.C1 = ∏(input.C1)
c1_out = calculate_and_c1([0.5, 0.5, 0.5])
# Result: 0.125
calculate_or_c1()
OR gate: out.C1 = 1.0 - ∏(1.0 - input.C1)
c1_out = calculate_or_c1([0.5, 0.5])
# Result: 0.75
calculate_xor_c1()
XOR gate: out.C1 = (a.C1 × (1-b.C1)) + ((1-a.C1) × b.C1)
c1_out = calculate_xor_c1([0.5, 0.5])
# Result: 0.5
Observability Module
build_observability()
Compute observability for all signals using backward propagation.
from opentestability.core.cop.observability import build_observability
Obs = build_observability(
nets,
primary_outputs,
gates,
C1,
reconvergent_sites=None,
max_iterations=10000
)
Parameters:
nets(List[str]): List of all signal namesprimary_outputs(List[str]): List of primary output signal namesgates(List[Tuple]): List of gate tuplesC1(Dict[str, float]): Dictionary of C1 probabilitiesreconvergent_sites(Set[str]): Set of reconvergent fanout points (optional)max_iterations(int): Maximum iterations (default: 10000)
Returns:
Dict[str, float]: Dictionary mapping signal names to observability probabilities
Algorithm:
- Initialize primary outputs to Obs = 1.0 (fully observable)
- Initialize other signals to 0.0
- Iterate backward through gates, computing input observabilities
- For fanouts, combine branches using union formula (if independent)
- Mark reconvergent sites for Bayesian processing
Example:
Obs = build_observability(nets, outputs, gates, C1)
print(f"Signal 'a' observability: {Obs['a']:.4f}")
calculate_branch_observability()
Calculate observability of a signal through a specific gate branch.
from opentestability.core.cop.observability import calculate_branch_observability
branch_obs = calculate_branch_observability(
signal, gate_type, gate_output, gate_inputs, output_obs, C1
)
Logic by Gate Type:
- AND/NAND: All side inputs must be 1 to observe signal
Obs = output_obs × ∏(side_input.C1)
- OR/NOR: All side inputs must be 0 to observe signal
Obs = output_obs × ∏(1 - side_input.C1)
- XOR/XNOR: Side inputs don’t block observation
Obs = output_obs
- INV/BUF: Direct pass-through
Obs = output_obs
combine_fanout_observabilities()
Combine observabilities from multiple fanout branches.
from opentestability.core.cop.observability import combine_fanout_observabilities
combined_obs = combine_fanout_observabilities(branch_obs_list)
Formula:
For independent branches: Obs = 1 - ∏(1 - Obs_branch)
This represents probability that signal is observable through at least one branch.
Reconvergence Module
Bayesian network-based reconvergence handling with correlation modeling.
extract_reconvergent_sites()
Extract set of reconvergent site signals from reconvergence data.
from opentestability.core.cop.reconvergence import extract_reconvergent_sites
sites = extract_reconvergent_sites(reconvergence_data)
Returns:
Set[str]: Set of signal names that are reconvergent sites
adjust_cop_for_reconvergence()
Adjust COP observability values for reconvergent sites using Bayesian correlation.
from opentestability.core.cop.reconvergence import adjust_cop_for_reconvergence
adjusted_obs = adjust_cop_for_reconvergence(Obs, C1, reconvergence_data, gates)
Parameters:
Obs(Dict): Observability probabilitiesC1(Dict): Controllability probabilitiesreconvergence_data(Dict): Reconvergence analysis datagates(List): List of gate tuples
Returns:
Dict[str, float]: Adjusted observability dictionary
How It Works:
- Identifies reconvergent fanouts from data
- Builds Bayesian network for reconvergent paths
- Calculates correlation coefficients
- Applies correlation-based adjustments instead of independence assumption
BayesianNetwork Class
Simplified Bayesian network for modeling signal dependencies.
from opentestability.core.cop.reconvergence import BayesianNetwork
bn = BayesianNetwork()
bn.build_from_paths(path1, path2)
correlation = bn.calculate_correlation(path1, path2)
Methods:
add_dependency()
bn.add_dependency(parent_signal, child_signal)
build_from_paths()
bn.build_from_paths(path1, path2)
calculate_correlation()
correlation = bn.calculate_correlation(path1, path2)
Returns correlation coefficient in [0, 1] based on shared ancestor signals.
calculate_correlated_observability()
Calculate observability for reconvergent site using correlation.
from opentestability.core.cop.reconvergence import calculate_correlated_observability
adjusted_obs = calculate_correlated_observability(site, branch_obs_list, correlation)
Formula:
- If correlation = 0: Use independent union
1 - ∏(1 - Obs_i) - If correlation = 1: Use maximum
max(Obs_i)(paths identical) - For 0 < correlation < 1: Interpolate between the two
Parallel Module
Parallel computation support for large circuits (>100,000 gates).
build_cop_with_parallel()
Build complete COP analysis with parallel computation.
from opentestability.core.cop.parallel import build_cop_with_parallel
C1, Obs = build_cop_with_parallel(
nets, inputs, outputs, gates,
reconvergent_sites, reconvergence_data,
max_workers=4
)
Parameters:
nets(List[str]): All signal namesinputs(List[str]): Primary inputsoutputs(List[str]): Primary outputsgates(List[Tuple]): Gate tuplesreconvergent_sites(Set[str]): Reconvergent site signalsreconvergence_data(Dict): Reconvergence analysis datamax_workers(int): Maximum parallel workers (default: 4)
Returns:
Tuple[Dict, Dict]: (C1, Obs) dictionaries
Performance:
- Automatic activation for circuits >100,000 gates
- 3-4x speedup on large circuits
- Thread-safe concurrent processing
Output Module
Output formatting for COP results.
write_cop()
Write COP results to text file.
from opentestability.core.cop.output import write_cop
write_cop(C1, Obs, filename)
Output Format:
============================================================
COP (Controllability Observability Program) Analysis
============================================================
--- CONTROLLABILITY PROBABILITIES (C1) ---
C1 = Probability that signal is 1
C0 = 1 - C1 (Probability that signal is 0)
signal_a C1: 0.500000 C0: 0.500000
signal_b C1: 0.500000 C0: 0.500000
...
--- OBSERVABILITY PROBABILITIES (Obs) ---
Obs = Probability that signal fault is observable at outputs
signal_a Obs: 0.750000
signal_b Obs: 0.750000
...
--- TESTABILITY METRICS ---
Testability = C1 * Obs (probability of setting and observing)
signal_a Testability: 0.375000
signal_b Testability: 0.375000
...
dump_json()
Write COP results to JSON file.
from opentestability.core.cop.output import dump_json
dump_json(C1, Obs, inputs, outputs, gates, filename)
JSON Schema:
{
"analysis_type": "COP",
"description": "Controllability Observability Program Analysis",
"primary_inputs": ["a", "b"],
"primary_outputs": ["z"],
"metrics": [
{
"gate": "AND2X1_0",
"output": "n1",
"inputs": ["a", "b"],
"c1": 0.25,
"c0": 0.75,
"obs": 1.0,
"testability": 0.25
}
]
}
format_cop_summary()
Generate summary of COP results for display.
from opentestability.core.cop.output import format_cop_summary
summary = format_cop_summary(C1, Obs, primary_inputs, primary_outputs)
print(summary)
Output:
============================================================
COP Analysis Summary
============================================================
Primary Inputs (2):
a C1: 0.5000
b C1: 0.5000
Primary Outputs (1):
z Obs: 1.0000 Testability: 0.7500
Average C1: 0.5625
Average Observability: 0.8750
Testability Statistics:
Average: 0.4531
Minimum: 0.1250
Maximum: 0.7500
============================================================
Complete Example
from opentestability.core.cop import run_cop
from opentestability.core.cop.controllability import build_controllability
from opentestability.core.cop.observability import build_observability
from opentestability.core.cop.reconvergence import (
extract_reconvergent_sites,
adjust_cop_for_reconvergence
)
from opentestability.core.cop.output import write_cop, dump_json
# Method 1: Simple high-level API
run_cop('circuit.txt', 'cop_results.txt',
json_flag=True,
reconvergence_algorithm='auto',
auto_parallel=True)
# Method 2: Manual step-by-step
# (Assuming you have nets, inputs, outputs, gates from netlist parser)
# Step 1: Compute controllability
C1 = build_controllability(nets, inputs, gates)
# Step 2: Compute observability
Obs = build_observability(nets, outputs, gates, C1)
# Step 3: Apply reconvergence adjustments (if data available)
if reconvergence_data:
reconv_sites = extract_reconvergent_sites(reconvergence_data)
Obs = adjust_cop_for_reconvergence(Obs, C1, reconvergence_data, gates)
# Step 4: Write outputs
write_cop(C1, Obs, 'results.txt')
dump_json(C1, Obs, inputs, outputs, gates, 'results.json')
Performance Considerations
Circuit Size Thresholds
| Circuit Size | Processing Mode | Expected Time |
|---|---|---|
| < 1,000 gates | Sequential | < 1 second |
| 1,000 - 100,000 gates | Sequential | 1-10 seconds |
| > 100,000 gates | Automatic Parallel | 3-4x faster |
Memory Usage
- Sequential: ~O(n) where n = number of gates
- Parallel: ~O(n × workers) due to thread overhead
- Typical: 1-2 MB per 1000 gates
Optimization Tips
- Use
auto_parallel=Truefor large circuits (default behavior) - Adjust
max_workersbased on available CPU cores - Use simple reconvergence algorithm for best speed/accuracy tradeoff
- Enable JSON output only when needed (saves I/O time)