00001
00002
00003
00004 #include "RodModule.h"
00005
00006
00007 namespace SctPixelRod {
00008
00009
00010
00011
00012 static long endianSwap = 0;
00013 static const long rodInitTimeout = 1;
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 HpiException::HpiException( std::string descriptor, unsigned long calcAddr,
00026 unsigned long readAddr) {
00027 m_descriptor = descriptor;
00028 m_calcAddr = calcAddr;
00029 m_readAddr = readAddr;
00030 }
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 RodException::RodException( std::string descriptor) {
00043 m_descriptor = descriptor;
00044 m_numData = 0;
00045 m_data1 = m_data2 = 0;
00046 }
00047 RodException::RodException( std::string descriptor, unsigned long data1) {
00048 m_descriptor = descriptor;
00049 m_numData = 1;
00050 m_data1 = data1;
00051 m_data2 = 0;
00052 }
00053 RodException::RodException( std::string descriptor, unsigned long data1,
00054 unsigned long data2) {
00055 m_descriptor = descriptor;
00056 m_numData = 2;
00057 m_data1 = data1;
00058 m_data2 = data2;
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 RodModule::RodModule( unsigned long baseAddr, unsigned long mapSize,
00075 VmeInterface & ourInterface, long numSlaves) throw (RodException&,
00076 VmeException&) :
00077 VmeModule(baseAddr, mapSize, ourInterface) {
00078 m_slot = baseAddr>>24;
00079 m_serialNumber = 0xFFFFFFFF;
00080 m_numSlaves = numSlaves;
00081 m_finBufferSize = 4096;
00082 m_masterImageName = std::string("");
00083 try {
00084 m_myVmePort = new VmePort(m_baseAddress, m_mapSize, VmeInterface::A32,
00085 m_ourInterface);
00086 }
00087 catch (std::bad_alloc & ba) {
00088 throw RodException("Failed to get VME Port.");
00089 }
00090 for (long i=0; i<4; i++) {
00091 m_slaveEmifName[i]= std::string("");
00092 m_slaveIpramName[i]= std::string("");
00093 m_slaveIdramName[i]= std::string("");
00094 m_slaveExtName[i]= std::string("");
00095 }
00096 for (long i=0; i<N_TXT_BUFFS; i++) {
00097 m_textBuff[i] = 0;
00098 };
00099 m_myTextState = TEXT_IDLE;
00100 m_myPrimState = PRIM_IDLE;
00101 m_textType = TEXT_UNDEF;
00102 }
00103
00104
00105
00106
00107
00108
00109 RodModule::~RodModule() {
00110 delete(m_myVmePort);
00111 m_myVmePort = 0;
00112 return;
00113 }
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 void RodModule::initialize() throw (RodException &, VmeException &) {
00133
00134 unsigned long hpicReadback;
00135 const unsigned long rodResetValue = 0x000000c0;
00136 unsigned long rodReset;
00137 unsigned long rodRegValue;
00138
00139
00140 rodRegValue = readRodStatusReg(0);
00141 if (endianSwap) {
00142 rodReset = endianReverse32(rodResetValue);
00143 }
00144 else {
00145 rodReset = rodResetValue;
00146 }
00147 m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], rodReset);
00148 sleep(1000);
00149 rodRegValue = readRodStatusReg(0);
00150
00151
00152 m_serialNumber = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[6]);
00153 if (endianSwap) m_serialNumber = endianReverse32(m_serialNumber);
00154 m_serialNumber = m_serialNumber & 0x3ff;
00155
00156
00157
00158 unsigned long hpicValue = 0x00010001;
00159
00160 hpiLoad(HPIC, hpicValue);
00161 hpicReadback = hpiFetch(HPIC);
00162 sleep(100);
00163
00164
00165 for (long i=0; ; ++i) {
00166 if (readRodStatusBit(0, SR_RUNNING)) {
00167 break;
00168 }
00169 if (i>rodInitTimeout*10) throw RodException("Master DSP init timed out. Tries, Limit:", i,
00170 rodInitTimeout);
00171 sleep(100);
00172 }
00173
00174 for (int i=0; i< N_TXT_BUFFS; i++) {
00175 m_textBuff[i] = (unsigned long *)mdspSingleRead(REPLY_BUFF_BASE + 4*i);
00176 }
00177
00178
00179 m_myTextState = TEXT_IDLE;
00180 m_myPrimState = PRIM_IDLE;
00181
00182 return;
00183 }
00184
00185
00186
00187
00188
00189
00190 void RodModule::reset() throw (RodException&, VmeException &) {
00191
00192 const unsigned long rodResetValue = 0x000000c0;
00193 unsigned long rodReset;
00194
00195 if (endianSwap) {
00196 rodReset = endianReverse32(rodResetValue);
00197 }
00198 else {
00199 rodReset = rodResetValue;
00200 }
00201 m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], rodReset);
00202 sleep(10000);
00203
00204
00205 unsigned long * buff;
00206 try {
00207 buff = new unsigned long[IDRAM_SZ/sizeof(long)]={0};
00208 }
00209 catch (std::bad_alloc & ba) {
00210 throw RodException("Reset() failed to allocate buffer. Size=",
00211 IDRAM_SZ/sizeof(long));
00212 }
00213 mdspBlockWrite(IDRAM_BASE, buff, IDRAM_SZ/sizeof(long));
00214 delete buff;
00215
00216
00217 resetMasterDsp();
00218 sleep(50);
00219 for (long i=0; i<m_numSlaves; i++) {
00220 resetSlaveDsp(i);
00221 sleep(50);
00222 };
00223
00224
00225 m_myTextState = TEXT_IDLE;
00226 m_myPrimState = PRIM_IDLE;
00227
00228 return;
00229 }
00230
00231
00232
00233
00234
00235
00236 void RodModule::status() throw() {
00237 cout << "Slot: " << m_slot;
00238 cout << "Serial Number:" << m_serialNumber;
00239 cout << "Number of slave DSPs: " << m_numSlaves;
00240 cout << endl;
00241 hex(cout);
00242 cout << "Status registers[0-2]: ";
00243 try {
00244 for (int i=0; i<3; i++) {
00245 cout << readRodStatusReg(i) << " " ;
00246 }
00247 }
00248 catch (VmeException &) {
00249 cout << "status() can read ROD status registers." << flush;
00250 }
00251 cout << endl;
00252
00253 cout << "Command registers[0-1]: ";
00254 try {
00255 for (int i=0; i<2; i++) {
00256 cout << readRodCommandReg(i) << " " ;
00257 }
00258 }
00259 catch (VmeException &) {
00260 cout << "status() can read ROD command registers." << flush;
00261 }
00262
00263 dec(cout);
00264 cout << "Primitive state: " << getPrimState() << " Text State: " <<
00265 getTextState();
00266 cout << endl;
00267 return;
00268 }
00269
00270
00271 void RodModule::initSlaveDsp(const std::string & emifFile, const std::string & ipramFile,
00272 const std::string & idramFile,const std::string & extFile,
00273 const long slaveNumber) throw (RodException&, NoImageFile&, VmeException &) {
00274
00275 unsigned long readBack;
00276 unsigned long hpicValue = 0x00010001;
00277
00278 if ((slaveNumber < 0) || (slaveNumber >= m_numSlaves)) throw RodException(
00279 "Slave Number out of Range. slaveNumber, m_numSlaves:", slaveNumber,
00280 m_numSlaves);
00281
00282
00283 slvHpiLoad(SLAVE_HPIC_BASE, hpicValue, slaveNumber);
00284 readBack = slvHpiFetch(SLAVE_HPIC_BASE, slaveNumber);
00285
00286
00287 loadSlaveImage(emifFile, SLAVE_EMIF_ADDR, slaveNumber);
00288 m_slaveEmifName[slaveNumber] = emifFile;
00289 loadSlaveImage(ipramFile, SLAVE_IPRAM_ADDR, slaveNumber);
00290 m_slaveIpramName[slaveNumber] = ipramFile;
00291 loadSlaveImage(idramFile, SLAVE_IDRAM_ADDR, slaveNumber);
00292 m_slaveIdramName[slaveNumber] = idramFile;
00293 loadSlaveImage(extFile, SLAVE_CE2_ADDR, slaveNumber);
00294 m_slaveExtName[slaveNumber] = extFile;
00295
00296
00297 startSlave(slaveNumber);
00298 return;
00299 }
00300
00301
00302
00303 void RodModule::loadSlaveImage(const std::string & fileName, const unsigned long address,
00304 const long slaveNum, char opt='n') throw (NoImageFile&, RodException&,
00305 VmeException &) {
00306
00307 long numWords;
00308 int fileSize;
00309 ifstream fin;
00310 fin.open(fileName.c_str(),ios::binary);
00311 if (fin.is_open()) {
00312
00313
00314 fin.seekg(0, ios::end);
00315 fileSize = fin.tellg();
00316 fin.seekg(0, ios::beg);
00317
00318
00319 char * buffer;
00320 try {
00321 buffer = new char[fileSize];
00322 }
00323 catch (std::bad_alloc & ba) {
00324 throw RodException(
00325 "loadSlaveImage buffer failed to allocate. buffer, fileSize:",
00326 (unsigned long)buffer, (unsigned long)fileSize);
00327 }
00328 fin.read(buffer, fileSize);
00329
00330
00331 numWords = (fileSize+3)/4;
00332 slvBlockWrite(address, (unsigned long*) buffer, numWords, slaveNum);
00333
00334
00335 if (opt=='v') {
00336 char* buffer2;
00337 try {
00338 buffer2 = new char[fileSize];
00339 }
00340 catch (std::bad_alloc & ba) {
00341 throw RodException(
00342 "loadSlaveImage buffer2 failed to allocate. buffer, fileSize:",
00343 (unsigned long)buffer, (unsigned long)fileSize);
00344 }
00345 slvBlockRead(address, (unsigned long*)buffer2, numWords, slaveNum);
00346
00347 for (int i=0; i<fileSize; i++) {
00348 if (buffer[i] != buffer2[i]) {
00349 delete [] buffer;
00350 delete [] buffer2;
00351 fin.close();
00352 char message[] = "loadSlaveImage buffer readback invalid for file, slavenum, index: ";
00353 throw RodException( *message+fileName.c_str(), slaveNum, i);
00354 }
00355 }
00356 }
00357
00358
00359 fin.close();
00360 delete [] buffer;
00361 }
00362 else {
00363 throw NoImageFile(fileName);
00364 }
00365 return;
00366 }
00367
00368
00369
00370
00371
00372
00373
00374 void RodModule::startSlave(const long slaveNumber, char mode='s')
00375 throw(VmeException &) {
00376 const unsigned long dspint = 0x2;
00377
00378 if (mode == 'q') {
00379 slvHpiLoad(SLAVE_HPIC_BASE, dspint, slaveNumber);
00380 }
00381
00382 else {
00383 long primData[4]={slaveNumber, 1, 2, 0x200000};
00384 RodPrimitive * startSlaveExec;
00385 try {
00386 startSlaveExec = new RodPrimitive(8, 1, START_SLAVE_EXECUTING,
00387 R_START_SLAVE_EXECUTING, primData);
00388 }
00389 catch (std::bad_alloc & ba) {
00390 throw RodException(
00391 "startSlave unable to allocate startSlaveExec. slaveNumber:", slaveNumber);
00392 }
00393 synchSendPrim(*startSlaveExec);
00394 delete startSlaveExec;
00395 }
00396
00397 return;
00398 }
00399
00400
00401
00402
00403 void RodModule::synchSendPrim(RodPrimitive & prim) throw (RodException&,
00404 VmeException &) {
00405 RodPrimList primList(1);
00406 long myTextLength;
00407 TEXT_BUFFER_TYPE myTextType;
00408 PrimState returnPState;
00409 TextBuffState returnTState;
00410
00411
00412 char * myTextBuffer;
00413 try {
00414 myTextBuffer = new char[TEXT_BUFF_SIZE];
00415 }
00416 catch (std::bad_alloc & ba) {
00417 throw RodException(
00418 "synchSendPrim failed to allocate text. Size=", TEXT_BUFF_SIZE);
00419 }
00420 primList.insert(primList.begin(), prim);
00421 try {
00422 primList.bufferBuild();
00423 }
00424 catch (PrimListException &p) {
00425
00426 cout << p.getDescriptor() << " ";
00427 cout << p.getData1() << ", " << p.getData2() << "\n";
00428 };
00429 try {
00430 this->sendPrimList(&primList);
00431 }
00432 catch (HpiException &h) {
00433 hex(cout);
00434
00435 cout << h.getDescriptor() << '\n';
00436 cout << "calcAddr: " << h.getCalcAddr() << ", readAddr: " <<
00437 h.getReadAddr() << '\n';
00438 dec(cout);
00439 };
00440
00441
00442
00443
00444
00445 do {
00446 returnPState = this->primHandler();
00447 returnTState = this->textHandler();
00448 if (returnTState == TEXT_RQ_SET) {
00449 do {
00450 returnTState = this->textHandler();
00451 } while (returnTState != TEXT_READOUT);
00452 this->getTextBuffer(myTextBuffer, myTextLength, myTextType);
00453 this->clearTextBuffer();
00454 for (int i=0; i<myTextLength; i++) {
00455 cout << myTextBuffer[i];
00456 if (0==(i+1)%64) cout << endl;
00457 }
00458 cout << endl;
00459 }
00460 } while (returnPState != PRIM_EXECUTING);
00461 do {
00462 try {
00463 returnPState = this->primHandler();
00464 }
00465 catch (RodException &r) {
00466 cout << r.getDescriptor() <<", " << r.getData1() << ", " << r.getData2()
00467 << '\n';
00468 }
00469 } while (returnPState != PRIM_WAITING);
00470 delete myTextBuffer;
00471
00472 return;
00473 }
00474
00475
00476
00477 void RodModule::sendPrimList(RodPrimList *l) throw(VmeException &) {
00478
00479 unsigned long * buffAddr;
00480 long buffCount;
00481
00482 if (!l->getBuffer()) {
00483 l->bufferBuild();
00484 };
00485 buffCount = l->numWords();
00486 buffAddr = l->getBuffer();
00487 mdspBlockWrite(PRIM_BUFF_BASE, buffAddr, buffCount);
00488 m_myPrimState = PRIM_LOADED;
00489
00490 return;
00491 }
00492
00493
00494
00495 PrimState RodModule::primHandler() throw(RodException &, VmeException &) {
00496 long wordCount;
00497 unsigned long status;
00498 unsigned long* buffptr;
00499 unsigned long replyBuffer;
00500 switch (m_myPrimState) {
00501 case PRIM_LOADED: {
00502 if (0==getDspAck()) {
00503 setInListReady();
00504 m_myPrimState = PRIM_EXECUTING;
00505 };
00506 break;
00507 };
00508 case PRIM_EXECUTING: {
00509 status = readRodStatusReg(0);
00510 if (1==getDspAck()) {
00511 if (status >> TEXT_BUFF_NOT_EMPTY[0]) {
00512
00513 }
00514 if (1==readRodStatusBit(0,OUTLIST_READY)) {
00515
00516 hpiLoad(HPIA, REPLY_BUFF_BASE);
00517 wordCount = hpiFetch(HPID_NOAUTO);
00518
00519
00520 RodOutList* outList;
00521 try {
00522 outList = new RodOutList(wordCount);
00523 }
00524 catch (std::bad_alloc & ba) {
00525 throw RodException("Outlist creation failed. WordCount=",
00526 wordCount);
00527 }
00528 if (0==outList->getBody()) throw RodException(
00529 "Outlist failed to allocate body array.WordCount=", wordCount);
00530 this->setOutList(outList);
00531
00532
00533 buffptr = m_myOutList->getBody();
00534 replyBuffer = REPLY_BUFF_BASE;
00535 mdspBlockRead(replyBuffer, buffptr, wordCount);
00536 m_myPrimState = PRIM_WAITING;
00537
00538
00539 clearVmeCommandRegBit(INLISTRDY);
00540 }
00541 else m_myPrimState = PRIM_IDLE;
00542 }
00543 break;
00544 };
00545 default: {
00546 break;
00547 };
00548 };
00549 return m_myPrimState;
00550 };
00551
00552
00553
00554 void RodModule::deleteOutList() throw() {
00555 delete m_myOutList;
00556 m_myOutList = 0;
00557 return;
00558 };
00559
00560
00561
00562 TextBuffState RodModule::textHandler() throw(VmeException &) {
00563 unsigned long regValue;
00564 unsigned long dataPtr;
00565 long txtLength, txtLength1, txtLength2, txtWords;
00566 switch (m_myTextState) {
00567 case TEXT_IDLE: {
00568 regValue = readRodStatusReg(0) & SR_TEXT_MASK;
00569 if (0==regValue) return m_myTextState;
00570 for (long i=0; i<4; i++) {
00571 if (regValue & SR_TEXT_BIT_MASK[i]) {
00572 m_textType = (TEXT_BUFFER_TYPE)i;
00573 };
00574 setVmeCommandRegBit(TEXT_BUFF_READ_REQ[m_textType]);
00575 m_myTextState = TEXT_RQ_SET;
00576 return m_myTextState;
00577 }
00578 break;
00579 };
00580 case TEXT_RQ_SET: {
00581 if (0==readRodStatusReg(0) & SR_TEXT_BIT_MASK[m_textType]) {
00582 return m_myTextState;
00583 };
00584 hpiLoad( HPIA, (unsigned long)m_textBuff[m_textType]);
00585 m_txtBuffer.dataEnd = hpiFetch(HPID_AUTO);
00586 m_txtBuffer.readIndx = hpiFetch(HPID_AUTO);
00587 m_txtBuffer.writeIndx = hpiFetch(HPID_AUTO);
00588 m_txtBuffer.mode = hpiFetch(HPID_AUTO);
00589 m_txtBuffer.overwrite = hpiFetch(HPID_AUTO);
00590 m_txtBuffer.overflow = hpiFetch(HPID_AUTO);
00591 m_txtBuffer.wrap = hpiFetch(HPID_AUTO);
00592 m_txtBuffer.occupied = hpiFetch(HPID_AUTO);
00593 m_txtBuffer.data = (char *)hpiFetch(HPID_AUTO);
00594 dataPtr = (unsigned long)m_txtBuffer.data;
00595
00596
00597 if (m_txtBuffer.readIndx < m_txtBuffer.writeIndx) {
00598 txtLength = m_txtBuffer.writeIndx - m_txtBuffer.readIndx;
00599 txtWords = (txtLength+3)/4;
00600 mdspBlockRead(dataPtr, (unsigned long*)m_textData, txtWords);
00601 }
00602 else {
00603 txtLength1 = TEXT_BUFF_SIZE - m_txtBuffer.readIndx;
00604 txtWords = (txtLength1+3)/4;
00605 mdspBlockRead(dataPtr+4*m_txtBuffer.readIndx, (unsigned long*)m_textData, txtWords);
00606 txtLength2 = m_txtBuffer.writeIndx;
00607 txtWords = (txtLength2+3)/4;
00608 mdspBlockRead(dataPtr, (unsigned long*)(m_textData+4*txtLength1), txtWords);
00609 txtLength = txtLength1 + txtLength2;
00610 };
00611 m_myTextState = TEXT_READOUT;
00612 m_txtBuffer.occupied = txtLength;
00613 return m_myTextState;
00614 break;
00615 };
00616 default: {
00617 return m_myTextState;
00618 break;
00619 };
00620 };
00621
00622 return m_myTextState;
00623 };
00624
00625
00626
00627
00628 void RodModule::getTextBuffer(char * buffer, long & length,
00629 TEXT_BUFFER_TYPE & type) throw() {
00630 length = m_txtBuffer.occupied;
00631 type = (TEXT_BUFFER_TYPE)m_textType;
00632 for (int i=0; i<m_txtBuffer.occupied; i++) {
00633 buffer[i] = m_textData[i];
00634 };
00635 return;
00636 };
00637
00638
00639
00640 void RodModule::clearTextBuffer() throw() {
00641 m_textType = TEXT_UNDEF;
00642 m_txtBuffer.occupied = 0;
00643 m_myTextState = TEXT_IDLE;
00644 return;
00645 };
00646
00647
00648
00649 void RodModule::hpiLoad(unsigned long hpiReg, unsigned long hpiValue)
00650 throw(VmeException &) {
00651
00652 if (endianSwap) hpiValue = endianReverse32(hpiValue);
00653 m_myVmePort->write32(hpiReg, hpiValue);
00654 };
00655
00656
00657
00658 unsigned long RodModule::hpiFetch(unsigned long hpiReg)
00659 throw(VmeException &){
00660
00661 unsigned long hpiValue;
00662
00663 hpiValue=m_myVmePort->read32(hpiReg);
00664 if (endianSwap) hpiValue = endianReverse32(hpiValue);
00665
00666 return hpiValue;
00667 };
00668
00669
00670
00671 unsigned long RodModule::mdspSingleRead(const unsigned long dspAddr)
00672 throw(VmeException &) {
00673 unsigned long value;
00674
00675
00676 hpiLoad(HPIA, dspAddr);
00677
00678
00679 value = m_myVmePort->read32(HPID_NOAUTO);
00680 if (endianSwap) {
00681 value = endianReverse32(value);
00682 }
00683 return value;
00684 };
00685
00686
00687
00688 void RodModule::mdspSingleWrite(unsigned long dspAddr, unsigned long buffer)
00689 throw(VmeException &) {
00690
00691
00692 hpiLoad(HPIA, dspAddr);
00693
00694
00695 if (endianSwap) {
00696 buffer = endianReverse32(buffer);
00697 }
00698
00699 m_myVmePort->write32(HPID_NOAUTO, buffer);
00700
00701 return;
00702 };
00703
00704
00705
00706
00707 void RodModule::mdspBlockRead(const unsigned long dspAddr, unsigned long buffer[],
00708 const long wordCount, HpidMode mode=DYNAMIC) throw (HpiException &,
00709 VmeException &) {
00710 unsigned long hpidAddr;
00711 long myCount, blockWordCount, wordIncr;
00712
00713
00714 switch (mode) {
00715 case AUTO:
00716 hpidAddr= HPID_AUTO;
00717 break;
00718 case NO_AUTO:
00719 hpidAddr = HPID_NOAUTO;
00720 break;
00721 case DYNAMIC:
00722 default:
00723 if (wordCount == 1){
00724 hpidAddr = HPID_NOAUTO;
00725 }
00726 else {
00727 hpidAddr = HPID_AUTO;
00728 };
00729 break;
00730 };
00731
00732
00733 hpiLoad(HPIA, dspAddr);
00734
00735
00736
00737
00738 if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00739 blockWordCount = MAX_HPID_WORD_ELEMENTS;
00740 } else {
00741 blockWordCount = wordCount;
00742 }
00743
00744
00745 for (myCount=wordCount, wordIncr=0; myCount>0;
00746 myCount-=blockWordCount, wordIncr+=blockWordCount) {
00747
00748
00749 if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00750 blockWordCount=MAX_HPID_WORD_ELEMENTS;
00751 }
00752 else {
00753 blockWordCount = myCount;
00754 }
00755
00756
00757
00758
00759 for (int i=0; i<blockWordCount; i++) {
00760 buffer[2*wordIncr+i] = m_myVmePort->read32(hpidAddr);
00761 }
00762
00763 if (endianSwap) {
00764 for (int i=0; i<blockWordCount; i++) {
00765 buffer[2*wordIncr+i] = endianReverse32(buffer[2*wordIncr+i]);
00766 }
00767 }
00768 }
00769 return;
00770 };
00771
00772
00773
00774 void RodModule::mdspBlockWrite(unsigned long dspAddr, unsigned long buffer[],
00775 long wordCount, HpidMode mode=DYNAMIC) throw (HpiException &,
00776 VmeException &) {
00777
00778 unsigned long hpidAddr;
00779 long myCount, blockWordCount, wordIncr;
00780
00781
00782 hpiLoad(HPIA, dspAddr);
00783
00784
00785 switch (mode) {
00786 case AUTO:
00787 hpidAddr= HPID_AUTO;
00788 break;
00789 case NO_AUTO:
00790 hpidAddr = HPID_NOAUTO;
00791 break;
00792 case DYNAMIC:
00793 default:
00794 if (wordCount == 1){
00795 hpidAddr = HPID_NOAUTO;
00796 }
00797 else {
00798 hpidAddr = HPID_AUTO;
00799 };
00800 break;
00801 };
00802
00803
00804
00805
00806 if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00807 blockWordCount = MAX_HPID_WORD_ELEMENTS;
00808 }
00809 else {
00810 blockWordCount = wordCount;
00811 }
00812
00813
00814 for (myCount=wordCount, wordIncr=0; myCount>0;
00815 myCount-=blockWordCount, wordIncr+=blockWordCount) {
00816
00817
00818 if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00819 blockWordCount=MAX_HPID_WORD_ELEMENTS;
00820 }
00821 else {
00822 blockWordCount = myCount;
00823 }
00824
00825
00826 if (endianSwap) {
00827 for (int i=0; i<blockWordCount; i++) {
00828 buffer[2*wordIncr+i] = endianReverse32(buffer[2*wordIncr+i]);
00829 }
00830 }
00831
00832
00833
00834
00835
00836 for (int i=0; i<blockWordCount; i++) {
00837 m_myVmePort->write32(hpidAddr, buffer[2*wordIncr+i]);
00838 }
00839 }
00840 return;
00841 };
00842
00843
00844
00845 void RodModule::mdspBlockDump(const unsigned long firstAddress,
00846 const unsigned long lastAddress,
00847 const std::string & fileName) throw(RodException &, VmeException &) {
00848
00849 long numBytes;
00850 ofstream fout;
00851 numBytes = lastAddress - firstAddress + 1;
00852 fout.open(fileName.c_str(), ios::binary);
00853 if (fout.is_open()) {
00854 unsigned long * buffer;
00855 try {
00856 buffer = new unsigned long[numBytes];
00857 }
00858 catch (std::bad_alloc & ba) {
00859 throw RodException(
00860 "mdspBlockDump failed to allocate buffer; buffer size in bytes=", numBytes);
00861 }
00862 mdspBlockRead(firstAddress, buffer, numBytes/4);
00863 fout.write(buffer, numBytes);
00864 fout.close();
00865 delete [] buffer;
00866 }
00867 else {
00868 throw RodException("mdspBlockDump failed to open file");
00869 }
00870 return;
00871 }
00872
00873
00874
00875 void RodModule::slvHpiLoad(unsigned long hpiReg, unsigned long hpiValue,
00876 long slaveNum) throw(VmeException &) {
00877
00878 unsigned long address;
00879 address = hpiReg + slaveNum*SLAVE_HPI_OFFSET;
00880
00881 mdspSingleWrite(address, hpiValue);
00882 };
00883
00884
00885
00886 unsigned long RodModule::slvHpiFetch(unsigned long hpiReg, long slaveNum)
00887 throw(VmeException &) {
00888
00889 unsigned long hpiValue;
00890 unsigned long address;
00891 address = hpiReg + slaveNum*SLAVE_HPI_OFFSET;
00892
00893 hpiValue=mdspSingleRead(address);
00894
00895 return hpiValue;
00896 };
00897
00898
00899 unsigned long RodModule::slvSingleRead(unsigned long dspAddr, long slaveNum )
00900 throw(VmeException &) {
00901
00902 unsigned long slvHpia, slvHpid;
00903 unsigned long value;
00904 slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET;
00905 slvHpid = SLAVE_HPID_NOAUTO_BASE * slaveNum*SLAVE_HPI_OFFSET;
00906
00907
00908 mdspSingleWrite(slvHpia, dspAddr);
00909
00910
00911 value = mdspSingleRead(slvHpid);
00912
00913 return value;
00914 };
00915
00916
00917
00918 void RodModule::slvSingleWrite(unsigned long dspAddr, unsigned long buffer,
00919 long slaveNum) throw(VmeException &) {
00920
00921 unsigned long slvHpia, slvHpid;
00922 slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET;
00923 slvHpid = SLAVE_HPID_NOAUTO_BASE * slaveNum*SLAVE_HPI_OFFSET;
00924
00925 mdspSingleWrite(slvHpia, dspAddr);
00926
00927
00928 mdspSingleWrite(slvHpid, buffer);
00929
00930 return;
00931 };
00932
00933
00934
00935 void RodModule::slvBlockRead(const unsigned long dspAddr, unsigned long buffer[],
00936 const long wordCount, long slaveNum, HpidMode mode=DYNAMIC)
00937 throw (HpiException &, VmeException &) {
00938
00939 unsigned long hpidAddr, dspAddrLocal, hpiaAfterFetch, hpiaAfterCalc;
00940 long myCount, blockWordCount, wordIncr;
00941 unsigned long slvHpia, slvHpidAuto, slvHpidNoAuto;
00942 slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET;
00943 slvHpidAuto = SLAVE_HPID_AUTO_BASE + slaveNum*SLAVE_HPI_OFFSET;
00944 slvHpidNoAuto = SLAVE_HPID_NOAUTO_BASE + slaveNum*SLAVE_HPI_OFFSET;
00945
00946
00947
00948 switch (mode) {
00949 case AUTO:
00950 hpidAddr= slvHpidAuto;
00951 break;
00952 case NO_AUTO:
00953 hpidAddr = slvHpidNoAuto;
00954 break;
00955 case DYNAMIC:
00956 default:
00957 if (wordCount == 1){
00958 hpidAddr = slvHpidNoAuto;
00959 }
00960 else {
00961 hpidAddr = slvHpidAuto;
00962 };
00963 break;
00964 };
00965
00966
00967 mdspSingleWrite(slvHpia, dspAddr);
00968
00969
00970
00971
00972 if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00973 blockWordCount = MAX_HPID_WORD_ELEMENTS;
00974 } else {
00975 blockWordCount = wordCount;
00976 }
00977
00978
00979 for (myCount=wordCount, wordIncr=0; myCount>0;
00980 myCount-=blockWordCount, wordIncr+=blockWordCount) {
00981
00982
00983 if (wordCount>MAX_HPID_WORD_ELEMENTS) {
00984 blockWordCount=MAX_HPID_WORD_ELEMENTS;
00985 }
00986 else {
00987 blockWordCount = myCount;
00988 }
00989
00990
00991 dspAddrLocal = dspAddr+ (4*wordIncr);
00992 mdspBlockRead(hpidAddr, &buffer[2*wordIncr], blockWordCount, NO_AUTO);
00993 }
00994
00995
00996 hpiaAfterFetch = mdspSingleRead(slvHpia);
00997 if (wordCount == 1) {
00998 hpiaAfterCalc = dspAddr;
00999 } else {
01000 hpiaAfterCalc = dspAddr+wordCount*4;
01001 }
01002
01003
01004
01005
01006
01007 return;
01008 };
01009
01010
01011
01012 void RodModule::slvBlockWrite(unsigned long dspAddr, unsigned long buffer[],
01013 long wordCount, long slaveNum, HpidMode mode=DYNAMIC)
01014 throw (HpiException &, VmeException &) {
01015
01016 unsigned long hpidAddr, dspAddrLocal, hpiaAfterFetch, hpiaAfterCalc;
01017 long myCount, blockWordCount, wordIncr;
01018 unsigned long slvHpia, slvHpidAuto, slvHpidNoAuto;
01019 slvHpia = SLAVE_HPIA_BASE + slaveNum*SLAVE_HPI_OFFSET;
01020 slvHpidAuto = SLAVE_HPID_AUTO_BASE + slaveNum*SLAVE_HPI_OFFSET;
01021 slvHpidNoAuto = SLAVE_HPID_NOAUTO_BASE + slaveNum*SLAVE_HPI_OFFSET;
01022
01023
01024 mdspSingleWrite(slvHpia, dspAddr);
01025
01026
01027 switch (mode) {
01028 case AUTO:
01029 hpidAddr= slvHpidAuto;
01030 break;
01031 case NO_AUTO:
01032 hpidAddr = slvHpidNoAuto;
01033 break;
01034 case DYNAMIC:
01035 default:
01036 if (wordCount == 1){
01037 hpidAddr = slvHpidNoAuto;
01038 }
01039 else {
01040 hpidAddr = slvHpidAuto;
01041 };
01042 break;
01043 };
01044
01045
01046
01047
01048 if (wordCount>MAX_HPID_WORD_ELEMENTS) {
01049 blockWordCount = MAX_HPID_WORD_ELEMENTS;
01050 }
01051 else {
01052 blockWordCount = wordCount;
01053 }
01054
01055
01056 for (myCount=wordCount, wordIncr=0; myCount>0;
01057 myCount-=blockWordCount, wordIncr+=blockWordCount) {
01058
01059
01060 if (wordCount>MAX_HPID_WORD_ELEMENTS) {
01061 blockWordCount=MAX_HPID_WORD_ELEMENTS;
01062 }
01063 else {
01064 blockWordCount = myCount;
01065 }
01066
01067
01068 dspAddrLocal = dspAddr+ (4*wordIncr);
01069 mdspBlockWrite(hpidAddr, &buffer[2*wordIncr], blockWordCount, NO_AUTO);
01070 }
01071
01072
01073 hpiaAfterFetch = mdspSingleRead(slvHpia);
01074
01075 if (wordCount == 1) {
01076 hpiaAfterCalc = dspAddr;
01077 }
01078 else {
01079 hpiaAfterCalc = dspAddr+wordCount*4-4;
01080 }
01081
01082
01083
01084
01085
01086
01087 return;
01088 };
01089
01090
01091
01092 void RodModule::resetMasterDsp() throw(VmeException &) {
01093 unsigned long value=0;
01094 unsigned long rodRegValue;
01095
01096 rodRegValue = readRodStatusReg(0);
01097 setBit(&value, 1);
01098 if (endianSwap) {
01099 value = endianReverse32(value);
01100 }
01101 m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], value);
01102 sleep(1000);
01103 rodRegValue = readRodStatusReg(0);
01104
01105 return;
01106 };
01107
01108
01109
01110 void RodModule::resetSlaveDsp(long slaveNumber) throw(VmeException &) {
01111 unsigned long value=0;
01112
01113 setBit(&value, 2+slaveNumber);
01114 if (endianSwap) {
01115 value = endianReverse32(value);
01116 }
01117 m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], value);
01118 sleep(1000);
01119
01120 return;
01121 };
01122
01123
01124
01125
01126 void RodModule::resetAllDsps() throw(VmeException &) {
01127 unsigned long value=0;
01128
01129 setBit(&value, 6);
01130 if (endianSwap) {
01131 value = endianReverse32(value);
01132 }
01133 m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[2], value);
01134 sleep(1000);
01135
01136 return;
01137 };
01138
01139
01140
01141 void RodModule::chipEraseHpi() throw(VmeException &) {
01142 unsigned long value = 0x10;
01143
01144
01145 commonEraseCommandsHpi(MDSP_FLASH_BOTTOM);
01146
01147
01148 mdspSingleWrite(MDSP_FLASH_BOTTOM+(0x5555<<2), value);
01149
01150
01151 sleep(CHIP_ERASE_TIME_MS);
01152 return;
01153 };
01154
01155
01156
01157 void RodModule::sectorErase(unsigned long sectorBaseAddress)
01158 throw(RodException &, VmeException &) {
01159 unsigned long flashBaseAddress;
01160
01161
01162 if ((sectorBaseAddress<FPGA_FLASH_0_BOTTOM)||
01163 (sectorBaseAddress>FPGA_FLASH_2_BOTTOM+FLASH_MEMORY_SIZE)) {
01164 throw RodException("Flash sector base addr out of range, sectorBaseAddress=",
01165 sectorBaseAddress);
01166 }
01167 if (sectorBaseAddress<FPGA_FLASH_1_BOTTOM) {
01168 flashBaseAddress = FPGA_FLASH_1_BOTTOM;
01169 }
01170 else {
01171 flashBaseAddress = FPGA_FLASH_2_BOTTOM;
01172 }
01173
01174
01175 commonEraseCommands(flashBaseAddress);
01176
01177
01178 vmeWriteElementFlash(0x30, sectorBaseAddress, WRITE_COMMAND_HANDSHAKE_BIT);
01179
01180
01181 sleep(SECTOR_ERASE_TIME_MS);
01182
01183 return;
01184 };
01185
01186
01187
01188 void RodModule::writeByteToFlash(unsigned long address, UINT8 data)
01189 throw (RodException &, VmeException &) {
01190 UINT8 readData;
01191 clock_t startTime;
01192 long updateAddress;
01193
01194 if (data!=0xFF) {
01195
01196 vmeWriteElementFlash(data, address, WRITE_DATA_HANDSHAKE_BIT);
01197 updateAddress = 0;
01198 }
01199 else {
01200 updateAddress = 1;
01201 }
01202
01203
01204 startTime = clock();
01205 while(1) {
01206 readData = readByteFromFlash(address, updateAddress);
01207 if (readData == data) return;
01208 else if((clock()-startTime)*CLOCKS_PER_SEC > FLASH_TIMEOUT) {
01209 throw RodException("Flash timeout in writeByteToFlash, FLASH_TIMEOUT=",
01210 (long)FLASH_TIMEOUT);
01211 }
01212 }
01213 return;
01214 };
01215
01216
01217
01218 void RodModule::writeBlockToFlash(unsigned long address, UINT8 *data,
01219 unsigned long numBytes) throw(VmeException &) {
01220 unsigned long index;
01221 for (index=0; index<numBytes; ++index) {
01222 if ((index%FLASH_SECTOR_SIZE)==0) {
01223 sectorErase(address+index);
01224 }
01225 writeByteToFlash(address+index, *(data+index));
01226 }
01227 return;
01228 };
01229
01230
01231
01232 void RodModule::writeBlockToFlashHpi(unsigned long address, UINT8 *data,
01233 unsigned long numBytes) throw (RodException &, VmeException &) {
01234 unsigned long index, sectorAddr;
01235 const unsigned long eraseData=0x30;
01236 const unsigned long data1=0xAA;
01237 const unsigned long data2=0x55;
01238 const unsigned long data3=0xA0;
01239 const unsigned long addr1=MDSP_FLASH_BOTTOM+(0x5555<<2);
01240 const unsigned long addr2=MDSP_FLASH_BOTTOM+(0x2AAA<<2);
01241 unsigned long byteRelAddr;
01242 long words;
01243
01244 for (index=0; index<numBytes; ++index) {
01245 if ((index%FLASH_SECTOR_SIZE)==0) {
01246
01247
01248 commonEraseCommandsHpi(MDSP_FLASH_BOTTOM);
01249
01250 sectorAddr = MDSP_FLASH_BOTTOM+
01251 ((address+index-MDSP_FLASH_BOTTOM)<<2);
01252 mdspSingleWrite(sectorAddr, eraseData);
01253
01254 sleep(SECTOR_ERASE_TIME_MS);
01255 };
01256 };
01257
01258
01259 byteRelAddr = address+index-MDSP_FLASH_BOTTOM;
01260 if (*(data+index) !=0xFF) {
01261 mdspSingleWrite(addr1, (unsigned long)data1);
01262 mdspSingleWrite(addr2, (unsigned long)data2);
01263 mdspSingleWrite(addr1, (unsigned long)data3);
01264 mdspSingleWrite(MDSP_FLASH_BOTTOM+(byteRelAddr<<2),(unsigned long)(data+index));
01265 };
01266
01267
01268 words = (numBytes+3)/4;
01269 UINT8 *buffer;
01270 try {
01271 buffer = new UINT8[words*4];
01272 }
01273 catch (std::bad_alloc & ba) {
01274 throw RodException("writeBlockToFlashHpi unable to get buffer.");
01275 }
01276 m_myVmePort->blockRead32(address+index, (unsigned long*)buffer, words*4);
01277 for (index=0; index<numBytes; ++index) {
01278 if(*(data+index)!=*(buffer+index)) {
01279 delete [] buffer;
01280 throw RodException("writeBlockToFlashHpi verify failed. index, data:", index,
01281 *(data+index));
01282 };
01283 delete [] buffer;
01284 }
01285 return;
01286 };
01287
01288
01289
01290 UINT8 RodModule::readByteFromFlash(unsigned long address, long updateAddress)
01291 throw (RodException &, VmeException &){
01292 UINT8 dataByte;
01293 unsigned long commandReg;
01294 clock_t startTime;
01295 unsigned long handshakeBitValue = 0;
01296 unsigned long valueD32;
01297
01298 if (updateAddress) {
01299 m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[4], address);
01300 }
01301
01302 setBit(&handshakeBitValue, READ_HANDSHAKE_BIT);
01303 m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[3], handshakeBitValue);
01304
01305
01306 startTime = clock();
01307 while (1) {
01308 commandReg = m_myVmePort->read32(FPGA_CONTROL_REG_REL_ADDR[3]);
01309 if (0==readBit(commandReg, READ_HANDSHAKE_BIT)) break;
01310 if ((clock()-startTime)>FLASH_TIMEOUT) throw RodException(
01311 "Timeout in readByteFromFlash. Address=", address);
01312 }
01313
01314
01315 valueD32 = m_myVmePort->read32(FPGA_STATUS_REG_REL_ADDR[7]);
01316 dataByte = (UINT8)(valueD32&0xFF);
01317 return dataByte;
01318 };
01319
01320
01321
01322 void RodModule::vmeWriteElementFlash(UINT8 value, unsigned long address,
01323 long handshakeBit) throw (RodException &, VmeException &) {
01324 unsigned long ctrlReg4Val;
01325 unsigned long commandReg;
01326 clock_t startTime;
01327 unsigned long handshakeBitValue=0;
01328
01329 ctrlReg4Val = (value<<24)| address;
01330 m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[4], ctrlReg4Val);
01331
01332
01333 setBit(&handshakeBitValue, handshakeBit);
01334 m_myVmePort->write32(FPGA_CONTROL_REG_REL_ADDR[3], handshakeBitValue);
01335
01336
01337 startTime = clock();
01338 while(1) {
01339 commandReg = m_myVmePort->read32(FPGA_CONTROL_REG_REL_ADDR[3]);
01340 if (0==readBit(commandReg, handshakeBit)) break;
01341 if ((clock()-startTime)>FLASH_TIMEOUT) throw RodException(
01342 "Timeout in vmeWriteElementFlash. Address, value=",
01343 address, (unsigned long)value);
01344 }
01345 return;
01346 };
01347
01348
01349
01350 void RodModule::readBlockFromFlash(unsigned long address, UINT8 *buffer,
01351 unsigned long numBytes) throw(VmeException &) {
01352 unsigned long index;
01353 for (index=0; index<numBytes; ++index) {
01354 if (0==(index%FLASH_SECTOR_SIZE)) {
01355 readByteFromFlash(address+index, (long)(buffer+index));
01356 }
01357 }
01358 return;
01359 };
01360
01361
01362
01363 void RodModule::commonEraseCommands(unsigned long flashBaseAddr)
01364 throw(VmeException &) {
01365
01366 const unsigned long addr1 = flashBaseAddr+0x5555;
01367 const unsigned long addr2 = flashBaseAddr+0x2AAA;
01368
01369
01370 vmeWriteElementFlash(0xAA, addr1, WRITE_COMMAND_HANDSHAKE_BIT);
01371
01372
01373 vmeWriteElementFlash(0x55, addr2, WRITE_COMMAND_HANDSHAKE_BIT);
01374
01375
01376 vmeWriteElementFlash(0x80, addr1, WRITE_COMMAND_HANDSHAKE_BIT);
01377
01378
01379 vmeWriteElementFlash(0xAA, addr1, WRITE_COMMAND_HANDSHAKE_BIT);
01380
01381
01382 vmeWriteElementFlash(0x55, addr2, WRITE_COMMAND_HANDSHAKE_BIT);
01383
01384 return;
01385 };
01386
01387
01388
01389 void RodModule::commonEraseCommandsHpi(unsigned long flashBaseAddr)
01390 throw(VmeException &) {
01391
01392 unsigned long buffer;
01393 const unsigned long addr1 = flashBaseAddr+(0x5555<<2);
01394 const unsigned long addr2 = flashBaseAddr+(0x2AAA<<2);
01395
01396
01397 buffer = 0xAA;
01398 m_myVmePort->write32(addr1, buffer);
01399
01400
01401 buffer = 0x55;
01402 m_myVmePort->write32(addr2, buffer);
01403
01404
01405 buffer = 0x80;
01406 m_myVmePort->write32(addr1, buffer);
01407
01408
01409 buffer = 0xAA;
01410 m_myVmePort->write32(addr1, buffer);
01411
01412
01413 buffer = 0x55;
01414 m_myVmePort->write32(addr2, buffer);
01415
01416 return;
01417 };
01418
01419
01420
01421 void RodModule::sleep(const double milliSecs) {
01422 clock_t start, delay;
01423 delay = clock_t(milliSecs * CLOCKS_PER_SEC/1000.);
01424
01425 start = clock();
01426 while (clock()-start< delay)
01427 ;
01428 return;
01429 };
01430
01431
01432
01433 unsigned long RodModule::checkSum(const unsigned long *sourceArray, const long wordCount) {
01434 unsigned long result=0;
01435 long i;
01436
01437 for (i=0; i<wordCount; ++i) {
01438 result ^= sourceArray[i];
01439 }
01440 return result;
01441 };
01442
01443
01444
01445 unsigned long RodModule::endianReverse32(const unsigned long inVal) {
01446 unsigned long outVal;
01447 outVal = (inVal & 0x000000ff) << 24;
01448 outVal |= (inVal & 0x0000ff00) << 8;
01449 outVal |= (inVal & 0x00ff0000) >> 8;
01450 outVal |= (inVal & 0xff000000) >> 24;
01451 return outVal;
01452 };
01453
01454 }
01455
01456
01457
01458
01459 ostream& std::operator<<(ostream& os, SctPixelRod::RodModule& rod) {
01460 os << "Slot: " << rod.getSlot() << endl;
01461 os << "Serial Number:" << rod.getSerialNumber() << endl;
01462 os << "Number of slave DSPs: " << rod.getNumSlaves() << endl;
01463 os << "Status registers[0-2]: ";
01464 try {
01465 for (int i=0; i<3; i++) {
01466 os << hex << rod.readRodStatusReg(i) << " ";
01467 }
01468 os << endl;
01469 }
01470 catch (SctPixelRod::VmeException &) {
01471 os << "VmeException while reading ROD status registers. " << endl;
01472 }
01473
01474 os << "Command registers[0-1]: ";
01475 try {
01476 for (int i=0; i<2; i++) {
01477 os << hex << rod.readRodCommandReg(i) << " ";
01478 }
01479 os << endl;
01480 }
01481 catch (SctPixelRod::VmeException &) {
01482 os << "VmeException while reading ROD command registers. " << endl;
01483 }
01484
01485 os << "Primitive state: " << rod.getPrimState() << " Text State: " <<
01486 rod.getTextState() << endl;
01487 return os;
01488 }
01489
01490