#include "dsat_util.h" #include #include #include #include #include #include #include #include #define ERROR -1 #define OK 0 #define maxLineLength 200 //#define RAND_MAX 0xfffffff; #define N 0x80000 //following are some constants and lookup tables #define SAME 2 // in the same segment(22 fibres), if rightmost track is within SAME number of fibres to the leftmost track, consider them the same int dblt_window[8][2] = {17,32,21,40,25,48,29,56,33,64,37,72,41,80,45,88}; int pt_lut[4][8] = {{80,27,16,12},{9,7,6,5},{4,4,3,3},{3,3,2,2,1}}; int xpl_lut[44] = {8,8,9,9,9,10,10,10,11,11,11,12,12,12,13,13,14,14,14,15,15,15,16,16,16,17,17,17,18,18,19,19,19, 20,20,20,21,21,21,22,22,22,23,23}; int xpl_offset[4] = {1,2,3,5}; int match_window[4] = {1,2,2,4}; //end of constants and lookup tables //stores track equations unsigned char eqs[2][N][16]; //stores pointers to eqs in the order of max, high, med and low unsigned int m[2][1761]; //stores u7 link_array to signlet and cps conversion table, last index [0]: layer [1]: fibre [2]: cps char evn_conv[6][196][3]; //stores u9 link_array to signlet and cps conversion table, last index [0]: layer [1]: fibre [2]: cps char odd_conv[6][196][3]; //stores dead doublets char dead_dblt[2][8][90]; //stores singlet hits unsigned char sglt[2][16][90]; //stores doublet hits unsigned char dblt[2][8][90]; //stores cps hits unsigned char cps[2][32]; // int octant[2] = {0}, sector[2] = {0}; // L2 invalid flags int bad_l2; // lvds_out readback int lvds_out_r[2]; //simulation data; int link_data[8][7]; //simulation results int mu_trk[2][7]; int ctoc[2][7]; int l2cft[2][27]; int l2cps[2][11]; int lvds_out[2]; char r2a; int version[4],singlet_eq[14]; //bus register bits int muon_patt[2],muon_fake[2],ctoc_zero[2],ctoc_patt[2],ctoc_fake[2],l2_fake[2],en_new[2],no_muon_trk[2],no_l1_trk[2],no_l2_trk[2],s_radial[2]; // command table typedef struct { char *name; int nargs; } a_cmd; // positions in table correspond to switch() constants below! static a_cmd cmds[] = { "help", 0, "quit", 0, "w_dfea",3, "r_dfea",3, "ld_fake",1, "eqs",1, "prog",2, "rnd_test",0 }; #define N_CMD (sizeof(cmds)/sizeof(a_cmd)) int parse_command( char *pb, char *tok[], unsigned int tokn[], int maxt); char *rl_gets (); int rd_eqs( char *file_name); int sim(int fd); int w_dfea(int fd, int addr, int data); int r_dfea(int fd, int addr); int programChip(int fd,int chip,char *Filename); int rnd_test(int fd, int cycle_num, int seed); static FILE *fp = NULL; // script input main( argc, argv) int argc; char *argv[]; { int fd = 0; FILE *ifp; int i,j,k,l,n,lnk[6] = {0,2,3,4,5,6}; int start_addr,init_flag,first_data,bad_version; unsigned addr,buf,data[512]; char line[maxLineLength]; int nt; // number of tokens in input char *pb, *tp, *p, *pp; // buffer pointer, token pointer char *tok[16]; // tokens in input commands char *link[8] = {"link1","link2","link3","link4","link5","link6","link7","link8"}; char *slayer[16] = {"ai","ao","bi","bo","ci","co","di","do","ei","eo","fi","fo","gi","go","hi","ho"}; char *dlayer[8] = {"a(","b(","c(","d(","e(","f(","g(","h("}; int dblt_range[8][2] = {3,46,5,56,9,64,14,71,21,76,28,81,38,83,44,89}; unsigned int tokn[16]; // numeric conversion of tokens static char *usage = "usage: fake_test [script_file] [-p mcs_list]"; if ( (fd = dsat_open((char*)DEVICE, O_RDWR|O_NONBLOCK)) <= 0 ) { perror("DSAT: Cannot open device"); exit(1); } dsat_read_word(fd,2,&buf); printf("DSAT version = 0x%02x\n",(buf >> 8) & 0xff); if( argc > 1) { for(i = 1; i < argc; i++) if(!strncasecmp(argv[i],"-p",2)){ if(argc > i+1){ if( (fp = fopen( argv[i+1], "r")) == NULL) { printf("Can't find mcs file %s\n",argv[i+1]); exit(1); } } else{ if( (fp = fopen("mcs_list", "r")) == NULL) { printf("Can't find file mcs_list\n"); exit(1); } } while( fgets(line,maxLineLength-1,fp) != NULL) { nt = parse_command( line, tok, tokn, 15); programChip(fd,tokn[0],tok[1]); } fclose(fp); fp = NULL; argc = i; } } if(argc > 1) if( (fp = fopen( argv[1], "r")) == NULL) { printf( "Can't open script file %s\n",argv[1]); exit(1); } while( (pb = rl_gets()) != NULL) { nt = parse_command( pb, tok, tokn, 15); if (nt) { for (i = 0; i < N_CMD; i++) { if(!strncasecmp( tok[0], cmds[i].name, strlen(tok[0]))) { switch( i) { case 0 : // help printf("help\n"); printf("quit quit program\n"); printf("w_dfea [address] [data] : write data to dfea at address\n"); printf("r_dfea [address] [N(default 1] : read N data words from dfea starting at address\n"); printf("eqs [equation_list_file] : read in equations specified in the file, default file name eqs_list\n"); printf("prog conf_file : program FPGA with conf_file in mcs format\n"); printf("rnd_test [m] [n] : run random test for m[default : 0x1000000] events with seed n[default: random]\n"); break; case 1 : //quit return OK; case 2 : // write dfea if(nt == 3) w_dfea(fd,tokn[1],tokn[2]); break; case 3 : // read dfea if(nt >= 2){ j = 1; if(nt == 3)j = tokn[2]; while(j-- > 0){ printf("address 0x%x data 0x%04x\n",tokn[1],r_dfea(fd,tokn[1])); tokn[1]++; } } break; case 4 : //read in fake data file if(nt < 2)tok[1] = "fake.txt\0"; if((ifp = fopen(tok[1],"r")) == NULL){ printf("fake data file %s not found\n",tok[1]); exit(1); } while( fgets(line,maxLineLength-1,ifp) != NULL) { if((p = strstr(line,"0x")) != NULL) addr = strtol(p+2,&pp,16); if((p = strstr(pp,"0x")) != NULL) buf = strtol(p+2,&pp,16); w_dfea(fd,addr,buf); } fclose(ifp); break; case 5 : // eqs read in equations if(nt < 2)tok[1] = "eqs_list\0"; if((ifp = fopen(tok[1],"r")) == NULL){ printf("equation file list %s not found\n",tok[1]); exit(1); } //clear all equation arrays for(j = 0; j < 6; j++) for(k = 0; k < 196; k++) for(l = 0; l < 3; l++){ evn_conv[j][k][l] = 0; odd_conv[j][k][l] = 0; } for(j = 0; j < 8; j++) for(k = 0; k < 90; k++){ dead_dblt[0][j][k] = 0; dead_dblt[1][j][k] = 0; } r2a = 0; while( fgets(line,maxLineLength-1,ifp) != NULL) { if((k = strlen(line)) > 1){ line[k-1] = '\0'; // j : 0x0 evn_max, 0x1 evn_high, 0x2 evn_med, 0x3 evn_low, 0x4 evn_cps, 0x5 evn_singlet, 0x6 evn_doublet // j : 0x7 odd_max, 0x8 odd_high, 0x9 odd_med, 0xa odd_low, 0xb odd_cps, 0xc odd_singlet, 0xd odd_doublet if(!strcmp(line,"r2a")) r2a = 1; else{ printf("file %s\n",line); rd_eqs(line); } } } //check DFEA2 firmware version to adujust lvds_in, lvds_out timing version[0] = r_dfea(fd,4); bad_version = 0; for(j = 5; j < 8; j++) if(((version[j-4]=r_dfea(fd,j)) > 0xa || version[0] > 0xa) && version[0] != version[j-4]) bad_version = 1; if(bad_version) printf("DFEA2 firmware version inconsistant! u7=0x%x u8=0x%x u9=0x%x u10=0x%x \n",version); fclose(ifp); break; case 6: // program FPGA if(nt == 2){ if(strstr(tok[1],"u7") != NULL) programChip(fd,0,tok[1]); if(strstr(tok[1],"u8") != NULL) programChip(fd,1,tok[1]); if(strstr(tok[1],"u9") != NULL) programChip(fd,2,tok[1]); if(strstr(tok[1],"u10") != NULL) programChip(fd,3,tok[1]); } //check DFEA2 firmware version to adujust lvds_in, lvds_out timing version[0] = r_dfea(fd,4); bad_version = 0; for(j = 5; j < 8; j++) if(((version[j-4]=r_dfea(fd,j)) > 0xa || version[0] > 0xa) && version[0] != version[j-4]) bad_version = 1; if(bad_version) printf("DFEA2 firmware version inconsistant! u7=0x%x u8=0x%x u9=0x%x u10=0x%x \n",version); break; case 7: //random number generate event data and test if(nt < 2) tokn[1] = 0x1000000; if(nt < 3) tokn[2] = -1; else tokn[2] &= 0xfffffff; rnd_test(fd,tokn[1],tokn[2]); break; } } } } } dsat_close(fd); } // int w_dfea(int fd, int addr, int data) { dsat_write_word(fd,0x10,&addr); dsat_write_word(fd,0x11,&data); return OK; } // int r_dfea(int fd, int addr) { int buf; dsat_write_word(fd,0x10,&addr); buf = 2; dsat_write_word(fd,0x12,&buf); dsat_read_word(fd,0x11,&buf); return buf; } // // parse input line into blank-separated tokens // ignore trailing comments (start with "#") // convert obvious numbers // int parse_command( char *pb, char *tok[], unsigned int tokn[], int maxt) { int nt = 0; char *tp, *p, *p2; int ct; // type: 1 = digits 2 = hex 4 = other while( (tp = strsep( &pb, " \t\n")) != NULL) { if( *tp != '\0') { tok[nt] = tp; // see what kind of chars are in there ct = 0; // special case for leading '0x' if( !strncasecmp( "0x", tp, 2)) { ct = 2; p2 = tp+2; } else p2 = tp; for( p=p2; *p && *p != '#'; ++p) { if( isdigit( *p) && ct==0){ ct = 1; if(maxt == 16) ct = 2; } else if( isxdigit( *p) && !isdigit( *p) && (ct!=4)) ct = 2; else if( !isxdigit( *p)) ct = 4; } switch( ct) { case 1: sscanf( p2, "%d", &tokn[nt]); break; case 2: sscanf( p2, "%x", &tokn[nt]); break; default: tokn[nt] = 0; } if( ++nt >= maxt) goto toomany; } } toomany: return nt; } /* A static variable for holding the line. */ static char *line_read = (char *)NULL; static char file_buf[256]; // // read a line from fp if non-null // or terminal using readline // keep a history // char *rl_gets () { int n; static char last_line[2048]; if( fp != NULL) { if( fgets( file_buf, 255, fp) == NULL){ //after file ends, using terminal input fclose(fp); fp = NULL; goto din; } else { if( (n = strlen( file_buf)) > 1) file_buf[n-1] = '\0'; return file_buf; } } din: #ifdef USE_READLINE /* If the buffer has already been allocated, return the memory to the free pool. */ if (line_read) { free (line_read); line_read = (char *)NULL; } /* Get a line from the user. */ line_read = readline ("fake_tst> "); /* If the line has any text in it, save it on the history. */ if (line_read && *line_read) if (strcasecmp(line_read, last_line)) { strcpy(last_line, line_read); add_history(line_read); } return (line_read); #else printf( "fake_tst> "); if( fgets( file_buf, 255, stdin) == NULL) return NULL; else { if( (n = strlen( file_buf)) > 1) file_buf[n-1] = '\0'; return file_buf; } #endif } // eq_type : 0x0 evn_max, 0x1 evn_high, 0x2 evn_med, 0x3 evn_low, 0x4 evn_cps, 0x5 evn_singlet, 0x6 evn_doublet // eq_type : 0x7 odd_max, 0x8 odd_high, 0x9 odd_med, 0xa odd_low, 0xb odd_cps, 0xc odd_singlet, 0xd odd_doublet int rd_eqs( char *file_name) { FILE *ifp=NULL; char *layer[16]; char *slayer[16] = {"ai","ao","bi","bo","ci","co","di","do","ei","eo","fi","fo","gi","go","hi","ho"}; char *dlayer[8] = {"a(","b(","c(","d(","e(","f(","g(","h("}; char line[200],*temp,*p,*pp; int i, j, k, l, en, begin_found = 0, m_ptr, m_offset, odd, nlayer,singlet,eq_type; ifp = fopen(file_name,"r"); if (!ifp) { printf("read equation: Can not open file %s\n",file_name); return ERROR; } // strcpy(line,file_name); //convert to lower case for(i = 0; i < strlen(line); i++) if(line[i] > 64 && line[i] < 91) line[i] += 32; if((p = strstr(line,"tsector")) != NULL) odd = strtol(p+7,&pp,10)%2; else{ if((p = strstr(line,"cps_map")) != NULL) odd = strtol(p+8,&pp,10)%2; else{ printf("file name: \"%s\" is not legal\n",line); return ERROR; } } eq_type = -1; if((p = strstr(line,"max")) != NULL) eq_type = odd*7; if((p = strstr(line,"high")) != NULL) eq_type = odd*7+1; if((p = strstr(line,"med")) != NULL) eq_type = odd*7+2; if((p = strstr(line,"low")) != NULL) eq_type = odd*7+3; if((p = strstr(line,"cps")) != NULL) eq_type = odd*7+4; if((p = strstr(line,"singlets")) != NULL) eq_type = odd*7+5; if((p = strstr(line,"doublets")) != NULL) eq_type = odd*7+6; if(eq_type < 0){ printf("file name: \"%s\" is not legal\n",line); return ERROR; } m_ptr = 1; m[odd][0] = 0; m_offset = 352*(eq_type%7); if(eq_type%7 < 4){ if(m_offset == 0) for(i = 0; i < nlayer; i++) eqs[odd][0][i] = 0; en = m[odd][m_offset]; } singlet = 0; while ( fgets(line, 200, ifp) != NULL) { int length,token; //remove comments if((p = strstr(line,"--")) != NULL) *p = '\0'; //find the length of the line length = strlen(line); for(i = 0; i < length; i++){ //convert to lower case if(line[i] > 64 && line[i] < 91) line[i] += 32; //remove space if(line[i] == ' '){ for(j = i; j < length; j++) line[j] = line[j+1]; length--; } } //search for beginning of equations if(begin_found != 1){ if(strstr(line,"ai:in") != NULL) singlet = 1; if(strstr(line,"begin") != NULL){ begin_found = 1; if(singlet){ for(i = 0; i < 16; i++) layer[i] = slayer[i]; nlayer = 16; } else{ for(i = 0; i < 8; i++) layer[i] = dlayer[i]; nlayer = 8; } } singlet_eq[eq_type] = singlet; } else{ if(strstr(line,"end") != NULL) break; //looking for "or" and replace it with ';' while((p = strstr(line,"or")) != NULL){ p[0] = ';'; p[1] = ' '; } switch(eq_type%7){ //processing cps equations case 4: //looking for cps( if((p = strstr(line,"cps(")) != NULL){ i = strtol(p+4,&pp,10); //looking for link if((p = strstr(line,"link")) != NULL){ j = strtol(p+4,&pp,10); if(j > 0)j--; } else{ printf("error in cps(%d)\n",i); return ERROR; } if((p = strstr(line,"array(")) != NULL){ k = strtol(p+6,&pp,10); if(eq_type == 4) evn_conv[j][k][2] = i+32; else odd_conv[j][k][2] = i+32; } else{ printf("error in cps(%d)\n",i); return ERROR; } } break; //processing singlets equations case 5: //looking for layer for(i = 0; i < 16; i++) if((p = strstr(line,slayer[i])) != NULL){ j = strtol(p+3,&pp,10); if((p = strstr(line,"link")) != NULL){ k = strtol(p+4,&pp,10); if(k)k--; l = strtol(p+6,&pp,10); if(eq_type == 5){ evn_conv[k][l][0] = i; evn_conv[k][l][1] = j; } else{ odd_conv[k][l][0] = i; odd_conv[k][l][1] = j; } } else{ printf("error in singlet %s(%d)\n",slayer[i],j); return ERROR; } } break; //processing doublets equations case 6: if((p = strstr(line,"'1'")) != NULL){ for(i = 0; i < 8; i++) if((p = strstr(line,dlayer[i])) != NULL){ j = strtol(p+2,&pp,10); dead_dblt[odd][i][j] = 1; break; } } break; //read track equations default: //looking for m( if((p = strstr(line,"m(")) != NULL){ i = strtol(p+2,&pp,10); //check if there are any missing m terms while(m_ptr <= i){ m[odd][m_ptr+m_offset] = en; m_ptr++; } } //looking for ';' do{ token = 0; if((p = strstr(line,";")) != NULL){ p[0] = '\0'; temp = p+1; token = 1; } for(i = 0; i < nlayer; i++){ if((p = strstr(line,layer[i])) != NULL){ eqs[odd][en][i] = strtol(p+2+singlet,&pp,10); } } strcpy(line,temp); if(token){ j = 0; for(i = 0; i < nlayer; i++) j += eqs[odd][en][i]; //do not include empty line if(j){ en++; //clear next product term for(i = 0; i < nlayer; i++) eqs[odd][en][i] = 0; } } if(en == N){ printf("too many equations found, exit\n"); return ERROR; } }while(token == 1); } } } fclose(ifp); if(eq_type%7 < 4){ do{ m[odd][m_ptr + m_offset] = en; m_ptr++; }while(m_ptr < 353); printf("%d equations found\n",en-m[odd][m_offset]); } return OK; } int sim(int fd) { int i, j, k, l, n, s, addr, l1, cr, fx, lvds_in[2], trk_fnd, nlayer[2] = {8,16}, right, link, link_word; int dblt_cnt[2],sglt_cnt[2][4]; int s1[4] = {0,352,704,1056},s2[4] = {352,704,1056,1760}; int tick_event, turn_event; int curve, pt, ptsub, phi; int cntrd, width, clstr[2][8][2], clstr_cnt[2][2], psc[2], clstr_ram[2][8]; int d, d_min, index, ccw, cw, nccw, ncw, total_trk[2]; int iso[2], iso_byte[2], pt_sum[2]; int data[7], mu_cnt[2], trk_cnt[2][4], track[2][4][7], prj_trk; int dblt_range[8][2] = {3,46,5,56,9,64,14,71,21,76,28,81,38,83,44,89}; int found_trk[2][1760],higher_pt,singlet,l2_total_trk,dbl_trk[2],old_trk_cnt; //clear hit arrays for(i=0;i<2;i++){ for(j=0;j<32;j++) cps[i][j] = 0; for(j=0;j<16;j++) for(k=0;k<90;k++) sglt[i][j][k] = 0; for(j=0;j<8;j++) for(k=0;k<90;k++) dblt[i][j][k] = 0; } //fill singlet and cps hits //eight LVDS link for(i = 0; i < 8; i++){ link = i; //swap link3 and link4 data if(i == 2)link = 3; if(i == 3)link = 2; for(j = 0; j < 7; j++){ k = j*28; link_word = link_data[link][j] & 0xfffffff; while(link_word != 0){ link_word = link_word >> 1; k++; if(link_word & 1){ switch(i){ case 0: case 1: if(l = evn_conv[i][k][1]){ n = evn_conv[i][k][0]; sglt[0][n][l] = 1; } if(l = evn_conv[i][k][2]) cps[0][l-32] = 1; break; case 6: case 7: if(l = odd_conv[i-6][k][1]){ n = odd_conv[i-6][k][0]; sglt[1][n][l] = 1; } if(l = odd_conv[i-6][k][2]) cps[1][l-32] = 1; break; default: if(l = evn_conv[i][k][1]){ n = evn_conv[i][k][0]; sglt[0][n][l] = 1; } if(l = evn_conv[i][k][2]) cps[0][l-32] = 1; if(l = odd_conv[i][k][1]){ n = odd_conv[i][k][0]; sglt[1][n][l] = 1; } if(l=odd_conv[i][k][2]) cps[1][l-32] = 1; } } } } } // fill doublet hits for(k = 0; k < 2; k++) for(i = 0; i < 8; i++){ l = 2*i; for(j = dblt_range[i][0]; j <= dblt_range[i][1]; j++){ if(dead_dblt[k][i][j]){ dblt[k][i][j] = 1; } if(!sglt[k][l][j-1] && sglt[k][l+1][j]) dblt[k][i][j] = 1; if(sglt[k][l][j]) dblt[k][i][j] = 1; } } //count singlets for(k = 0; k < 2; k++) for(i = 0; i < 4; i++){ sglt_cnt[k][i] = 0; if(version[2*k+1] > 0xd) if(s_radial[k]){ for(l = i*4; l < i*4+4; l++) for(j = dblt_window[l/2][0]; j <= dblt_window[l/2][1]; j++) sglt_cnt[k][i] += sglt[k][l][j]; } else{ for(l = 0; l < 16;l++) for(j = dblt_window[l/2][0]+i*(l/2+4); j < dblt_window[l/2][0]+(i+1)*(l/2+4); j++) sglt_cnt[k][i] += sglt[k][l][j]; } } //count doublets for(k = 0; k < 2; k++){ dblt_cnt[k] = 0; for(i = 0; i < 8; i++) for(j = dblt_window[i][0]; j <= dblt_window[i][1]; j++) dblt_cnt[k] += dblt[k][i][j]; } //read tick, turn, fx, cr for this event turn_event = r_dfea(fd, 0xe); i = r_dfea(fd, 0xd); tick_event = i & 0xff; lvds_in[0] = (i & 0x100) >> 8; lvds_in[1] = (i & 0x200) >> 9; lvds_out_r[0] = (i & 0x400) >> 10; lvds_out_r[1] = (i & 0x800) >> 11; fx = (i & 0x1000) >> 12; cr = (i & 0x2000) >> 13; bad_l2 = (i & 0x8000) >> 15; //track finding //search for all tracks for(i = 0; i < 2; i++){ for(pt = 0; pt < 4; pt++){ if(r2a && (version[2*i+1] < 0xb || pt > 1)) singlet = 0; else singlet = 1; for(s = s1[pt]; s < s2[pt]; s++) for(k = m[i][s]; k < m[i][s+1]; k++){ found_trk[i][s] = 1; for(l = 0; l < nlayer[singlet]; l++) if(n = eqs[i][k][l]) if((!dblt[i][l][n] && !singlet) || (!sglt[i][l][n] && singlet)){ found_trk[i][s] = 0; break; } if(found_trk[i][s]) break; } } } //search for even and odd sectors for(i = 0; i < 2; i++){ mu_cnt[i] = 0; dbl_trk[i] = 0; for(pt = 0; pt < 4; pt++){ trk_cnt[i][pt] = 0; //search tracks in segments of twenty two for(s = s1[pt]; s < s2[pt]; s += 22){ //search from high phi to low phi for(j = s+21; j >= s; j--){ if((trk_fnd = found_trk[i][j]) && version[2*i+1] > 0xa){ //check for ghost tracks (no cross sector veto as of Jan-22-2006) phi = j%44; //if phi is even check neighbouring phi bins if((phi%2 == 0) && ((phi && found_trk[i][j-1]) || found_trk[i][j+1])) trk_fnd = 0; higher_pt = j - 88; if(higher_pt < 0) higher_pt += 44; //not the highest Pt, check ghost track from higher Pt bins if(higher_pt >= r2a*s1[pt] && (found_trk[i][higher_pt] || (phi > 0 && found_trk[i][higher_pt-1]) || (phi < 43 && found_trk[i][higher_pt+1]))) trk_fnd = 0; } if(trk_fnd){ //save muon track if(mu_cnt[i] < 6){ mu_trk[i][mu_cnt[i]] = j; mu_cnt[i]++; } //save CTOC track if(trk_cnt[i][pt] < 7){ track[i][pt][trk_cnt[i][pt]] = j - s1[pt]; trk_cnt[i][pt]++; } //if more CTOC tracks are needed, search from right if(trk_cnt[i][pt] < 7){ for(right = s; right < j - SAME; right++){ if((trk_fnd = found_trk[i][right]) && version[2*i+1] > 0xa){ //check for ghost tracks (no cross sector veto as of Jan-22-2006) phi = right%44; //if phi is even check neighbouring phi bins if((phi%2 == 0) && ((phi && found_trk[i][right-1]) || found_trk[i][right+1])) trk_fnd = 0; higher_pt = right - 88; if(higher_pt < 0) higher_pt += 44; //not the highest Pt, check ghost track from higher Pt bins if(higher_pt >= r2a*s1[pt] && (found_trk[i][higher_pt] || (phi > 0 && found_trk[i][higher_pt-1]) || (phi < 43 && found_trk[i][higher_pt+1]))) trk_fnd = 0; } if(trk_fnd){ track[i][pt][trk_cnt[i][pt]] = right - s1[pt]; trk_cnt[i][pt]++; if(trk_cnt[i][pt] == 2) dbl_trk[i] = 1; break; } } } break; } } if(mu_cnt[i] == 6 && trk_cnt[i][pt] == 7) break; } if(pt == 0 & muon_fake[i] == 1 && tick_event == 0xa){ if(mu_cnt[i] == 0) mu_cnt[i] = 1; mu_trk[i][0] = 0x15; } } } //clusters for(i = 0; i < 2; i++){ psc[i] = 0; for(k = 0; k < 2; k++){ cntrd = 0; width = 0; clstr_cnt[i][k] = 0; for(l = 16; l < 32; l++){ if(k) j = 31 - l; else j = l; if(cps[i][j]){ cntrd += j; width++; } else if(width){ clstr[i][clstr_cnt[i][k]+4*k][0] = cntrd/width; if(width > 7) width = 7; clstr[i][clstr_cnt[i][k]+4*k][1] = width; clstr_cnt[i][k]++; //psc counts only up to three if(psc[i] < 3) psc[i]++; cntrd = 0; width = 0; } if(clstr_cnt[i][k] == 4) break; } //if cps(0) or cps(31) = '1' if(width){ clstr[i][clstr_cnt[i][k]+4*k][0] = cntrd/width; if(width > 7) width = 7; clstr[i][clstr_cnt[i][k]+4*k][1] = width; clstr_cnt[i][k]++; //psc counts only up to three if(psc[i] < 3) psc[i]++; } for(j = clstr_cnt[i][k]; j < 4; j++){ clstr[i][j+4*k][0] = 0; clstr[i][j+4*k][1] = 0; } } } //format CFT tracks for(i = 0; i < 2; i++){ pt_sum[i] = 0; iso_byte[i] = 0; total_trk[i] = 0; old_trk_cnt = 0; for(j = 0; j < 8; j++) if(clstr[i][j][0] < 24 && clstr[i][j][0] > 7) clstr_ram[i][j] = ((clstr[i][j][0] - 8) << 19) + (clstr[i][j][1] << 16) + (sector[i] << 3); else clstr_ram[i][j] = 0; for(j = 0; j < 4; j++){ ccw = 0; cw = 0; nccw = 0; ncw = 0; for(k = 0; k < 7; k++) if(k >= trk_cnt[i][j]) track[i][j][k] = 0; else{ curve = (track[i][j][k]/44 + 1)%2; ptsub = track[i][j][k]/88; pt_sum[i] += pt_lut[j][ptsub]; phi = track[i][j][k]%44; //l2CFT only accept six tracks per pt bin if(no_l2_trk[i] == 0 && k < 6) l2cft[i][total_trk[i]+2] = (sector[i] << 16) + (curve << 13) + (j << 11) + (ptsub << 8) + (phi << 1); iso_byte[i] |= curve*8; //cluster matching prj_trk = xpl_lut[phi] + (2*curve - 1)*xpl_offset[j]; d_min = 30; for(n = 0; n < 8; n++) if(clstr[i][n][1]){ d = clstr[i][n][0] - prj_trk; if(d < 0) d = -d; if(d < d_min){ d_min = d; index = n; } } if(no_l1_trk[i] == 0 && d_min <= match_window[j]){ //l2CFT only accept six tracks per pt bin if(no_l2_trk[i] == 0 && k < 6){ l2cft[i][total_trk[i]+2] += (((clstr[i][index][0]-8) & 0xf) <<20) + 0x8000; if(clstr[i][index][0] > 23 || clstr[i][index][0] < 8) l2cft[i][total_trk[i]+2] += 0x80; else{ if(!(clstr_ram[i][index] & 0x8000)) clstr_ram[i][index] += 0x8000 + (curve <<13) + (j <<11) + (ptsub <<8); } } if(curve) ccw++; else cw++; iso_byte[i] |= 16; } else{ if(curve) nccw++; else ncw++; } //l2CFT only accept six tracks per pt bin if(k < 6) total_trk[i]++; } ctoc[i][1+j] = (sglt_cnt[i][j] << 16); if(!no_l1_trk[i]) ctoc[i][1+j] += (ccw << 13) + (cw << 10) + (nccw << 5) + (ncw << 2); if(j == 2) ctoc[i][1+j] += psc[i]; if(!(iso_byte[i] & 0x80) && (total_trk[i] - old_trk_cnt == 1)) iso_byte[i] |= 0x80 + 2*j; old_trk_cnt = total_trk[i]; } //in L1 CTOC, only pt_sum(7 downto 2) are kept ctoc[i][5] = ((pt_sum[i] & 0xfc) << 16) + (dblt_cnt[i] << 8); if((iso_byte[i] & 0x80) == 0) iso_byte[i] += 0x86; if(dblt_cnt[i] < 16) iso_byte[i]++; } //format muon tracks for(i = 0; i < 2; i++){ if(muon_patt[i]){ mu_cnt[i] = 6; j = r_dfea(fd,0x10+i*8) & 0xff; if(j == 0xff) mu_cnt[i] = 1; if(j < 0x80) mu_cnt[i] = 0; if(j & 0x80) lvds_out[i] = 1; else lvds_out[i] = 0; for(n = 0;n < 6;n++){ mu_trk[i][n] = j + (j << 8); j = (j + 1) & 0xff; } mu_trk[i][6] = 0; } else{ if(no_muon_trk[i]) mu_cnt[i] = 0; if(mu_cnt[i]) lvds_out[i] = 1; else lvds_out[i] = 0; for(j = 0; j < 7; j++) if(mu_cnt[i] <= j) mu_trk[i][j] = 0; else{ curve = (mu_trk[i][j]/44 + 1)%2; pt = mu_trk[i][j]/352; if(pt > 3)pt = 3; ptsub = (mu_trk[i][j] - pt*352)/88; phi = mu_trk[i][j]%44; mu_trk[i][j] = 0x8000 + (curve << 11) + (pt << 9) + (ptsub << 6) + phi; if((!r2a || en_new[i]) && version[2*i+1] > 0xa){ //cluster matching prj_trk = xpl_lut[phi] + (2*curve - 1)*xpl_offset[pt]; for(n = 0; n < 8; n++) if(clstr[i][n][1]){ d = clstr[i][n][0] - prj_trk; if(d < 0) d = -d; if(d <= match_window[pt]){ mu_trk[i][j] |= 1 << 12; break; } } } } } } for(i = 0; i < 2; i++){ iso[i] = 0; ctoc[i][0] = 0xe00002f + (octant[i] <<19) + (cr <<18) + (s_radial[i] << 16) + (sector[i] << 8); // if(tick_event == 0x7) if(fx) ctoc[i][0] += 0x20000; //isolation byte if(no_l1_trk[i] == 1){ iso_byte[i] &= 0x1; iso_byte[i] |= 0x86; } if(lvds_in[i] == 0 && mu_cnt[i] == 1 && dbl_trk[i] == 0 && mu_cnt[1-i] == 0){ ctoc[i][5] += iso_byte[i]; //set iso bit for(j = 0; j < total_trk[i]; j++) l2cft[i][2+j]++; iso[i] = 1; } //muon isolation bit if(muon_patt[i] == 0 && (!r2a || en_new[i]) && version[2*i+1] > 0xb) mu_trk[i][5] |= iso[i] << 13; if(ctoc_fake[i] == 1){ ctoc[i][0] &= 0xe06002f; for(j = 1; j < 6; j++) ctoc[i][j] = 0; } if(ctoc_fake[i] == 2){ ctoc[i][0] &= 0xe06002f; ctoc[i][1] = 0; ctoc[i][2] = 0x1000020; ctoc[i][3] = 0x1000004; ctoc[i][4] = 0x1000004; ctoc[i][5] = 0x1081800; } if(ctoc_fake[i] == 3){ ctoc[i][0] = 0xe00002f; ctoc[i][1] = 0x0111111; ctoc[i][2] = 0x0222222; ctoc[i][3] = 0x0444444; ctoc[i][4] = 0x0888888; ctoc[i][5] = 0x0ffffff; } ctoc[i][6] = 0 ; //ctoc parity for(j = 0; j < 6; j++){ n = 0; for(k = 0; k < 24; k++) if(ctoc[i][j] & (1 << k)) n = 1 - n; ctoc[i][j] |= (n << 24); ctoc[i][6] ^= ctoc[i][j]; } ctoc[i][6] &= 0xffffff; //sort and zero compress l2cps k = 0; for(l = 0; l < 2; l++) for(n = 0; n < 4; n++){ if(l) j = n; else j = 7 - n; if(clstr_ram[i][j]){ l2cps[i][k+2] = clstr_ram[i][j]; //l2cps iso bit if(iso[i]) l2cps[i][k+2]++; k++; } } if(no_l2_trk[i]) k = 0; l2cps[i][0] = (octant[i] <<19) + (((k&7) ^ (k/8)) <<16) + (k <<10) + ((k/8) <<9); switch(k & 7){ case 7: case 4: case 2: case 1: l2cps[i][0] += 0x100; default: l2cps[i][0] += 0xe0000c0; } l2cps[i][1] = tick_event + (turn_event << 8); if(l2_fake[i] == 3){ l2cps[i][0] = 0xe8209c0 + (octant[i] << 19); l2cps[i][2] = 0x19a000 + (sector[i] << 3); l2cps[i][3] = 0x6bb300 + (sector[i] << 3); k = 2; } //zero padding l2cps for(j = k+2; j < 11; j++) l2cps[i][j] = 0; //cps parity for(j = 0; j < k+2; j++){ n = 0; for(l = 0; l < 24; l++) if(l2cps[i][j] & (1 << l)) n = 1 - n; l2cps[i][j] |= (n << 24); l2cps[i][k+2] ^= l2cps[i][j]; } l2cps[i][k+2] &= 0xffffff; //l2cft if(no_l2_trk[i]) l2_total_trk = 0; else l2_total_trk = total_trk[i]; l2cft[i][0] = (octant[i] <<19) + (((l2_total_trk & 7) ^ (l2_total_trk/8)) <<16) + (l2_total_trk <<10); switch(l2_total_trk & 7){ case 7: case 4: case 2: case 1: l2cft[i][0] += 0x100; default: l2cft[i][0] += 0xe000028; } if(l2_total_trk < 24 && l2_total_trk > 7) l2cft[i][0] += 0x200; l2cft[i][1] = tick_event + (turn_event << 8); if(l2_fake[i] == 2){ l2cft[i][0] = 0xe841128 + (octant[i] << 19); l2cft[i][2] = 0x30a00e + (sector[i] << 16); l2cft[i][3] = 0x91a + (sector[i] << 16); l2cft[i][4] = 0xd0b350 + (sector[i] << 16); l2cft[i][5] = 0x3a2c + (sector[i] << 16); l2_total_trk = 4; } for(j = l2_total_trk+2; j < 27; j++) l2cft[i][j] = 0; //cft parity for(j = 0; j < l2_total_trk+2; j++){ n = 0; for(k = 0; k < 24; k++) if(l2cft[i][j] & (1 << k)) n = 1 - n; l2cft[i][j] |= (n << 24); l2cft[i][l2_total_trk+2] ^= l2cft[i][j]; } l2cft[i][l2_total_trk+2] &= 0xffffff; if(ctoc_zero[i]){ for(j = 0; j < 7; j++) ctoc[i][j] = 0; for(j = 0; j < 11; j++) l2cps[i][j] = 0; for(j = 0; j < 27; j++) l2cft[i][j] = 0; } if(ctoc_patt[i]){ ctoc[i][0] = r_dfea(fd,0x20+i*16); ctoc[i][0] += r_dfea(fd,0x21+i*16) << 16; for(j = 1; j < 7; j++) ctoc[i][j] = ((ctoc[i][j-1] << 1) & 0xfffffff) + 1 - (ctoc[i][j-1] >> 27); l2cps[i][0] = r_dfea(fd,0x40+i*32); l2cps[i][0] += r_dfea(fd,0x41+i*32) << 16; for(j = 1; j < 12; j++) l2cps[i][j] = ((l2cps[i][j-1] << 1) & 0xfffffff) + 1 - (l2cps[i][j-1] >> 27); l2cft[i][0] = r_dfea(fd,0x80+i*64); l2cft[i][0] += r_dfea(fd,0x81+i*64) << 16; for(j = 1; j < 27; j++) l2cft[i][j] = ((l2cft[i][j-1] << 1) & 0xfffffff) + 1 - (l2cft[i][j-1] >> 27); } } return OK; } // programs chip with MCS file int programChip(int fd,int chip,char *Filename) { FILE *f; int ln = 0; char line[maxLineLength]; char *chip_name[4] = {"U7", "U8", "U9", "U10"}; unsigned buf; // open mcs file f = fopen(Filename,"r"); if (!f) { printf("programChip: Cannot open file %s\n",Filename); return ERROR; } //reprogram the chip w_dfea(fd,3,(1 << chip)); printf("program %s with file %s\n",chip_name[chip],Filename); printf("reprogram %s command sent\n",chip_name[chip]); // wait for init go high while(!(r_dfea(fd,3) & (1 << (4+chip)))){ } printf("init goes high\n"); //done signal should be low if(r_dfea(fd,3) & (1 << chip)){ printf("Done is high, something is wrong!\n"); return ERROR; } // program the chip using data from a file // write address buf = chip+4; dsat_write_word(fd,0x10,&buf); // set up for data writing if( ioctl(fd, PPSETMODE, &addr_mode) ) { perror(__func__); return -1; } buf = 0x11; if ( write(fd, &buf, 1) != 1 ) { perror(__func__); return -1; } if( ioctl(fd, PPSETMODE, &data_mode)) { perror(__func__); return -1; } // loop over record in the file and read them in the array "line" while ( fgets(line, maxLineLength, f) != NULL) { char c1[3],c2[5]; unsigned char data[200]; int i,byte_count,address,address_bias,rec_type,total; ln++; if(ln%0x1000 == 0){ printf("\rcurrent line: 0x%x",ln); fflush(stdout); } // check that the record has more than 9 characters if ( strlen(line) < 9 ) { printf("programChip: Error while reading " "line %d: it has less than 9 characters\n",ln); return ERROR; } // number of bytes in the record (first two hex numbers) strncpy(c1,line+1,2); c1[2] = '\0'; sscanf(c1,"%x",&byte_count); // address (hex numbers 3-6) strncpy(c2,line+3,4); c2[4] = '\0'; sscanf(c2,"%x",&address); // record type (hex numbers 7-8) strncpy(c1,line+7,2); c1[2] = '\0'; sscanf(c1,"%x",&rec_type); // calculate checksum total = byte_count+address/256+address%256+rec_type; // loop over the rest of the characters in the record and // convert them to int for (i=0; i<(byte_count+1);i++) { strncpy(c1,line+2*i+9,2); c1[2] = '\0'; data[i] = strtol(c1,NULL,16); total = total + data[i]; } // check the checksum for the record if (total%256 != 0) { printf("programChip: Error while reading line " "%d - a checksum error is found\n",ln); return ERROR; } //byte count must be even if(byte_count%2 == 1)byte_count++; // only data records are written if (rec_type == 0) { // for (i=0; i 0xf000000) buf = 0; else buf = j & random() & 0x1fff; w_dfea(fd,0xb9,buf); muon_patt[0] = buf & 0x1; muon_fake[0] = (buf >> 1) & 0x1; ctoc_zero[0] = (buf >> 2) & 0x1; ctoc_patt[0] = (buf >> 3) & 0x1; ctoc_fake[0] = (buf >> 4) & 0x3; l2_fake[0] = (buf >> 6) & 0x3; en_new[0] = (buf >> 8) & 0x1; no_muon_trk[0] = (buf >> 9) & 0x1; no_l1_trk[0] = (buf >> 10) & 0x1; no_l2_trk[0] = (buf >> 11) & 0x1; s_radial[0] = (buf >> 12) & 0x1; if((j = random() & 0xfffffff) > 0xf000000) buf = 0; else buf = j & random() & 0x1fff; w_dfea(fd,0xf9,buf); muon_patt[1] = buf & 0x1; muon_fake[1] = (buf >> 1) & 0x1; ctoc_zero[1] = (buf >> 2) & 0x1; ctoc_patt[1] = (buf >> 3) & 0x1; ctoc_fake[1] = (buf >> 4) & 0x3; l2_fake[1] = (buf >> 6) & 0x3; en_new[1] = (buf >> 8) & 0x1; no_muon_trk[1] = (buf >> 9) & 0x1; no_l1_trk[1] = (buf >> 10) & 0x1; no_l2_trk[1] = (buf >> 11) & 0x1; s_radial[1] = (buf >> 12) & 0x1; } //generate link data for(i = 0; i < 8; i++){ for(j = 0; j < 7; j++){ link_data[i][j] = random(); for(k = 0; k < 1; k++) link_data[i][j] &= random(); if(i == 1 || i == 6) link_data[i][j] &= 0xffffff8; else link_data[i][j] &= 0xffffffe; if(j%7 == 6) link_data[i][j]++; addr = 0x180 + i*0x10 + 2*j; w_dfea(fd,addr,link_data[i][j] & 0xffff); w_dfea(fd,addr+1,link_data[i][j] >> 16); } } //trigger w_dfea(fd,2,0x100); //check if new muon bits are enabled for run2a en_new[0] = (r_dfea(fd,0xB9) & 0x100) >> 8; en_new[1] = (r_dfea(fd,0xF9) & 0x100) >> 8; //call simulation sim(fd); for(sec = 0; sec < 2 ;sec++){ //check results //check lvds_out if(lvds_out_r[sec] != lvds_out[sec]){ printf("\nlvds_out[%d] does not match, should be %d \n",sec,lvds_out[sec]); err_cnt[0][sec]++; } //check muon tracks for(j = 0; j < 7; j++) data[j] = r_dfea(fd,sec*8+0x10+j); for(j = 0; j < 7; j++){ if(data[j] ^ mu_trk[sec][j]){ printf("\nmu%d real:",sec); for(k = 0; k < 7; k++) printf(" 0x%04x",data[k]); printf("\n"); printf("mu%d sim:",sec); for(k = 0; k < 7; k++) printf(" 0x%04x",mu_trk[sec][k]); printf("\n"); err_cnt[1][sec]++; break; } } //check l1 for(j = 0; j < 7; j++){ data[j] = r_dfea(fd,sec*0x10+0x20+j*2); data[j] += r_dfea(fd,sec*0x10+0x20+j*2+1) << 16; } for(j = 0; j < 7; j++){ if(data[j] & 0x80000000) invalid_l1_cnt++; //bit 31 of data is L1CTOC invalid flag (overwritten by L2CFT/L2CPS) else if(data[j] ^ ctoc[sec][j]){ printf("\nl1_%d real:",sec); for(k = 0; k < 7; k++) printf(" x%07x",data[k]); printf("\n"); printf("l1_%d sim:",sec); for(k = 0; k < 7; k++) printf(" x%07x",ctoc[sec][k]); printf("\n"); err_cnt[2][sec]++; break; } } if(!bad_l2){ if(l2_fake[sec] != 1){ //check l2cps for(j = 0; j < 11; j++){ data[j] = r_dfea(fd,sec*0x20+0x40+j*2); data[j] += r_dfea(fd,sec*0x20+0x40+j*2+1) << 16; } for(j = 0; j < 11; j++) if(data[j] ^ l2cps[sec][j]){ printf("\nl2cps_%d real:",sec); for(k = 0; k < 11; k++) printf(" x%07x",data[k]); printf("\n"); printf("l2cps_%d sim:",sec); for(k = 0; k < 11; k++) printf(" x%07x",l2cps[sec][k]); printf("\n"); err_cnt[3][sec]++; break; } //check l2CFT for(j = 0; j < 27; j++){ data[j] = r_dfea(fd,sec*0x40+0x80+j*2); data[j] += r_dfea(fd,sec*0x40+0x80+j*2+1) << 16; } for(j = 0; j < 27; j++) if(data[j] ^ l2cft[sec][j]){ printf("\nl2cft_%d real:",sec); for(k = 0; k < 27; k++) printf(" x%07x",data[k]); printf("\n"); printf("l2cft_%d sim:",sec); for(k = 0; k < 27; k++) printf(" x%07x",l2cft[sec][k]); printf("\n"); err_cnt[4][sec]++; break; } } } else bad_l2_cnt++; } if(cycle%10 == 9){ printf("\revent%d",cycle); for(sec = 0; sec < 2; sec++) for(i = 0; i < 5; i++) if(err_cnt[i][sec] != 0) printf(" err%d=%d",sec*5+i,err_cnt[i][sec]); fflush(stdout); } j = 0; for(sec = 0; sec < 2; sec++) for(i = 0;i < 5;i++) j += err_cnt[i][sec]; if(j) break; } printf("\ntest done\n"); if(invalid_l1_cnt) printf("invalid l1 count: %d\n",invalid_l1_cnt); if(bad_l2_cnt) printf("bad l2 count: %d\n",bad_l2_cnt); return OK; }