Skip to content

Commit

Permalink
Refactored filters starting with P. See #650.
Browse files Browse the repository at this point in the history
  • Loading branch information
azonenberg committed Aug 28, 2022
1 parent 544f013 commit 1dbb9fd
Show file tree
Hide file tree
Showing 14 changed files with 239 additions and 110 deletions.
45 changes: 45 additions & 0 deletions scopehal/Filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,42 @@ class Filter : public OscilloscopeChannel
samples.MarkModifiedFromCpu();
}

/**
@brief Samples an analog waveform on all edges of a clock, interpolating linearly to get sub-sample accuracy.
The sampling rate of the data and clock signals need not be equal or uniform.
The sampled waveform is sparse and has a time scale in femtoseconds,
regardless of the incoming waveform's time scale and sampling uniformity.
@param data The data signal to sample. Can be be sparse or uniform of any type.
@param clock The clock signal to use. Must be sparse or uniform digital.
@param samples Output waveform. Must be sparse and same data type as data.
*/
template<class T>
__attribute__((noinline))
static void SampleOnAnyEdgesBaseWithInterpolation(WaveformBase* data, WaveformBase* clock, SparseWaveform<T>& samples)
{
data->PrepareForCpuAccess();
clock->PrepareForCpuAccess();
samples.PrepareForCpuAccess();

auto udata = dynamic_cast<UniformWaveform<T>*>(data);
auto sdata = dynamic_cast<SparseWaveform<T>*>(data);

auto uclock = dynamic_cast<UniformDigitalWaveform*>(clock);
auto sclock = dynamic_cast<SparseDigitalWaveform*>(clock);

if(udata && uclock)
SampleOnAnyEdgesWithInterpolation(udata, uclock, samples);
else if(udata && sclock)
SampleOnAnyEdgesWithInterpolation(udata, sclock, samples);
else if(sdata && sclock)
SampleOnAnyEdgesWithInterpolation(sdata, sclock, samples);
else if(sdata && uclock)
SampleOnAnyEdgesWithInterpolation(sdata, uclock, samples);
}

/**
@brief Prepares a sparse or uniform analog waveform for CPU access
*/
Expand Down Expand Up @@ -977,6 +1013,15 @@ class Filter : public OscilloscopeChannel
FindFallingEdges(udata, edges);
}

static void FindZeroCrossings(
SparseAnalogWaveform* sdata, UniformAnalogWaveform* udata, float threshold, std::vector<int64_t>& edges)
{
if(sdata)
FindZeroCrossings(sdata, threshold, edges);
else
FindZeroCrossings(udata, threshold, edges);
}

static void FindZeroCrossings(
SparseDigitalWaveform* sdata, UniformDigitalWaveform* udata, std::vector<int64_t>& edges)
{
Expand Down
23 changes: 15 additions & 8 deletions scopeprotocols/PAM4DemodulatorFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,14 @@ void PAM4DemodulatorFilter::Refresh()
}

//Sample the input data
auto din = GetAnalogInputWaveform(0);
auto clk = GetDigitalInputWaveform(1);
AnalogWaveform samples;
SampleOnAnyEdgesWithInterpolation(din, clk, samples);
auto din = GetInputWaveform(0);
auto clk = GetInputWaveform(1);
din->PrepareForCpuAccess();
clk->PrepareForCpuAccess();

SparseAnalogWaveform samples;
SampleOnAnyEdgesBaseWithInterpolation(din, clk, samples);
samples.PrepareForCpuAccess();
size_t len = samples.m_samples.size();

//Get the thresholds
Expand All @@ -107,20 +111,20 @@ void PAM4DemodulatorFilter::Refresh()
};

//Create the captures
auto dcap = new DigitalWaveform;
auto dcap = new SparseDigitalWaveform;
dcap->m_timescale = 1;
dcap->m_startTimestamp = din->m_startTimestamp;
dcap->m_startFemtoseconds = din->m_startFemtoseconds;
dcap->m_triggerPhase = 0;
dcap->m_densePacked = false;
dcap->PrepareForCpuAccess();
SetData(dcap, 0);

auto ccap = new DigitalWaveform;
auto ccap = new SparseDigitalWaveform;
ccap->m_timescale = 1;
ccap->m_startTimestamp = din->m_startTimestamp;
ccap->m_startFemtoseconds = din->m_startFemtoseconds;
ccap->m_triggerPhase = 0;
ccap->m_densePacked = false;
ccap->PrepareForCpuAccess();
SetData(ccap, 1);

//Decode the input data, one symbol (two output bits) at a time
Expand Down Expand Up @@ -179,4 +183,7 @@ void PAM4DemodulatorFilter::Refresh()
dcap->m_samples[i*2 + 1] = 0;
}
}

ccap->MarkModifiedFromCpu();
dcap->MarkModifiedFromCpu();
}
14 changes: 9 additions & 5 deletions scopeprotocols/PCIe128b130bDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,24 @@ void PCIe128b130bDecoder::Refresh()
SetData(NULL, 0);
return;
}
auto din = GetDigitalInputWaveform(0);
auto clkin = GetDigitalInputWaveform(1);
auto din = GetInputWaveform(0);
auto clkin = GetInputWaveform(1);
din->PrepareForCpuAccess();
clkin->PrepareForCpuAccess();

//Create the capture
auto cap = new PCIe128b130bWaveform;
cap->m_timescale = 1;
cap->m_startTimestamp = din->m_startTimestamp;
cap->m_startFemtoseconds = din->m_startFemtoseconds;
cap->PrepareForCpuAccess();

//Record the value of the data stream at each clock edge
DigitalWaveform data;
SampleOnAnyEdges(din, clkin, data);
SparseDigitalWaveform data;
SampleOnAnyEdgesBase(din, clkin, data);

//Look at each phase and figure out block alignment
size_t end = data.m_offsets.size() - 130;
size_t end = data.size() - 130;
size_t best_offset = 0;
size_t best_errors = end;
for(size_t offset=0; offset < 130; offset ++)
Expand Down Expand Up @@ -215,6 +218,7 @@ void PCIe128b130bDecoder::Refresh()
}

SetData(cap, 0);
cap->MarkModifiedFromCpu();
}

Gdk::Color PCIe128b130bWaveform::GetColor(size_t i)
Expand Down
4 changes: 4 additions & 0 deletions scopeprotocols/PCIeDataLinkDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,14 @@ void PCIeDataLinkDecoder::Refresh()
return;
}
auto data = dynamic_cast<PCIeLogicalWaveform*>(GetInputWaveform(0));
data->PrepareForCpuAccess();

//Create the capture
auto cap = new PCIeDataLinkWaveform;
cap->m_timescale = data->m_timescale;
cap->m_startTimestamp = data->m_startTimestamp;
cap->m_startFemtoseconds = data->m_startFemtoseconds;
cap->PrepareForCpuAccess();
SetData(cap, 0);

enum
Expand Down Expand Up @@ -621,6 +623,8 @@ void PCIeDataLinkDecoder::Refresh()
break; //end STATE_END
}
}

cap->MarkModifiedFromCpu();
}

/**
Expand Down
8 changes: 7 additions & 1 deletion scopeprotocols/PCIeGen2LogicalDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ void PCIeGen2LogicalDecoder::Refresh()
ssize_t nports = m_parameters[m_portCountName].GetIntVal();
vector<IBM8b10bWaveform*> inputs;
for(ssize_t i=0; i<nports; i++)
inputs.push_back(dynamic_cast<IBM8b10bWaveform*>(GetInputWaveform(i)));
{
auto wfm = dynamic_cast<IBM8b10bWaveform*>(GetInputWaveform(i));
inputs.push_back(wfm);
wfm->PrepareForCpuAccess();
}

if(nports == 0)
{
Expand All @@ -127,6 +131,7 @@ void PCIeGen2LogicalDecoder::Refresh()
cap->m_startTimestamp = in0->m_startTimestamp;
cap->m_startFemtoseconds = in0->m_startFemtoseconds;
cap->m_triggerPhase = 0;
cap->PrepareForCpuAccess();

//Find the first comma symbol in each lane so we can synchronize them to each other
//TODO: this might fail if we have a partial set of commas right at the start of the capture and there's a few symbols
Expand Down Expand Up @@ -316,6 +321,7 @@ void PCIeGen2LogicalDecoder::Refresh()
}

SetData(cap, 0);
cap->MarkModifiedFromCpu();
}

uint8_t PCIeGen2LogicalDecoder::RunScrambler(uint16_t& state)
Expand Down
8 changes: 7 additions & 1 deletion scopeprotocols/PCIeGen3LogicalDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ void PCIeGen3LogicalDecoder::Refresh()
ssize_t nports = m_parameters[m_portCountName].GetIntVal();
vector<PCIe128b130bWaveform*> inputs;
for(ssize_t i=0; i<nports; i++)
inputs.push_back(dynamic_cast<PCIe128b130bWaveform*>(GetInputWaveform(i)));
{
auto din = dynamic_cast<PCIe128b130bWaveform*>(GetInputWaveform(i));
inputs.push_back(din);
din->PrepareForCpuAccess();
}

if(nports == 0)
{
Expand All @@ -104,6 +108,7 @@ void PCIeGen3LogicalDecoder::Refresh()
cap->m_startTimestamp = in0->m_startTimestamp;
cap->m_startFemtoseconds = in0->m_startFemtoseconds;
cap->m_triggerPhase = 0;
cap->PrepareForCpuAccess();

//Find the first skip ordered set in each lane so we can synchronize them to each other
//TODO: this might fail if we have a partial set of SOS's right at the start of the capture and there's a few
Expand Down Expand Up @@ -475,6 +480,7 @@ void PCIeGen3LogicalDecoder::Refresh()
}

SetData(cap, 0);
cap->MarkModifiedFromCpu();
}

/**
Expand Down
4 changes: 4 additions & 0 deletions scopeprotocols/PCIeTransportDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,14 @@ void PCIeTransportDecoder::Refresh()
return;
}
auto data = dynamic_cast<PCIeDataLinkWaveform*>(GetInputWaveform(0));
data->PrepareForCpuAccess();

//Create the capture
auto cap = new PCIeTransportWaveform;
cap->m_timescale = data->m_timescale;
cap->m_startTimestamp = data->m_startTimestamp;
cap->m_startFemtoseconds = data->m_startFemtoseconds;
cap->PrepareForCpuAccess();
SetData(cap, 0);

enum
Expand Down Expand Up @@ -905,6 +907,8 @@ void PCIeTransportDecoder::Refresh()
break;
}
}

cap->MarkModifiedFromCpu();
}

Gdk::Color PCIeTransportWaveform::GetColor(size_t i)
Expand Down
26 changes: 12 additions & 14 deletions scopeprotocols/PRBSCheckerFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,14 @@ void PRBSCheckerFilter::Refresh()

//Sample the input data stream
//TODO: allow single rate clocks too?
auto din = GetDigitalInputWaveform(0);
auto clkin = GetDigitalInputWaveform(1);
DigitalWaveform data;
SampleOnAnyEdges(din, clkin, data);
auto din = GetInputWaveform(0);
auto clkin = GetInputWaveform(1);
din->PrepareForCpuAccess();
clkin->PrepareForCpuAccess();

SparseDigitalWaveform data;
data.PrepareForCpuAccess();
SampleOnAnyEdgesBase(din, clkin, data);

auto poly = static_cast<PRBSGeneratorFilter::Polynomials>(m_parameters[m_polyname].GetIntVal());

Expand All @@ -146,17 +150,9 @@ void PRBSCheckerFilter::Refresh()
}

//Create the output "error found" waveform
auto dout = dynamic_cast<DigitalWaveform*>(GetData(0));
if(!dout)
{
dout = new DigitalWaveform;
SetData(dout, 0);
}
auto dout = SetupEmptySparseDigitalOutputWaveform(din, 0);
dout->PrepareForCpuAccess();
dout->m_timescale = 1;
dout->m_triggerPhase = 0;
dout->m_startTimestamp = data.m_startTimestamp;
dout->m_startFemtoseconds = data.m_startFemtoseconds;
dout->m_densePacked = true;
dout->Resize(len);

//Read the first N bits of state into the seed
Expand All @@ -179,4 +175,6 @@ void PRBSCheckerFilter::Refresh()
bool value = PRBSGeneratorFilter::RunPRBS(prbs, poly);
dout->m_samples[i] = (value != data.m_samples[i]);
}

dout->MarkModifiedFromCpu();
}
21 changes: 9 additions & 12 deletions scopeprotocols/PRBSGeneratorFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,45 +162,42 @@ void PRBSGeneratorFilter::Refresh()
int64_t fs = (t - floor(t)) * FS_PER_SECOND;

//Create the two output waveforms
DigitalWaveform* dat = dynamic_cast<DigitalWaveform*>(GetData(0));
auto dat = dynamic_cast<UniformDigitalWaveform*>(GetData(0));
if(!dat)
{
dat = new DigitalWaveform;
dat = new UniformDigitalWaveform;
SetData(dat, 0);
}
dat->PrepareForCpuAccess();
dat->m_timescale = samplePeriod;
dat->m_triggerPhase = 0;
dat->m_startTimestamp = floor(t);
dat->m_startFemtoseconds = fs;
dat->m_densePacked = true;
dat->Resize(depth);

DigitalWaveform* clk = dynamic_cast<DigitalWaveform*>(GetData(1));
auto clk = dynamic_cast<UniformDigitalWaveform*>(GetData(1));
if(!clk)
{
clk = new DigitalWaveform;
clk = new UniformDigitalWaveform;
SetData(clk, 1);
}
clk->PrepareForCpuAccess();
clk->m_timescale = samplePeriod;
clk->m_triggerPhase = samplePeriod / 2;
clk->m_startTimestamp = floor(t);
clk->m_startFemtoseconds = fs;
clk->m_densePacked = true;
clk->Resize(depth);

bool lastclk = false;
uint32_t prbs = rand();
for(size_t i=0; i<depth; i++)
{
//Fill clock
clk->m_offsets[i] = i;
clk->m_durations[i] = 1;
clk->m_samples[i] = lastclk;
lastclk = !lastclk;

//Fill data
dat->m_offsets[i] = i;
dat->m_durations[i] = 1;
dat->m_samples[i] = RunPRBS(prbs, poly);
}

clk->MarkModifiedFromCpu();
dat->MarkModifiedFromCpu();
}
10 changes: 7 additions & 3 deletions scopeprotocols/ParallelBus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,16 @@ void ParallelBus::Refresh()
int width = m_parameters[m_widthname].GetIntVal();

//Make sure we have an input for each channel in use
vector<DigitalWaveform*> inputs;
vector<SparseDigitalWaveform*> inputs;
for(int i=0; i<width; i++)
{
auto din = GetDigitalInputWaveform(i);
auto din = dynamic_cast<SparseDigitalWaveform*>(GetInputWaveform(i));
if(din == NULL)
{
SetData(NULL, 0);
return;
}
din->PrepareForCpuAccess();
inputs.push_back(din);
}
if(inputs.empty())
Expand All @@ -108,7 +109,8 @@ void ParallelBus::Refresh()

//Merge all of our samples
//TODO: handle variable sample rates etc
auto cap = new DigitalBusWaveform;
auto cap = new SparseDigitalBusWaveform;
cap->PrepareForCpuAccess();
cap->Resize(len);
cap->CopyTimestamps(inputs[0]);
#pragma omp parallel for
Expand All @@ -135,4 +137,6 @@ void ParallelBus::Refresh()
m_inputs[i].m_channel = NULL;
}
}

cap->MarkModifiedFromCpu();
}

0 comments on commit 1dbb9fd

Please sign in to comment.