• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

simulator/Simulator.cxx (r4864/r4190)

Go to the documentation of this file.
00001 #include "Simulator.h"
00002 
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <unistd.h>
00006 #include <errno.h>
00007 #include <fcntl.h>
00008 #include <poll.h>
00009 #include <math.h>
00010 #include <string.h>
00011 
00012 
00013 #include <time.h>
00014 #include <sys/time.h>
00015 #include <sys/timex.h>
00016 
00017 #include "roc/Message.h"
00018 
00019 struct sc_config gC;
00020 
00021 struct sc_data gD;
00022 
00023 double get_clock()
00024 {
00025    static double firsttm = 0.;
00026 
00027    //   if (errno!=0) printf("Before gettimeofday errno!=%d\n", errno);
00028    
00029    struct timeval tv;
00030    struct timezone tz;
00031    if (gettimeofday(&tv, &tz)<0) {
00032       int k = errno;
00033       printf("problem to get time err = %d %d %d\n", k, EFAULT, EINVAL);
00034    }
00035    double tttt = 1.*tv.tv_sec + tv.tv_usec * 1e-6;
00036 
00037    if (firsttm == 0.) firsttm = tttt;
00038 
00039    //   if (errno!=0) printf("After gettimeofday errno!=0 tm = %5.3f\n", tttt-firsttm);
00040 
00041    /*   ntptimeval val;
00042    ntp_gettime(&val);
00043    double tttt = val.time.tv_sec + val.time.tv_usec * 1e-6;
00044    if (firsttm == 0.) firsttm = tttt;
00045    */
00046    return tttt - firsttm;
00047 }
00048 
00049 bool SetNonBlockSocket(int fd)
00050 {
00051    int opts = fcntl(fd, F_GETFL);
00052    if (opts < 0) {
00053       printf(("fcntl(F_GETFL) failed\n"));
00054       return false;
00055    }
00056    opts = (opts | O_NONBLOCK);
00057    if (fcntl(fd, F_SETFL,opts) < 0) {
00058       printf(("fcntl(F_SETFL) failed\n"));
00059       return false;
00060    }
00061    return true;
00062 }
00063 
00064 int StartUdp(int& portnum, int portmin = 0, int portmax = 0)
00065 {
00066 
00067    int fd = socket(PF_INET, SOCK_DGRAM, 0);
00068    if (fd<0) return -1;
00069 
00070    struct sockaddr_in m_addr;
00071    int numtests = 1; // at least test value of portnum
00072    if ((portmin>0) && (portmax>0) && (portmin<=portmax)) numtests+=(portmax-portmin+1);
00073 
00074    if (SetNonBlockSocket(fd))
00075       for(int ntest=0;ntest<numtests;ntest++) {
00076          if ((ntest==0) && (portnum<0)) continue;
00077          if (ntest>0) portnum = portmin - 1 + ntest;
00078 
00079          memset(&m_addr, 0, sizeof(m_addr));
00080          m_addr.sin_family = AF_INET;
00081          m_addr.sin_port = htons(portnum);
00082 
00083          if (!bind(fd, (struct sockaddr*)&m_addr, sizeof(m_addr))) return fd;
00084       }
00085 
00086    close(fd);
00087    return -1;
00088 }
00089 
00090 const char* IpToStr(in_addr_t src_ip)
00091 {
00092    static char buf[200];
00093    snprintf(buf, sizeof(buf), "%u.%u.%u.%u",
00094             src_ip & 0xff, (src_ip >> 8) & 0xff,
00095             (src_ip >> 16) & 0xff, (src_ip >> 24) & 0xff);
00096    return buf;
00097 }
00098 
00099 
00100 UdpSimulator::UdpSimulator(int rocid, int syncscale, int period0, int period1, int ctrlport)
00101 {
00102    printf("Starting ROC Simulator...\n");
00103    memset(nxRegister, 0, sizeof(nxRegister));
00104    nxRegister[0] = ROC_SIMULATOR_HW_VERSION;
00105 
00106    memset(gpioRegs, 0, sizeof(gpioRegs));
00107 
00108    syncMDelay() = syncscale;
00109    gpioConfig() = (3 << (base::SYNC_S0*4));
00110 
00111    periodAUX0 = 2000000;
00112    if (period0>=0) gpioConfig() |= (3 << (base::AUX0*4));
00113    if (period0>0) periodAUX0 = (unsigned) period0;
00114 
00115    periodAUX1 = 20000;
00116    if (period1>=0) gpioConfig() |= (3 << (base::AUX1*4));
00117    if (period1>0) periodAUX1 = (unsigned) period1;
00118 
00119    resetSimulator();
00120 
00121    recvDataSize = 0;
00122    sendDataSize = 0;
00123    takeDataSize = 0;
00124    memset(&fStat, 0, sizeof(fStat));
00125 
00126    setLostRates(0., 0.);
00127 
00128    srand(3442143);
00129 
00130    gC.ctrlPort = ROC_DEFAULT_CTRLPORT;
00131    gC.dataPort = ROC_DEFAULT_DATAPORT;
00132 
00133    if (ctrlport>1000) {
00134       gC.ctrlPort = ctrlport;
00135       gC.dataPort = ctrlport-1;
00136    }
00137 
00138    gC.rocNumber = rocid;
00139    gC.flushTimeout = 1000;
00140 
00141    gD.high_water = 2000;   /* Maximum number of buffers to be used in normal situation */
00142    gD.low_water = 50;      /* Number of buffers to enable data taking after is was stopped */
00143 
00144    gD.headid = 0;         // id of buffer which is now filled
00145    gD.send_limit = 0;    /* limit for sending - can be in front of existing header */
00146    gD.resend_size = 0;   /* number of indexes to be resended */
00147    gD.last_req_pkt_id = 0; /* id of last request packet, should be always send back */
00148 
00149    gD.masterConnected = false; // 1 if master controller is connected
00150    gD.masterDataPort = 0;
00151    gD.masterPort = 0;
00152    gD.masterIp = 0;
00153    gD.lastMasterPacketId = 0;
00154    gD.master_retry_buf_rawsize = 0;
00155 
00156    gD.controlPort = 0;
00157    gD.controlIp = 0;
00158    gD.lastControlPacketId = 0;
00159    gD.control_retry_buf_rawsize = 0;
00160 
00161    gD.controlLocked = 0;
00162    gD.lockedTime = get_clock();
00163 
00164    gD.daqState = 0;
00165    gD.data_taking_on = false;
00166    gD.lastMasterTime = get_clock();
00167 
00168    for (int n=0;n<ROC_CMD_LST_SIZE/4;n++)
00169       gD.cmdsList[n] = 0;
00170 
00171    for (int n=0;n<ROC_CMD_LST_NUMBER;n++) {
00172       int aa = n * ROC_CMD_LST_SIZE / 4 / ROC_CMD_LST_NUMBER;
00173 
00174       if (n==0) {
00175          gD.cmdsList[aa++] = ROC_CMD_LST_PUT | ROC_NX_FIFO_RESET;
00176          gD.cmdsList[aa++] = 1;
00177          gD.cmdsList[aa++] = ROC_CMD_LST_PUT | ROC_NX_FIFO_RESET;
00178          gD.cmdsList[aa++] = 0;
00179          gD.cmdsList[aa++] = ROC_CMD_LST_PUT | ROC_ETH_START_DAQ;
00180          gD.cmdsList[aa++] = 1;
00181       } else
00182       if (n==1) {
00183          gD.cmdsList[aa++] = ROC_CMD_LST_PUT | ROC_ETH_STOP_DAQ;
00184          gD.cmdsList[aa++] = 1;
00185       }
00186 
00187       gD.cmdsList[aa++] = ROC_CMD_LST_PUT | ROC_CMD_LST_ACTIVE;
00188       gD.cmdsList[aa++] = 0;
00189    }
00190 
00191    gD.cmdListPtr = ROC_CMD_LST_SIZE / 4;
00192 
00193 
00194    s_data = 0;
00195    s_ctrl = 0;
00196 }
00197 
00198 UdpSimulator::~UdpSimulator()
00199 {
00200    //readout network fifo
00201    close(s_data);
00202    close(s_ctrl);
00203 }
00204 
00205 void UdpSimulator::resetSimulator()
00206 {
00207 
00208    // start with epoch wich has 24 bit already filled
00209 //   uint64_t first_stamp = (0x1000000ULL << 14);
00210    uint64_t first_stamp = 0;
00211 
00212    nextEventNumber = 0;
00213    clockScrewUp = 1. + gC.rocNumber / 1000.;
00214    nextTimeHit = first_stamp + 5674;
00215    nextHitCounter = 1;                 // generate only one hit for first event
00216    nextTimeNoise = first_stamp + 3456; // indicate when time stamp message should be
00217    nextTimeSync = first_stamp + 0x345; // indicate when next time sync message should appear
00218    nextTimeAUX0 = first_stamp + 0x500 + periodAUX0;  // first AUX0 signal will be after first sync
00219    nextTimeAUX1 = first_stamp + 0x764 + periodAUX1;  // first AUX1 signal will be after first sync
00220    nextAUX0Falling = true;
00221    nextAUX1Falling = true;
00222    lastEpoch = (first_stamp >> 14) - 1;    // last epoch set in data stream
00223    nextSyncEvent = 0;
00224 }
00225 
00226 
00227 bool UdpSimulator::doRecvLost()
00228 {
00229    totalRecvCounter++;
00230 
00231    if ((recvLostRate <=0.) || (recvLostRate >=1)) return false;
00232 
00233    if (recvLostCounter>0) {
00234       --recvLostCounter;
00235       if (recvLostCounter==0) totalRecvLosts++;
00236       return (recvLostCounter==0);
00237    }
00238 
00239    recvLostCounter = 1 + int (2. * rand() / RAND_MAX / recvLostRate);
00240 
00241    return false;
00242 }
00243 
00244 
00245 bool UdpSimulator::doSendLost()
00246 {
00247    totalSendCounter++;
00248 
00249    if ((sendLostRate <=0.) || (sendLostRate >=1)) return false;
00250 
00251    if (sendLostCounter>0) {
00252       sendLostCounter--;
00253       if (sendLostCounter==0) totalSendLosts++;
00254       return sendLostCounter==0;
00255    }
00256 
00257    sendLostCounter = 1 + int (2. * rand() / RAND_MAX / sendLostRate);
00258 
00259    return false;
00260 }
00261 
00262 void UdpSimulator::setLostRates(double recv, double send)
00263 {
00264    recvLostRate = recv; // relative loss rate of packets recieve
00265    sendLostRate = send; // relative loss rate of packets send
00266 
00267    recvLostCounter = 0; // backward counter to next recv lost
00268    sendLostCounter = 0; // backward counter to next send lost
00269 
00270    totalSendCounter = 0; totalSendLosts = 0;
00271    totalRecvCounter = 0; totalRecvLosts = 0;
00272 }
00273 
00274 bool UdpSimulator::initNewSockets()
00275 {
00276    int portnum = gC.ctrlPort;
00277 
00278    s_ctrl = StartUdp(portnum);
00279    if (s_ctrl<=0) {
00280       printf("Cannot start control port %d\n", portnum);
00281       return false;
00282    }
00283 
00284    portnum = gC.dataPort;
00285    s_data = StartUdp(portnum, portnum, portnum+100);
00286    if (s_data<=0) {
00287       printf("Cannot start data port %d\n", portnum);
00288       return false;
00289    }
00290    gC.dataPort = portnum;
00291 
00292    printf("New ctrl port %d data port %d\n", gC.ctrlPort, gC.dataPort);
00293 
00294    return true;
00295 }
00296 
00297 void UdpSimulator::dispatchNewSockets(int tmout)
00298 {
00299    struct pollfd fds[2];
00300    fds[0].fd = s_ctrl;
00301    fds[0].events = POLLIN;
00302    fds[0].revents = 0;
00303    fds[1].fd = s_data;
00304    fds[1].events = POLLIN;
00305    fds[1].revents = 0;
00306 
00307    int res = poll(fds, 2, tmout);
00308 
00309    if (res==0) return;
00310 
00311    struct sockaddr from;
00312    socklen_t fromlen;
00313 
00314    char recvbuf[2000];
00315 
00316    for (int n=0;n<2;n++) {
00317       if ((fds[n].revents & POLLIN) == 0) continue;
00318 
00319       res = recvfrom(n==0 ? s_ctrl : s_data, recvbuf, sizeof(recvbuf), MSG_DONTWAIT, &from, &fromlen);
00320 
00321       if (res<=0)
00322          printf("fail by receiving from %s socket res = %d err = %d socket = %d\n", (n==0 ? "ctrl" : "data"), res, errno, (n==0 ? s_ctrl : s_data));
00323       else
00324          OnRawData(n, recvbuf, res, &from, fromlen);
00325    }
00326 }
00327 
00328 #define NODE_FORBIDDEN 0
00329 #define NODE_MASTER    1
00330 #define NODE_CONTROL   2
00331 #define NODE_OBSERVER  3
00332 #define NODE_SKIP      4
00333 
00334 
00335 int UdpSimulator::checkCtrlOperationAllowed(roc::UdpMessageFull* pkt, in_addr_t src_ip, int src_port)
00336 {
00337    bool ismaster = (gD.masterIp == src_ip) && (gD.masterPort == src_port);
00338    bool iscontrol = (gD.controlIp == src_ip) && (gD.controlPort == src_port);
00339 
00340    if ((pkt->tag == ROC_POKE) && (pkt->address == ROC_ETH_MASTER_LOGIN)) {
00341 
00342       if (pkt->value==0) {
00343          if (gD.masterConnected && !ismaster) {
00344             printf("Master already connected\n");
00345             return NODE_FORBIDDEN;
00346          }
00347 
00348          if (iscontrol) {
00349             gD.controlIp = 0;
00350             gD.controlPort = 0;
00351             iscontrol = false;
00352          }
00353 
00354          if (!ismaster) {
00355             gD.masterIp = src_ip;
00356             gD.masterPort = src_port;
00357 
00358             gD.masterConnected = true;
00359             ismaster = true;
00360             gD.lastMasterPacketId = 0;
00361 
00362             printf("Master is %s : %d\n", IpToStr(src_ip), src_port);
00363          }
00364       } else
00365       if (pkt->value==1) {
00366          if (gD.controlConnected && !iscontrol) {
00367             printf("Control already connected\n");
00368             return NODE_FORBIDDEN;
00369          }
00370 
00371          if (ismaster) {
00372             gD.masterIp = 0;
00373             gD.masterPort = 0;
00374             ismaster = false;
00375          }
00376 
00377          if (!iscontrol) {
00378             gD.controlIp = src_ip;
00379             gD.controlPort = src_port;
00380 
00381             gD.controlConnected = true;
00382             iscontrol = true;
00383             gD.lastControlPacketId = 0;
00384 
00385             printf("Control is %s : %d\n", IpToStr(src_ip), src_port);
00386          }
00387       } else
00388          return NODE_OBSERVER;
00389    }
00390 
00391    if (gD.controlLocked) {
00392       if (((gD.controlLocked==1) && ismaster) || ((gD.controlLocked==2) && iscontrol)) {
00393          // if locked, operation from the same node are allowed
00394       } else
00395          return NODE_SKIP;
00396    }
00397 
00398    if (ismaster) {
00399       gD.masterConnected = true;
00400       gD.lastMasterTime = get_clock();
00401       return NODE_MASTER;
00402    }
00403 
00404    if (iscontrol) {
00405       gD.controlConnected = true;
00406       gD.lastControlTime = get_clock();
00407       return NODE_CONTROL;
00408    }
00409 
00410    // for moment allow all PEEK operations for slave
00411    if (pkt->tag == ROC_PEEK) return NODE_OBSERVER;
00412 
00413 
00414    return NODE_FORBIDDEN; // reject operation
00415 }
00416 
00417 void UdpSimulator::OnRawData(int number, const char* buf, int datalen, struct sockaddr* sa_from, socklen_t sa_len)
00418 {
00419    if (sa_len != sizeof(struct sockaddr_in)) return;// IPv4
00420 
00421    if (doRecvLost()) return;
00422 
00423    recvDataSize += datalen;
00424 
00425    //   printf("OnRawData number %d  size=%d addrlen=%d errno=%d   from:", number, datalen, sa_len, (int) errno);
00426    //   uint8_t* p1 = (uint8_t*) sa_from;
00427    //   for (int n=0;n<sa_len;n++) printf(" %3u", (unsigned) p1[n]);
00428    //   printf("\n");
00429 
00430    struct sockaddr_in sa;
00431    memcpy(&sa, sa_from, sa_len);
00432    in_addr_t src_ip;
00433    memcpy(&src_ip, &sa.sin_addr, 4);
00434 
00435    if (src_ip == 0) {
00436      printf("Dummy source IP address - ignore\n");
00437      return; 
00438    }
00439 
00440    int src_port = ntohs(sa.sin_port);
00441 
00442    if (number==0) {
00443 
00444       roc::UdpMessageFull* pkt = (roc::UdpMessageFull*) buf;
00445 
00446       if (ntohl(pkt->password) != ROC_PASSWORD) return;
00447 
00448       pkt->address = ntohl(pkt->address);
00449       pkt->value = ntohl(pkt->value);
00450 
00451       int nodekind = checkCtrlOperationAllowed(pkt, src_ip, src_port);
00452 
00453       // ignore packet if control channel locked
00454       if (nodekind==NODE_SKIP) return;
00455 
00456       int rawdatasize = 0;
00457 
00458       if (nodekind == NODE_FORBIDDEN) {
00459          // if operation not allowed, just reply with same packet, but
00460          // set error return code 8
00461          pkt->value = 8; // forbidden
00462       } else
00463       if ((nodekind==NODE_MASTER) && (pkt->id == gD.lastMasterPacketId)) {
00464           // just send again previous reply
00465          rawdatasize = gD.master_retry_buf_rawsize;
00466          memcpy(pkt->rawdata, gD.master_retry_buf, rawdatasize);
00467          printf("!!! resend master packet %u!!!\n", (unsigned) ntohl(pkt->id));
00468       } else
00469       if ((nodekind==NODE_CONTROL) && (pkt->id == gD.lastControlPacketId)) {
00470          // just send again previous reply
00471          rawdatasize = gD.control_retry_buf_rawsize;
00472          memcpy(pkt->rawdata, gD.control_retry_buf, rawdatasize);
00473          printf("!!! resend control packet %u!!!\n", (unsigned) ntohl(pkt->id));
00474       } else
00475       switch(pkt->tag) {
00476          case ROC_PEEK:
00477             pkt->address = GetReg(nodekind, pkt->address, &pkt->value, pkt->rawdata, &rawdatasize);
00478             break;
00479 
00480          case ROC_POKE:
00481             pkt->value = PutReg(nodekind, pkt->address, pkt->value, pkt->rawdata);
00482             break;
00483 
00484          case ROC_NOPER:
00485             // pkt->address = pkt->address;
00486 
00487             // if we get request to lock our control
00488             if (pkt->value == 1) {
00489                printf("LOCK control\n");
00490                if (nodekind==NODE_MASTER) gD.controlLocked = 1; else
00491                if (nodekind==NODE_CONTROL) gD.controlLocked = 2;
00492                gD.lockedTime = get_clock();
00493             } else
00494             if (gD.controlLocked) {
00495                printf("UNLOCK control\n");
00496                gD.controlLocked = 0;
00497                gD.lockedTime = 0;
00498             }
00499 
00500             pkt->value = NOper(nodekind, pkt->address, (uint32_t*) pkt->rawdata);
00501             rawdatasize = pkt->address * 8;
00502             break;
00503       }
00504 
00505       pkt->address = htonl(pkt->address);
00506       pkt->value = htonl(pkt->value);
00507 
00508       if (!doSendLost()) {
00509          sendto(s_ctrl, (char*)pkt, sizeof(roc::UdpMessage) + rawdatasize, MSG_DONTWAIT, sa_from, sa_len);
00510          sendDataSize += sizeof(roc::UdpMessage) + rawdatasize;
00511       }
00512 
00513       if ((nodekind==NODE_MASTER) && (pkt->id != gD.lastMasterPacketId)) {
00514          gD.lastMasterPacketId = pkt->id;
00515          memcpy(gD.master_retry_buf, pkt->rawdata, rawdatasize);
00516          gD.master_retry_buf_rawsize = rawdatasize;
00517       } else
00518       if ((nodekind==NODE_CONTROL) && (pkt->id != gD.lastControlPacketId)) {
00519          gD.lastControlPacketId = pkt->id;
00520          memcpy(gD.control_retry_buf, pkt->rawdata, rawdatasize);
00521          gD.control_retry_buf_rawsize = rawdatasize;
00522       }
00523 
00524    } else {
00525       roc::UdpDataRequestFull* pkt = (roc::UdpDataRequestFull*) buf;
00526 
00527       if (ntohl(pkt->password) != ROC_PASSWORD) return;
00528 
00529       gD.lastMasterTime = get_clock();
00530 
00531       pkt->reqpktid = ntohl(pkt->reqpktid);
00532       pkt->frontpktid = ntohl(pkt->frontpktid);
00533       pkt->tailpktid = ntohl(pkt->tailpktid);
00534       pkt->numresend = ntohl(pkt->numresend);
00535 
00536       for (unsigned n=0; n<pkt->numresend; n++)
00537          pkt->resend[n] = ntohl(pkt->resend[n]);
00538 
00539       memcpy(&gD.masterDataAddr, sa_from, sa_len);
00540 
00541       processDataRequest(pkt);
00542    }
00543 }
00544 
00545 uint32_t UdpSimulator::GetReg(int nodekind, uint32_t addr, uint32_t *retVal, void* rawdata, int* rawdatasize)
00546 {
00547    switch (addr) {
00548       case ROC_ETH_SWV:
00549          *retVal = ROC_SIMULATOR_SW_VERSION;
00550          return 0;
00551       case ROC_HWV:
00552          *retVal = ROC_SIMULATOR_HW_VERSION;
00553          return 0;
00554       case ROC_ETH_HWV:
00555          *retVal = ROC_SIMULATOR_HW_VERSION;
00556          return 0;
00557       case ROC_FPGA_TYPE:
00558          *retVal = ROC_SIMULATOR_FPGA_TYPE;
00559          return 0;
00560       case ROC_SVN_REVISION:
00561          *retVal = 1;
00562          return 0;
00563       case ROC_BUILD_TIME:
00564          *retVal = 41*3600*24*365;
00565          return 0;
00566       case ROC_ROCID:
00567          *retVal = gC.rocNumber;
00568          return 0;
00569       case ROC_TYPE:
00570          *retVal = 0x10002; // NXYTER FX20
00571          return 0;
00572       case ROC_ETH_LOWWATER:
00573          *retVal = gD.low_water;
00574          return 0;
00575       case ROC_ETH_HIGHWATER:
00576          *retVal = gD.high_water;
00577          return 0;
00578       case ROC_ETH_DATAPORT:
00579          *retVal = gC.dataPort;
00580          return 0;
00581       case ROC_ETH_STATBLOCK: {
00582          if ((rawdata==0) || (rawdatasize==0)) return 2;
00583          roc::BoardStatistic* stat = (roc::BoardStatistic*) rawdata;
00584          stat->daqState = htonl(gD.daqState);
00585          stat->dataRate = htonl(fStat.dataRate);
00586          stat->sendRate = htonl(fStat.sendRate);
00587          stat->recvRate = htonl(fStat.recvRate);
00588          stat->nopRate = htonl(0);
00589          stat->frameRate = htonl(0);
00590          stat->takePerf = htonl(0);
00591          stat->dispPerf = htonl(0);
00592          stat->sendPerf = htonl(0);
00593 
00594          *rawdatasize = sizeof(roc::BoardStatistic);
00595          return 0;
00596       }
00597       case ROC_NX_I2C_DATA:
00598       case ROC_NX_I2C_SLAVEADDR:
00599       case ROC_NX_I2C_ERROR:
00600          return 0;
00601 
00602       default:
00603          if ((addr>=ROC_CMD_LST_MEM) && (addr<ROC_CMD_LST_MEM + ROC_CMD_LST_SIZE)) {
00604             if(addr % 4) return 2;
00605             addr = (addr - ROC_CMD_LST_MEM) / 4;
00606             *retVal = gD.cmdsList[addr];
00607             return 0;
00608          } else
00609          if ((addr>=ROC_NX_HWV) && (addr<ROC_NX_HWV + NX_REG_SIZE*4)) {
00610             *retVal = nxRegister[(addr-ROC_NX_HWV)/4];
00611             return 0;
00612          } else
00613          if ((addr>=base::GPIO_CONFIG) && (addr < base::GPIO_CONFIG + GPIO_REG_SIZE*4)) {
00614             *retVal = gpioRegs[(addr - base::GPIO_CONFIG)/4];
00615             return 0;
00616          } else {
00617             printf("Unknown register 0x%x\n", addr);
00618          }
00619          break;
00620    }
00621 
00622    return 2;
00623 }
00624 
00625 uint32_t UdpSimulator::PutReg(int nodekind, uint32_t addr, uint32_t val, uint8_t* rawdata)
00626 {
00627    printf("Roc:%u Put 0x%04x = 0x%04x\n", gC.rocNumber, addr, val);
00628 
00629    switch (addr) {
00630       case ROC_ETH_START_DAQ:
00631          printf("Roc:%u Starting DAQ ...\n", gC.rocNumber);
00632          gD.buf.clear();
00633          gD.send_limit = 0;
00634          gD.headid = 0;
00635          gD.resend_size = 0;
00636          gD.last_req_pkt_id = 0;
00637          gD.next_send_id = 0;
00638          gD.data_taking_on = true;
00639          gD.lastFlushTime = get_clock();
00640          // if lost rate specified, drop start message
00641          gD.droppkt_id = (sendLostRate <=0.) ? 0 - 1 : gD.headid;
00642          makeSysMessage(roc::SYSMSG_DAQ_START);
00643          gD.daqState = 1;
00644          return 0;
00645       case ROC_ETH_SUSPEND_DAQ:
00646          printf("Roc:%u DAQ suspended.\n", gC.rocNumber);
00647          // if lost rate specified, drop stop message
00648          gD.droppkt_id = (sendLostRate <=0.) ? 0 - 1 : gD.headid;
00649          // gD.droppkt_id = 0 - 1;
00650          // printf("Try to drop packet 0x%x with stop message\n",gD.droppkt_id);
00651          makeSysMessage(roc::SYSMSG_DAQ_FINISH);
00652          gD.daqState = 2;
00653          gD.data_taking_on = false;
00654          return 0;
00655       case ROC_ETH_STOP_DAQ:
00656          printf("Roc:%u DAQ stopped.\n", gC.rocNumber);
00657          gD.daqState = 0;
00658          gD.buf.clear();
00659          gD.send_limit = 0;
00660          gD.headid = 0;
00661          gD.data_taking_on = false;
00662          return 0;
00663       case ROC_ROCID:
00664          printf("Set ROC id to %d.\n",val);
00665          gC.rocNumber = val;
00666          return 0;
00667       case ROC_ETH_MASTER_LOGIN:
00668          if (nodekind==NODE_MASTER) {
00669             printf("Master login & simulator reset.\n");
00670             resetSimulator();
00671          }
00672          return 0;
00673 
00674       case ROC_ETH_MASTER_LOGOUT:
00675          if (nodekind==NODE_MASTER) {
00676             printf("Master is logout.\n");
00677             gD.masterConnected = false;
00678             gD.daqState = 0;
00679             totalSendLosts = 0;
00680             totalSendCounter = 0;
00681             totalRecvLosts = 0;
00682             totalRecvCounter = 0;
00683             gD.masterIp = 0;
00684             gD.masterPort = 0;
00685             gD.lastMasterPacketId = 0;
00686             if (gD.controlLocked == 1) gD.controlLocked = 0;
00687          } else
00688          if (nodekind==NODE_CONTROL) {
00689             printf("Controller is logout.\n");
00690             gD.controlConnected = false;
00691             gD.controlPort = 0;
00692             gD.controlIp = 0;
00693             gD.lastControlPacketId = 0;
00694             if (gD.controlLocked == 2) gD.controlLocked = 0;
00695          }
00696          return 0;
00697 
00698       case ROC_ETH_LOWWATER:
00699          gD.low_water = val;
00700          return 0;
00701 
00702       case ROC_ETH_HIGHWATER:
00703          gD.high_water = val;
00704          return 0;
00705 
00706       case ROC_ETH_MASTER_DATAPORT:
00707          if (nodekind != NODE_MASTER) {
00708             printf("ERROR! Cannot change master data port from controller.\n");
00709             return 3;
00710          }
00711          gD.masterDataPort = val;
00712          printf("Set Target data port to (%d).\n",val);
00713          return 0;
00714       case ROC_NX_FIFO_RESET:
00715          return 0;
00716       case ROC_ETH_BUFFER_FLUSH_TIMER:
00717          gC.flushTimeout = val;
00718          return 0;
00719       case ROC_ETH_CONSOLE_OUTPUT:
00720          return 0;
00721       case ROC_ETH_CONSOLE_CMD:
00722          printf("Execute console command %s.\n", rawdata);
00723          return 0;
00724       case ROC_NX_NXACTIVE:
00725       case ROC_ETH_OCM:
00726          return 0;
00727 
00728       case ROC_NX_I2C_DATA:
00729       case ROC_NX_I2C_RESET:
00730       case ROC_NX_I2C_REGRESET:
00731       case ROC_NX_I2C_SLAVEADDR:
00732       case ROC_NX_I2C_REGISTER:
00733       case ROC_NX_I2C_SWITCH:
00734          return 0;
00735 
00736       case ROC_ADDSYSMSG:
00737          if (gD.data_taking_on)
00738             makeSysMessage(roc::SYSMSG_USER, val);
00739          return 0;
00740 
00741       case ROC_CMD_LST_ACTIVE:
00742          gD.cmdListPtr = ROC_CMD_LST_SIZE / 4;
00743          return 0;
00744 
00745       case ROC_CMD_LST_NR:
00746          // set pointer on the beginning of the list
00747          gD.cmdListPtr = (val % ROC_CMD_LST_NUMBER) * ROC_CMD_LST_SIZE / ROC_CMD_LST_NUMBER / 4;
00748          return 0;
00749 
00750       case ROC_ETH_DLM:
00751          // set pointer on the beginning of the correspondent list
00752          if (val>=8)
00753             gD.cmdListPtr = ((val-8) % ROC_CMD_LST_NUMBER) * ROC_CMD_LST_SIZE / ROC_CMD_LST_NUMBER / 4;
00754          return 0;
00755 
00756       default:
00757          if ((addr>=ROC_CMD_LST_MEM) && (addr<ROC_CMD_LST_MEM + ROC_CMD_LST_SIZE)) {
00758             if(addr % 4) return 2;
00759             addr = (addr - ROC_CMD_LST_MEM) / 4;
00760             gD.cmdsList[addr] = val;
00761             return 0;
00762          } else
00763          if ((addr>=ROC_NX_HWV) && (addr < ROC_NX_HWV + NX_REG_SIZE*4)) {
00764             nxRegister[(addr-ROC_NX_HWV)/4] = val;
00765             return 0;
00766          } else
00767          if ((addr>=base::GPIO_CONFIG) && (addr < base::GPIO_CONFIG + GPIO_REG_SIZE*4)) {
00768             gpioRegs[(addr - base::GPIO_CONFIG)/4] = val;
00769             return 0;
00770          }
00771    }
00772 
00773    printf("Roc:%u Put 0x%04x = 0x%04x Fails\n", gC.rocNumber, addr, val);
00774 
00775    return 2;
00776 }
00777 
00778 uint32_t UdpSimulator::NOper(int nodekind, uint32_t num, uint32_t* arr)
00779 {
00780    for (unsigned n=0; n<num; n++) {
00781       uint32_t addr_oper = ntohl(*arr); arr++;
00782       uint32_t value = ntohl(*arr);
00783 
00784       uint32_t oper = addr_oper & NOPER_OPER_MASK;
00785       uint32_t addr = addr_oper & NOPER_ADDR_MASK;
00786 
00787       if (oper == NOPER_PUT) {
00788          uint32_t res = PutReg(nodekind, addr, value, 0);
00789          if (res!=0) return res | (n << 8);
00790       } else
00791       if (oper == NOPER_GET) {
00792          uint32_t res = GetReg(nodekind, addr, &value);
00793          if (res!=0) return res | (n << 8);
00794       } else
00795          return 2 | (n << 8);
00796 
00797       *arr = htonl(value); arr++;
00798    }
00799 
00800    return 0;
00801 }
00802 
00803 
00804 void UdpSimulator::fillRareSyncData(uint8_t* target, uint16_t numOfDatas)
00805 {
00806    uint32_t nextepoch = 0;
00807 
00808    uint64_t min = 0;
00809 
00810    roc::Message msg;
00811 
00812    while (numOfDatas > 0) {
00813 
00814       min = nextTimeNoise;
00815       if (min > nextTimeSync) min = nextTimeSync;
00816       if (min > nextTimeAUX0) min = nextTimeAUX0;
00817       if (min > nextTimeAUX1) min = nextTimeAUX1;
00818       if (min > nextTimeHit) min = nextTimeHit;
00819 
00820       bool accept_data = true;
00821 
00822       nextepoch = min >> 14;
00823       msg.reset();
00824 
00825       if (nextepoch != lastEpoch) {
00826          msg.setMessageType(roc::MSG_EPOCH);
00827          msg.setEpochNumber(nextepoch);
00828          lastEpoch = nextepoch;
00829       } else
00830 
00831       if (nextTimeHit == min) {
00832         // random channel, random spectrum:
00833 
00834          //pseudo hit data
00835         msg.setMessageType(roc::MSG_HIT);
00836         msg.setNxNumber(rand() % 4);
00837         msg.setNxChNum(rand() % 128);
00838         msg.setNxTs(nextTimeHit & 0x3fff);
00839         msg.setNxAdcValue(rand() % 0x4000);
00840         msg.setNxLastEpoch(0);
00841 
00842         nextHitCounter--;
00843         if (nextHitCounter == 0) {
00844            nextEventNumber++;
00845            nextHitCounter = 3 + (rand() % 6); // produce between 3 and 8 hits per event
00846            nextTimeHit = uint64_t(nextEventNumber * 73747 * clockScrewUp); // produce event every 73.747 microsec or about 13.5 KHz
00847         }
00848         nextTimeHit += (1 + rand() % 7); // maximum event duration 8hits * 7 nanosec = 56 nanosec
00849       } else
00850 
00851       if (nextTimeNoise == min) {
00852         // random channel, random spectrum:
00853 
00854         msg.setMessageType(roc::MSG_HIT);
00855         msg.setNxNumber(rand() % 4);
00856         msg.setNxChNum(rand() % 128);
00857         msg.setNxTs(nextTimeNoise & 0x3fff);
00858         msg.setNxAdcValue(rand() % 0x4000);
00859         msg.setNxLastEpoch(0);
00860 
00861         nextTimeNoise += (rand() % 0x4000); // about 2 noise hits per epoch
00862       } else
00863 
00864       if (nextTimeSync == min) {
00865 
00866          accept_data = ((gpioConfig() >> (base::SYNC_S0*4)) & 3) != 0;
00867 
00868          if (accept_data) {
00869             msg.setMessageType(roc::MSG_SYNC);
00870             msg.setSyncChNum(0);
00871             msg.setSyncTs(nextTimeSync & 0x3fff);
00872             msg.setSyncEpochLSB(nextepoch & 0x1);
00873             msg.setSyncData(nextSyncEvent & 0xffffffL);
00874             msg.setSyncStFlag(0);
00875          }
00876 
00877          // every n epochs new time sync, period depends from id
00878          // as result, all other times must be suppressed
00879          nextSyncEvent += (1 << syncMDelay());
00880          nextTimeSync = uint64_t(0x345 + nextSyncEvent * 0x4000 * clockScrewUp);
00881 
00882       } else
00883 
00884       if (nextTimeAUX0 == min) {
00885 
00886          accept_data = (gpioConfig() & (1 << (base::AUX0*4 + (nextAUX0Falling ? 1 : 0)))) != 0;
00887 
00888          if (accept_data) {
00889             msg.setMessageType(roc::MSG_AUX);
00890             msg.setAuxChNum(0);
00891             msg.setAuxTs(nextTimeAUX0 & 0x3fff);
00892             msg.setAuxEpochLSB(nextepoch & 0x1);
00893             msg.setAuxFalling(nextAUX0Falling ? 1 : 0);
00894             msg.setAuxOverflow(0);
00895          }
00896 
00897          nextTimeAUX0 += periodAUX0; // without time correction
00898          nextAUX0Falling = !nextAUX0Falling;
00899 
00900       } else
00901 
00902       if (nextTimeAUX1 == min) {
00903 
00904          accept_data = (gpioConfig() & (1 << (base::AUX1*4 + (nextAUX1Falling ? 1 : 0)))) != 0;
00905 
00906          if (accept_data) {
00907             msg.setMessageType(roc::MSG_AUX);
00908             msg.setAuxChNum(1);
00909             msg.setAuxTs(nextTimeAUX1 & 0x3fff);
00910             msg.setAuxEpochLSB(nextepoch & 0x1);
00911             msg.setAuxFalling(nextAUX1Falling ? 1 : 0);
00912             msg.setAuxOverflow(0);
00913          }
00914 
00915          nextTimeAUX1 += periodAUX1; // without time correction
00916          nextAUX1Falling = !nextAUX1Falling;
00917       }
00918 
00919       if (accept_data) {
00920          msg.copyto(target, roc::formatEth2);
00921          numOfDatas--;
00922          target+=6;
00923       }
00924    }
00925 }
00926 
00927 void UdpSimulator::makeSysMessage(uint8_t typ, uint32_t arg)
00928 {
00929    roc::Message msg;
00930 
00931    msg.setMessageType(roc::MSG_SYS);
00932    msg.setSysMesType(typ);
00933    msg.setSysMesData(arg);
00934 
00935    roc::UdpDataPacketFull pkt;
00936 
00937 //   pkt.msgs[0] = ((0x7 << 5) | (gC.rocNumber << 2) | 0)  & 0xFF;//msg type, roc#, unused
00938 //   pkt.msgs[1] = typ;
00939 //   pkt.msgs[2] = 0;
00940 //   pkt.msgs[3] = 0;
00941 //   pkt.msgs[4] = 0;
00942 //   pkt.msgs[5] = 0;
00943 
00944    msg.copyto(pkt.msgs, roc::formatEth2);
00945 
00946    pkt.nummsg = htonl(1);
00947    pkt.pktid = htonl(gD.headid++);
00948    printf("Put sys msg %u arg %u in pkt with id %u\n", (unsigned) typ, (unsigned) arg, ntohl(pkt.pktid));
00949    gD.buf.push_back(pkt);
00950 }
00951 
00952 void UdpSimulator::processDataRequest(roc::UdpDataRequestFull* pkt)
00953 {
00954    gD.last_req_pkt_id = pkt->reqpktid;
00955    gD.send_limit = pkt->frontpktid;
00956 
00957 //   printf("Next send limit is %u size = %u\n",gD.send_limit, gD.buf.size());
00958 
00959    while (gD.buf.size() > 0) {
00960       uint32_t diff = pkt->tailpktid - ntohl(gD.buf.front().pktid);
00961       if ((diff !=0) && (diff < 0x1000000)) gD.buf.pop_front();
00962                                        else break;
00963       if ((gD.daqState==1) && !gD.data_taking_on)
00964          if (gD.buf.size() < gD.low_water)
00965             gD.data_taking_on = true;
00966    }
00967 
00968    for (unsigned n=0; n<pkt->numresend; n++)
00969       if (gD.resend_size<RESEND_MAX_SIZE) {
00970          gD.resend_indx[gD.resend_size] = pkt->resend[n];
00971          gD.resend_size++;
00972       }
00973 }
00974 
00975 
00976 bool UdpSimulator::sendDataPacket(uint32_t pktid)
00977 {
00978    if (gD.droppkt_id == pktid) {
00979       printf("Explicit drop of packet 0x%x\n", gD.droppkt_id);
00980       gD.droppkt_id = rand();
00981       return true;
00982    }
00983 
00984    if (gD.buf.size()==0) return false;
00985 
00986 
00987 
00988 //   printf("Send data packet %u size %u front %u\n",
00989 //             pktid, gD.buf.size(), ntohl(gD.buf.front().pktid));
00990 
00991    std::list<roc::UdpDataPacketFull>::iterator iter = gD.buf.begin();
00992 
00993    while (iter != gD.buf.end()) {
00994 
00995       if (ntohl(iter->pktid) == pktid) {
00996           iter->lastreqid = htonl(gD.last_req_pkt_id);
00997 
00998 //          if (!doSendLost())
00999 //             dataSocket_.SendToBuf(gD.masterIp, gD.masterDataPort,
01000 //                (char*) &(*iter), sizeof(roc::UdpDataPacket) + ntohl(iter->nummsg) * 6);
01001 
01002 /*          struct sockaddr_in sa;
01003           memcpy(&sa.sin_addr, &gD.masterIp,  4);
01004           sa.sin_port = htons(gD.masterDataPort);
01005 
01006           printf("Sending addr: ");
01007           for (int n=0; n<sizeof(sa);n++) printf("%02x ", ((char*) &sa)[n]);
01008           printf("\n");
01009 */
01010           if (!doSendLost()) {
01011              sendto(s_data,
01012                    (char*) &(*iter),
01013                    sizeof(roc::UdpDataPacket) + ntohl(iter->nummsg) * 6,
01014                    MSG_DONTWAIT,
01015                    (const sockaddr*) & gD.masterDataAddr,
01016                    sizeof(gD.masterDataAddr));
01017 
01018              sendDataSize += sizeof(roc::UdpDataPacket) + ntohl(iter->nummsg) * 6;
01019           }
01020 
01021           return true;
01022       }
01023 
01024       iter++;
01025    }
01026 
01027    return false;
01028 }
01029 
01030 
01031 
01032 void UdpSimulator::mainLoop()
01033 {
01034    roc::UdpDataPacketFull pkt;
01035 
01036    printf("UdpSimulator is running...\n");
01037 
01038    bool did_something = false;
01039    bool send_something = false;
01040 
01041    gD.lastMasterTime = get_clock();
01042    double last_tm = get_clock();
01043    double last_stat_time = last_tm;
01044 
01045    while (true) {
01046 
01047       if (!did_something)
01048          dispatchNewSockets(100);
01049 
01050       did_something = false;
01051 
01052       if (gD.data_taking_on) {
01053          fillRareSyncData(pkt.msgs, 243);
01054          pkt.nummsg = htonl(243);
01055          pkt.pktid = htonl(gD.headid++);
01056          gD.buf.push_back(pkt);
01057          takeDataSize += 243*6;
01058 
01059 //         printf("Add packet %u  total size %u\n", ntohl(pkt.pktid), gD.buf.size());
01060          if (gD.buf.size() > gD.high_water) gD.data_taking_on = false;
01061       }
01062 
01063 
01064       // execute next command from the list
01065       if (gD.cmdListPtr < ROC_CMD_LST_SIZE / 4) {
01066          if (gD.cmdsList[gD.cmdListPtr] & ROC_CMD_LST_PUT)
01067             PutReg(NODE_MASTER, gD.cmdsList[gD.cmdListPtr] & ROC_CMD_LST_ADDRMASK, gD.cmdsList[gD.cmdListPtr+1], 0);
01068          gD.cmdListPtr += 2;
01069       }
01070 
01071       double curr_tm = get_clock();
01072 
01073       // process flush timeout
01074       if (gD.daqState && (fabs(curr_tm - gD.lastFlushTime) > gC.flushTimeout*0.001)) {
01075          // we have always full buffer, therefore just resend last buffer
01076 
01077          uint32_t prev_send_id = gD.next_send_id - 1;
01078 
01079          if (!send_something)
01080             if (gD.headid - prev_send_id <= gD.buf.size())
01081                if (sendDataPacket(prev_send_id))
01082                   printf("Flush buffer id 0x%x  datataking %d total %u limit 0x%x next_send 0x%x \n", prev_send_id, gD.data_taking_on, (unsigned) gD.buf.size(), (unsigned) gD.send_limit, gD.next_send_id);
01083 
01084          send_something = false;
01085          gD.lastFlushTime = get_clock();
01086       }
01087 
01088       if (gD.masterConnected && fabs(curr_tm - gD.lastMasterTime) > 10) {
01089          printf("Disconnect master after 10 sec!\n");
01090          gD.masterConnected = false;
01091          gD.data_taking_on = false;
01092          gD.daqState = 0;
01093       }
01094 
01095       if (gD.controlLocked && fabs(curr_tm - gD.lockedTime) > 3) {
01096          printf("Control unlocked after 3 sec!\n");
01097          gD.controlLocked = 0;
01098       }
01099 
01100       if (gD.controlConnected && fabs(gD.lastControlTime - curr_tm) > 10) {
01101          printf("Disconnect control after 10 sec!\n");
01102          gD.controlConnected = false;
01103       }
01104 
01105       if (fabs(gD.lastMasterTime - curr_tm) > 3000) {
01106          printf("No news from master last 3000 sec, stop main loop!!\n");
01107          break;
01108       }
01109 
01110       // retransmit when required
01111       if (gD.resend_size > 0) {
01112          sendDataPacket(gD.resend_indx[--gD.resend_size]);
01113          did_something = true;
01114          send_something = true;
01115       } else
01116       // if one allowed to send
01117       if (gD.send_limit != gD.next_send_id)
01118          if (gD.send_limit - gD.next_send_id < 0x1000000)
01119             if (sendDataPacket(gD.next_send_id)) {
01120                gD.next_send_id++;
01121                did_something = true;
01122                send_something = true;
01123             }
01124 
01125       if (fabs(curr_tm - last_tm) > 10.) {
01126          if (totalSendLosts>0)
01127             printf("Send:%8u Lost:%5.1f%s\n", (unsigned) totalSendCounter, 100. * totalSendLosts/totalSendCounter, "%");
01128          if (totalRecvLosts>0)
01129             printf("Recv:%8u Lost:%5.1f%s\n", (unsigned) totalRecvCounter, 100. * totalRecvLosts/totalRecvCounter, "%");
01130          last_tm = curr_tm;
01131       }
01132 
01133       if (curr_tm - last_stat_time >= 1.) {
01134          memset(&fStat, 0, sizeof(fStat));
01135          fStat.dataRate = takeDataSize;
01136          fStat.sendRate = sendDataSize;
01137          fStat.recvRate = recvDataSize;
01138 
01139          takeDataSize = 0;
01140          recvDataSize = 0;
01141          sendDataSize = 0;
01142 
01143          last_stat_time = curr_tm;
01144       }
01145    }
01146 }
01147 

Generated on Tue Dec 10 2013 04:52:23 for ROCsoft by  doxygen 1.7.1