[subexp-daq] Question on COUNTER_DIFF in crate.c

Hans Toshihide Törnqvist hans.tornqvist at chalmers.se
Fri Feb 16 16:01:49 CET 2024


Dear Günter,

I had a quick look in the Caen v767 manual and thought I could mention a 
few of my thoughts.

There is an event-counter register on offset 0x4c which holds the number 
of events transferred to the output buffer. This can be read out and 
returned in readout_dt.

Note here that the time from accepting a trigger to starting the readout 
of the module must be sufficiently long, otherwise you might get a value 
before the complete event has been finished! If the module behaves 
correctly this counter should only update once the last word of an event 
is ready to be read from the output buffer.
This waiting time is typically controlled with the "conversion time" 
that can be set in the TRIMI, or the trigger module in general. Waking 
up the readout computer which accesses the module can take an 
"arbitrary" time on top of the conversion time, so one can play around 
with this value a bit.

There is an adaptive conversion time (acvt) feature in nurdlib that I 
have not tested myself for quite some time. It polls event-counters 
until some timeout, and adjusts the CVT on-the-fly to reduce the overall 
waiting time and polling calls. Could be interesting if you would like 
to go that far in optimising your setup, but I do not know how well the 
Sis 3316 supports this feature.

Back to the v767. It looks like the headers in the payload have the same 
event-counter in the lowest 10 bits. I would suggest that parse_data 
checks this value with the module event-counter. The End-of-block word 
has an event-size value which should also be checked with the size of 
the payload, but I would not check every time measurement word on a 
typically slow VME controller.

That's enough for now :)

Best regards,
Hans

On 2024-02-16 15:39, Hans Toshihide Törnqvist wrote:
> Dear Günter,
> 
> On 2024-02-16 13:50, Weber, Guenter Dr. wrote:
>>
>> Dear Håkan,
>>
>> thank you. This explanation makes some sense.
>>
>> Could you also explain the concept of "shadow module". What is it good 
>> for?
> 
> It's rather "shadow readout mode". The idea is to read data from a 
> module continuously in parallel to conversion and buffering, instead of 
> performing every task of acquisition in sequence where every task has to 
> wait for all the others to finish.
> 
> The advantage is that this can significantly reduce the time where a 
> module is unable to convert and buffer signals.
> 
> The potential disadvantage is that the data traffic on for example a VME 
> backplane could induce noise in the analog measurement.
> 
> The non-shadow mode is the default and best tested mode, due to present 
> module support, cooperation of modules in experiments, and historical 
> reasons.
> 
>> Also I would like to point out that the implementation of readout_dt 
>> for the V560 module that we used as a reference looks weird to us:
>>
>> uint32_t
>> caen_v560_readout_dt(structCrate*a_crate, structModule*a_module)
>> {
>>      (void)a_crate;
>> LOGF(spam)(LOGL, NAME" readout_dt {");
>> a_module->event_counter.value++;
>> LOGF(spam)(LOGL, NAME" readout_dt(ctr=0x%08x) }",
>> a_module->event_counter.value);
>> return0;
>> }
>>
>> Here the counter is incremented every time the module is 'touched' by 
>> the readout_dt function. In the loop that starts at line 1240 in 
>> crate.c the function readout_dt is executed for the module until the 
>> test around line 1270 is passed or the timeout around line 1280 
>> happens. Thus an initial mismatch between the (software) counter of 
>> module V560 and the crate that prevents the loop from being existed at 
>> the first trial will grow steadily as the module is accessed via 
>> readout_dt many, many times until it runs into the timeout. What is 
>> this good for?
> 
> Nurdlib avoids resetting counters and instead latches and saves counter 
> values (e.g. soft crate counters and module counters) during dead-time 
> when counters should not change. After the first event, both counters 
> must have incremented by 1. Any particular start value such as 0 or 1 
> has no deeper meaning, it's the progression that is important.
> 
> Resetting tends to carry with it the idea of "after a reset, or setting 
> something to 0, everything is fine". It moves the focus away from 
> getting the complete logic correct, at least that is the feeling I get.
> 
> Now, to actually discuss your case :)
> Are you seeing that the mismatch between the crate counter and the v560 
> keeps increasing for new events? Or do you have such a problem with the 
> dummy module? (I still did not find the slot to look at it...)
> 
>> To my (current) understanding it is pointless to try to mimic the 
>> function of a true hardware counter within the module by a counter 
>> that only exists in software. The better way would be to tell crate.c 
>> that this module does not have such a counter so that the check is 
>> pointless. Is this understanding correct? And if yes, how can I tell 
>> NURDLIB to skip this check?
> 
> A software counter would be a consistency check of the implementation, 
> but you are correct that it has little to do with the signals that are 
> recorded. One can send the same random signal to different modules and 
> verify correlation at some point after digitisation, and definitely no 
> later than online monitoring while data is recorded.
> 
> I think it's possible to give the module counter a mask of 0. The 
> counter check should in principle be:
> 
> mask = ctr_a_mask & ctr_b_mask;
> ctr_a = ctr_a_raw - ctr_a_latch;
> ctr_b = ctr_b_raw - ctr_b_latch;
> if ( (ctr_a & mask) == (ctr_b & mask) ) { all good! }
> 
> If either mask is 0 the condition will always pass. There is maybe a 
> better way to make this clear than built into the masking, but I would 
> say that using a module without any kind of sync-check in 
> event-per-event analysis is overall dangerous...
> 
> Hope that helps!
> 
> Best regards,
> Hans
> 
>> Best greetings
>>
>> Günter
>>
>>
>>
>> ------------------------------------------------------------------------
>> *Von:* subexp-daq <subexp-daq-bounces at lists.chalmers.se> im Auftrag 
>> von Håkan T Johansson <f96hajo at chalmers.se>
>> *Gesendet:* Freitag, 16. Februar 2024 13:25:59
>> *An:* Discuss use of Nurdlib, TRLO II, drasi and UCESB.
>> *Betreff:* Re: [subexp-daq] Question on COUNTER_DIFF in crate.c
>>
>> Dear Günter,
>>
>> I think Hans might have to correct me.
>>
>> This is not exactly what this code does, but typically the modules have a
>> trigger/event counter, which is incremented for each gate/common signal
>> they receive on the front-panel.
>>
>> When the readout is event-by-event, these counters are checked 
>> strictly by
>> nurdlib, in order to detect cabling issues, double-triggers and so on.
>> This is especially important for modules that have multi-event buffers,
>> that otherwise easily can become desynchronised.  (It takes of course 
>> some
>> time to read these counters, which contributes to the overall deadtime.
>> But the amount of times this has 'saved' data-taking by detecting issues
>> early make it very worthwhile.)
>>
>>
>> What the code you refer to is doing is I think 'abusing' this a bit.
>> There is typically some time (order of us) between the trigger, and when
>> the signals have been digitised and the data becomes available.  Often,
>> those counters are only updated after that is the case.  To me it looks
>> like this function use the counters (which we anyhow want to check) to
>> wait for the modules to have finished converting one event.
>>
>>
>> Best regards,
>> Håkan
>>
>>
>>
>>
>>
>> On Fri, 16 Feb 2024, Weber, Guenter Dr. wrote:
>>
>>>
>>> Dear friends,
>>>
>>>
>>> we are now trying to add a new module into NURDLIB. At the beginning, 
>>> we just want to have a 'software version' of the module, so no
>>> hardware involved yet.
>>>
>>>
>>> We are stuck with the following code in crate.c (line 1262 and 
>>> following):
>>>
>>>
>>>             diff_module = COUNTER_DIFF(*module->crate_counter,
>>>                 module->event_counter, module->this_minus_crate);
>>>             /* TODO: Clean this. */
>>>             shadow_counter.value =
>>>                 module->shadow.data_counter_value;
>>>             shadow_counter.mask = module->event_counter.mask;
>>>             diff_shadow = COUNTER_DIFF(*module->crate_counter,
>>>                 shadow_counter, module->this_minus_crate);
>>>
>>>
>>> As we understand, the idea here is to check with a call of readout_dt 
>>> if the module's internal counter agrees with the counter of the
>>> crate for the given module. Basicly when the crate thinks it has 
>>> accessed the module n times, the module should report the same number of
>>> access attempts. Is this understanding correct?
>>>
>>>
>>> If yes, how exactly should the module increment it's internal 
>>> counter? If this is done on readout_dt, a mismatch between the crate 
>>> and the
>>> internal counter occurs as soon as we stop the aquisition.
>>>
>>>
>>> I can explain in more details, but maybe first you can explain to us 
>>> what the whole idea behind this check is? To us it looks like also
>>> the dummy module implementation will have problems with it.
>>>
>>>
>>>
>>>
>>> Thank you very much!
>>>
>>>
>>>
>>>
>>> Best greetings
>>>
>>> Günter
>>>
>>>
>>>
>>>
>>


More information about the subexp-daq mailing list