X-Git-Url: https://sigrok.org/gitweb/?p=pulseview.git;a=blobdiff_plain;f=pv%2Fdata%2Flogicsnapshot.cpp;h=797a00bc54789f2cd4de2f7067448cf98aec0b96;hp=5665d35f8c3d58916b3df6ed41c11227f13d39cf;hb=8bd26d8b9c831b509ee3241ea4dac6f50c023622;hpb=5cef1ea3c6a3ed3851c631354bf9168a154179dc diff --git a/pv/data/logicsnapshot.cpp b/pv/data/logicsnapshot.cpp index 5665d35f..797a00bc 100644 --- a/pv/data/logicsnapshot.cpp +++ b/pv/data/logicsnapshot.cpp @@ -27,10 +27,14 @@ #include +#include "config.h" #include "logicsnapshot.h" -using namespace boost; -using namespace std; +using boost::lock_guard; +using boost::recursive_mutex; +using std::max; +using std::min; +using std::pair; namespace pv { namespace data { @@ -40,10 +44,13 @@ 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) : +LogicSnapshot::LogicSnapshot(const sr_datafeed_logic &logic, + const uint64_t expected_num_samples) : Snapshot(logic.unitsize), _last_append_sample(0) { + set_capacity(expected_num_samples); + lock_guard lock(_mutex); memset(_mip_map, 0, sizeof(_mip_map)); append_payload(logic); @@ -56,6 +63,80 @@ LogicSnapshot::~LogicSnapshot() free(l.data); } +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( const sr_datafeed_logic &logic) { @@ -70,14 +151,33 @@ void LogicSnapshot::append_payload( 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 + 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)); } } @@ -98,14 +198,12 @@ void LogicSnapshot::append_payload_to_mipmap() if (m0.length == prev_length) return; - reallocate_mip_map(m0); + reallocate_mipmap_level(m0); 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 + + const uint8_t *const end_src_ptr = (uint8_t*)_data + m0.length * _unit_size * MipMapScaleFactor; for (src_ptr = (uint8_t*)_data + prev_length * _unit_size * MipMapScaleFactor; @@ -116,13 +214,13 @@ void LogicSnapshot::append_payload_to_mipmap() diff_counter = MipMapScaleFactor; while (diff_counter-- > 0) { - const uint64_t sample = *(uint64_t*)src_ptr; + 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; + pack_sample(dest_ptr, accumulator); dest_ptr += _unit_size; } @@ -140,12 +238,12 @@ 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 = + 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; @@ -156,11 +254,11 @@ void LogicSnapshot::append_payload_to_mipmap() diff_counter = MipMapScaleFactor; while (diff_counter-- > 0) { - accumulator |= *(uint64_t*)src_ptr; + accumulator |= unpack_sample(src_ptr); src_ptr += _unit_size; } - *(uint64_t*)dest_ptr = accumulator; + pack_sample(dest_ptr, accumulator); } } } @@ -170,7 +268,7 @@ uint64_t LogicSnapshot::get_sample(uint64_t index) const assert(_data); assert(index < _sample_count); - return *(uint64_t*)((uint8_t*)_data + index * _unit_size); + return unpack_sample((uint8_t*)_data + index * _unit_size); } void LogicSnapshot::get_subsampled_edges( @@ -187,7 +285,7 @@ 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); @@ -204,7 +302,10 @@ void LogicSnapshot::get_subsampled_edges( { //----- Continue to search -----// level = min_level; - fast_forward = true; + + // We cannot fast-forward if there is no mip-map data at + // at the minimum level. + fast_forward = (_mip_map[level].data != NULL); if (min_length < MipMapScaleFactor) { @@ -241,7 +342,8 @@ void LogicSnapshot::get_subsampled_edges( // We can fast forward only if there was no change const bool sample = (get_sample(index) & sig_mask) != 0; - fast_forward = last_sample == sample; + if (last_sample != sample) + fast_forward = false; } if (fast_forward) { @@ -342,15 +444,17 @@ 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 + + return unpack_sample((uint8_t*)_mip_map[level].data + _unit_size * offset); }