oscura 0.4.0__py3-none-any.whl → 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oscura/__init__.py +1 -1
- oscura/analyzers/digital/__init__.py +48 -0
- oscura/analyzers/digital/extraction.py +195 -0
- oscura/analyzers/digital/ic_database.py +498 -0
- oscura/analyzers/digital/timing_paths.py +339 -0
- oscura/analyzers/digital/vintage.py +377 -0
- oscura/analyzers/digital/vintage_result.py +148 -0
- oscura/analyzers/protocols/__init__.py +22 -1
- oscura/analyzers/protocols/parallel_bus.py +449 -0
- oscura/automotive/__init__.py +1 -1
- oscura/export/__init__.py +12 -0
- oscura/export/wavedrom.py +430 -0
- oscura/exporters/json_export.py +47 -0
- oscura/exporters/vintage_logic_csv.py +247 -0
- oscura/reporting/__init__.py +7 -0
- oscura/reporting/vintage_logic_report.py +523 -0
- oscura/utils/autodetect.py +5 -1
- oscura/visualization/digital_advanced.py +718 -0
- oscura/visualization/figure_manager.py +156 -0
- {oscura-0.4.0.dist-info → oscura-0.5.0.dist-info}/METADATA +1 -1
- {oscura-0.4.0.dist-info → oscura-0.5.0.dist-info}/RECORD +24 -19
- oscura/automotive/dtc/data.json +0 -2763
- oscura/schemas/bus_configuration.json +0 -322
- oscura/schemas/device_mapping.json +0 -182
- oscura/schemas/packet_format.json +0 -418
- oscura/schemas/protocol_definition.json +0 -363
- {oscura-0.4.0.dist-info → oscura-0.5.0.dist-info}/WHEEL +0 -0
- {oscura-0.4.0.dist-info → oscura-0.5.0.dist-info}/entry_points.txt +0 -0
- {oscura-0.4.0.dist-info → oscura-0.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"""CSV export functions for vintage logic analysis results.
|
|
2
|
+
|
|
3
|
+
This module provides specialized CSV exporters for vintage logic analysis data,
|
|
4
|
+
including timing measurements, IC identification, and bill of materials.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
>>> from oscura.exporters.vintage_logic_csv import export_bom_csv
|
|
8
|
+
>>> export_bom_csv(result, "bom.csv")
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import csv
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from oscura.analyzers.digital.vintage_result import VintageLogicAnalysisResult
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def export_timing_measurements_csv(
|
|
22
|
+
result: VintageLogicAnalysisResult,
|
|
23
|
+
path: str | Path,
|
|
24
|
+
) -> None:
|
|
25
|
+
"""Export timing measurements to CSV.
|
|
26
|
+
|
|
27
|
+
Creates a CSV file with columns: parameter, measured_value_ns, measurement_type.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
result: Vintage logic analysis result.
|
|
31
|
+
path: Output CSV file path.
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
>>> export_timing_measurements_csv(result, "timing.csv")
|
|
35
|
+
"""
|
|
36
|
+
path = Path(path)
|
|
37
|
+
|
|
38
|
+
with path.open("w", newline="") as csvfile:
|
|
39
|
+
writer = csv.writer(csvfile)
|
|
40
|
+
|
|
41
|
+
# Write header
|
|
42
|
+
writer.writerow(["parameter", "measured_value_ns", "measurement_type"])
|
|
43
|
+
|
|
44
|
+
# Write timing measurements
|
|
45
|
+
for param_name, value in result.timing_measurements.items():
|
|
46
|
+
# Determine measurement type from parameter name
|
|
47
|
+
if "_t_pd" in param_name:
|
|
48
|
+
meas_type = "propagation_delay"
|
|
49
|
+
elif "_t_su" in param_name:
|
|
50
|
+
meas_type = "setup_time"
|
|
51
|
+
elif "_t_h" in param_name:
|
|
52
|
+
meas_type = "hold_time"
|
|
53
|
+
elif "_t_w" in param_name:
|
|
54
|
+
meas_type = "pulse_width"
|
|
55
|
+
else:
|
|
56
|
+
meas_type = "other"
|
|
57
|
+
|
|
58
|
+
writer.writerow([param_name, f"{value * 1e9:.3f}", meas_type])
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def export_ic_identification_csv(
|
|
62
|
+
result: VintageLogicAnalysisResult,
|
|
63
|
+
path: str | Path,
|
|
64
|
+
) -> None:
|
|
65
|
+
"""Export IC identification results to CSV.
|
|
66
|
+
|
|
67
|
+
Creates a CSV file with columns: ic_name, confidence, family, timing_params,
|
|
68
|
+
validation_status.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
result: Vintage logic analysis result.
|
|
72
|
+
path: Output CSV file path.
|
|
73
|
+
|
|
74
|
+
Example:
|
|
75
|
+
>>> export_ic_identification_csv(result, "ic_identification.csv")
|
|
76
|
+
"""
|
|
77
|
+
path = Path(path)
|
|
78
|
+
|
|
79
|
+
with path.open("w", newline="") as csvfile:
|
|
80
|
+
writer = csv.writer(csvfile)
|
|
81
|
+
|
|
82
|
+
# Write header
|
|
83
|
+
writer.writerow(
|
|
84
|
+
[
|
|
85
|
+
"ic_name",
|
|
86
|
+
"confidence",
|
|
87
|
+
"family",
|
|
88
|
+
"t_pd_ns",
|
|
89
|
+
"t_su_ns",
|
|
90
|
+
"t_h_ns",
|
|
91
|
+
"t_w_ns",
|
|
92
|
+
"validation_status",
|
|
93
|
+
]
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Write IC identification results
|
|
97
|
+
for ic_result in result.identified_ics:
|
|
98
|
+
# Extract timing parameters
|
|
99
|
+
t_pd = ic_result.timing_params.get("t_pd", 0) * 1e9
|
|
100
|
+
t_su = ic_result.timing_params.get("t_su", 0) * 1e9
|
|
101
|
+
t_h = ic_result.timing_params.get("t_h", 0) * 1e9
|
|
102
|
+
t_w = ic_result.timing_params.get("t_w", 0) * 1e9
|
|
103
|
+
|
|
104
|
+
# Determine validation status
|
|
105
|
+
validation_failed = any(v.get("passes") is False for v in ic_result.validation.values())
|
|
106
|
+
validation_status = "FAIL" if validation_failed else "PASS"
|
|
107
|
+
|
|
108
|
+
writer.writerow(
|
|
109
|
+
[
|
|
110
|
+
ic_result.ic_name,
|
|
111
|
+
f"{ic_result.confidence:.3f}",
|
|
112
|
+
ic_result.family,
|
|
113
|
+
f"{t_pd:.3f}" if t_pd > 0 else "",
|
|
114
|
+
f"{t_su:.3f}" if t_su > 0 else "",
|
|
115
|
+
f"{t_h:.3f}" if t_h > 0 else "",
|
|
116
|
+
f"{t_w:.3f}" if t_w > 0 else "",
|
|
117
|
+
validation_status,
|
|
118
|
+
]
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def export_bom_csv(
|
|
123
|
+
result: VintageLogicAnalysisResult,
|
|
124
|
+
path: str | Path,
|
|
125
|
+
) -> None:
|
|
126
|
+
"""Export bill of materials to CSV.
|
|
127
|
+
|
|
128
|
+
Creates a CSV file compatible with spreadsheet programs and procurement systems.
|
|
129
|
+
Columns: part_number, description, quantity, category, notes.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
result: Vintage logic analysis result.
|
|
133
|
+
path: Output CSV file path.
|
|
134
|
+
|
|
135
|
+
Example:
|
|
136
|
+
>>> export_bom_csv(result, "bom.csv")
|
|
137
|
+
"""
|
|
138
|
+
path = Path(path)
|
|
139
|
+
|
|
140
|
+
with path.open("w", newline="") as csvfile:
|
|
141
|
+
writer = csv.writer(csvfile)
|
|
142
|
+
|
|
143
|
+
# Write header
|
|
144
|
+
writer.writerow(["part_number", "description", "quantity", "category", "notes"])
|
|
145
|
+
|
|
146
|
+
# Write BOM entries
|
|
147
|
+
for entry in result.bom:
|
|
148
|
+
writer.writerow(
|
|
149
|
+
[
|
|
150
|
+
entry.part_number,
|
|
151
|
+
entry.description,
|
|
152
|
+
entry.quantity,
|
|
153
|
+
entry.category,
|
|
154
|
+
entry.notes or "",
|
|
155
|
+
]
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def export_voltage_levels_csv(
|
|
160
|
+
result: VintageLogicAnalysisResult,
|
|
161
|
+
path: str | Path,
|
|
162
|
+
) -> None:
|
|
163
|
+
"""Export voltage levels to CSV.
|
|
164
|
+
|
|
165
|
+
Creates a CSV file with measured voltage levels for the detected logic family.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
result: Vintage logic analysis result.
|
|
169
|
+
path: Output CSV file path.
|
|
170
|
+
|
|
171
|
+
Example:
|
|
172
|
+
>>> export_voltage_levels_csv(result, "voltage_levels.csv")
|
|
173
|
+
"""
|
|
174
|
+
path = Path(path)
|
|
175
|
+
|
|
176
|
+
with path.open("w", newline="") as csvfile:
|
|
177
|
+
writer = csv.writer(csvfile)
|
|
178
|
+
|
|
179
|
+
# Write header
|
|
180
|
+
writer.writerow(["parameter", "voltage_v", "logic_family"])
|
|
181
|
+
|
|
182
|
+
# Write voltage levels
|
|
183
|
+
for param, value in result.voltage_levels.items():
|
|
184
|
+
writer.writerow([param, f"{value:.3f}", result.detected_family])
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def export_all_vintage_logic_csv(
|
|
188
|
+
result: VintageLogicAnalysisResult,
|
|
189
|
+
output_dir: str | Path,
|
|
190
|
+
*,
|
|
191
|
+
prefix: str = "",
|
|
192
|
+
) -> dict[str, Path]:
|
|
193
|
+
"""Export all vintage logic analysis data to CSV files.
|
|
194
|
+
|
|
195
|
+
Convenience function that exports all data types to separate CSV files.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
result: Vintage logic analysis result.
|
|
199
|
+
output_dir: Output directory for CSV files.
|
|
200
|
+
prefix: Optional prefix for file names.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
Dictionary mapping data type to output file path.
|
|
204
|
+
|
|
205
|
+
Example:
|
|
206
|
+
>>> paths = export_all_vintage_logic_csv(result, "./output", prefix="analysis_")
|
|
207
|
+
>>> print(paths["bom"]) # PosixPath('./output/analysis_bom.csv')
|
|
208
|
+
"""
|
|
209
|
+
output_dir = Path(output_dir)
|
|
210
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
211
|
+
|
|
212
|
+
paths: dict[str, Path] = {}
|
|
213
|
+
|
|
214
|
+
# Export timing measurements
|
|
215
|
+
if result.timing_measurements:
|
|
216
|
+
timing_path = output_dir / f"{prefix}timing_measurements.csv"
|
|
217
|
+
export_timing_measurements_csv(result, timing_path)
|
|
218
|
+
paths["timing_measurements"] = timing_path
|
|
219
|
+
|
|
220
|
+
# Export IC identification
|
|
221
|
+
if result.identified_ics:
|
|
222
|
+
ic_path = output_dir / f"{prefix}ic_identification.csv"
|
|
223
|
+
export_ic_identification_csv(result, ic_path)
|
|
224
|
+
paths["ic_identification"] = ic_path
|
|
225
|
+
|
|
226
|
+
# Export BOM
|
|
227
|
+
if result.bom:
|
|
228
|
+
bom_path = output_dir / f"{prefix}bom.csv"
|
|
229
|
+
export_bom_csv(result, bom_path)
|
|
230
|
+
paths["bom"] = bom_path
|
|
231
|
+
|
|
232
|
+
# Export voltage levels
|
|
233
|
+
if result.voltage_levels:
|
|
234
|
+
voltage_path = output_dir / f"{prefix}voltage_levels.csv"
|
|
235
|
+
export_voltage_levels_csv(result, voltage_path)
|
|
236
|
+
paths["voltage_levels"] = voltage_path
|
|
237
|
+
|
|
238
|
+
return paths
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
__all__ = [
|
|
242
|
+
"export_all_vintage_logic_csv",
|
|
243
|
+
"export_bom_csv",
|
|
244
|
+
"export_ic_identification_csv",
|
|
245
|
+
"export_timing_measurements_csv",
|
|
246
|
+
"export_voltage_levels_csv",
|
|
247
|
+
]
|
oscura/reporting/__init__.py
CHANGED
|
@@ -138,6 +138,10 @@ from oscura.reporting.template_system import (
|
|
|
138
138
|
list_templates,
|
|
139
139
|
load_template,
|
|
140
140
|
)
|
|
141
|
+
from oscura.reporting.vintage_logic_report import (
|
|
142
|
+
VintageLogicReport,
|
|
143
|
+
generate_vintage_logic_report,
|
|
144
|
+
)
|
|
141
145
|
|
|
142
146
|
__all__ = [
|
|
143
147
|
# Comprehensive Analysis Report API (CAR-001 through CAR-007)
|
|
@@ -187,6 +191,8 @@ __all__ = [
|
|
|
187
191
|
"TemplateEngine",
|
|
188
192
|
"TemplateSection",
|
|
189
193
|
"UnsupportedFormatError",
|
|
194
|
+
# Vintage Logic Reporting
|
|
195
|
+
"VintageLogicReport",
|
|
190
196
|
"VisualEmphasis",
|
|
191
197
|
"aggregate_batch_measurements",
|
|
192
198
|
"analyze",
|
|
@@ -235,6 +241,7 @@ __all__ = [
|
|
|
235
241
|
"generate_presentation_from_report",
|
|
236
242
|
"generate_report",
|
|
237
243
|
"generate_summary",
|
|
244
|
+
"generate_vintage_logic_report",
|
|
238
245
|
"get_available_analyses",
|
|
239
246
|
"get_axis_scaling",
|
|
240
247
|
"list_templates",
|