Notes on Programming the SFI Sequencer RAM for FASTBUS Execution in a CODA Readout list --------------------------------------------------------------------------------------- -- David Abbott -- Jlab Data Acquisition Group -- June 1998 The Struck FASTBUS Interface Module (SFI) executes FASTBUS Functions through an on-board Sequencer. The existing library of FASTBUS standard routines provides an API for this sequencer, by sending it the appropiate instructions based on the users input for addressing, reading, writing, etc... As an alternative to "instructing the sequencer on the fly" for each FASTBUS routine, one can preprogram in Sequencer RAM the instructions one wishes to execute. Then the user has only to issue one instruction to the Sequencer, and that is the instruction to execute the "list" of instructions from RAM. The implication of using this feature in a CODA Readout list is that one can reduce the total execution time of the Primary Readout List by as much a 40% depending on the number of FASTBUS actions being performed. Below I describe what is necessary to implement SFI Sequencer RAM execution in a current CODA 2.0 Readout List. Step 1: Include in your Readout list a new routine responsible for programming the Sequencer RAM. This routine must be written in embedded C, but a number of Macros have been defined to facilitate the FASTBUS programming. /* SEQUENCER MACROS for RAM List Programming */ SFI_RAM_LOAD_ENABLE(a) Enable SFI to Load new RAM List at address a. Valid Addresses start at 256Byte Boundaries (i.e. 0x100, 0x200) SFI_RAM_LOAD_DISABLE Disable SFI Ram Loading and Re-enable Sequencer. SFI_LOAD_ADDR(a) Load SFI block transfer desination address (a). If a=0 then load current event buffer pointer. SFI_SET_OUT_REG(m) Set/Clear SFI outputs specified by m. These include SFI_CLEAR_OUT_REG(m) the NIM, ECL, LED, and TTL Front-Panel outputs. SFI_WAIT Idle loop necessary after FBEND Instruction. /* FASTBUS MACROS for RAM List Programming */ FBAC(p,s) Address Control: Primary Addr p, Secondary Addr s FBAD(p,s) Address Data: Primary Addr p, Secondary Addr s FBSAW(s) Secondary Address Write: Secondary Addr s FBWC(p,s,d) Address,Write,Relase to Control: Prim Addr p, Sec Addr s, Data d FBWD(p,s,d) Address,Write,Relase to Data: Prim Addr p, Sec Addr s, Data d FBR Read (Returns Data word to Sequencer FIFO) FBW(d) Write: Data d FBREL Release the Bus FBBR(c) Block Read (B32 VME, Clear Word Count): Count Limit c FBBRF(c) Block Read (B64 VME, Clear Word Count): Count Limit c FBBRNC(c) Block Read (B32 VME, NO Clear Word Count): Count Limit c FBBRNCF(c) Block Read (B65 VME, NO Clear Word Count): Count Limit c FBSWC Store Block Read Word Count (Returns Data word to Sequencer FIFO) FBEND End of RAM list Marker /* Example Readout List Routine*/ begin SFIRamLoad %% SFI_RAM_LOAD_ENABLE(RAM_ADDR); /* Setup Sequencer for RAM List Loading at RAM_ADDR */ /* Load the List */ FBWC(ADC_SLOT,0,0x400); /* Address ADC CSR0 Write 0x400 and release (Load Next Event) */ FBAD(ADC_SLOT,0); /* Address ADC DSR0 */ FBBR(100); /* Start Block Read (And Clear Word Counter) */ FBREL; /* Release the Bus */ FBWC(TDC1_SLOT,0,0x400); /* Address TDC CSR0 Write 0x400 and release (Load Next Event) */ FBAD(TDC1_SLOT,0); /* Address TDC DSR0 */ FBBRNC(100); /* Start Block Read (Don't clear word counter) */ FBREL; /* Release the Bus */ FBAD(TDC2_SLOT,0); /* Address TDC DSR0 */ FBBRNC(100); /* Start Block Read (Don't clear word counter) */ FBREL; /* Release the Bus */ FBSWC; /* Store Final Word Count in FIFO */ FBWC(TDC2_SLOT,0,0x800000); /* Address TDC CSR0 Write 0x800000 and Release (Increment Event Counter) */ FBEND; /* End of List */ SFI_WAIT; /* Wait a little */ SFI_RAM_LOAD_DISABLE; /* Re-enable Sequencer */ %% end SFIRamLoad Step 2: Call your SFI RAM Programming routine at Download or Prestart. The RAM programming will stay there until a SFI power cycle or SFI/VME Reset. Example: begin Prestart ... #Program SFI Sequencer Ram SFIRamLoad(); ... end Prestart Step 3: In the "trigger" routine replace the multiple FASTBUS actions/functions with a single Sequencer API routine fpram(). unsigned long fpram(ramAddr,nRet,rData) (Execute SFI Sequencer RAM loaded List) unsigned long ramAddr; Start Address in Seq. RAM of List (On 256 Byte boundary) int nRet; Number of Return data words generated from List (not BR data) unsigned long *rData; Pointer to Return words (not BR data) fpram() returns 0 if successful otherwise it returns a Sequencer error code. The user MUST be aware of the number of return (from FIFO) words he expects from his list (nRet). This does NOT include Block Read data, only single cycle read data, and Block Read Word Counts. The user must pass this count as well as a pointer to an array to store this data in the call to fpram(). If the User is doing a Block Read in his RAM list then Address location at which to store the BR data must be passed (via SFI_ADDR_LOAD) to the SFI prior to the fpram() call. Example: begin trigger user_trig variable wc ... %% SFI_LOAD_ADDR(0); fbres = fpram(RAM_ADDR,1,&wc); if(fbres) { *rol->dabufp++ = 0xfb000bad; *rol->dabufp++ = fbres; *rol->dabufp++ = wc; }else{ rol->dabufp += (wc&0x00ffffff); } %% ... end trigger NOTE: Several files/Libraries have been updated to support this feature. Readout lists must be updated and recompiled, and the new FASTBUS library must be downloaded to vxWorks SBCs for changes to take effect. Header files: (Replace in $CODA/common/include) SFI_source.h: Updated to include new headers sfi_fb_macros.h: New file with Macros to support RAM programming sfi.h Updated to include new global pointers Library: (Replace in $CODA/VXWORKSXXX/lib) libsfifb.o Updated to include fpram() routine.