oscura 0.5.0__py3-none-any.whl → 0.6.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 +169 -167
- oscura/analyzers/__init__.py +3 -0
- oscura/analyzers/classification.py +659 -0
- oscura/analyzers/digital/__init__.py +0 -48
- oscura/analyzers/digital/edges.py +325 -65
- oscura/analyzers/digital/extraction.py +0 -195
- oscura/analyzers/digital/quality.py +293 -166
- oscura/analyzers/digital/timing.py +260 -115
- oscura/analyzers/digital/timing_numba.py +334 -0
- oscura/analyzers/entropy.py +605 -0
- oscura/analyzers/eye/diagram.py +176 -109
- oscura/analyzers/eye/metrics.py +5 -5
- oscura/analyzers/jitter/__init__.py +6 -4
- oscura/analyzers/jitter/ber.py +52 -52
- oscura/analyzers/jitter/classification.py +156 -0
- oscura/analyzers/jitter/decomposition.py +163 -113
- oscura/analyzers/jitter/spectrum.py +80 -64
- oscura/analyzers/ml/__init__.py +39 -0
- oscura/analyzers/ml/features.py +600 -0
- oscura/analyzers/ml/signal_classifier.py +604 -0
- oscura/analyzers/packet/daq.py +246 -158
- oscura/analyzers/packet/parser.py +12 -1
- oscura/analyzers/packet/payload.py +50 -2110
- oscura/analyzers/packet/payload_analysis.py +361 -181
- oscura/analyzers/packet/payload_patterns.py +133 -70
- oscura/analyzers/packet/stream.py +84 -23
- oscura/analyzers/patterns/__init__.py +26 -5
- oscura/analyzers/patterns/anomaly_detection.py +908 -0
- oscura/analyzers/patterns/clustering.py +169 -108
- oscura/analyzers/patterns/clustering_optimized.py +227 -0
- oscura/analyzers/patterns/discovery.py +1 -1
- oscura/analyzers/patterns/matching.py +581 -197
- oscura/analyzers/patterns/pattern_mining.py +778 -0
- oscura/analyzers/patterns/periodic.py +121 -38
- oscura/analyzers/patterns/sequences.py +175 -78
- oscura/analyzers/power/conduction.py +1 -1
- oscura/analyzers/power/soa.py +6 -6
- oscura/analyzers/power/switching.py +250 -110
- oscura/analyzers/protocol/__init__.py +17 -1
- oscura/analyzers/protocols/__init__.py +1 -22
- oscura/analyzers/protocols/base.py +6 -6
- oscura/analyzers/protocols/ble/__init__.py +38 -0
- oscura/analyzers/protocols/ble/analyzer.py +809 -0
- oscura/analyzers/protocols/ble/uuids.py +288 -0
- oscura/analyzers/protocols/can.py +257 -127
- oscura/analyzers/protocols/can_fd.py +107 -80
- oscura/analyzers/protocols/flexray.py +139 -80
- oscura/analyzers/protocols/hdlc.py +93 -58
- oscura/analyzers/protocols/i2c.py +247 -106
- oscura/analyzers/protocols/i2s.py +138 -86
- oscura/analyzers/protocols/industrial/__init__.py +40 -0
- oscura/analyzers/protocols/industrial/bacnet/__init__.py +33 -0
- oscura/analyzers/protocols/industrial/bacnet/analyzer.py +708 -0
- oscura/analyzers/protocols/industrial/bacnet/encoding.py +412 -0
- oscura/analyzers/protocols/industrial/bacnet/services.py +622 -0
- oscura/analyzers/protocols/industrial/ethercat/__init__.py +30 -0
- oscura/analyzers/protocols/industrial/ethercat/analyzer.py +474 -0
- oscura/analyzers/protocols/industrial/ethercat/mailbox.py +339 -0
- oscura/analyzers/protocols/industrial/ethercat/topology.py +166 -0
- oscura/analyzers/protocols/industrial/modbus/__init__.py +31 -0
- oscura/analyzers/protocols/industrial/modbus/analyzer.py +525 -0
- oscura/analyzers/protocols/industrial/modbus/crc.py +79 -0
- oscura/analyzers/protocols/industrial/modbus/functions.py +436 -0
- oscura/analyzers/protocols/industrial/opcua/__init__.py +21 -0
- oscura/analyzers/protocols/industrial/opcua/analyzer.py +552 -0
- oscura/analyzers/protocols/industrial/opcua/datatypes.py +446 -0
- oscura/analyzers/protocols/industrial/opcua/services.py +264 -0
- oscura/analyzers/protocols/industrial/profinet/__init__.py +23 -0
- oscura/analyzers/protocols/industrial/profinet/analyzer.py +441 -0
- oscura/analyzers/protocols/industrial/profinet/dcp.py +263 -0
- oscura/analyzers/protocols/industrial/profinet/ptcp.py +200 -0
- oscura/analyzers/protocols/jtag.py +180 -98
- oscura/analyzers/protocols/lin.py +219 -114
- oscura/analyzers/protocols/manchester.py +4 -4
- oscura/analyzers/protocols/onewire.py +253 -149
- oscura/analyzers/protocols/parallel_bus/__init__.py +20 -0
- oscura/analyzers/protocols/parallel_bus/centronics.py +92 -0
- oscura/analyzers/protocols/parallel_bus/gpib.py +137 -0
- oscura/analyzers/protocols/spi.py +192 -95
- oscura/analyzers/protocols/swd.py +321 -167
- oscura/analyzers/protocols/uart.py +267 -125
- oscura/analyzers/protocols/usb.py +235 -131
- oscura/analyzers/side_channel/power.py +17 -12
- oscura/analyzers/signal/__init__.py +15 -0
- oscura/analyzers/signal/timing_analysis.py +1086 -0
- oscura/analyzers/signal_integrity/__init__.py +4 -1
- oscura/analyzers/signal_integrity/sparams.py +2 -19
- oscura/analyzers/spectral/chunked.py +129 -60
- oscura/analyzers/spectral/chunked_fft.py +300 -94
- oscura/analyzers/spectral/chunked_wavelet.py +100 -80
- oscura/analyzers/statistical/checksum.py +376 -217
- oscura/analyzers/statistical/classification.py +229 -107
- oscura/analyzers/statistical/entropy.py +78 -53
- oscura/analyzers/statistics/correlation.py +407 -211
- oscura/analyzers/statistics/outliers.py +2 -2
- oscura/analyzers/statistics/streaming.py +30 -5
- oscura/analyzers/validation.py +216 -101
- oscura/analyzers/waveform/measurements.py +9 -0
- oscura/analyzers/waveform/measurements_with_uncertainty.py +31 -15
- oscura/analyzers/waveform/spectral.py +500 -228
- oscura/api/__init__.py +31 -5
- oscura/api/dsl/__init__.py +582 -0
- oscura/{dsl → api/dsl}/commands.py +43 -76
- oscura/{dsl → api/dsl}/interpreter.py +26 -51
- oscura/{dsl → api/dsl}/parser.py +107 -77
- oscura/{dsl → api/dsl}/repl.py +2 -2
- oscura/api/dsl.py +1 -1
- oscura/{integrations → api/integrations}/__init__.py +1 -1
- oscura/{integrations → api/integrations}/llm.py +201 -102
- oscura/api/operators.py +3 -3
- oscura/api/optimization.py +144 -30
- oscura/api/rest_server.py +921 -0
- oscura/api/server/__init__.py +17 -0
- oscura/api/server/dashboard.py +850 -0
- oscura/api/server/static/README.md +34 -0
- oscura/api/server/templates/base.html +181 -0
- oscura/api/server/templates/export.html +120 -0
- oscura/api/server/templates/home.html +284 -0
- oscura/api/server/templates/protocols.html +58 -0
- oscura/api/server/templates/reports.html +43 -0
- oscura/api/server/templates/session_detail.html +89 -0
- oscura/api/server/templates/sessions.html +83 -0
- oscura/api/server/templates/waveforms.html +73 -0
- oscura/automotive/__init__.py +8 -1
- oscura/automotive/can/__init__.py +10 -0
- oscura/automotive/can/checksum.py +3 -1
- oscura/automotive/can/dbc_generator.py +590 -0
- oscura/automotive/can/message_wrapper.py +121 -74
- oscura/automotive/can/patterns.py +98 -21
- oscura/automotive/can/session.py +292 -56
- oscura/automotive/can/state_machine.py +6 -3
- oscura/automotive/can/stimulus_response.py +97 -75
- oscura/automotive/dbc/__init__.py +10 -2
- oscura/automotive/dbc/generator.py +84 -56
- oscura/automotive/dbc/parser.py +6 -6
- oscura/automotive/dtc/data.json +2763 -0
- oscura/automotive/dtc/database.py +2 -2
- oscura/automotive/flexray/__init__.py +31 -0
- oscura/automotive/flexray/analyzer.py +504 -0
- oscura/automotive/flexray/crc.py +185 -0
- oscura/automotive/flexray/fibex.py +449 -0
- oscura/automotive/j1939/__init__.py +45 -8
- oscura/automotive/j1939/analyzer.py +605 -0
- oscura/automotive/j1939/spns.py +326 -0
- oscura/automotive/j1939/transport.py +306 -0
- oscura/automotive/lin/__init__.py +47 -0
- oscura/automotive/lin/analyzer.py +612 -0
- oscura/automotive/loaders/blf.py +13 -2
- oscura/automotive/loaders/csv_can.py +143 -72
- oscura/automotive/loaders/dispatcher.py +50 -2
- oscura/automotive/loaders/mdf.py +86 -45
- oscura/automotive/loaders/pcap.py +111 -61
- oscura/automotive/uds/__init__.py +4 -0
- oscura/automotive/uds/analyzer.py +725 -0
- oscura/automotive/uds/decoder.py +140 -58
- oscura/automotive/uds/models.py +7 -1
- oscura/automotive/visualization.py +1 -1
- oscura/cli/analyze.py +348 -0
- oscura/cli/batch.py +142 -122
- oscura/cli/benchmark.py +275 -0
- oscura/cli/characterize.py +137 -82
- oscura/cli/compare.py +224 -131
- oscura/cli/completion.py +250 -0
- oscura/cli/config_cmd.py +361 -0
- oscura/cli/decode.py +164 -87
- oscura/cli/export.py +286 -0
- oscura/cli/main.py +115 -31
- oscura/{onboarding → cli/onboarding}/__init__.py +3 -3
- oscura/{onboarding → cli/onboarding}/help.py +80 -58
- oscura/{onboarding → cli/onboarding}/tutorials.py +97 -72
- oscura/{onboarding → cli/onboarding}/wizard.py +55 -36
- oscura/cli/progress.py +147 -0
- oscura/cli/shell.py +157 -135
- oscura/cli/validate_cmd.py +204 -0
- oscura/cli/visualize.py +158 -0
- oscura/convenience.py +125 -79
- oscura/core/__init__.py +4 -2
- oscura/core/backend_selector.py +3 -3
- oscura/core/cache.py +126 -15
- oscura/core/cancellation.py +1 -1
- oscura/{config → core/config}/__init__.py +20 -11
- oscura/{config → core/config}/defaults.py +1 -1
- oscura/{config → core/config}/loader.py +7 -5
- oscura/{config → core/config}/memory.py +5 -5
- oscura/{config → core/config}/migration.py +1 -1
- oscura/{config → core/config}/pipeline.py +99 -23
- oscura/{config → core/config}/preferences.py +1 -1
- oscura/{config → core/config}/protocol.py +3 -3
- oscura/{config → core/config}/schema.py +426 -272
- oscura/{config → core/config}/settings.py +1 -1
- oscura/{config → core/config}/thresholds.py +195 -153
- oscura/core/correlation.py +5 -6
- oscura/core/cross_domain.py +0 -2
- oscura/core/debug.py +9 -5
- oscura/{extensibility → core/extensibility}/docs.py +158 -70
- oscura/{extensibility → core/extensibility}/extensions.py +160 -76
- oscura/{extensibility → core/extensibility}/logging.py +1 -1
- oscura/{extensibility → core/extensibility}/measurements.py +1 -1
- oscura/{extensibility → core/extensibility}/plugins.py +1 -1
- oscura/{extensibility → core/extensibility}/templates.py +73 -3
- oscura/{extensibility → core/extensibility}/validation.py +1 -1
- oscura/core/gpu_backend.py +11 -7
- oscura/core/log_query.py +101 -11
- oscura/core/logging.py +126 -54
- oscura/core/logging_advanced.py +5 -5
- oscura/core/memory_limits.py +108 -70
- oscura/core/memory_monitor.py +2 -2
- oscura/core/memory_progress.py +7 -7
- oscura/core/memory_warnings.py +1 -1
- oscura/core/numba_backend.py +13 -13
- oscura/{plugins → core/plugins}/__init__.py +9 -9
- oscura/{plugins → core/plugins}/base.py +7 -7
- oscura/{plugins → core/plugins}/cli.py +3 -3
- oscura/{plugins → core/plugins}/discovery.py +186 -106
- oscura/{plugins → core/plugins}/lifecycle.py +1 -1
- oscura/{plugins → core/plugins}/manager.py +7 -7
- oscura/{plugins → core/plugins}/registry.py +3 -3
- oscura/{plugins → core/plugins}/versioning.py +1 -1
- oscura/core/progress.py +16 -1
- oscura/core/provenance.py +8 -2
- oscura/{schemas → core/schemas}/__init__.py +2 -2
- oscura/core/schemas/bus_configuration.json +322 -0
- oscura/core/schemas/device_mapping.json +182 -0
- oscura/core/schemas/packet_format.json +418 -0
- oscura/core/schemas/protocol_definition.json +363 -0
- oscura/core/types.py +4 -0
- oscura/core/uncertainty.py +3 -3
- oscura/correlation/__init__.py +52 -0
- oscura/correlation/multi_protocol.py +811 -0
- oscura/discovery/auto_decoder.py +117 -35
- oscura/discovery/comparison.py +191 -86
- oscura/discovery/quality_validator.py +155 -68
- oscura/discovery/signal_detector.py +196 -79
- oscura/export/__init__.py +18 -20
- oscura/export/kaitai_struct.py +513 -0
- oscura/export/scapy_layer.py +801 -0
- oscura/export/wireshark/README.md +15 -15
- oscura/export/wireshark/generator.py +1 -1
- oscura/export/wireshark/templates/dissector.lua.j2 +2 -2
- oscura/export/wireshark_dissector.py +746 -0
- oscura/guidance/wizard.py +207 -111
- oscura/hardware/__init__.py +19 -0
- oscura/{acquisition → hardware/acquisition}/__init__.py +4 -4
- oscura/{acquisition → hardware/acquisition}/file.py +2 -2
- oscura/{acquisition → hardware/acquisition}/hardware.py +7 -7
- oscura/{acquisition → hardware/acquisition}/saleae.py +15 -12
- oscura/{acquisition → hardware/acquisition}/socketcan.py +1 -1
- oscura/{acquisition → hardware/acquisition}/streaming.py +2 -2
- oscura/{acquisition → hardware/acquisition}/synthetic.py +3 -3
- oscura/{acquisition → hardware/acquisition}/visa.py +33 -11
- oscura/hardware/firmware/__init__.py +29 -0
- oscura/hardware/firmware/pattern_recognition.py +874 -0
- oscura/hardware/hal_detector.py +736 -0
- oscura/hardware/security/__init__.py +37 -0
- oscura/hardware/security/side_channel_detector.py +1126 -0
- oscura/inference/__init__.py +4 -0
- oscura/inference/active_learning/README.md +7 -7
- oscura/inference/active_learning/observation_table.py +4 -1
- oscura/inference/alignment.py +216 -123
- oscura/inference/bayesian.py +113 -33
- oscura/inference/crc_reverse.py +101 -55
- oscura/inference/logic.py +6 -2
- oscura/inference/message_format.py +342 -183
- oscura/inference/protocol.py +95 -44
- oscura/inference/protocol_dsl.py +180 -82
- oscura/inference/signal_intelligence.py +1439 -706
- oscura/inference/spectral.py +99 -57
- oscura/inference/state_machine.py +810 -158
- oscura/inference/stream.py +270 -110
- oscura/iot/__init__.py +34 -0
- oscura/iot/coap/__init__.py +32 -0
- oscura/iot/coap/analyzer.py +668 -0
- oscura/iot/coap/options.py +212 -0
- oscura/iot/lorawan/__init__.py +21 -0
- oscura/iot/lorawan/crypto.py +206 -0
- oscura/iot/lorawan/decoder.py +801 -0
- oscura/iot/lorawan/mac_commands.py +341 -0
- oscura/iot/mqtt/__init__.py +27 -0
- oscura/iot/mqtt/analyzer.py +999 -0
- oscura/iot/mqtt/properties.py +315 -0
- oscura/iot/zigbee/__init__.py +31 -0
- oscura/iot/zigbee/analyzer.py +615 -0
- oscura/iot/zigbee/security.py +153 -0
- oscura/iot/zigbee/zcl.py +349 -0
- oscura/jupyter/display.py +125 -45
- oscura/{exploratory → jupyter/exploratory}/__init__.py +8 -8
- oscura/{exploratory → jupyter/exploratory}/error_recovery.py +298 -141
- oscura/jupyter/exploratory/fuzzy.py +746 -0
- oscura/{exploratory → jupyter/exploratory}/fuzzy_advanced.py +258 -100
- oscura/{exploratory → jupyter/exploratory}/legacy.py +464 -242
- oscura/{exploratory → jupyter/exploratory}/parse.py +167 -145
- oscura/{exploratory → jupyter/exploratory}/recovery.py +119 -87
- oscura/jupyter/exploratory/sync.py +612 -0
- oscura/{exploratory → jupyter/exploratory}/unknown.py +299 -176
- oscura/jupyter/magic.py +4 -4
- oscura/{ui → jupyter/ui}/__init__.py +2 -2
- oscura/{ui → jupyter/ui}/formatters.py +3 -3
- oscura/{ui → jupyter/ui}/progressive_display.py +153 -82
- oscura/loaders/__init__.py +171 -63
- oscura/loaders/binary.py +88 -1
- oscura/loaders/chipwhisperer.py +153 -137
- oscura/loaders/configurable.py +208 -86
- oscura/loaders/csv_loader.py +458 -215
- oscura/loaders/hdf5_loader.py +278 -119
- oscura/loaders/lazy.py +87 -54
- oscura/loaders/mmap_loader.py +1 -1
- oscura/loaders/numpy_loader.py +253 -116
- oscura/loaders/pcap.py +226 -151
- oscura/loaders/rigol.py +110 -49
- oscura/loaders/sigrok.py +201 -78
- oscura/loaders/tdms.py +81 -58
- oscura/loaders/tektronix.py +291 -174
- oscura/loaders/touchstone.py +182 -87
- oscura/loaders/vcd.py +215 -117
- oscura/loaders/wav.py +155 -68
- oscura/reporting/__init__.py +9 -7
- oscura/reporting/analyze.py +352 -146
- oscura/reporting/argument_preparer.py +69 -14
- oscura/reporting/auto_report.py +97 -61
- oscura/reporting/batch.py +131 -58
- oscura/reporting/chart_selection.py +57 -45
- oscura/reporting/comparison.py +63 -17
- oscura/reporting/content/executive.py +76 -24
- oscura/reporting/core_formats/multi_format.py +11 -8
- oscura/reporting/engine.py +312 -158
- oscura/reporting/enhanced_reports.py +949 -0
- oscura/reporting/export.py +86 -43
- oscura/reporting/formatting/numbers.py +69 -42
- oscura/reporting/html.py +139 -58
- oscura/reporting/index.py +137 -65
- oscura/reporting/output.py +158 -67
- oscura/reporting/pdf.py +67 -102
- oscura/reporting/plots.py +191 -112
- oscura/reporting/sections.py +88 -47
- oscura/reporting/standards.py +104 -61
- oscura/reporting/summary_generator.py +75 -55
- oscura/reporting/tables.py +138 -54
- oscura/reporting/templates/enhanced/protocol_re.html +525 -0
- oscura/reporting/templates/index.md +13 -13
- oscura/sessions/__init__.py +14 -23
- oscura/sessions/base.py +3 -3
- oscura/sessions/blackbox.py +106 -10
- oscura/sessions/generic.py +2 -2
- oscura/sessions/legacy.py +783 -0
- oscura/side_channel/__init__.py +63 -0
- oscura/side_channel/dpa.py +1025 -0
- oscura/utils/__init__.py +15 -1
- oscura/utils/autodetect.py +1 -5
- oscura/utils/bitwise.py +118 -0
- oscura/{builders → utils/builders}/__init__.py +1 -1
- oscura/{comparison → utils/comparison}/__init__.py +6 -6
- oscura/{comparison → utils/comparison}/compare.py +202 -101
- oscura/{comparison → utils/comparison}/golden.py +83 -63
- oscura/{comparison → utils/comparison}/limits.py +313 -89
- oscura/{comparison → utils/comparison}/mask.py +151 -45
- oscura/{comparison → utils/comparison}/trace_diff.py +1 -1
- oscura/{comparison → utils/comparison}/visualization.py +147 -89
- oscura/{component → utils/component}/__init__.py +3 -3
- oscura/{component → utils/component}/impedance.py +122 -58
- oscura/{component → utils/component}/reactive.py +165 -168
- oscura/{component → utils/component}/transmission_line.py +3 -3
- oscura/{filtering → utils/filtering}/__init__.py +6 -6
- oscura/{filtering → utils/filtering}/base.py +1 -1
- oscura/{filtering → utils/filtering}/convenience.py +2 -2
- oscura/{filtering → utils/filtering}/design.py +169 -93
- oscura/{filtering → utils/filtering}/filters.py +2 -2
- oscura/{filtering → utils/filtering}/introspection.py +2 -2
- oscura/utils/geometry.py +31 -0
- oscura/utils/imports.py +184 -0
- oscura/utils/lazy.py +1 -1
- oscura/{math → utils/math}/__init__.py +2 -2
- oscura/{math → utils/math}/arithmetic.py +114 -48
- oscura/{math → utils/math}/interpolation.py +139 -106
- oscura/utils/memory.py +129 -66
- oscura/utils/memory_advanced.py +92 -9
- oscura/utils/memory_extensions.py +10 -8
- oscura/{optimization → utils/optimization}/__init__.py +1 -1
- oscura/{optimization → utils/optimization}/search.py +2 -2
- oscura/utils/performance/__init__.py +58 -0
- oscura/utils/performance/caching.py +889 -0
- oscura/utils/performance/lsh_clustering.py +333 -0
- oscura/utils/performance/memory_optimizer.py +699 -0
- oscura/utils/performance/optimizations.py +675 -0
- oscura/utils/performance/parallel.py +654 -0
- oscura/utils/performance/profiling.py +661 -0
- oscura/{pipeline → utils/pipeline}/base.py +1 -1
- oscura/{pipeline → utils/pipeline}/composition.py +11 -3
- oscura/{pipeline → utils/pipeline}/parallel.py +3 -2
- oscura/{pipeline → utils/pipeline}/pipeline.py +1 -1
- oscura/{pipeline → utils/pipeline}/reverse_engineering.py +412 -221
- oscura/{search → utils/search}/__init__.py +3 -3
- oscura/{search → utils/search}/anomaly.py +188 -58
- oscura/utils/search/context.py +294 -0
- oscura/{search → utils/search}/pattern.py +138 -10
- oscura/utils/serial.py +51 -0
- oscura/utils/storage/__init__.py +61 -0
- oscura/utils/storage/database.py +1166 -0
- oscura/{streaming → utils/streaming}/chunked.py +302 -143
- oscura/{streaming → utils/streaming}/progressive.py +1 -1
- oscura/{streaming → utils/streaming}/realtime.py +3 -2
- oscura/{triggering → utils/triggering}/__init__.py +6 -6
- oscura/{triggering → utils/triggering}/base.py +6 -6
- oscura/{triggering → utils/triggering}/edge.py +2 -2
- oscura/{triggering → utils/triggering}/pattern.py +2 -2
- oscura/{triggering → utils/triggering}/pulse.py +115 -74
- oscura/{triggering → utils/triggering}/window.py +2 -2
- oscura/utils/validation.py +32 -0
- oscura/validation/__init__.py +121 -0
- oscura/{compliance → validation/compliance}/__init__.py +5 -5
- oscura/{compliance → validation/compliance}/advanced.py +5 -5
- oscura/{compliance → validation/compliance}/masks.py +1 -1
- oscura/{compliance → validation/compliance}/reporting.py +127 -53
- oscura/{compliance → validation/compliance}/testing.py +114 -52
- oscura/validation/compliance_tests.py +915 -0
- oscura/validation/fuzzer.py +990 -0
- oscura/validation/grammar_tests.py +596 -0
- oscura/validation/grammar_validator.py +904 -0
- oscura/validation/hil_testing.py +977 -0
- oscura/{quality → validation/quality}/__init__.py +4 -4
- oscura/{quality → validation/quality}/ensemble.py +251 -171
- oscura/{quality → validation/quality}/explainer.py +3 -3
- oscura/{quality → validation/quality}/scoring.py +1 -1
- oscura/{quality → validation/quality}/warnings.py +4 -4
- oscura/validation/regression_suite.py +808 -0
- oscura/validation/replay.py +788 -0
- oscura/{testing → validation/testing}/__init__.py +2 -2
- oscura/{testing → validation/testing}/synthetic.py +5 -5
- oscura/visualization/__init__.py +9 -0
- oscura/visualization/accessibility.py +1 -1
- oscura/visualization/annotations.py +64 -67
- oscura/visualization/colors.py +7 -7
- oscura/visualization/digital.py +180 -81
- oscura/visualization/eye.py +236 -85
- oscura/visualization/interactive.py +320 -143
- oscura/visualization/jitter.py +587 -247
- oscura/visualization/layout.py +169 -134
- oscura/visualization/optimization.py +103 -52
- oscura/visualization/palettes.py +1 -1
- oscura/visualization/power.py +427 -211
- oscura/visualization/power_extended.py +626 -297
- oscura/visualization/presets.py +2 -0
- oscura/visualization/protocols.py +495 -181
- oscura/visualization/render.py +79 -63
- oscura/visualization/reverse_engineering.py +171 -124
- oscura/visualization/signal_integrity.py +460 -279
- oscura/visualization/specialized.py +190 -100
- oscura/visualization/spectral.py +670 -255
- oscura/visualization/thumbnails.py +166 -137
- oscura/visualization/waveform.py +150 -63
- oscura/workflows/__init__.py +3 -0
- oscura/{batch → workflows/batch}/__init__.py +5 -5
- oscura/{batch → workflows/batch}/advanced.py +150 -75
- oscura/workflows/batch/aggregate.py +531 -0
- oscura/workflows/batch/analyze.py +236 -0
- oscura/{batch → workflows/batch}/logging.py +2 -2
- oscura/{batch → workflows/batch}/metrics.py +1 -1
- oscura/workflows/complete_re.py +1144 -0
- oscura/workflows/compliance.py +44 -54
- oscura/workflows/digital.py +197 -51
- oscura/workflows/legacy/__init__.py +12 -0
- oscura/{workflow → workflows/legacy}/dag.py +4 -1
- oscura/workflows/multi_trace.py +9 -9
- oscura/workflows/power.py +42 -62
- oscura/workflows/protocol.py +82 -49
- oscura/workflows/reverse_engineering.py +351 -150
- oscura/workflows/signal_integrity.py +157 -82
- oscura-0.6.0.dist-info/METADATA +643 -0
- oscura-0.6.0.dist-info/RECORD +590 -0
- oscura/analyzers/digital/ic_database.py +0 -498
- oscura/analyzers/digital/timing_paths.py +0 -339
- oscura/analyzers/digital/vintage.py +0 -377
- oscura/analyzers/digital/vintage_result.py +0 -148
- oscura/analyzers/protocols/parallel_bus.py +0 -449
- oscura/batch/aggregate.py +0 -300
- oscura/batch/analyze.py +0 -139
- oscura/dsl/__init__.py +0 -73
- oscura/exceptions.py +0 -59
- oscura/exploratory/fuzzy.py +0 -513
- oscura/exploratory/sync.py +0 -384
- oscura/export/wavedrom.py +0 -430
- oscura/exporters/__init__.py +0 -94
- oscura/exporters/csv.py +0 -303
- oscura/exporters/exporters.py +0 -44
- oscura/exporters/hdf5.py +0 -217
- oscura/exporters/html_export.py +0 -701
- oscura/exporters/json_export.py +0 -338
- oscura/exporters/markdown_export.py +0 -367
- oscura/exporters/matlab_export.py +0 -354
- oscura/exporters/npz_export.py +0 -219
- oscura/exporters/spice_export.py +0 -210
- oscura/exporters/vintage_logic_csv.py +0 -247
- oscura/reporting/vintage_logic_report.py +0 -523
- oscura/search/context.py +0 -149
- oscura/session/__init__.py +0 -34
- oscura/session/annotations.py +0 -289
- oscura/session/history.py +0 -313
- oscura/session/session.py +0 -520
- oscura/visualization/digital_advanced.py +0 -718
- oscura/visualization/figure_manager.py +0 -156
- oscura/workflow/__init__.py +0 -13
- oscura-0.5.0.dist-info/METADATA +0 -407
- oscura-0.5.0.dist-info/RECORD +0 -486
- /oscura/core/{config.py → config/legacy.py} +0 -0
- /oscura/{extensibility → core/extensibility}/__init__.py +0 -0
- /oscura/{extensibility → core/extensibility}/registry.py +0 -0
- /oscura/{plugins → core/plugins}/isolation.py +0 -0
- /oscura/{builders → utils/builders}/signal_builder.py +0 -0
- /oscura/{optimization → utils/optimization}/parallel.py +0 -0
- /oscura/{pipeline → utils/pipeline}/__init__.py +0 -0
- /oscura/{streaming → utils/streaming}/__init__.py +0 -0
- {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/WHEEL +0 -0
- {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/entry_points.txt +0 -0
- {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/licenses/LICENSE +0 -0
oscura/exporters/spice_export.py
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
"""SPICE PWL export functionality for Oscura.
|
|
2
|
-
|
|
3
|
-
This module provides export to SPICE Piece-Wise Linear (PWL) format for
|
|
4
|
-
use in circuit simulation tools like LTspice, ngspice, Cadence, etc.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Example:
|
|
8
|
-
>>> from oscura.exporters.spice_export import export_pwl
|
|
9
|
-
>>> export_pwl(trace, "stimulus.pwl")
|
|
10
|
-
>>> # Use in SPICE: V1 in 0 PWL file=stimulus.pwl
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from __future__ import annotations
|
|
14
|
-
|
|
15
|
-
from pathlib import Path
|
|
16
|
-
from typing import TYPE_CHECKING, Any
|
|
17
|
-
|
|
18
|
-
import numpy as np
|
|
19
|
-
|
|
20
|
-
from oscura.core.types import DigitalTrace, WaveformTrace
|
|
21
|
-
|
|
22
|
-
if TYPE_CHECKING:
|
|
23
|
-
from numpy.typing import NDArray
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def export_pwl(
|
|
27
|
-
data: WaveformTrace | DigitalTrace | NDArray[Any] | tuple[NDArray[Any], NDArray[Any]],
|
|
28
|
-
path: str | Path,
|
|
29
|
-
*,
|
|
30
|
-
time_scale: float = 1.0,
|
|
31
|
-
amplitude_scale: float = 1.0,
|
|
32
|
-
time_offset: float = 0.0,
|
|
33
|
-
amplitude_offset: float = 0.0,
|
|
34
|
-
precision: int = 12,
|
|
35
|
-
comment: str | None = None,
|
|
36
|
-
downsample: int = 1,
|
|
37
|
-
format_style: str = "ltspice",
|
|
38
|
-
) -> None:
|
|
39
|
-
"""Export data to SPICE PWL (Piece-Wise Linear) format.
|
|
40
|
-
|
|
41
|
-
Creates a PWL file that can be used as a stimulus source in SPICE
|
|
42
|
-
circuit simulators. The format consists of time-value pairs.
|
|
43
|
-
|
|
44
|
-
Args:
|
|
45
|
-
data: Data to export. Can be:
|
|
46
|
-
- WaveformTrace or DigitalTrace
|
|
47
|
-
- NumPy array (uses trace.time_vector or generates index-based time)
|
|
48
|
-
- Tuple of (time_array, value_array)
|
|
49
|
-
path: Output file path.
|
|
50
|
-
time_scale: Scaling factor for time values (e.g., 1e-9 for ns).
|
|
51
|
-
amplitude_scale: Scaling factor for amplitude values.
|
|
52
|
-
time_offset: Offset to add to all time values.
|
|
53
|
-
amplitude_offset: Offset to add to all amplitude values.
|
|
54
|
-
precision: Decimal precision for output values.
|
|
55
|
-
comment: Optional comment to include at top of file.
|
|
56
|
-
downsample: Downsample factor to reduce file size (1 = no downsampling).
|
|
57
|
-
format_style: Output format style:
|
|
58
|
-
- "ltspice": LTspice compatible (time value pairs)
|
|
59
|
-
- "ngspice": ngspice compatible (same as ltspice)
|
|
60
|
-
- "hspice": HSPICE compatible (with header)
|
|
61
|
-
|
|
62
|
-
Raises:
|
|
63
|
-
TypeError: If data type is not supported.
|
|
64
|
-
|
|
65
|
-
Example:
|
|
66
|
-
>>> # Export as stimulus for simulation
|
|
67
|
-
>>> export_pwl(trace, "input.pwl")
|
|
68
|
-
>>> # In LTspice: V1 in 0 PWL file=input.pwl
|
|
69
|
-
|
|
70
|
-
>>> # Scale time to nanoseconds for display
|
|
71
|
-
>>> export_pwl(trace, "input.pwl", time_scale=1e9)
|
|
72
|
-
|
|
73
|
-
References:
|
|
74
|
-
EXP-005
|
|
75
|
-
"""
|
|
76
|
-
path = Path(path)
|
|
77
|
-
|
|
78
|
-
# Extract time and value arrays
|
|
79
|
-
if isinstance(data, WaveformTrace | DigitalTrace):
|
|
80
|
-
time = data.time_vector
|
|
81
|
-
values = data.data
|
|
82
|
-
elif isinstance(data, tuple) and len(data) == 2:
|
|
83
|
-
time, values = data
|
|
84
|
-
elif isinstance(data, np.ndarray):
|
|
85
|
-
# Generate time based on array index (assume 1 unit per sample)
|
|
86
|
-
time = np.arange(len(data), dtype=np.float64)
|
|
87
|
-
values = data
|
|
88
|
-
else:
|
|
89
|
-
raise TypeError(f"Unsupported data type: {type(data)}")
|
|
90
|
-
|
|
91
|
-
# Apply downsampling
|
|
92
|
-
if downsample > 1:
|
|
93
|
-
time = time[::downsample]
|
|
94
|
-
values = values[::downsample]
|
|
95
|
-
|
|
96
|
-
# Apply scaling and offset
|
|
97
|
-
time = time * time_scale + time_offset
|
|
98
|
-
values = values * amplitude_scale + amplitude_offset
|
|
99
|
-
|
|
100
|
-
# Write to file
|
|
101
|
-
with open(path, "w") as f:
|
|
102
|
-
# Write comment/header
|
|
103
|
-
if format_style == "hspice":
|
|
104
|
-
f.write("* HSPICE PWL Data\n")
|
|
105
|
-
if comment:
|
|
106
|
-
f.write(f"* {comment}\n")
|
|
107
|
-
f.write(f"* Points: {len(time)}\n")
|
|
108
|
-
f.write("*\n")
|
|
109
|
-
elif comment:
|
|
110
|
-
f.write(f"; {comment}\n")
|
|
111
|
-
|
|
112
|
-
# Write time-value pairs
|
|
113
|
-
fmt = f"{{:.{precision}g}} {{:.{precision}g}}\n"
|
|
114
|
-
f.writelines(fmt.format(t, v) for t, v in zip(time, values, strict=False))
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
def export_pwl_multi(
|
|
118
|
-
traces: dict[str, WaveformTrace | DigitalTrace | NDArray[Any]],
|
|
119
|
-
path: str | Path,
|
|
120
|
-
*,
|
|
121
|
-
time_scale: float = 1.0,
|
|
122
|
-
amplitude_scale: float = 1.0,
|
|
123
|
-
precision: int = 12,
|
|
124
|
-
downsample: int = 1,
|
|
125
|
-
) -> None:
|
|
126
|
-
"""Export multiple traces to individual PWL files.
|
|
127
|
-
|
|
128
|
-
Creates separate PWL files for each trace in the dictionary,
|
|
129
|
-
with filenames based on the dictionary keys.
|
|
130
|
-
|
|
131
|
-
Args:
|
|
132
|
-
traces: Dictionary mapping signal names to trace data.
|
|
133
|
-
path: Output directory path.
|
|
134
|
-
time_scale: Scaling factor for time values.
|
|
135
|
-
amplitude_scale: Scaling factor for amplitude values.
|
|
136
|
-
precision: Decimal precision for output values.
|
|
137
|
-
downsample: Downsample factor to reduce file size.
|
|
138
|
-
|
|
139
|
-
Example:
|
|
140
|
-
>>> traces = {
|
|
141
|
-
... "clk": clock_trace,
|
|
142
|
-
... "data": data_trace,
|
|
143
|
-
... "reset": reset_trace,
|
|
144
|
-
... }
|
|
145
|
-
>>> export_pwl_multi(traces, "stimuli/")
|
|
146
|
-
>>> # Creates: stimuli/clk.pwl, stimuli/data.pwl, stimuli/reset.pwl
|
|
147
|
-
|
|
148
|
-
References:
|
|
149
|
-
EXP-005
|
|
150
|
-
"""
|
|
151
|
-
path = Path(path)
|
|
152
|
-
path.mkdir(parents=True, exist_ok=True)
|
|
153
|
-
|
|
154
|
-
for name, data in traces.items():
|
|
155
|
-
# Sanitize filename
|
|
156
|
-
safe_name = "".join(c if c.isalnum() or c in "_-" else "_" for c in name)
|
|
157
|
-
file_path = path / f"{safe_name}.pwl"
|
|
158
|
-
|
|
159
|
-
export_pwl(
|
|
160
|
-
data,
|
|
161
|
-
file_path,
|
|
162
|
-
time_scale=time_scale,
|
|
163
|
-
amplitude_scale=amplitude_scale,
|
|
164
|
-
precision=precision,
|
|
165
|
-
downsample=downsample,
|
|
166
|
-
comment=f"Signal: {name}",
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
def generate_spice_source(
|
|
171
|
-
pwl_path: str | Path,
|
|
172
|
-
node_positive: str = "in",
|
|
173
|
-
node_negative: str = "0",
|
|
174
|
-
source_name: str = "V1",
|
|
175
|
-
source_type: str = "voltage",
|
|
176
|
-
) -> str:
|
|
177
|
-
"""Generate SPICE source definition for a PWL file.
|
|
178
|
-
|
|
179
|
-
Args:
|
|
180
|
-
pwl_path: Path to PWL file.
|
|
181
|
-
node_positive: Positive node name.
|
|
182
|
-
node_negative: Negative node name (usually "0" for ground).
|
|
183
|
-
source_name: Source instance name.
|
|
184
|
-
source_type: Source type ("voltage" or "current").
|
|
185
|
-
|
|
186
|
-
Returns:
|
|
187
|
-
SPICE source definition string.
|
|
188
|
-
|
|
189
|
-
Example:
|
|
190
|
-
>>> line = generate_spice_source("input.pwl", "in", "0", "V1")
|
|
191
|
-
>>> print(line)
|
|
192
|
-
V1 in 0 PWL file=input.pwl
|
|
193
|
-
|
|
194
|
-
References:
|
|
195
|
-
EXP-005
|
|
196
|
-
"""
|
|
197
|
-
prefix = "V" if source_type == "voltage" else "I"
|
|
198
|
-
|
|
199
|
-
# Ensure source name starts with correct prefix
|
|
200
|
-
if not source_name.upper().startswith(prefix):
|
|
201
|
-
source_name = f"{prefix}{source_name}"
|
|
202
|
-
|
|
203
|
-
return f"{source_name} {node_positive} {node_negative} PWL file={pwl_path}"
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
__all__ = [
|
|
207
|
-
"export_pwl",
|
|
208
|
-
"export_pwl_multi",
|
|
209
|
-
"generate_spice_source",
|
|
210
|
-
]
|
|
@@ -1,247 +0,0 @@
|
|
|
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
|
-
]
|