146 lines
6.7 KiB
Matlab
146 lines
6.7 KiB
Matlab
classdef IMDD_base_system_minimal_integration_test < IMDDTestCase
|
|
% First integration test for the reduced IM/DD base-system workflow.
|
|
%
|
|
% The goal of this test is not to freeze the full waveform exactly.
|
|
% Instead, it checks stable system-level contracts:
|
|
% - the reduced end-to-end chain runs without errors
|
|
% - key signal objects have the expected lengths and sampling rates
|
|
% - the DSP outputs return finite, bounded metrics
|
|
% - the intermediate optical and electrical stages stay physically sane
|
|
% - MLSE does not regress relative to the preceding FFE stage
|
|
%
|
|
% Thresholds are intentionally provisional in this first iteration.
|
|
% Once the team has reviewed repeated runs, these can be tightened.
|
|
|
|
properties
|
|
workflow
|
|
end
|
|
|
|
methods (TestClassSetup)
|
|
function runReducedImddWorkflowOnce(testCase)
|
|
% Run the deterministic reduced workflow once and share the
|
|
% resulting signals/metrics across all test methods.
|
|
testCase.workflow = buildReducedImddWorkflow("minimal");
|
|
end
|
|
end
|
|
|
|
methods (Test, TestTags = {'integration', 'slow', 'imdd'})
|
|
function reducedWorkflowBuildsExpectedSignalStages(testCase)
|
|
wf = testCase.workflow;
|
|
|
|
testCase.verifyClass(wf.Tx_bits, 'Informationsignal');
|
|
testCase.verifyClass(wf.Symbols, 'Informationsignal');
|
|
testCase.verifyClass(wf.Digi_sig, 'Informationsignal');
|
|
testCase.verifyClass(wf.El_sig, 'Electricalsignal');
|
|
testCase.verifyClass(wf.Opt_sig_tx, 'Opticalsignal');
|
|
testCase.verifyClass(wf.Opt_sig, 'Opticalsignal');
|
|
testCase.verifyClass(wf.Rx_sig_after_pd, 'Electricalsignal');
|
|
testCase.verifyClass(wf.Scpe_sig_pre_mf, 'Informationsignal');
|
|
testCase.verifyClass(wf.Scpe_sig, 'Informationsignal');
|
|
testCase.verifyClass(wf.Synced_sig_centered, 'Informationsignal');
|
|
testCase.verifyClass(wf.Synced_sig, 'Informationsignal');
|
|
|
|
testCase.verifyGreaterThan(length(wf.Tx_bits.signal), 0);
|
|
testCase.verifyGreaterThan(length(wf.Symbols.signal), 0);
|
|
testCase.verifyEqual(wf.Digi_sig.fs, wf.params.fdac);
|
|
% Tx_bits is a bit-level container and does not carry a
|
|
% sampling-rate contract on this path.
|
|
testCase.verifyEqual(wf.Symbols.fs, wf.params.fsym);
|
|
testCase.verifyEqual(wf.El_sig.fs, wf.params.fdac * wf.params.kover);
|
|
testCase.verifyEqual(wf.Opt_sig_tx.fs, wf.El_sig.fs);
|
|
testCase.verifyEqual(wf.Opt_sig.fs, wf.Opt_sig_tx.fs);
|
|
testCase.verifyEqual(wf.Rx_sig_after_pd.fs, wf.Opt_sig.fs);
|
|
testCase.verifyEqual(wf.Scpe_sig_pre_mf.fs, wf.params.fadc);
|
|
|
|
% After the matched filter, the signal is intentionally reduced
|
|
% to 2 samples per symbol for the downstream DSP chain.
|
|
testCase.verifyEqual(wf.Scpe_sig.fs, 2 * wf.params.fsym);
|
|
testCase.verifyEqual(wf.Synced_sig_centered.fs, 2 * wf.params.fsym);
|
|
testCase.verifyEqual(wf.Synced_sig.fs, 2 * wf.params.fsym);
|
|
|
|
% The synchronized signal is explicitly cropped to 2 samples per
|
|
% transmitted symbol before equalization.
|
|
testCase.verifyEqual(length(wf.Synced_sig.signal), 2 * length(wf.Symbols.signal));
|
|
end
|
|
|
|
function reducedWorkflowProducesFiniteSignalsAndMetrics(testCase)
|
|
wf = testCase.workflow;
|
|
|
|
finiteSignals = {
|
|
wf.Digi_sig.signal
|
|
wf.El_sig.signal
|
|
wf.Opt_sig_tx.signal
|
|
wf.Opt_sig.signal
|
|
wf.Rx_sig_after_pd.signal
|
|
wf.Scpe_sig_pre_mf.signal
|
|
wf.Scpe_sig.signal
|
|
wf.Synced_sig_centered.signal
|
|
wf.Synced_sig.signal
|
|
};
|
|
|
|
for idx = 1:numel(finiteSignals)
|
|
sig = finiteSignals{idx};
|
|
testCase.verifyFalse(any(isnan(sig), 'all'));
|
|
testCase.verifyFalse(any(isinf(sig), 'all'));
|
|
end
|
|
|
|
txOptPower = signalPower(wf.Opt_sig_tx.signal);
|
|
fiberOptPower = signalPower(wf.Opt_sig.signal);
|
|
pdPower = signalPower(wf.Rx_sig_after_pd.signal);
|
|
preMfVariance = signalVariance(wf.Scpe_sig_pre_mf.signal);
|
|
mfVariance = signalVariance(wf.Scpe_sig.signal);
|
|
centeredMean = mean(wf.Synced_sig_centered.signal(:));
|
|
|
|
testCase.verifyGreaterThan(txOptPower, 0);
|
|
testCase.verifyGreaterThan(fiberOptPower, 0);
|
|
testCase.verifyGreaterThan(pdPower, 0);
|
|
testCase.verifyGreaterThan(preMfVariance, 0);
|
|
testCase.verifyGreaterThan(mfVariance, 0);
|
|
testCase.verifyLessThanOrEqual(abs(centeredMean), 1e-12);
|
|
|
|
testCase.verifyGreaterThanOrEqual(wf.ffe_results.metrics.BER, 0);
|
|
testCase.verifyLessThanOrEqual(wf.ffe_results.metrics.BER, 1);
|
|
testCase.verifyGreaterThanOrEqual(wf.mlse_results.metrics.BER, 0);
|
|
testCase.verifyLessThanOrEqual(wf.mlse_results.metrics.BER, 1);
|
|
|
|
testCase.verifyTrue(isfinite(wf.ffe_results.metrics.GMI));
|
|
testCase.verifyTrue(isfinite(wf.ffe_results.metrics.AIR));
|
|
testCase.verifyTrue(isfinite(wf.mlse_results.metrics.GMI));
|
|
testCase.verifyTrue(isfinite(wf.mlse_results.metrics.AIR));
|
|
end
|
|
|
|
function reducedWorkflowMeetsProvisionalPerformanceChecks(testCase)
|
|
wf = testCase.workflow;
|
|
|
|
% These are deliberately loose first-pass regression guards.
|
|
% Tighten them only after repeated baseline runs are reviewed.
|
|
% First observed baseline on 2026-03-24 for this reduced setup:
|
|
% FFE BER ~= 2.58e-1
|
|
%
|
|
% This threshold is intentionally loose for the first
|
|
% integration-test iteration. Tighten it only after the reduced
|
|
% workflow has been reviewed across repeated runs and code
|
|
% changes.
|
|
provisionalMaxFfeBer = 3e-1;
|
|
provisionalMaxMlseBer = 3e-1;
|
|
|
|
testCase.verifyLessThanOrEqual(wf.ffe_results.metrics.BER, provisionalMaxFfeBer);
|
|
testCase.verifyLessThanOrEqual(wf.mlse_results.metrics.BER, provisionalMaxMlseBer);
|
|
|
|
% MLSE should not regress relative to the direct FFE path on
|
|
% this deterministic reduced setup.
|
|
testCase.verifyLessThanOrEqual( ...
|
|
wf.mlse_results.metrics.BER, ...
|
|
wf.ffe_results.metrics.BER + 1e-12);
|
|
end
|
|
end
|
|
end
|
|
function p = signalPower(signal)
|
|
p = mean(abs(signal(:)).^2);
|
|
end
|
|
|
|
function v = signalVariance(signal)
|
|
centered = signal(:) - mean(signal(:));
|
|
v = mean(abs(centered).^2);
|
|
end
|