/********************************************************************\
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 ...
|