From a6bf666aaeea9c44697424d9815d85feccf9eedc Mon Sep 17 00:00:00 2001 From: dreamsourcelabTAI Date: Sat, 2 Apr 2022 16:56:08 +0800 Subject: [PATCH] fix: parallel protocol lose the last annotation --- DSView/pv/data/decoderstack.cpp | 8 +- libsigrokdecode4DSL/decoders/parallel/pd.py | 120 ++++++++++++++------ libsigrokdecode4DSL/instance.c | 2 +- libsigrokdecode4DSL/libsigrokdecode.h | 2 + libsigrokdecode4DSL/session.c | 41 +++++++ libsigrokdecode4DSL/type_decoder.c | 14 ++- 6 files changed, 145 insertions(+), 42 deletions(-) diff --git a/DSView/pv/data/decoderstack.cpp b/DSView/pv/data/decoderstack.cpp index a75fcd75..ed777d4b 100755 --- a/DSView/pv/data/decoderstack.cpp +++ b/DSView/pv/data/decoderstack.cpp @@ -508,11 +508,12 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod char *error = NULL; bool bError = false; bool bEndTime = false; + //struct srd_push_param push_param; if( i >= decode_end){ qDebug()<<"decode data index have been end:"<m_bStop) { std::vector chunk; @@ -521,6 +522,7 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod for (int j =0 ; j < logic_di->dec_num_channels; j++) { int sig_index = logic_di->dec_channelmap[j]; + if (sig_index == -1) { chunk.push_back(NULL); chunk_const.push_back(0); @@ -534,6 +536,7 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod } } } + if (chunk_end > decode_end) chunk_end = decode_end; if (chunk_end - i > MaxChunkSize) @@ -574,7 +577,10 @@ void DecoderStack::decode_data(const uint64_t decode_start, const uint64_t decod // the task is normal ends,so all samples was processed; if (!bError && bEndTime){ + srd_session_end(session, &error); + if (error) + _error_message = QString::fromLocal8Bit(error); } qDebug()<<"send to decoder times:"< 0: - self.es_word = self.samplenum + self.es_word = cur_dex self.putw([1, [self.fmt_word.format(self.saved_word)]]) self.putpw(['WORD', self.saved_word]) self.saved_word = None - # Defer annotations for individual items until the next sample - # is taken, and the previous sample's end samplenumber has - # become available. - if self.first: - # Save the start sample and item for later (no output yet). - self.ss_item = self.samplenum - self.first = False - self.saved_item = item - else: - # Output the saved item (from the last CLK edge to the current). - self.es_item = self.samplenum - self.putpb(['ITEM', self.saved_item]) - self.putb([0, [self.fmt_item.format(self.saved_item)]]) - self.ss_item = self.samplenum - self.saved_item = item + if item is None: + return - # Get as many items as the configured wordsize specifies. + # Get as many items as the configured wordsize specifies. if not self.items: - self.ss_word = self.samplenum + self.ss_word = cur_dex + self.items.append(item) ws = self.options['wordsize'] + if len(self.items) < ws: return # Collect words and prepare annotation details, but defer emission # until the end samplenumber becomes available. endian = self.options['endianness'] + if endian == 'big': self.items.reverse() - word = sum([self.items[i] << (i * used_pins) for i in range(ws)]) + + word = sum([self.items[i] << (i * self.num_item_bits) for i in range(ws)]) self.saved_word = word self.items = [] + def end(self): + cur_dex = self.last_samplenum + #the last annotation + self.put_py(self.prv_dex, cur_dex, ['ITEM', self.saved_item]) + self.put_ann(self.prv_dex, cur_dex, [0, [self.fmt_item.format(self.saved_item)]]) + self.handel_word(None, cur_dex) + def decode(self): # Determine which (optional) channels have input data. Insist in # a non-empty input data set. Cope with sparse connection maps. # Store enough state to later "compress" sampled input data. max_possible = len(self.optional_channels) + idx_channels = [ idx if self.has_channel(idx) else None for idx in range(max_possible) ] + has_channels = [idx for idx in idx_channels if idx is not None] if not has_channels: raise ChannelError('At least one channel has to be supplied.') max_connected = max(has_channels) + self.have_clock = self.has_channel(0) + self.prv_dex = self.samplenum + have_clock = self.have_clock + # Determine .wait() conditions, depending on the presence of a # clock signal. Either inspect samples on the configured edge of # the clock, or inspect samples upon ANY edge of ANY of the pins # which provide input data. - if self.has_channel(0): + if have_clock: edge = self.options['clock_edge'][0] - conds = {0: edge} + conds = {0: edge} #'f' or 'r' else: conds = [{idx: 'e'} for idx in has_channels] - + # Pre-determine which input data to strip off, the width of # individual items and multiplexed words, as well as format # strings here. This simplifies call sites which run in tight @@ -198,16 +227,33 @@ class Decoder(srd.Decoder): num_word_items = self.options['wordsize'] num_word_bits = num_item_bits * num_word_items num_digits = (num_item_bits + 3) // 4 - self.fmt_item = "{{:0{}x}}".format(num_digits) + self.fmt_item = "{{:0{}X}}".format(num_digits) num_digits = (num_word_bits + 3) // 4 - self.fmt_word = "{{:0{}x}}".format(num_digits) + self.fmt_word = "{{:0{}X}}".format(num_digits) + self.num_item_bits = num_item_bits # Keep processing the input stream. Assume "always zero" for # not-connected input lines. Pass data bits (all inputs except # clock) to the handle_bits() method. + + is_first = True + the_conds = conds + while True: - (clk, d0, d1, d2, d3, d4, d5, d6, d7) = self.wait(conds) - pins = (clk, d0, d1, d2, d3, d4, d5, d6, d7) + if not have_clock and is_first: + #get the value at sample 0 + conds = None + else: + conds = the_conds + + (clk, d0, d1, d2, d3, d4, d5, d6, d7,d8, d9,d10 ,d11 ,d12 ,d13 ,d14 ,d15 ,d16 ,d17 ,d18 ,d19 ,d20 ,d21 ,d22 ,d23 ,d24 ,d25 ,d26 ,d27 ,d28 ,d29 ,d30 ,d31 ) = self.wait(conds) + pins = (clk, d0, d1, d2, d3, d4, d5, d6, d7,d8, d9, d10, d11, d12,d13 ,d14 ,d15 ,d16 ,d17 ,d18 ,d19 ,d20 ,d21 ,d22 ,d23 ,d24 ,d25 ,d26 ,d27 ,d28 ,d29 ,d30 ,d31 ) bits = [0 if idx is None else pins[idx] for idx in idx_channels] item = bitpack(bits[1:idx_strip]) - self.handle_bits(item, num_item_bits) + + if not have_clock and is_first: + is_first = False + self.saved_item = item + continue + + self.handle_bits(item) diff --git a/libsigrokdecode4DSL/instance.c b/libsigrokdecode4DSL/instance.c index 47e2fc19..a0f66be4 100755 --- a/libsigrokdecode4DSL/instance.c +++ b/libsigrokdecode4DSL/instance.c @@ -381,7 +381,7 @@ SRD_API struct srd_decoder_inst *srd_inst_new(struct srd_session *sess, di->dec_num_channels = g_slist_length(di->decoder->channels) + g_slist_length(di->decoder->opt_channels); - if (di->dec_num_channels) { + if (di->dec_num_channels > 0) { di->dec_channelmap = g_malloc(sizeof(int) * di->dec_num_channels); for (i = 0; i < di->dec_num_channels; i++) diff --git a/libsigrokdecode4DSL/libsigrokdecode.h b/libsigrokdecode4DSL/libsigrokdecode.h index 3847eb3f..bf180b55 100755 --- a/libsigrokdecode4DSL/libsigrokdecode.h +++ b/libsigrokdecode4DSL/libsigrokdecode.h @@ -392,6 +392,8 @@ SRD_API int srd_session_destroy(struct srd_session *sess); SRD_API int srd_pd_output_callback_add(struct srd_session *sess, int output_type, srd_pd_output_callback cb, void *cb_data); +SRD_API int srd_session_end(struct srd_session *sess, char **error); + /* decoder.c */ SRD_API const GSList *srd_decoder_list(void); SRD_API struct srd_decoder *srd_decoder_get_by_id(const char *id); diff --git a/libsigrokdecode4DSL/session.c b/libsigrokdecode4DSL/session.c index 32597486..a48ddf30 100755 --- a/libsigrokdecode4DSL/session.c +++ b/libsigrokdecode4DSL/session.c @@ -407,4 +407,45 @@ SRD_PRIV struct srd_pd_callback *srd_pd_output_callback_find( return pd_cb; } +SRD_API int srd_session_end(struct srd_session *sess, char **error) +{ + GSList *d; + struct srd_decoder_inst *di; + PyGILState_STATE gstate; + PyObject *py_res; + + if (!sess || !sess->di_list){ + return SRD_ERR; + } + + gstate = PyGILState_Ensure(); + + for (d = sess->di_list; d; d = d->next) + { + di = d->data; + + if (PyObject_HasAttrString(di->py_inst, "end")) + { + //set the last sample index + PyObject *py_cur_samplenum = PyLong_FromUnsignedLongLong(di->abs_cur_samplenum); + PyObject_SetAttrString(di->py_inst, "last_samplenum", py_cur_samplenum); + Py_DECREF(py_cur_samplenum); + + py_res = PyObject_CallMethod(di->py_inst, "end", NULL); + + if (!py_res) + { + srd_exception_catch(error, "Protocol decoder instance %s", + di->inst_id); + PyGILState_Release(gstate); + return SRD_ERR_PYTHON; + } + } + } + + PyGILState_Release(gstate); + + return SRD_OK; +} + /** @} */ diff --git a/libsigrokdecode4DSL/type_decoder.c b/libsigrokdecode4DSL/type_decoder.c index 947150b3..94beaefa 100755 --- a/libsigrokdecode4DSL/type_decoder.c +++ b/libsigrokdecode4DSL/type_decoder.c @@ -661,6 +661,7 @@ static PyObject *Decoder_register(PyObject *self, PyObject *args, pdo = cmp; break; } + if (pdo) { py_new_output_id = Py_BuildValue("i", pdo->pdo_id); PyGILState_Release(gstate); @@ -1002,7 +1003,7 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args) uint64_t skip_count; gboolean found_match; struct srd_decoder_inst *di; - PyGILState_STATE gstate; + PyGILState_STATE gstate; if (!self || !args) return NULL; @@ -1088,7 +1089,7 @@ static PyObject *Decoder_wait(PyObject *self, PyObject *args) Py_INCREF(di->py_pinvalues); return (PyObject *)di->py_pinvalues; - } + } /* No match, reset state for the next chunk. */ di->got_new_samples = FALSE; @@ -1170,7 +1171,14 @@ static PyObject *Decoder_has_channel(PyObject *self, PyObject *args) PyGILState_Release(gstate); - return (di->dec_channelmap[idx] == -1) ? Py_False : Py_True; + if (di->dec_channelmap[idx] == -1){ + Py_INCREF(Py_False); + return Py_False; + } + else{ + Py_INCREF(Py_True); + return Py_True; + } err: PyGILState_Release(gstate);