00001 #!/usr/local/bin/python 00002 # 00003 # Copyright 2004 00004 # by 00005 # The Board of Trustees of the 00006 # Leland Stanford Junior University. 00007 # All rights reserved. 00008 # 00009 00010 __facility__ = "Online" 00011 __abstract__ = "GLAST LAT Coincidence based Trigger System Interface classes" 00012 __author__ = "Jim Panetta <panetta@slac.stanford.edu> SLAC - GLAST I&T" 00013 __date__ = "2/14/04" 00014 __version__ = "$Revision: 2.10 $" 00015 __release__ = "$Name: R04-12-00 $" 00016 __credits__ = "SLAC" 00017 00018 import LATTE.copyright_SLAC 00019 00020 00021 from TrgObject import TrgObject 00022 from TrgGemAbstract import TrgGemAbstract 00023 from TrgGemRegisterGeometry import AcdTileNumbering 00024 from TrgGemRegisterGeometry import RoiRegisterMap 00025 00026 """TrgGemRegisters: Register shape defintions for a GASU trigger system""" 00027 00028 00029 class TrgGemRegisters(TrgGemAbstract): 00030 """\brief TrgGemRegisters class definition 00031 00032 Implements the register shape definitions for a GASU trigger system 00033 """ 00034 ROI_REGISTER_MIN = 0 00035 ROI_REGISTER_MAX = 53 00036 TILE_REGISTER_MIN = 0 00037 TILE_REGISTER_MAX = 11 00038 TILE_REGISTER_SIZE = 9 00039 NULLENGINE = 0xe 00040 00041 def __init__(self): 00042 """\brief TrgGem constructor 00043 """ 00044 TrgGemAbstract.__init__(self) 00045 00046 # protected: 00047 def configurationRegister(self): 00048 """\brief configurationRegister() method 00049 00050 Method to construct the value of the GEM configuration register 00051 \return An integer 00052 """ 00053 # Configuration register format defined in LAT-01545-03: Sec 2.3.1 00054 conf = 0x0 00055 conf |= ( self.useAcdAsTrigger() ) << 0 00056 conf |= ( self.responseHeaderParityEven() ) << 1 00057 conf |= ( self.responseDataParityEven() ) << 2 00058 conf |= ( self.eventHeaderParityEven() ) << 3 00059 conf |= ( self.eventDataParityEven() ) << 4 00060 conf |= ( self.triggerParityEven() ) << 5 00061 conf |= ( self.inhibitContribution() ) << 6 00062 conf |= ( self.version() & 0xffffL ) << 16 # meaningless. Field is RO 00063 00064 return conf 00065 00066 def widthRegister(self): 00067 """\brief widthRegister method 00068 00069 \return integer 00070 00071 Returns a 32 bit integer corresponding to the WINDOW_WIDTH register 00072 of the GEM. Ref: LAT-TD-01545, S 2.9.1 00073 """ 00074 return (self.width() & 0x1f) 00075 00076 def periodicRateRegister(self): 00077 """\brief periodicRateRegister method 00078 00079 \return integer 00080 00081 Returns a 32 bit integer corresponding to the PERIODIC_RATE register 00082 of the GEM. Ref: LAT-TD-01545, S 2.3.3.1 00083 """ 00084 # prescale is 24 bits. 00085 rate = 0 00086 rate |= ( self.periodicCondition().definition().prescale() & 0xffffff ) 00087 rate |= ( self.periodicCondition().definition().source() & 0x1 ) << 31 00088 return rate 00089 00090 def periodicModeRegister(self): 00091 """\brief periodicModeRegister method 00092 00093 \return integer 00094 00095 Returns a 32 bit integer corresponding to the PERIODIC_MODE register 00096 of the GEM. Ref: LAT-TD-01545, S 2.3.3.2 00097 """ 00098 mode = 1 00099 if self.periodicCondition().definition().limit() != 0: 00100 mode = 0 00101 return mode 00102 00103 def periodicLimitRegister(self): 00104 """\brief periodicLimitRegister method 00105 00106 \return integer 00107 00108 Returns a 32 bit integer corresponding to the PERIODIC_LIMITS register 00109 of the GEM. Ref: LAT-TD-01545, S 2.3.3.3 00110 """ 00111 limit = 0 00112 limit |= ( self.periodicCondition().definition().limit() & 0xffffL ) 00113 return limit 00114 00115 def sequenceRegister(self): 00116 """\brief sequenceRegister method 00117 00118 \return integer 00119 00120 Returns a 32 bit integer corresponding to the SEQUENCE register 00121 of the GEM. Ref: LAT-TD-01545, S 2.3.4 00122 """ 00123 # yes, this is 17 bits... 00124 seq = 0 00125 seq |= ( self.sequence().definition().eventTag() & 0x3 ) 00126 seq |= ( self.sequence().definition().eventNumber() & 0x7fffL ) << 2 00127 return seq 00128 00129 def templateRegister(self, registerNumber): 00130 """\brief templateRegister method 00131 00132 \param registerNumber An registerNumber value 00133 \return integer 00134 00135 Returns a 32 bit integer corresponding to the message engine 00136 template register of the TAM. Ref: LAT-TD-01545, S 2.5 00137 Context portion is defined in 1.8.6.1 00138 """ 00139 # note: There is an exact correspondence between the engineNumber 00140 # and the registerNumber 00141 00142 if registerNumber < TrgObject.ENGINE_NUMBER_MIN or \ 00143 registerNumber > TrgObject.ENGINE_NUMBER_MAX: 00144 raise IndexError, "Register index out of bounds" 00145 eng = self.engines().engine(registerNumber) 00146 return self.__parseEngine(eng) 00147 00148 def __parseEngine(self, eng): 00149 presc = eng.prescale() 00150 if presc < 0: 00151 inhibit = 1 00152 presc = 0 00153 else: 00154 inhibit = 0 00155 00156 reg = 0 00157 reg |= ( presc & 0xff ) 00158 reg |= ( inhibit & 0x1 ) << 15 00159 00160 engReq = eng.request() 00161 calstr = ( engReq.sequence() & 0x2 ) >> 1 00162 tack = ( engReq.sequence() & 0x1 ) 00163 context = 0 00164 context |= ( calstr & 0x1 ) 00165 # 2 bits for tag 00166 context |= ( tack & 0x1 ) << 3 00167 context |= ( engReq.fourRange() & 0x1 ) << 4 00168 context |= ( engReq.zeroSuppress() & 0x1 ) << 5 00169 context |= ( engReq.marker() & 0x7 ) << 6 00170 context |= ( engReq.destination() & 0x3f ) << 9 00171 00172 reg |= ( context & 0xffffL ) << 16 00173 00174 return reg 00175 00176 def lookupTableRegister(self, registerNumber): 00177 """\brief lookupTableRegister method 00178 00179 \param registerNumber A reference into the Scheduler register set 00180 \return integer 00181 00182 Returns a 32 bit integer referencing the TAM generator used for a 00183 particular trigger summary 00184 Ref: LAT-TD-01545, S 2.7 00185 """ 00186 nReg = ( TrgObject.CONDITIONS_NUMBER_MAX + 1 ) / 8 00187 if registerNumber < 0 or registerNumber > nReg: 00188 raise IndexError, "Register index out of bounds" 00189 00190 reg = 0 00191 for contrib in range(8): 00192 reg |= ( self.__lutEntry(contrib + (registerNumber << 3)) << (contrib << 2L) ) 00193 return reg 00194 00195 def __lutEntry(self, conditionValue): 00196 engineSet = self.engines() 00197 for engineNumber in range(TrgObject.ENGINE_NUMBER_MAX+1): 00198 if engineSet.engine(engineNumber).participate(conditionValue): 00199 return engineNumber 00200 00201 return TrgGemRegisters.NULLENGINE # Condition value has no engine. Disable it. 00202 00203 def roiRegister(self, registerNumber): 00204 """\brief roiRegister method 00205 00206 \param registerNumber A reference into the ROI generator registers 00207 \return integer 00208 00209 Returns a 32 bit integer referencing the 54 ROI registers defined in 00210 Ref: LAT-TD-01545, S 2.8 00211 """ 00212 # two ways to define this register. 1) ACD is trigger (coincidence mode) 00213 # 2) ACD is veto (shadow mode) 00214 # The code is the same regardless of intent. :-) 00215 if registerNumber < TrgGemRegisters.ROI_REGISTER_MIN or \ 00216 registerNumber > TrgGemRegisters.ROI_REGISTER_MAX: 00217 raise IndexError, "Register index out of bounds" 00218 00219 reg = 0 00220 roiSet = self.roi() 00221 # RoiRegisterMap[n] returns ("name0","name1") 00222 # AcdTileNumbering["name"] returns tile number 00223 tile0 = AcdTileNumbering[ RoiRegisterMap[registerNumber][0] ] 00224 tile1 = AcdTileNumbering[ RoiRegisterMap[registerNumber][1] ] 00225 reg |= ( self.__roiValue(roiSet, tile0) & 0xffffL ) 00226 reg |= ( self.__roiValue(roiSet, tile1) & 0xffffL ) << 16 00227 return reg 00228 00229 def __roiValue(self, roiSet, tileNumber): 00230 """ constructs either: 00231 a) the set of 8 region pairs that define the 16 bits of coincidence info 00232 b) the tower mask information 00233 The code is the same regardless of intent. :-) 00234 00235 \param roiSet is passed to save function overhead. 00236 \param tileNumber As elsewhere 00237 c.f. figure 75, 76, 77, LAT-TD-01545 00238 """ 00239 pairSet = 0 00240 for region in range(TrgObject.ROI_NUMBER_MAX + 1): 00241 bit = roiSet.roi(region).tile(tileNumber) # tile returns 1 or 0 00242 pairSet |= (bit << region) 00243 return pairSet 00244 00245 def towerEnableRegister(self, registerNumber): 00246 """\brief towerEnableRegister method 00247 00248 \param registerNumber A reference into the tower enable registers 00249 \return integer 00250 00251 Returns a 32 bit object corresponding to figures 78/79 of the GEM 00252 documentation. This is used to construct the registers 00253 TOWERS_0_3, etc. 00254 Ref: LAT-TD-01545, 2.9.1 00255 """ 00256 # 4 towers/register 00257 nReg = ( TrgObject.TOWER_NUMBER_MAX + 1 ) / 4 00258 if registerNumber < 0 or registerNumber > nReg: 00259 raise IndexError, "Register index out of bounds" 00260 00261 reg = 0 00262 for twr in range(4): 00263 reg |= ( self.__tower3bit(twr + (registerNumber << 2)) << twr*3 ) 00264 return reg 00265 00266 def __tower3bit(self, towerIndex): 00267 if towerIndex < TrgObject.TOWER_NUMBER_MIN or \ 00268 towerIndex > TrgObject.TOWER_NUMBER_MAX: 00269 raise IndexError, "towerIndex out of bounds" 00270 00271 tower = self.inputEnables().towers().tower(towerIndex) 00272 twr = 0 00273 if tower is not None: 00274 twr |= ( tower.calorimeter().useLowEnergy() & 0x1 ) 00275 twr |= ( tower.calorimeter().useHighEnergy() & 0x1 ) << 1 00276 twr |= ( tower.tracker().use() & 0x1 ) << 2 00277 00278 return twr 00279 00280 def towerBusyEnableRegister(self): 00281 """\brief towerBusyEnableRegister method 00282 00283 \return integer 00284 00285 Returns a 32 bit integer corresponding to the Tower Busy enable register 00286 """ 00287 twrBusy = 0 00288 towerBusy = self.inputEnables().towerBusy() 00289 for tower in range(TrgObject.TOWER_NUMBER_MAX +1): 00290 # # Tower is ON if one or more of the inputs is enabled 00291 # if self.__tower3bit(tower) != 0: 00292 # twrBusy |= ( 1 << tower ) 00293 if towerBusy.tower(tower): 00294 twrBusy |= ( 1 << tower ) 00295 00296 return twrBusy 00297 00298 def externalEnableRegister(self): 00299 """\brief externalEnableRegister method 00300 00301 \return integer 00302 00303 Returns a 32 bit integer corresponding to the external enable register 00304 """ 00305 ext = 0 00306 if self.inputEnables().external().external(): 00307 ext = 0x1 00308 return ext 00309 00310 def cnoEnableRegister(self): 00311 """\brief cnoEnableRegister method 00312 00313 \return integer 00314 00315 Returns a 32 bit integer corresponding to the ACD CNO enable register 00316 Ref: LAT-TD-01545, 2.9.2 00317 """ 00318 00319 enab = self.inputEnables().cno() 00320 cno = 0 00321 cno |= ( enab.LA1() & 0x1 ) 00322 cno |= ( enab.RB1() & 0x1 ) << 1 00323 cno |= ( enab.LA2() & 0x1 ) << 2 00324 cno |= ( enab.LB2() & 0x1 ) << 3 00325 cno |= ( enab.RA2() & 0x1 ) << 4 00326 cno |= ( enab.RB2() & 0x1 ) << 5 00327 cno |= ( enab.LA3() & 0x1 ) << 6 00328 cno |= ( enab.RB3() & 0x1 ) << 7 00329 cno |= ( enab.LA4() & 0x1 ) << 8 00330 cno |= ( enab.LB4() & 0x1 ) << 9 00331 cno |= ( enab.RA4() & 0x1 ) << 10 00332 cno |= ( enab.RB4() & 0x1 ) << 11 00333 00334 return cno 00335 00336 def tileEnableRegister(self, registerNumber): 00337 """\brief tileEnableRegister method 00338 00339 \param registerNumber 00340 \return integer 00341 00342 Returns a 32 bit integer corresponding to the ACD tile enable register. 00343 Ref: LAT-TD-01545, 2.9.3 00344 """ 00345 # 108 'real' tiles, 9 tiles/register --> 12 registers 00346 if registerNumber < TrgGemRegisters.TILE_REGISTER_MIN or \ 00347 registerNumber > TrgGemRegisters.TILE_REGISTER_MAX: 00348 raise IndexError, "registerNumber out of bounds" 00349 00350 reg = 0 00351 00352 tto = self.inputEnables().tiles() 00353 for t in range(TrgGemRegisters.TILE_REGISTER_SIZE): 00354 tile = t + (TrgGemRegisters.TILE_REGISTER_SIZE) * registerNumber 00355 reg |= ( tto.tile(tile) & 0x1 ) << t 00356 reg |= ( tto.tile(tile) & 0x2 ) << (t+8) # using 1 bit offset here 00357 return reg 00358 00359 00360 # Pure virtual function implementation 00361 # Defaults from ACD Roadmap document 00362 def width(self): 00363 return 0x5 00364 00365 def responseHeaderParityEven(self): 00366 return False 00367 00368 def responseDataParityEven(self): 00369 return False 00370 00371 def eventHeaderParityEven(self): 00372 return False 00373 00374 def eventDataParityEven(self): 00375 return False 00376 00377 def triggerParityEven(self): 00378 return False 00379 00380 def inhibitContribution(self): 00381 return False 00382