X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fdata%2Flogicsnapshot.cpp;h=a89c8f93e36261862c5f4bad70696b80e50e5aba;hp=a7a84cf916d1cad33d4f16fb60d7c45b3fbfacd0;hb=ff008de665c7990d5f3408f918ff090d8e6c60b2;hpb=f06ab14342ff8ed391bb3df5e30cf6faa3422090 diff --git a/pv/data/logicsnapshot.cpp b/pv/data/logicsnapshot.cpp index a7a84cf9..a89c8f93 100644 --- a/pv/data/logicsnapshot.cpp +++ b/pv/data/logicsnapshot.cpp @@ -25,12 +25,18 @@ #include #include -#include +#include "logicsnapshot.hpp" -#include "logicsnapshot.h" +#include -using namespace boost; -using namespace std; +using std::lock_guard; +using std::recursive_mutex; +using std::max; +using std::min; +using std::pair; +using std::shared_ptr; + +using sigrok::Logic; namespace pv { namespace data { @@ -40,50 +46,146 @@ const int LogicSnapshot::MipMapScaleFactor = 1 << MipMapScalePower; const float LogicSnapshot::LogMipMapScaleFactor = logf(MipMapScaleFactor); const uint64_t LogicSnapshot::MipMapDataUnit = 64*1024; // bytes -LogicSnapshot::LogicSnapshot(const sr_datafeed_logic &logic) : - Snapshot(logic.unitsize), - _last_append_sample(0) +LogicSnapshot::LogicSnapshot(shared_ptr logic, uint64_t samplerate, + const uint64_t expected_num_samples) : + Snapshot(samplerate, logic->unit_size()), + last_append_sample_(0) { - lock_guard lock(_mutex); - memset(_mip_map, 0, sizeof(_mip_map)); + set_capacity(expected_num_samples); + + lock_guard lock(mutex_); + memset(mip_map_, 0, sizeof(mip_map_)); append_payload(logic); } LogicSnapshot::~LogicSnapshot() { - lock_guard lock(_mutex); - BOOST_FOREACH(MipMapLevel &l, _mip_map) + lock_guard lock(mutex_); + for (MipMapLevel &l : mip_map_) free(l.data); } -void LogicSnapshot::append_payload( - const sr_datafeed_logic &logic) +uint64_t LogicSnapshot::unpack_sample(const uint8_t *ptr) const +{ +#ifdef HAVE_UNALIGNED_LITTLE_ENDIAN_ACCESS + return *(uint64_t*)ptr; +#else + uint64_t value = 0; + switch(unit_size_) { + default: + value |= ((uint64_t)ptr[7]) << 56; + /* FALLTHRU */ + case 7: + value |= ((uint64_t)ptr[6]) << 48; + /* FALLTHRU */ + case 6: + value |= ((uint64_t)ptr[5]) << 40; + /* FALLTHRU */ + case 5: + value |= ((uint64_t)ptr[4]) << 32; + /* FALLTHRU */ + case 4: + value |= ((uint32_t)ptr[3]) << 24; + /* FALLTHRU */ + case 3: + value |= ((uint32_t)ptr[2]) << 16; + /* FALLTHRU */ + case 2: + value |= ptr[1] << 8; + /* FALLTHRU */ + case 1: + value |= ptr[0]; + /* FALLTHRU */ + case 0: + break; + } + return value; +#endif +} + +void LogicSnapshot::pack_sample(uint8_t *ptr, uint64_t value) +{ +#ifdef HAVE_UNALIGNED_LITTLE_ENDIAN_ACCESS + *(uint64_t*)ptr = value; +#else + switch(unit_size_) { + default: + ptr[7] = value >> 56; + /* FALLTHRU */ + case 7: + ptr[6] = value >> 48; + /* FALLTHRU */ + case 6: + ptr[5] = value >> 40; + /* FALLTHRU */ + case 5: + ptr[4] = value >> 32; + /* FALLTHRU */ + case 4: + ptr[3] = value >> 24; + /* FALLTHRU */ + case 3: + ptr[2] = value >> 16; + /* FALLTHRU */ + case 2: + ptr[1] = value >> 8; + /* FALLTHRU */ + case 1: + ptr[0] = value; + /* FALLTHRU */ + case 0: + break; + } +#endif +} + +void LogicSnapshot::append_payload(shared_ptr logic) { - assert(_unit_size == logic.unitsize); - assert((logic.length % _unit_size) == 0); + assert(unit_size_ == logic->unit_size()); + assert((logic->data_length() % unit_size_) == 0); - lock_guard lock(_mutex); + lock_guard lock(mutex_); - append_data(logic.data, logic.length / _unit_size); + append_data(logic->data_pointer(), + logic->data_length() / unit_size_); // Generate the first mip-map from the data append_payload_to_mipmap(); } -void LogicSnapshot::reallocate_mip_map(MipMapLevel &m) +void LogicSnapshot::get_samples(uint8_t *const data, + int64_t start_sample, int64_t end_sample) const +{ + assert(data); + assert(start_sample >= 0); + assert(start_sample <= (int64_t)sample_count_); + assert(end_sample >= 0); + assert(end_sample <= (int64_t)sample_count_); + assert(start_sample <= end_sample); + + lock_guard lock(mutex_); + + const size_t size = (end_sample - start_sample) * unit_size_; + memcpy(data, (const uint8_t*)data_.data() + start_sample * unit_size_, size); +} + +void LogicSnapshot::reallocate_mipmap_level(MipMapLevel &m) { const uint64_t new_data_length = ((m.length + MipMapDataUnit - 1) / MipMapDataUnit) * MipMapDataUnit; if (new_data_length > m.data_length) { m.data_length = new_data_length; - m.data = realloc(m.data, new_data_length * _unit_size); + + // Padding is added to allow for the uint64_t write word + m.data = realloc(m.data, new_data_length * unit_size_ + + sizeof(uint64_t)); } } void LogicSnapshot::append_payload_to_mipmap() { - MipMapLevel &m0 = _mip_map[0]; + MipMapLevel &m0 = mip_map_[0]; uint64_t prev_length; const uint8_t *src_ptr; uint8_t *dest_ptr; @@ -92,23 +194,21 @@ void LogicSnapshot::append_payload_to_mipmap() // Expand the data buffer to fit the new samples prev_length = m0.length; - m0.length = _sample_count / MipMapScaleFactor; + m0.length = sample_count_ / MipMapScaleFactor; // Break off if there are no new samples to compute if (m0.length == prev_length) return; - reallocate_mip_map(m0); + reallocate_mipmap_level(m0); - dest_ptr = (uint8_t*)m0.data + prev_length * _unit_size; + dest_ptr = (uint8_t*)m0.data + prev_length * unit_size_; // Iterate through the samples to populate the first level mipmap - accumulator = 0; - diff_counter = MipMapScaleFactor; - const uint8_t *end_src_ptr = (uint8_t*)_data + - m0.length * _unit_size * MipMapScaleFactor; - for (src_ptr = (uint8_t*)_data + - prev_length * _unit_size * MipMapScaleFactor; + const uint8_t *const end_src_ptr = (uint8_t*)data_.data() + + m0.length * unit_size_ * MipMapScaleFactor; + for (src_ptr = (uint8_t*)data_.data() + + prev_length * unit_size_ * MipMapScaleFactor; src_ptr < end_src_ptr;) { // Accumulate transitions which have occurred in this sample @@ -116,21 +216,21 @@ void LogicSnapshot::append_payload_to_mipmap() diff_counter = MipMapScaleFactor; while (diff_counter-- > 0) { - const uint64_t sample = *(uint64_t*)src_ptr; - accumulator |= _last_append_sample ^ sample; - _last_append_sample = sample; - src_ptr += _unit_size; + const uint64_t sample = unpack_sample(src_ptr); + accumulator |= last_append_sample_ ^ sample; + last_append_sample_ = sample; + src_ptr += unit_size_; } - *(uint64_t*)dest_ptr = accumulator; - dest_ptr += _unit_size; + pack_sample(dest_ptr, accumulator); + dest_ptr += unit_size_; } // Compute higher level mipmaps for (unsigned int level = 1; level < ScaleStepCount; level++) { - MipMapLevel &m = _mip_map[level]; - const MipMapLevel &ml = _mip_map[level-1]; + MipMapLevel &m = mip_map_[level]; + const MipMapLevel &ml = mip_map_[level-1]; // Expand the data buffer to fit the new samples prev_length = m.length; @@ -140,37 +240,36 @@ void LogicSnapshot::append_payload_to_mipmap() if (m.length == prev_length) break; - reallocate_mip_map(m); + reallocate_mipmap_level(m); // Subsample the level lower level src_ptr = (uint8_t*)ml.data + - _unit_size * prev_length * MipMapScaleFactor; - const uint8_t *end_dest_ptr = - (uint8_t*)m.data + _unit_size * m.length; + unit_size_ * prev_length * MipMapScaleFactor; + const uint8_t *const end_dest_ptr = + (uint8_t*)m.data + unit_size_ * m.length; for (dest_ptr = (uint8_t*)m.data + - _unit_size * prev_length; + unit_size_ * prev_length; dest_ptr < end_dest_ptr; - dest_ptr += _unit_size) + dest_ptr += unit_size_) { accumulator = 0; diff_counter = MipMapScaleFactor; while (diff_counter-- > 0) { - accumulator |= *(uint64_t*)src_ptr; - src_ptr += _unit_size; + accumulator |= unpack_sample(src_ptr); + src_ptr += unit_size_; } - *(uint64_t*)dest_ptr = accumulator; + pack_sample(dest_ptr, accumulator); } } } uint64_t LogicSnapshot::get_sample(uint64_t index) const { - assert(_data); - assert(index < _sample_count); + assert(index < sample_count_); - return *(uint64_t*)((uint8_t*)_data + index * _unit_size); + return unpack_sample((uint8_t*)data_.data() + index * unit_size_); } void LogicSnapshot::get_subsampled_edges( @@ -187,9 +286,9 @@ void LogicSnapshot::get_subsampled_edges( assert(start <= end); assert(min_length > 0); assert(sig_index >= 0); - assert(sig_index < SR_MAX_NUM_PROBES); + assert(sig_index < 64); - lock_guard lock(_mutex); + lock_guard lock(mutex_); const uint64_t block_length = (uint64_t)max(min_length, 1.0f); const unsigned int min_level = max((int)floorf(logf(min_length) / @@ -207,7 +306,7 @@ void LogicSnapshot::get_subsampled_edges( // We cannot fast-forward if there is no mip-map data at // at the minimum level. - fast_forward = (_mip_map[level].data != NULL); + fast_forward = (mip_map_[level].data != NULL); if (min_length < MipMapScaleFactor) { @@ -265,7 +364,7 @@ void LogicSnapshot::get_subsampled_edges( // Check if we reached the last block at this // level, or if there was a change in this block - if (offset >= _mip_map[level].length || + if (offset >= mip_map_[level].length || (get_subsample(level, offset) & sig_mask)) break; @@ -275,7 +374,7 @@ void LogicSnapshot::get_subsampled_edges( // higher level mip-map block ascend one // level if (level + 1 >= ScaleStepCount || - !_mip_map[level + 1].data) + !mip_map_[level + 1].data) break; level++; @@ -290,7 +389,7 @@ void LogicSnapshot::get_subsampled_edges( // Zoom in, and slide right until we encounter a change, // and repeat until we reach min_level while (1) { - assert(_mip_map[level].data); + assert(mip_map_[level].data); const int level_scale_power = (level + 1) * MipMapScalePower; @@ -299,7 +398,7 @@ void LogicSnapshot::get_subsampled_edges( // Check if we reached the last block at this // level, or if there was a change in this block - if (offset >= _mip_map[level].length || + if (offset >= mip_map_[level].length || (get_subsample(level, offset) & sig_mask)) { // Zoom in unless we reached the minimum @@ -346,16 +445,18 @@ void LogicSnapshot::get_subsampled_edges( } // Add the final state - edges.push_back(pair(end, - get_sample(end) & sig_mask)); + const bool end_sample = get_sample(end) & sig_mask; + if (last_sample != end_sample) + edges.push_back(pair(end, end_sample)); + edges.push_back(pair(end + 1, end_sample)); } uint64_t LogicSnapshot::get_subsample(int level, uint64_t offset) const { assert(level >= 0); - assert(_mip_map[level].data); - return *(uint64_t*)((uint8_t*)_mip_map[level].data + - _unit_size * offset); + assert(mip_map_[level].data); + return unpack_sample((uint8_t*)mip_map_[level].data + + unit_size_ * offset); } uint64_t LogicSnapshot::pow2_ceil(uint64_t x, unsigned int power)