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
|
@@ -6,7 +6,7 @@ configuration options.
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Example:
|
|
9
|
-
>>> from oscura.config.settings import get_settings, Settings
|
|
9
|
+
>>> from oscura.core.config.settings import get_settings, Settings
|
|
10
10
|
>>> settings = get_settings()
|
|
11
11
|
>>> settings.enable_feature("advanced_analysis")
|
|
12
12
|
>>> if settings.is_feature_enabled("advanced_analysis"):
|
|
@@ -15,7 +15,7 @@ from pathlib import Path
|
|
|
15
15
|
|
|
16
16
|
import yaml
|
|
17
17
|
|
|
18
|
-
from oscura.config.schema import validate_against_schema
|
|
18
|
+
from oscura.core.config.schema import validate_against_schema
|
|
19
19
|
from oscura.core.exceptions import ConfigurationError
|
|
20
20
|
|
|
21
21
|
logger = logging.getLogger(__name__)
|
|
@@ -206,129 +206,25 @@ class ThresholdRegistry:
|
|
|
206
206
|
# Double-check locking pattern
|
|
207
207
|
if cls._instance is None:
|
|
208
208
|
cls._instance = super().__new__(cls)
|
|
209
|
-
cls._instance._families = {}
|
|
210
|
-
cls._instance._profiles = {}
|
|
211
|
-
cls._instance._session_overrides = {}
|
|
212
|
-
cls._instance._state_lock = threading.Lock()
|
|
209
|
+
cls._instance._families = {}
|
|
210
|
+
cls._instance._profiles = {}
|
|
211
|
+
cls._instance._session_overrides = {}
|
|
212
|
+
cls._instance._state_lock = threading.Lock()
|
|
213
213
|
cls._instance._register_builtins()
|
|
214
214
|
return cls._instance
|
|
215
215
|
|
|
216
216
|
def _register_builtins(self) -> None:
|
|
217
217
|
"""Register built-in logic family definitions."""
|
|
218
|
-
builtins =
|
|
219
|
-
# TTL
|
|
220
|
-
LogicFamily(
|
|
221
|
-
name="TTL",
|
|
222
|
-
VIH=2.0,
|
|
223
|
-
VIL=0.8,
|
|
224
|
-
VOH=2.4,
|
|
225
|
-
VOL=0.4,
|
|
226
|
-
VCC=5.0,
|
|
227
|
-
description="Standard TTL (74xx series)",
|
|
228
|
-
),
|
|
229
|
-
# CMOS variants
|
|
230
|
-
LogicFamily(
|
|
231
|
-
name="CMOS_5V",
|
|
232
|
-
VIH=3.5,
|
|
233
|
-
VIL=1.5,
|
|
234
|
-
VOH=4.9,
|
|
235
|
-
VOL=0.1,
|
|
236
|
-
VCC=5.0,
|
|
237
|
-
description="CMOS 5V (74HCxx series)",
|
|
238
|
-
),
|
|
239
|
-
LogicFamily(
|
|
240
|
-
name="LVTTL_3V3",
|
|
241
|
-
VIH=2.0,
|
|
242
|
-
VIL=0.8,
|
|
243
|
-
VOH=2.4,
|
|
244
|
-
VOL=0.4,
|
|
245
|
-
VCC=3.3,
|
|
246
|
-
description="Low Voltage TTL 3.3V",
|
|
247
|
-
),
|
|
248
|
-
LogicFamily(
|
|
249
|
-
name="LVCMOS_3V3",
|
|
250
|
-
VIH=2.0,
|
|
251
|
-
VIL=0.7,
|
|
252
|
-
VOH=2.4,
|
|
253
|
-
VOL=0.4,
|
|
254
|
-
VCC=3.3,
|
|
255
|
-
description="Low Voltage CMOS 3.3V",
|
|
256
|
-
),
|
|
257
|
-
LogicFamily(
|
|
258
|
-
name="LVCMOS_2V5",
|
|
259
|
-
VIH=1.7,
|
|
260
|
-
VIL=0.7,
|
|
261
|
-
VOH=2.0,
|
|
262
|
-
VOL=0.4,
|
|
263
|
-
VCC=2.5,
|
|
264
|
-
description="Low Voltage CMOS 2.5V",
|
|
265
|
-
),
|
|
266
|
-
LogicFamily(
|
|
267
|
-
name="LVCMOS_1V8",
|
|
268
|
-
VIH=1.17,
|
|
269
|
-
VIL=0.63,
|
|
270
|
-
VOH=1.35,
|
|
271
|
-
VOL=0.45,
|
|
272
|
-
VCC=1.8,
|
|
273
|
-
description="Low Voltage CMOS 1.8V",
|
|
274
|
-
),
|
|
275
|
-
LogicFamily(
|
|
276
|
-
name="LVCMOS_1V5",
|
|
277
|
-
VIH=0.975,
|
|
278
|
-
VIL=0.525,
|
|
279
|
-
VOH=1.125,
|
|
280
|
-
VOL=0.375,
|
|
281
|
-
VCC=1.5,
|
|
282
|
-
description="Low Voltage CMOS 1.5V",
|
|
283
|
-
),
|
|
284
|
-
LogicFamily(
|
|
285
|
-
name="LVCMOS_1V2",
|
|
286
|
-
VIH=0.84, # 0.7 * 1.2
|
|
287
|
-
VIL=0.36, # 0.3 * 1.2
|
|
288
|
-
VOH=1.1,
|
|
289
|
-
VOL=0.1,
|
|
290
|
-
VCC=1.2,
|
|
291
|
-
description="Low Voltage CMOS 1.2V",
|
|
292
|
-
),
|
|
293
|
-
# ECL
|
|
294
|
-
LogicFamily(
|
|
295
|
-
name="ECL",
|
|
296
|
-
VIH=-0.9,
|
|
297
|
-
VIL=-1.7,
|
|
298
|
-
VOH=-0.9,
|
|
299
|
-
VOL=-1.75,
|
|
300
|
-
VCC=-5.2,
|
|
301
|
-
description="Emitter-Coupled Logic (ECL 10K)",
|
|
302
|
-
),
|
|
303
|
-
]
|
|
218
|
+
builtins = _get_builtin_logic_families()
|
|
304
219
|
|
|
305
220
|
for family in builtins:
|
|
306
|
-
self._families[family.name] = family
|
|
221
|
+
self._families[family.name] = family
|
|
307
222
|
|
|
308
223
|
# Built-in profiles
|
|
309
|
-
builtin_profiles =
|
|
310
|
-
ThresholdProfile(
|
|
311
|
-
name="strict",
|
|
312
|
-
base_family="TTL",
|
|
313
|
-
tolerance=0,
|
|
314
|
-
description="Exact specification values",
|
|
315
|
-
),
|
|
316
|
-
ThresholdProfile(
|
|
317
|
-
name="relaxed",
|
|
318
|
-
base_family="TTL",
|
|
319
|
-
tolerance=20,
|
|
320
|
-
description="20% tolerance for real-world signals",
|
|
321
|
-
),
|
|
322
|
-
ThresholdProfile(
|
|
323
|
-
name="auto",
|
|
324
|
-
base_family="TTL",
|
|
325
|
-
tolerance=10,
|
|
326
|
-
description="Auto-adjusted based on signal confidence",
|
|
327
|
-
),
|
|
328
|
-
]
|
|
224
|
+
builtin_profiles = _get_builtin_profiles()
|
|
329
225
|
|
|
330
226
|
for profile in builtin_profiles:
|
|
331
|
-
self._profiles[profile.name] = profile
|
|
227
|
+
self._profiles[profile.name] = profile
|
|
332
228
|
|
|
333
229
|
def get_family(self, name: str) -> LogicFamily:
|
|
334
230
|
"""Get logic family by name.
|
|
@@ -342,32 +238,56 @@ class ThresholdRegistry:
|
|
|
342
238
|
Raises:
|
|
343
239
|
KeyError: If family not found
|
|
344
240
|
"""
|
|
345
|
-
with self._state_lock:
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
241
|
+
with self._state_lock:
|
|
242
|
+
family = self._lookup_family(name)
|
|
243
|
+
return self._apply_overrides_if_needed(family)
|
|
244
|
+
|
|
245
|
+
def _lookup_family(self, name: str) -> LogicFamily:
|
|
246
|
+
"""Look up family by name (exact or case-insensitive).
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
name: Family name to look up.
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
Logic family definition.
|
|
253
|
+
|
|
254
|
+
Raises:
|
|
255
|
+
KeyError: If family not found.
|
|
256
|
+
"""
|
|
257
|
+
# Try exact match first
|
|
258
|
+
if name in self._families:
|
|
259
|
+
return self._families[name]
|
|
260
|
+
|
|
261
|
+
# Try case-insensitive match
|
|
262
|
+
if name.upper() in self._families:
|
|
263
|
+
return self._families[name.upper()]
|
|
264
|
+
|
|
265
|
+
available = list(self._families.keys())
|
|
266
|
+
raise KeyError(f"Logic family '{name}' not found. Available: {available}")
|
|
267
|
+
|
|
268
|
+
def _apply_overrides_if_needed(self, family: LogicFamily) -> LogicFamily:
|
|
269
|
+
"""Apply session overrides to family if configured.
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
family: Base family.
|
|
369
273
|
|
|
370
|
-
|
|
274
|
+
Returns:
|
|
275
|
+
Family with overrides applied, or original if no overrides.
|
|
276
|
+
"""
|
|
277
|
+
if not self._session_overrides:
|
|
278
|
+
return family
|
|
279
|
+
|
|
280
|
+
return LogicFamily(
|
|
281
|
+
name=family.name,
|
|
282
|
+
VIH=self._session_overrides.get("VIH", family.VIH),
|
|
283
|
+
VIL=self._session_overrides.get("VIL", family.VIL),
|
|
284
|
+
VOH=self._session_overrides.get("VOH", family.VOH),
|
|
285
|
+
VOL=self._session_overrides.get("VOL", family.VOL),
|
|
286
|
+
VCC=self._session_overrides.get("VCC", family.VCC),
|
|
287
|
+
description=family.description,
|
|
288
|
+
temperature_range=family.temperature_range,
|
|
289
|
+
source="override",
|
|
290
|
+
)
|
|
371
291
|
|
|
372
292
|
def list_families(self) -> list[str]:
|
|
373
293
|
"""List all available logic families.
|
|
@@ -375,8 +295,8 @@ class ThresholdRegistry:
|
|
|
375
295
|
Returns:
|
|
376
296
|
List of family names
|
|
377
297
|
"""
|
|
378
|
-
with self._state_lock:
|
|
379
|
-
return sorted(self._families.keys())
|
|
298
|
+
with self._state_lock:
|
|
299
|
+
return sorted(self._families.keys())
|
|
380
300
|
|
|
381
301
|
def register_family(self, family: LogicFamily, *, namespace: str = "user") -> None:
|
|
382
302
|
"""Register custom logic family.
|
|
@@ -390,7 +310,7 @@ class ThresholdRegistry:
|
|
|
390
310
|
>>> registry.register_family(custom)
|
|
391
311
|
>>> # Available as "user.my_custom"
|
|
392
312
|
"""
|
|
393
|
-
with self._state_lock:
|
|
313
|
+
with self._state_lock:
|
|
394
314
|
# Namespace custom families
|
|
395
315
|
if namespace and not family.name.startswith(f"{namespace}."):
|
|
396
316
|
name = f"{namespace}.{family.name}"
|
|
@@ -410,7 +330,7 @@ class ThresholdRegistry:
|
|
|
410
330
|
source=family.source,
|
|
411
331
|
)
|
|
412
332
|
|
|
413
|
-
self._families[name] = family
|
|
333
|
+
self._families[name] = family
|
|
414
334
|
logger.info(f"Registered custom logic family: {name}")
|
|
415
335
|
|
|
416
336
|
def set_threshold_override(self, **kwargs: float) -> None:
|
|
@@ -428,20 +348,20 @@ class ThresholdRegistry:
|
|
|
428
348
|
>>> registry.set_threshold_override(VIH=2.5, VIL=0.7)
|
|
429
349
|
"""
|
|
430
350
|
valid_keys = {"VIH", "VIL", "VOH", "VOL", "VCC"}
|
|
431
|
-
with self._state_lock:
|
|
351
|
+
with self._state_lock:
|
|
432
352
|
for key, value in kwargs.items():
|
|
433
353
|
if key not in valid_keys:
|
|
434
354
|
raise ValueError(f"Invalid threshold key: {key}. Valid: {valid_keys}")
|
|
435
355
|
if not 0.0 <= value <= 10.0:
|
|
436
356
|
raise ValueError(f"Threshold {key}={value}V out of range (0-10V)")
|
|
437
|
-
self._session_overrides[key] = value
|
|
357
|
+
self._session_overrides[key] = value
|
|
438
358
|
|
|
439
359
|
logger.info(f"Set threshold overrides: {kwargs}")
|
|
440
360
|
|
|
441
361
|
def reset_overrides(self) -> None:
|
|
442
362
|
"""Reset session threshold overrides."""
|
|
443
|
-
with self._state_lock:
|
|
444
|
-
self._session_overrides.clear()
|
|
363
|
+
with self._state_lock:
|
|
364
|
+
self._session_overrides.clear()
|
|
445
365
|
logger.info("Reset threshold overrides")
|
|
446
366
|
|
|
447
367
|
def get_profile(self, name: str) -> ThresholdProfile:
|
|
@@ -456,12 +376,12 @@ class ThresholdRegistry:
|
|
|
456
376
|
Raises:
|
|
457
377
|
KeyError: If profile not found.
|
|
458
378
|
"""
|
|
459
|
-
with self._state_lock:
|
|
460
|
-
if name not in self._profiles:
|
|
379
|
+
with self._state_lock:
|
|
380
|
+
if name not in self._profiles:
|
|
461
381
|
raise KeyError(
|
|
462
382
|
f"Profile '{name}' not found. Available: {list(self._profiles.keys())}"
|
|
463
|
-
)
|
|
464
|
-
return self._profiles[name]
|
|
383
|
+
)
|
|
384
|
+
return self._profiles[name]
|
|
465
385
|
|
|
466
386
|
def apply_profile(self, name: str) -> LogicFamily:
|
|
467
387
|
"""Apply a threshold profile.
|
|
@@ -490,14 +410,14 @@ class ThresholdRegistry:
|
|
|
490
410
|
>>> registry.set_threshold_override(VIH=2.5)
|
|
491
411
|
>>> registry.save_profile("my_profile")
|
|
492
412
|
"""
|
|
493
|
-
with self._state_lock:
|
|
413
|
+
with self._state_lock:
|
|
494
414
|
profile = ThresholdProfile(
|
|
495
415
|
name=name,
|
|
496
416
|
base_family=base_family or "TTL",
|
|
497
|
-
overrides=dict(self._session_overrides),
|
|
417
|
+
overrides=dict(self._session_overrides),
|
|
498
418
|
description=f"User profile {name}",
|
|
499
419
|
)
|
|
500
|
-
self._profiles[name] = profile
|
|
420
|
+
self._profiles[name] = profile
|
|
501
421
|
|
|
502
422
|
if path:
|
|
503
423
|
path = Path(path)
|
|
@@ -513,6 +433,128 @@ class ThresholdRegistry:
|
|
|
513
433
|
logger.info(f"Saved profile to {path}")
|
|
514
434
|
|
|
515
435
|
|
|
436
|
+
def _get_builtin_logic_families() -> list[LogicFamily]:
|
|
437
|
+
"""Get list of built-in logic family definitions.
|
|
438
|
+
|
|
439
|
+
Returns:
|
|
440
|
+
List of standard logic families.
|
|
441
|
+
"""
|
|
442
|
+
return [
|
|
443
|
+
# TTL
|
|
444
|
+
LogicFamily(
|
|
445
|
+
name="TTL",
|
|
446
|
+
VIH=2.0,
|
|
447
|
+
VIL=0.8,
|
|
448
|
+
VOH=2.4,
|
|
449
|
+
VOL=0.4,
|
|
450
|
+
VCC=5.0,
|
|
451
|
+
description="Standard TTL (74xx series)",
|
|
452
|
+
),
|
|
453
|
+
# CMOS variants
|
|
454
|
+
LogicFamily(
|
|
455
|
+
name="CMOS_5V",
|
|
456
|
+
VIH=3.5,
|
|
457
|
+
VIL=1.5,
|
|
458
|
+
VOH=4.9,
|
|
459
|
+
VOL=0.1,
|
|
460
|
+
VCC=5.0,
|
|
461
|
+
description="CMOS 5V (74HCxx series)",
|
|
462
|
+
),
|
|
463
|
+
LogicFamily(
|
|
464
|
+
name="LVTTL_3V3",
|
|
465
|
+
VIH=2.0,
|
|
466
|
+
VIL=0.8,
|
|
467
|
+
VOH=2.4,
|
|
468
|
+
VOL=0.4,
|
|
469
|
+
VCC=3.3,
|
|
470
|
+
description="Low Voltage TTL 3.3V",
|
|
471
|
+
),
|
|
472
|
+
LogicFamily(
|
|
473
|
+
name="LVCMOS_3V3",
|
|
474
|
+
VIH=2.0,
|
|
475
|
+
VIL=0.7,
|
|
476
|
+
VOH=2.4,
|
|
477
|
+
VOL=0.4,
|
|
478
|
+
VCC=3.3,
|
|
479
|
+
description="Low Voltage CMOS 3.3V",
|
|
480
|
+
),
|
|
481
|
+
LogicFamily(
|
|
482
|
+
name="LVCMOS_2V5",
|
|
483
|
+
VIH=1.7,
|
|
484
|
+
VIL=0.7,
|
|
485
|
+
VOH=2.0,
|
|
486
|
+
VOL=0.4,
|
|
487
|
+
VCC=2.5,
|
|
488
|
+
description="Low Voltage CMOS 2.5V",
|
|
489
|
+
),
|
|
490
|
+
LogicFamily(
|
|
491
|
+
name="LVCMOS_1V8",
|
|
492
|
+
VIH=1.17,
|
|
493
|
+
VIL=0.63,
|
|
494
|
+
VOH=1.35,
|
|
495
|
+
VOL=0.45,
|
|
496
|
+
VCC=1.8,
|
|
497
|
+
description="Low Voltage CMOS 1.8V",
|
|
498
|
+
),
|
|
499
|
+
LogicFamily(
|
|
500
|
+
name="LVCMOS_1V5",
|
|
501
|
+
VIH=0.975,
|
|
502
|
+
VIL=0.525,
|
|
503
|
+
VOH=1.125,
|
|
504
|
+
VOL=0.375,
|
|
505
|
+
VCC=1.5,
|
|
506
|
+
description="Low Voltage CMOS 1.5V",
|
|
507
|
+
),
|
|
508
|
+
LogicFamily(
|
|
509
|
+
name="LVCMOS_1V2",
|
|
510
|
+
VIH=0.84, # 0.7 * 1.2
|
|
511
|
+
VIL=0.36, # 0.3 * 1.2
|
|
512
|
+
VOH=1.1,
|
|
513
|
+
VOL=0.1,
|
|
514
|
+
VCC=1.2,
|
|
515
|
+
description="Low Voltage CMOS 1.2V",
|
|
516
|
+
),
|
|
517
|
+
# ECL
|
|
518
|
+
LogicFamily(
|
|
519
|
+
name="ECL",
|
|
520
|
+
VIH=-0.9,
|
|
521
|
+
VIL=-1.7,
|
|
522
|
+
VOH=-0.9,
|
|
523
|
+
VOL=-1.75,
|
|
524
|
+
VCC=-5.2,
|
|
525
|
+
description="Emitter-Coupled Logic (ECL 10K)",
|
|
526
|
+
),
|
|
527
|
+
]
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
def _get_builtin_profiles() -> list[ThresholdProfile]:
|
|
531
|
+
"""Get list of built-in threshold profiles.
|
|
532
|
+
|
|
533
|
+
Returns:
|
|
534
|
+
List of standard threshold profiles.
|
|
535
|
+
"""
|
|
536
|
+
return [
|
|
537
|
+
ThresholdProfile(
|
|
538
|
+
name="strict",
|
|
539
|
+
base_family="TTL",
|
|
540
|
+
tolerance=0,
|
|
541
|
+
description="Exact specification values",
|
|
542
|
+
),
|
|
543
|
+
ThresholdProfile(
|
|
544
|
+
name="relaxed",
|
|
545
|
+
base_family="TTL",
|
|
546
|
+
tolerance=20,
|
|
547
|
+
description="20% tolerance for real-world signals",
|
|
548
|
+
),
|
|
549
|
+
ThresholdProfile(
|
|
550
|
+
name="auto",
|
|
551
|
+
base_family="TTL",
|
|
552
|
+
tolerance=10,
|
|
553
|
+
description="Auto-adjusted based on signal confidence",
|
|
554
|
+
),
|
|
555
|
+
]
|
|
556
|
+
|
|
557
|
+
|
|
516
558
|
def load_logic_family(path: str | Path) -> LogicFamily:
|
|
517
559
|
"""Load logic family from YAML/JSON file.
|
|
518
560
|
|
oscura/core/correlation.py
CHANGED
|
@@ -20,8 +20,8 @@ import asyncio
|
|
|
20
20
|
import contextvars
|
|
21
21
|
import functools
|
|
22
22
|
import uuid
|
|
23
|
-
from collections.abc import Callable
|
|
24
|
-
from typing import Any, ParamSpec, TypeVar
|
|
23
|
+
from collections.abc import Callable, Coroutine
|
|
24
|
+
from typing import Any, ParamSpec, TypeVar, cast
|
|
25
25
|
|
|
26
26
|
# Context variable for correlation ID (thread-safe and async-safe)
|
|
27
27
|
_correlation_id: contextvars.ContextVar[str | None] = contextvars.ContextVar(
|
|
@@ -180,9 +180,8 @@ def with_correlation_id(
|
|
|
180
180
|
async def async_wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
181
181
|
with CorrelationContext(corr_id):
|
|
182
182
|
# func returns a Coroutine, we need to await it
|
|
183
|
-
coro = func(*args, **kwargs)
|
|
184
|
-
|
|
185
|
-
return await coro # type: ignore[misc, no-any-return]
|
|
183
|
+
coro = cast("Coroutine[Any, Any, R]", func(*args, **kwargs))
|
|
184
|
+
return await coro
|
|
186
185
|
|
|
187
186
|
return async_wrapper # type: ignore[return-value]
|
|
188
187
|
else:
|
|
@@ -192,7 +191,7 @@ def with_correlation_id(
|
|
|
192
191
|
with CorrelationContext(corr_id):
|
|
193
192
|
return func(*args, **kwargs)
|
|
194
193
|
|
|
195
|
-
return sync_wrapper
|
|
194
|
+
return sync_wrapper
|
|
196
195
|
|
|
197
196
|
return decorator
|
|
198
197
|
|
oscura/core/cross_domain.py
CHANGED
oscura/core/debug.py
CHANGED
|
@@ -5,11 +5,11 @@ verbosity levels for troubleshooting and diagnostics.
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
Example:
|
|
8
|
-
>>> from oscura.core.debug import enable_debug, is_debug_enabled,
|
|
8
|
+
>>> from oscura.core.debug import enable_debug, is_debug_enabled, DebugContext
|
|
9
9
|
>>> enable_debug(level='verbose')
|
|
10
10
|
>>> if is_debug_enabled():
|
|
11
11
|
... logger.debug("Extra diagnostic information")
|
|
12
|
-
>>> with
|
|
12
|
+
>>> with DebugContext(level='trace'):
|
|
13
13
|
... # Temporarily increase verbosity
|
|
14
14
|
... analyze_complex_signal()
|
|
15
15
|
|
|
@@ -157,7 +157,7 @@ def get_debug_level() -> DebugLevel:
|
|
|
157
157
|
return DebugLevel(_debug_level.get())
|
|
158
158
|
|
|
159
159
|
|
|
160
|
-
class
|
|
160
|
+
class DebugContext:
|
|
161
161
|
"""Context manager for temporary debug level changes.
|
|
162
162
|
|
|
163
163
|
Temporarily sets a debug level for the duration of a code block,
|
|
@@ -168,7 +168,7 @@ class debug_context:
|
|
|
168
168
|
|
|
169
169
|
Example:
|
|
170
170
|
>>> # Normal debug level
|
|
171
|
-
>>> with
|
|
171
|
+
>>> with DebugContext(level='trace'):
|
|
172
172
|
... # Temporarily enable trace-level debugging
|
|
173
173
|
... analyze_signal(complex_data)
|
|
174
174
|
>>> # Back to normal debug level
|
|
@@ -190,7 +190,7 @@ class debug_context:
|
|
|
190
190
|
self.token: contextvars.Token | None = None # type: ignore[type-arg]
|
|
191
191
|
self.previous_log_level: str | None = None
|
|
192
192
|
|
|
193
|
-
def __enter__(self) ->
|
|
193
|
+
def __enter__(self) -> DebugContext:
|
|
194
194
|
"""Enter the debug context and set new level."""
|
|
195
195
|
# Save current debug level
|
|
196
196
|
self.token = _debug_level.set(self.level)
|
|
@@ -226,6 +226,10 @@ class debug_context:
|
|
|
226
226
|
set_log_level(self.previous_log_level)
|
|
227
227
|
|
|
228
228
|
|
|
229
|
+
# Backward compatibility alias (deprecated, use DebugContext)
|
|
230
|
+
debug_context = DebugContext
|
|
231
|
+
|
|
232
|
+
|
|
229
233
|
def should_log_debug(min_level: DebugLevel = DebugLevel.NORMAL) -> bool:
|
|
230
234
|
"""Check if debug logging should occur at specified level.
|
|
231
235
|
|