Back Midas Rome Roody Rootana
  Midas DAQ System, Page 61 of 146  Not logged in ELOG logo
New entries since:Wed Dec 31 16:00:00 1969
ID Date Author Topic Subjectdown
  1845   21 Feb 2020 Stefan RittForumWritting Midas Events via FPGAs
> Hi, Stefan - is this our famous 64-bit misalignement? Where we have each alternating bank aligned and misaligned at 64 bits? Without changing the data
> format, one can always store data in 64-bit aligned banks by inserting a dummy banks between real banks:
> 
> event header
> bank header
> bank1 --- 64-bit aligned --- with data
> bank2 --- misaligned, no data
> bank3 --- 64-bit aligned --- with data
> bank4 --- misaligned, no data
> ...
> 
> for sure, wastes space for bank2, bank4, etc, but at 12 bytes per bank, maybe this is negligible overhead compared to total event size.
> 
> BTW, aligned-to-64-bit is old news. The the PWB FPGA, I have 128-bit data paths to DDR RAM, the data has to be aligned to 128 bits, or else!

Ok, so what about the following: When we do a bk_init32, we add a parameter "alignment", which might be 1,4,8,16 and "old". We store this alignment in the bank header, so the 
decoding works correctly. Now "old" means the current encoding, which is screwed up and produces the results you mention above, but we have to keep it (actually make it the 
default!) for backward compatibility. But then we can ask for 64-bit alignment or even 128-bit alignment if that helps the DAQ speed.

The only problem I see is if one writes data with the new library using 128-bit alignment for example, and wants to read it back with old code. Then it would explode. So if we 
make this modification, we have to announce it carefully and also adjust all ROOTANA & Co libraries to read back any midas data.

Stefan
  Draft   23 Feb 2020 Marius KoeppelForumWritting Midas Events via FPGAs
> > We also agree and found the problem now.
> 
> Good. what was wrong?
> 
> > - Own DMA engine since we are doing burst writing DMA with PCIe 3.0. 
> > - Own device driver
> 
> Scary stuff.
> 
> > - no interrupts 
> 
> Right. Best I can tell, interrupts no longer useful in Linux - interrupt handler cannot do any real work, has to hand off to a kernel thread, resulting
> in so much latency and overhead that one might as well poll for the data... And for DMA data transfers, the data rate is well known,
> so easy to predict how long the DMA will run for and sleep for that amount of time instead of waiting for an interrupt.
> 
> K.O.

So the problem was that we assumed that the bank (with the header) needs to be 64bit aligned. Even more we aligned the hole Midas event to 256bit in the fpga since we have a  250mhz x 256 Bit interface for PCIe. But then we saw that you align the bank data to 64bit -> crash of mdump etc. For now we generate the data on the FPGA in the „old“ Midas format. So having a flag for changing to a different alignment would be actually really nice. 

Cheers,
Marius
  2308   12 Dec 2021 Marius KoeppelBug ReportWritting MIDAS Events via FPGAs
Dear all,

in 13 Feb 2020 to 21 Feb 2020 we had a talk about how I try to create MIDAS events directly on a FPGA and 
than use DMA to hand the event over to MIDAS. In the thread I also explained how I do it in my MIDAS frontend. 

For testing the DAQ I created a dummy frontend which was emulating my FPGA (see attached file). The interesting code is 
in the function read_stream_thread and there I just fill a array according to the 32b BANKS which are 64b aligned (more or less
the lines 306-369). And than I do:

    uint32_t * dma_buf_volatile;
    dma_buf_volatile = dma_buf_dummy;

    copy_n(&dma_buf_volatile[0], sizeof(dma_buf_dummy)/4, pdata);

    pdata+=sizeof(dma_buf_dummy);
    rb_increment_wp(rbh, sizeof(dma_buf_dummy)); // in byte length

to send the data to the buffer.

This summer (Mai - July) everything was working fine but today I did not get the data into MIDAS. 
I was hopping around a bit with the commits and everything was at least working until: 3921016ce6d3444e6c647cbc7840e73816564c78.

Thanks,
Marius
Attachment 1: dummy_fe.cpp
/********************************************************************\

  Name:         dummy_fe.cxx
  Created by:   Frederik Wauters
  Changed by:   Marius Koeppel

  Contents:     Dummy frontend producing stream data

\********************************************************************/

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <algorithm>
#include <random>

#include <iostream>
#include <unistd.h>
#include <bitset>

#include "midas.h"
#include "msystem.h"
#include "mcstd.h"

#include <thread>
#include <chrono>

#include "mfe.h"

using namespace std;

/*-- Globals -------------------------------------------------------*/

/* The frontend name (client name) as seen by other MIDAS clients   */
const char *frontend_name = "Dummy Stream Frontend";
/* The frontend file name, don't change it */
const char *frontend_file_name = __FILE__;

/* frontend_loop is called periodically if this variable is TRUE    */
BOOL frontend_call_loop = FALSE;

/* a frontend status page is displayed with this frequency in ms    */
INT display_period = 0;

/* maximum event size produced by this frontend */
INT max_event_size = 1 << 25; // 32MB

/* maximum event size for fragmented events (EQ_FRAGMENTED) */
INT max_event_size_frag = 5 * 1024 * 1024;

/* buffer size to hold events */
INT event_buffer_size = 10000 * max_event_size;

/*-- Function declarations -----------------------------------------*/

INT read_stream_thread(void *param);
uint64_t generate_random_pixel_hit(uint64_t time_stamp);
uint32_t generate_random_pixel_hit_swb(uint32_t time_stamp);

BOOL equipment_common_overwrite = TRUE; //true is overwriting the common odb  


/* DMA Buffer and related */
volatile uint32_t *dma_buf;
#define MUDAQ_DMABUF_DATA_ORDER         25 // 29, 25 for 32 MB
#define MUDAQ_DMABUF_DATA_LEN           (1 << MUDAQ_DMABUF_DATA_ORDER)  // in bytes
size_t dma_buf_size = MUDAQ_DMABUF_DATA_LEN;
uint32_t dma_buf_nwords = dma_buf_size/sizeof(uint32_t);




/*-- Equipment list ------------------------------------------------*/

EQUIPMENT equipment[] = {

   {"Stream",              /* equipment name */
    {1, 0,                     /* event ID, trigger mask */
     "SYSTEM",                  /* event buffer */
     EQ_USER,               /* equipment type */
     0,                         /* event source */
     "MIDAS",                   /* format */
     TRUE,                      /* enabled */
     RO_RUNNING ,        /* read always and update ODB */
     100,                     /* poll for 100ms */
     0,                         /* stop run after this event limit */
     0,                         /* number of sub events */
     0,                         /* log history every event */
     "", "", ""} ,
    NULL,              /* readout routine */
   },

   {""}
};


/*-- Dummy routines ------------------------------------------------*/

INT poll_event(INT source, INT count, BOOL test)
{
   return 1;
};

INT interrupt_configure(INT cmd, INT source, POINTER_T adr)
{
   return 1;
};

/*-- Frontend Init -------------------------------------------------*/

INT frontend_init()
{
  // create ring buffer for readout thread
  create_event_rb(0);

  // create readout thread
  ss_thread_create(read_stream_thread, NULL);
    
  set_equipment_status(equipment[0].name, "Ready for running", "var(--mgreen)");

  return CM_SUCCESS;
}

/*-- Frontend Exit -------------------------------------------------*/

INT frontend_exit()
{
 return CM_SUCCESS;
}

/*-- Frontend Loop -------------------------------------------------*/

INT frontend_loop()
{
  return CM_SUCCESS;
}

/*-- Begin of Run --------------------------------------------------*/

INT begin_of_run(INT run_number, char *error)
{
  set_equipment_status(equipment[0].name, "Running", "var(--mgreen)");
  return CM_SUCCESS;
}

/*-- End of Run ----------------------------------------------------*/

INT end_of_run(INT run_number, char *error)
{
  set_equipment_status(equipment[0].name, "Ready for running", "var(--mgreen)");
  return CM_SUCCESS;
}

/*-- Pause Run -----------------------------------------------------*/

INT pause_run(INT run_number, char *error)
{
   return CM_SUCCESS;
}

/*-- Resume Run ----------------------------------------------------*/

INT resume_run(INT run_number, char *error)
{
   return CM_SUCCESS;
}


uint64_t generate_random_pixel_hit(uint64_t time_stamp)
{

  // Bits 63 - 35: TimeStamp (29 bits)
  // Bits 34 - 30: Tot       (5 bits)
  // Bits 29 - 26: Layer     (4 bits)
  // Bits 25 - 21: Phi       (5 bits)
  // Bits 20 - 16: ChipID    (5 bits)
  // Bits 15 -  8: Col       (8 bits)
  // Bits  7 -  0: Row       (8 bits)

  uint64_t tot = rand() % 31; // 0 to 31
  uint64_t layer = rand() % 15; // 0 to 15
  uint64_t phi = rand() % 31; // 0 to 31
  uint64_t chipID = rand() % 5; // 0 to 31
  uint64_t col = rand() % 250; // 0 to 255
  uint64_t row = rand() % 250; // 0 to 255

  uint64_t hit = (time_stamp << 35) | (tot << 30) | (layer << 26) | (phi << 21) | (chipID << 16) | (col << 8) | row;

  //printf("tot: 0x%2.2x,layer: 0x%2.2x,phi: 0x%2.2x,chipID: 0x%2.2x,col: 0x%2.2x,row: 0x%2.2x\n",tot,layer,phi,chipID,col,row);
  //cout << hex << hit << endl;
  //cout << hex << time_stamp << endl;
  //cout << hex << (hit >> 35 & 0x7FFFFFFFF) << endl;
  //cout << hex << (hit >> 32) << endl;

  return hit;
}

uint32_t generate_random_pixel_hit_swb(uint32_t time_stamp)
{

  uint32_t tot = rand() % 31; // 0 to 31
  uint32_t chipID = rand() % 5; // 0 to 5
  uint32_t col = rand() % 250; // 0 to 250
  uint32_t row = rand() % 250; // 0 to 250

  uint32_t hit = (time_stamp << 28) | (chipID << 22) | (row << 13) | (col << 5) | tot << 1;

//   if ( print ) {
//     printf("ts:%8.8x,chipID:%8.8x,row:%8.8x,col:%8.8x,tot:%8.8x\n", time_stamp,chipID,row,col,tot);
//     printf("hit:%8.8x\n", hit);
//     std::cout << std::bitset<32>(hit) << std::endl;
//   }

  return hit;
}

uint64_t generate_random_scifi_hit(uint32_t time_stamp, uint32_t counter1, uint32_t counter2)
{
    uint64_t asic = rand() % 8;
    uint64_t hit_type = 1;
    uint64_t channel_number = rand() % 32;
    uint64_t timestamp_bad = 0;
    uint64_t coarse_counter_value = (time_stamp >> 5) & 0x7FFF; 
    uint64_t fine_counter_value = time_stamp & 0x1F;
    uint64_t energy_flag = rand() % 2;
    uint64_t fpga_id = 10 + rand() % 4;
    if (counter1 > 0) {
        fpga_id = counter1;
    }

    return (asic << 60) | (hit_type << 59) | (channel_number << 54) | (timestamp_bad << 53) | (coarse_counter_value << 38) | (fine_counter_value << 33) | (energy_flag << 32) | (fpga_id << 28) | ((time_stamp & 0x0FFFFFFF));

}

uint64_t generate_random_delta_t_exponential(float lambda)
{
    float r = rand()/(1.0+RAND_MAX);
    return ceil(-log(1.0-r)/lambda);
}

uint64_t generate_random_delta_t_gauss(float mu, float sigma)
{
    std::default_random_engine generator;
    generator.seed(rand());
    std::normal_distribution<float> distribution(mu,sigma);
    float r = ceil(distribution(generator));
    if (r<0.0) r=0.0;
    return r;
}



INT read_stream_thread(void *param)
{

  uint32_t* pdata;

  // init bank structure - 64bit alignment
  uint32_t SERIAL = 0x00000001;
  uint32_t TIME = 0x00000001;

  uint64_t hit;

  // tell framework that we are alive
  signal_readout_thread_active(0, TRUE);

  // obtain ring buffer for inter-thread data exchange
  int rbh = get_event_rbh(0);
  int status;

  while (is_readout_thread_enabled()) {

    // obtain buffer space
    status = rb_get_wp(rbh, (void **)&pdata, 10);

    // just sleep and try again if buffer has no space
    if (status == DB_TIMEOUT) {
      set_equipment_status(equipment[0].name, "Buffer full", "var(--myellow)");
      continue;
    }

    if (status != DB_SUCCESS){
       cout << "!DB_SUCCESS" << endl;
       break;
    }

    // don't readout events if we are not running
    if (run_state != STATE_RUNNING) {
      set_equipment_status(equipment[0].name, "Not running", "var(--myellow)");
      continue;
    }

    set_equipment_status(equipment[0].name, "Running", "var(--mgreen)");

    int nEvents = 5000;
    size_t eventSize=76;
    uint32_t dma_buf_dummy[nEvents*eventSize];

    uint64_t prev_mutrig_hit = 0;
    uint64_t delta_t_1 = 100;
... 212 more lines ...
  2313   26 Jan 2022 Konstantin OlchanskiBug ReportWritting MIDAS Events via FPGAs
> today I did not get the data into MIDAS. 

Any error messages printed by the frontend? any error message in midas.log? core dumps? crashes?

I do not understand what you mean by "did not get the data into midas". You create events
and send them to a midas event buffer and you do not see them there? With mdump?
Do you see this both connected locally and connected remotely through the mserver?

BTW, I see you are using the mfe.c frontend. Event data handling in mfe.c frontends
is quite convoluted and impossible to straighten out. I recommend that you use
the tmfe c++ frontend instead. Event data handling is much simplified and is easier to debug
compared to the mfe.c frontend. There is examples in the midas repository and there are
tutorials for converting frontends from mfe.c to tmfe posted in this forum here.

BTW, the commit you refer to only changed some html files, could not have affected
your data.

K.O.
  2317   26 Jan 2022 Marius KoeppelBug ReportWritting MIDAS Events via FPGAs
> Any error messages printed by the frontend? any error message in midas.log? core dumps? crashes? 
> I do not understand what you mean by "did not get the data into midas". You create events
> and send them to a midas event buffer and you do not see them there? With mdump?
> Do you see this both connected locally and connected remotely through the mserver?

I simply don't see the event counter counting up and I also don't see them using mdump. No logs, no dumps and no crashes - every is quite. I only tested it locally.
 
> BTW, I see you are using the mfe.c frontend. Event data handling in mfe.c frontends
> is quite convoluted and impossible to straighten out. I recommend that you use
> the tmfe c++ frontend instead. Event data handling is much simplified and is easier to debug
> compared to the mfe.c frontend. There is examples in the midas repository and there are
> tutorials for converting frontends from mfe.c to tmfe posted in this forum here.

I know the code I used is really old that's why I was so surprised that it suddenly did not work. But I am on the way to change it. Also Stefan gave me some comments on how to improve the code. But still changing them did not really change the behavior. 

> BTW, the commit you refer to only changed some html files, could not have affected
> your data.

I just hopped around and the commit I send was the first one which worked again. But it's of course not the one where the stuff broke. I did a bit of git-bisect and ended up with this commit as the first one where my frontend is not working anymore: 91582e4172d534bf9b10e661a423c399fd1a69f4

Cheers,
Marius
  2322   26 Jan 2022 Konstantin OlchanskiBug ReportWritting MIDAS Events via FPGAs
> 
> > Any error messages printed by the frontend? any error message in midas.log? core dumps? crashes? 
> > I do not understand what you mean by "did not get the data into midas". You create events
> > and send them to a midas event buffer and you do not see them there? With mdump?
> > Do you see this both connected locally and connected remotely through the mserver?
> 
> I simply don't see the event counter counting up and I also don't see them using mdump. No logs, no dumps and no crashes - every is quite. I only tested it locally.
>

If you are connected locally (no mserver), I want to know the value returned by bm_send_event(). Simplest
if you edit mfe.c and everywhere it calls bm_send_event() and rpc_send_event(), print the returned value.

It would be very interesting to see if bm_send_event() returns 1 (SUCCESS), but the event vanishes
without a trace.

Before you do that, try something simpler:

Run "mdump -s -d", it will print some event buffer internals.

Watch to see if any data pointers change when you send your events ("wp", "rp", etc).

If nothing changes at all, then we are not sending anything (fault is in your code or on mfe.c).

If you see "wp" counting up, then we definitely write your events into the buffer and mdump & mlogger should see them.

But there is some funny logic for event_id and trigger_mask and it is worth checking their
values. For a good test, set event_id=1 and trigger_mask=0x1. There might be trouble if either is set to zero.

K.O.
  2325   26 Jan 2022 Marius KoeppelBug ReportWritting MIDAS Events via FPGAs
> If you are connected locally (no mserver), I want to know the value returned by bm_send_event(). Simplest
> if you edit mfe.c and everywhere it calls bm_send_event() and rpc_send_event(), print the returned value.
> 
> It would be very interesting to see if bm_send_event() returns 1 (SUCCESS), but the event vanishes
> without a trace.

I checked bm_send_event(rbh, (EVENT_HEADER*)(&pdata[0]), 0, 20); which gives me back 1. I also check the status of rb_increment_wp which is also 1.

> Before you do that, try something simpler:
> Run "mdump -s -d", it will print some event buffer internals.
> Watch to see if any data pointers change when you send your events ("wp", "rp", etc).

"rp" & "wp" are not counting up. 

> But there is some funny logic for event_id and trigger_mask and it is worth checking their
> values. For a good test, set event_id=1 and trigger_mask=0x1. There might be trouble if either is set to zero.

Changing both to 0x1 did not change the behavior. 

Cheers,
Marius
  2326   28 Jan 2022 Stefan RittBug ReportWritting MIDAS Events via FPGAs
I finally got the dummy program working. There were several issues:

- event_buffer_size was defined as 10000 * 32 MB = 320 GB, exceeding the RAM of the computer

- SERIAL number starting with 1. Actually in midas, event serial numbers always started with zero, but this was wrong in the documentation at 
https://midas.triumf.ca/MidasWiki/index.php/Event_Structure, so I also fixed the documentation

- the event header time stamp must be seconds since 1.1.1970, and thus the function ss_time() should be used to set it

- calling set_equipment_status() for each event slows down the event collection considerably, since this function access the ODB each time

- dma_buf_dummy is defined inside the event loop, so it gets allocated and de-allocated on the stack for each event. Of course this might vanish 
when the real FPGA buffer will be used.

- The line pdata+=sizeof(dma_buf_dummy); is wrong. pdata is pointer to uint32_t, but the sizeof() operation returns the size of the 
dma_buf_dummy in bytes. Therefore, pdata gets incremented by four times the size of dma_buf_dummy

- Instead the call to std::this_thread::sleep_for(std::chrono::milliseconds(2000)); one can call the standard midas call ss_sleep(2000); which 
is a bit shorter

- Finally, sending many events to the ring buffer triggered a bug in the midas ring buffer functions which were lingering there since 2007. I'm 
glad that this happened and now could be fixed. Not sure if other experiments where affected in the last decade by that. This could have 
manifested itself in lost events or crashing front-ends. Anyhow, now it's fixed. You need to update midas to get the fix.

I attached a working version of the dummy program for your reference. Banks a different but the principle should become clear.

Stefan
Attachment 1: dummy_fe.cpp
/********************************************************************\

  Name:         dummy_fe.cxx
  Created by:   Frederik Wauters
  Changed by:   Marius Koeppel

  Contents:     Dummy frontend producing stream data

\********************************************************************/

#include <algorithm>
#include <math.h>
#include <random>
#include <stdio.h>
#include <stdlib.h>

#include <bitset>
#include <iostream>
#include <unistd.h>

#include "midas.h"
#include "msystem.h"

#include <chrono>
#include <thread>

#include "mfe.h"

using namespace std;

/*-- Globals -------------------------------------------------------*/

/* The frontend name (client name) as seen by other MIDAS clients   */
const char *frontend_name = "Dummy FE SWB";
/* The frontend file name, don't change it */
const char *frontend_file_name = __FILE__;

/* frontend_loop is called periodically if this variable is TRUE    */
BOOL frontend_call_loop = FALSE;

/* a frontend status page is displayed with this frequency in ms    */
INT display_period = 0;

/* maximum event size produced by this frontend */
INT max_event_size = 1 * (1024 * 1024);// 32MB

/* maximum event size for fragmented events (EQ_FRAGMENTED) */
INT max_event_size_frag = 5 * 1024 * 1024;

/* buffer size to hold events */
INT event_buffer_size = 2 * max_event_size;

/*-- Function declarations -----------------------------------------*/

INT read_stream_thread(void *param);
uint32_t generate_random_pixel_hit_swb(uint32_t time_stamp);
uint32_t generate_random_beam_ref_hit(uint32_t time_stamp, uint32_t chipID);

BOOL equipment_common_overwrite = TRUE;//true is overwriting the common odb

/* DMA Buffer and related */
volatile uint32_t *dma_buf;
#define MUDAQ_DMABUF_DATA_ORDER 25                          // 29, 25 for 32 MB
#define MUDAQ_DMABUF_DATA_LEN (1 << MUDAQ_DMABUF_DATA_ORDER)// in bytes
size_t dma_buf_size = MUDAQ_DMABUF_DATA_LEN;
uint32_t dma_buf_nwords = dma_buf_size / sizeof(uint32_t);

/*-- Equipment list ------------------------------------------------*/

EQUIPMENT equipment[] = {

   {
      "Stream SWB", /* equipment name */
      {1, 0,        /* event ID, trigger mask */
       "SYSTEM",    /* event buffer */
       EQ_USER,     /* equipment type */
       0,           /* event source */
       "MIDAS",     /* format */
       TRUE,        /* enabled */
       RO_RUNNING,  /* read always and update ODB */
       100,         /* poll for 100ms */
       0,           /* stop run after this event limit */
       0,           /* number of sub events */
       0,           /* log history every event */
       "", "", ""},
      NULL, /* readout routine */
   },

   {""}};

/*-- Dummy routines ------------------------------------------------*/

INT poll_event(INT source, INT count, BOOL test) {
   return 1;
};

INT interrupt_configure(INT cmd, INT source, POINTER_T adr) {
   return 1;
};

/*-- Frontend Init -------------------------------------------------*/

INT frontend_init() {
   // create ring buffer for readout thread
   create_event_rb(0);

   // create readout thread
   ss_thread_create(read_stream_thread, NULL);

   return CM_SUCCESS;
}

/*-- Frontend Exit -------------------------------------------------*/

INT frontend_exit() {
   return CM_SUCCESS;
}

/*-- Frontend Loop -------------------------------------------------*/

INT frontend_loop() {
   return CM_SUCCESS;
}

/*-- Begin of Run --------------------------------------------------*/

INT begin_of_run(INT run_number, char *error) {
   return CM_SUCCESS;
}

/*-- End of Run ----------------------------------------------------*/

INT end_of_run(INT run_number, char *error) {
   return CM_SUCCESS;
}

/*-- Pause Run -----------------------------------------------------*/

INT pause_run(INT run_number, char *error) {
   return CM_SUCCESS;
}

/*-- Resume Run ----------------------------------------------------*/

INT resume_run(INT run_number, char *error) {
   return CM_SUCCESS;
}

/*------------------------------------------------------------------*/

uint32_t generate_random_pixel_hit_swb(uint32_t time_stamp) {
   uint32_t tot = rand() % 32;  // 0 to 31
   uint32_t chipID = rand() % 3;// 0 to 2
   uint32_t col = rand() % 256; // 0 to 256
   uint32_t row = rand() % 250; // 0 to 250

   uint32_t hit = (time_stamp << 28) | (chipID << 22) | (row << 14) | (col << 6) | (tot << 1);

   //   if ( print ) {
   //     printf("ts:%8.8x,chipID:%8.8x,row:%8.8x,col:%8.8x,tot:%8.8x\n", time_stamp,chipID,row,col,tot);
   //     printf("hit:%8.8x\n", hit);
   //     std::cout << std::bitset<32>(hit) << std::endl;
   //   }

   if (((hit >> 22) & 0x3f) > 2)
      printf("Hit %8.8x", hit);

   if (chipID > 2)
      printf("ChipID %8.8x", chipID);

   return hit;
}

uint32_t generate_random_beam_ref_hit(uint32_t time_stamp, uint32_t chipID) {
   uint32_t fastTS = rand() % 4194303 / 2;// 0 to 4194303

   uint32_t hit = (time_stamp << 28) | (chipID << 22) | (fastTS << 1);

   if (((hit >> 22) & 0x3f) > 4) {
      printf("Hit Ref %8.8x\n", hit);
      printf("Ref fast %8.8x\n", fastTS);
      printf("ChipID Ref %8.8x\n", chipID);
      printf("Time Ref %8.8x\n", time_stamp);
      printf("Chip %8.8x\n", ((hit >> 22) & 0x3f));
   }

   return hit;
}

INT read_stream_thread(void *param) {
   uint32_t *pdata;

   // init bank structure - 64bit alignment
   uint32_t SERIAL = 0;

   // tell framework that we are alive
   signal_readout_thread_active(0, TRUE);

   // obtain ring buffer for inter-thread data exchange
   int rbh = get_event_rbh(0);
   int status;

   int nEvents = 5000;
   size_t eventSize = 32; // in 4-byte words
   size_t dmaBufSize = nEvents * eventSize * sizeof(uint32_t); // buffer size in bytes
   uint32_t * dma_buf_dummy = (uint32_t *) malloc(dmaBufSize);

   while (is_readout_thread_enabled()) {

      // don't readout events if we are not running
      if (!readout_enabled()) {
         // do not produce events when run is stopped
         ss_sleep(10);// don't eat all CPU
         continue;
      }

      // obtain buffer space with 10 ms timeout
      status = rb_get_wp(rbh, (void **) &pdata, 10);

      // just try again if buffer has no space
      if (status == DB_TIMEOUT)
         continue;

      if (status != DB_SUCCESS) {
         cout << "!DB_SUCCESS" << endl;
         break;
      }

      for (int i = 0; i < nEvents; i++) {
         // event header
         dma_buf_dummy[ 0 + i * eventSize] = 0x00000001;           // Trigger Mask & Event ID
         dma_buf_dummy[ 1 + i * eventSize] = SERIAL++;             // Serial number
         dma_buf_dummy[ 2 + i * eventSize] = ss_time();            // time
         dma_buf_dummy[ 3 + i * eventSize] = eventSize * 4 - 4 * 4;// event size

         dma_buf_dummy[ 4 + i * eventSize] = eventSize * 4 - 6 * 4;// all bank size
         dma_buf_dummy[ 5 + i * eventSize] = 0x31;                 // flags

         // bank PCD0 first FEB
         dma_buf_dummy[ 6 + i * eventSize] = 'P' << 0 | 'C' << 8 | 'D' << 16 | '0' << 24;// bank name
         dma_buf_dummy[ 7 + i * eventSize] = 0x06;                                       // bank type TID_DWORD
         dma_buf_dummy[ 8 + i * eventSize] = 10 * 4;                                     // data size
         dma_buf_dummy[ 9 + i * eventSize] = 0x0;                                        // reserved

         dma_buf_dummy[10 + i * eventSize] = 0xE80000BC;                                // preamble
         dma_buf_dummy[11 + i * eventSize] = 0x00000000;                                // TS0
         dma_buf_dummy[12 + i * eventSize] = ss_time();                                 // TS1
         dma_buf_dummy[13 + i * eventSize] = 0xFC000000;                                // sub header
         dma_buf_dummy[14 + i * eventSize] = generate_random_pixel_hit_swb(ss_time());  // hit0
         dma_buf_dummy[15 + i * eventSize] = generate_random_pixel_hit_swb(ss_time());  // hit1
         dma_buf_dummy[16 + i * eventSize] = generate_random_beam_ref_hit(ss_time(), 3);// chip 3 beam ref bits 22:1 -> fast TS
         dma_buf_dummy[17 + i * eventSize] = generate_random_beam_ref_hit(ss_time(), 4);// chip 4 sintilator bits 22:1 -> fast TS
         dma_buf_dummy[18 + i * eventSize] = 0xFC00009C;                                // TRAILER
         dma_buf_dummy[19 + i * eventSize] = 0xAFFEAFFE;                                // PADDING

         // bank PCD1 second FEB
         dma_buf_dummy[20 + i * eventSize] = 'P' << 0 | 'C' << 8 | 'D' << 16 | '1' << 24;// bank name
         dma_buf_dummy[21 + i * eventSize] = 0x6;                                       // bank type TID_DWORD
         dma_buf_dummy[22 + i * eventSize] = 8 * 4;                                     // data size
         dma_buf_dummy[23 + i * eventSize] = 0x0;                                       // reserved

         dma_buf_dummy[24 + i * eventSize] = 0xE80001BC;                              // preamble
         dma_buf_dummy[25 + i * eventSize] = 0x00000000;                              // TS0
         dma_buf_dummy[26 + i * eventSize] = ss_time();                               // TS1
         dma_buf_dummy[27 + i * eventSize] = 0xFC000000;                              // sub header
         dma_buf_dummy[28 + i * eventSize] = generate_random_pixel_hit_swb(ss_time());// hit0
         dma_buf_dummy[29 + i * eventSize] = generate_random_pixel_hit_swb(ss_time());// hit1
         dma_buf_dummy[30 + i * eventSize] = 0xFC00009C;                              // TRAILER
         dma_buf_dummy[31 + i * eventSize] = 0xAFFEAFFE;                              // PADDING
      }

      memcpy(pdata, dma_buf_dummy, dmaBufSize);

      // print data
      if (true) {
         auto *eh = (EVENT_HEADER *) (&pdata[0]);
         auto *bh = (BANK_HEADER *) (&pdata[4]);
         auto *ba = (BANK32A *) (&pdata[6]);
         char bank_name[5];
         bank_name[4] = 0;
         memcpy(bank_name, (char *) (ba->name), 4);
         printf("EID=%4.4x TM=%4.4x SERNO=%8.8x TS=%8.8x EDsiz=%8.8x\n", eh->event_id, eh->trigger_mask, eh->serial_number, eh->time_stamp, eh->data_size);
         printf("DAsiz=%8.8x FLAG=%8.8x\n", bh->data_size, bh->flags);
         printf("BAname=%s TYP=%8.8x BAsiz=%8.8x BAres=%8.8x\n", bank_name, ba->type, ba->data_size, ba->reserved);
      }

      rb_increment_wp(rbh, dmaBufSize);// in byte length

      ss_sleep(300);// limit data rate
   }

   free(dma_buf_dummy);

   return 0;
}
  2347   16 Feb 2022 Marius KoeppelBug ReportWritting MIDAS Events via FPGAs
I just came back to this and started to use the dummy frontend.
Unfortunately, I have a problem during run cycles: 

Starting the frontend and starting a run works fine -> seeing events with mdump and also on the web GUI. 
But when I stop the run and try to start the next run the frontend is sending no events anymore.
It get stuck at line 221 (if (status == DB_TIMEOUT)).
I tried to reduce the nEvents to 1 which helped in terms of DB_TIMEOUT but still I don't get any events after I did a stop / start cycle -> no events in mdump and no events counting up at the web GUI.
If I kill the frontend in the terminal (ctrl+c) and restart it, while the run is still running, it starts to send events again.

Cheers,
Marius
  2349   03 Mar 2022 Stefan RittBug ReportWritting MIDAS Events via FPGAs
> Starting the frontend and starting a run works fine -> seeing events with mdump and also on the web GUI. 
> But when I stop the run and try to start the next run the frontend is sending no events anymore.
> It get stuck at line 221 (if (status == DB_TIMEOUT)).
> I tried to reduce the nEvents to 1 which helped in terms of DB_TIMEOUT but still I don't get any events after I did a stop / start cycle -> no events in mdump and no events counting up at the web GUI.
> If I kill the frontend in the terminal (ctrl+c) and restart it, while the run is still running, it starts to send events again.

This problem has (likely) been fixed in the current version. Please pull develop and try again. Was a recursive call to the event collection routine which is only triggered if you send events faster than 
the logger can digest, so not many people see it.

Best,
Stefan
  2352   07 Mar 2022 Marius KoeppelBug ReportWritting MIDAS Events via FPGAs
> This problem has (likely) been fixed in the current version. Please pull develop and try again. Was a recursive call to the event collection routine which is only triggered if you send events faster than 
> the logger can digest, so not many people see it.

I just pulled the current version (d945fa9) but the problem as explained in 2347 stays the same.

Best,
Marius
  2375   25 Mar 2022 Marius KoeppelBug ReportWritting MIDAS Events via FPGAs
I finally found the problem why the readout stops after a run transition. 

In my dummy frontend the serial number was not reset to zero at run start. 
This leads to a mismatch of the serial number in the function receive_trigger_event of mfe.cxx:1247.
Which is than resulting in the problem that the function founds never a new event in all ring buffers and nothing get read out of the buffer.

Nevertheless, it would be nice that the system would tell the user that there is a mismatch in the serial number (printing a warning / error etc.). 

Cheers,
Marius
  994   28 Apr 2014 Tom StuttardForumWords written as zero in Midas bank
Hi,

I am having some trouble with the data in my Midas bank. I am filling a midas
bank in my frontend (one of several in my system), and this bank is then being
added to the overall event by the event builder.

I check the data as it enters the bank, and also check again after I close the
bank in my frontend (using pdata's original value), and in both cases my data is
as I expect.

However, when I view the data in the .mid file (using mdump), there is a
problem. The correct number of words are there, and the values are correct up
until the 148th word. However, all subsequent words are 0.

I have also noticed that if I change my word size from 32bit (DWORD) to 16bit
(WORD), I observe the same behaviour except that now the first 296 words are
correct and all others are zero.

Note that other frontends in the system are not suffering this issue.

Does anyone have any ideas about how to solve this problem?
  981   12 Mar 2014 Andreas SuterInfoWindows support droped?
In the old SVN midas world it was typically such that the Windows dll's and
exe's were ready to be used when checking out. I am not so sure this is the case
for the current version, since when I use the packed dll's  and exe's (e.g.
odbedit.exe) I get the warning that this is running midas 2.0.0 but the current
version (on the linux server) is 2.1.

What does this mean?

1) A little bug in the packed windows part, but up-to-date dll's and exe's?
2) The dll's and exe's are not bundled any more to up-to-date version?

If 2) is the case, I would like to get a hint how to build midas under Windows
(Windows 7), since we still have some few Windows clients.  
  983   14 Mar 2014 Konstantin OlchanskiInfoWindows support droped?
> In the old SVN midas world it was typically such that the Windows dll's and
> exe's were ready to be used when checking out.

The Windows executables are no longer included in the midas git repository. Old versions are still available in 
the git repository - they got pulled in during conversion from svn.

One reason for removing them is that neither myself, nor Pierre, nor Stefan have ready access to a Windows 
development environment and we cannot keep Windows binaries up to date. Theoretically we can setup a 
Windows machine just for compiling MIDAS, but then there is a question of which Windows we should use and 
how much priority we should put into it. I do not think there is any demand for MIDAS on Windows at TRIUMF.

(Personally, I think Windows is no longer a viable platform for any business use - with Microsoft focusing on 
"experiences", "tiles", touch screens, portable devices, and other gimmicks - rather than on providing a solid OS 
to get work done)

> I am not so sure this is the case
> for the current version, since when I use the packed dll's  and exe's (e.g.
> odbedit.exe) I get the warning that this is running midas 2.0.0 but the current
> version (on the linux server) is 2.1. What does this mean?

You can ignore this message. Stefan incremented the MIDAS version when we migrated to git, but
there are no changes to the MIDAS RPC mechanism and we are still fully compatible with old versions,
at least in the MIDAS RPC and in the mserver.

So tools like odbedit.exe should still work okey when connecting from Windows to MIDAS running on Linux or 
MacOS.

But old frontend programs may cause some trouble because the ODB layout changed somewhat with new things 
added to /eq/xxx/common. Simplest is to try, if it works, it works.

> 1) A little bug in the packed windows part, but up-to-date dll's and exe's?
> 2) The dll's and exe's are not bundled any more to up-to-date version?

Case (2) is the case. Personally I do not have any capability to build Windows binaries. Same for Pierre and I think 
for Stefan.

> If 2) is the case, I would like to get a hint how to build midas under Windows
> (Windows 7), since we still have some few Windows clients.  

I do not think pre-built executables will ever return - the new way of things is to "cut-and-paste" the "git clone" 
command from a web page, type "make", and be done with it. If your OS does not have "git", "make" & etc, you 
should switch to a real OS.

On the MIDAS software side, we have no problem with supporting Windows - same as on any other platform, 
please try to build and run it, report any problems, fixes, patches and improvements - we will commit them into 
the midas repository.

K.O.
  986   17 Mar 2014 Stefan RittInfoWindows support droped?
> The Windows executables are no longer included in the midas git repository. Old versions are still available in 
> the git repository - they got pulled in during conversion from svn.
> 
> One reason for removing them is that neither myself, nor Pierre, nor Stefan have ready access to a Windows 
> development environment and we cannot keep Windows binaries up to date. Theoretically we can setup a 
> Windows machine just for compiling MIDAS, but then there is a question of which Windows we should use and 
> how much priority we should put into it. I do not think there is any demand for MIDAS on Windows at TRIUMF.

I double checked and can confirm that the executables in GIT are very old. So I tried to compile the current version for Windows. I found that I had to change lots 
of places (basically all the new files written by KO) to make it work again, so it took me half a day, but now should be fine.

I'm not sure if it's a good idea to keep .exe files in GIT, maybe we should remove it some day, but for the moment I updated the executables to the current 
version. Feedback welcome.

/Stefan
  1211   14 Oct 2016 Luka PavelicForumWiener PCIVME link
Hello, 
I'm trying to make Wiener PCIVME link work with MIDAS. 
In documentation/VME dirvers/ it's saying: "wevmemm.c PCI/VME Wiener board
supported. (see Wiener PCI)".
Provided link is dead. Does anyone have that file? I would appreciate very very
much if someone could send it to me.

Thank you and best regards, 
L.P.
  1212   14 Oct 2016 Konstantin OlchanskiForumWiener PCIVME link
> Hello, 
> I'm trying to make Wiener PCIVME link work with MIDAS. 
> In documentation/VME dirvers/ it's saying: "wevmemm.c PCI/VME Wiener board
> supported. (see Wiener PCI)".
> Provided link is dead. Does anyone have that file? I would appreciate very very
> much if someone could send it to me.
> 
> Thank you and best regards, 
> L.P.

Hi, I am not familiar with this module, I am pretty sure I have never seen one.
I do not see any code for it in the midas distribution.
I do not see any reference to it on the wiener web site (http://www.wiener-d.com/)

For obsolete modules, they direct us to http://file.wiener-d.com/ which is dead.

The next best step is to contact Wiener customer support. They usually reply very quickly.

If you have no luck getting answer directly from Wiener, you can ask me to contact them through
our sales representative. He is always super very helpful.

K.O.
  Draft   14 Oct 2016 Pierre-Andre AmaudruzForumWiener PCIVME link
> > Hello, 
> > I'm trying to make Wiener PCIVME link work with MIDAS. 
> > In documentation/VME dirvers/ it's saying: "wevmemm.c PCI/VME Wiener board
> > supported. (see Wiener PCI)".
> > Provided link is dead. Does anyone have that file? I would appreciate very very
> > much if someone could send it to me.
> > 
> > Thank you and best regards, 
> > L.P.
> 
> Hi, I am not familiar with this module, I am pretty sure I have never seen one.
> I do not see any code for it in the midas distribution.
> I do not see any reference to it on the wiener web site (http://www.wiener-d.com/)
> 
> For obsolete modules, they direct us to http://file.wiener-d.com/ which is dead.
> 
> The next best step is to contact Wiener customer support. They usually reply very quickly.
> 
> If you have no luck getting answer directly from Wiener, you can ask me to contact them through
> our sales representative. He is always super very helpful.
> 
> K.O.

Hi, 
I'm having a meeting with Wiener during this weekend, I'll try to dig some info about that module. But I do recall that we had this interface and provided a driver for it.
More later... 
PAA
  1215   14 Oct 2016 Pierre-Andre AmaudruzForumWiener PCIVME link
> > Hello, 
> > I'm trying to make Wiener PCIVME link work with MIDAS. 
> > In documentation/VME dirvers/ it's saying: "wevmemm.c PCI/VME Wiener 
board
> > supported. (see Wiener PCI)".
> > Provided link is dead. Does anyone have that file? I would appreciate 
very very
> > much if someone could send it to me.
> > 
> > Thank you and best regards, 
> > L.P.
> 
> Hi, I am not familiar with this module, I am pretty sure I have never 
seen one.
> I do not see any code for it in the midas distribution.
> I do not see any reference to it on the wiener web site 
(http://www.wiener-d.com/)
> 
> For obsolete modules, they direct us to http://file.wiener-d.com/ which 
is dead.
> 
> The next best step is to contact Wiener customer support. They usually 
reply very quickly.
> 
> If you have no luck getting answer directly from Wiener, you can ask me 
to contact them through
> our sales representative. He is always super very helpful.
> 
> K.O.

Hi, I do recall that we had this interface a while ago. 
I'll be meeting with Wiener during the weekend and will post my findings 
later. 
PAA 
ELOG V3.1.4-2e1708b5