unit jtag.vme; interface uses jtag.types, Classes; const VME_VERSION_NUMBER = '12.1'; // // Maximum declarations // VMEHEXMAX = 60000; // The hex file is split 60k per file SCANMAX = 64000; // The maximum SDR/SIR burst // // Supported JTAG state transitions // type TJTAGTransition = packed record CurrState : TJTAGState; // Transition from this state. NextState : TJTAGState; // Transition to this state. Pattern : byte; // The targetory of TMS Pulses : byte; // The number of steps. end; // // Flow control register nit definitions. A set bit indicates // that the register currently exhibits the corresponding mode. // TFlowControlBit = ( fcbIntelPrgm, // Intelligent programming is in effect. fcbCascade, // Currently splitting large SDR. fcbRepeatLoop, // Currently executing a repeat loop. fcbShiftRight, // The next data stream needs a right shift. fcbShiftLeft, // The next data stream needs a right left. fcbVerifyUES // Continue if fail is in effect. ); TFlowControl = set of TFlowControlBit; // // DataType register bit definitions. A set bit indicates that the // register currently holds the corresponding type of data. // TDataTypeBit = ( dtExpress, // Simultaneous program and verify. dtCompress, // Data is compressed dtSIRData, // SIR is the active SVF command. dtSDRData, // SDR is the active SVF command. dtTDIData, // TDI data is present. dtTDOData, // TDO data is present. dtMASKData, // MASK data is present. dtCRCData, // CRC data is present. dtHeap, // Data is from the heap. dtLHeap, // Data is from intel data buffer. dtVariable, // Data is from a declared variable. dtCMASKData, // CMASK data is present. dtDMASKData, // DMASK data is present. dtRMASKData, // RMASK data is present, dtREADData // READ data is present. ); TDataType = set of TDataTypeBit; TVendor = ( vLattice = 1, vAltera = 2, vXilinx = 3 ); // // Opcode definitions // TOpcode = ( opEndData = $00, // The end of the current SDR data stream. opRunTest = $01, // The duration to stay at the stable state. opEndDR = $02, // The stable state after SDR. opEndIR = $03, // The stable state after SIR. opEndState = $04, // The stable state after RUNTEST. opTRST = $05, // Assert the TRST pin. opHIR = $06, // The sum of the IR bits of the leading devices. opTIR = $07, // The sum of the IR bits of the trailing devices. opHDR = $08, // The number of leading devices. opTDR = $09, // The number of trailing devices. opIspEN = $0a, // Assert the ispEN pin. opFrequency = $0b, // The maximum clock rate to run the JTAG state machine. opState = $10, // Move to the next stable(?) state. opSIR = $11, // The instruction stream follows. opSDR = $12, // The data stream follows. opTDI = $13, // The following data stream feeds into device. opTDO = $14, // The following data stream is compared against the device. opMASK = $15, // The following data stream is used as a mask. opXSDR = $16, // The following data stream is for simultaneous program and verify. opXTDI = $17, // The following data stream is for shift in only. It must be stored // for the next XSDR. opXTDO = $18, // There is no data stream. The data stream was stored from the // previous XTDI. opMEM = $19, // The maximum memory needed to allocate in order to hold one row of data. opWAIT = $1A, // The duration of delay to observe. opTCK = $1B, // The number of TCK pulses. opSEC = $1C, // The delay time in seconds that must be observed. opSMASK = $1D, // The mask for TDI data. opMAX = $1E, // The absolute maximum wait time. opON = $1F, // Assert the targeted pin. opOFF = $20, // Deassert the targeted pin. opSHR = $23, // Set the flow control register for right shift. opSHL = $24, // Set the flow control register for left shift. opSetFlow = $30, // Change the flow control register. opResetFlow = $31, // Clear the flow control register. opHEAP = $32, // The memory size needed to hold one loop. opREPEAT = $33, // The beginning of the loop. opLeftParen = $35, // The beginning of data following the loop. opVAR = $55, // Placeholder for loop data. opCRC = $47, // The following data stream is used for CRC calculation. opCMask = $48, // The following data steram is used as a mask for CRC calculation. opRMask = $49, // The following data stream is used as a mask for read and save. opREAD = $50, // The following data stream is used for read and save. opVendor = $56, // Vendor code. opENDLOOP = $59, // The end of the repeat loop. opSecureHeap= $60, // Used to secure the HEAP opcode. opVUES = $61, // Support continue if fail. opDMask = $62, // The following data stream is used for dynamic I/O. opComment = $63, // Support SVF comments in the VME file. opHeader = $64, // Support header in VME file. opFileCRC = $65, // Support crc-protected VME file. opLCount = $66, // Support intelligent programming. opLDelay = $67, // Support intelligent programming. opLSDR = $68, // Support intelligent programming. opLHeap = $69, // Memory needed to hold intelligent data buffer. opContinue = $70, // Allow continuation. opLVDS = $71, // Support LVDS. opEndVME = $7F, // End of the VME file. opEndFile = $FF // End of file. ); TReturnCode = ( VME_OK = 0, VME_VerificationFailure = -1, VME_FileReadFailure = -2, VME_VersionFailure = -3, VME_InvalidFile = -4, VME_ArgumentFailure = -5, VME_CRCFailure = -5 ); TLVDSPair = packed record PositiveIndex : word; NegativeIndex : word; Update : boolean; end; type TispVM = class; TPin = (pinTCK,pinTMS,pinTDI,pinTDO,pinTRST,pinENA); TTransferMode = (tmNone, tmRead, tmWrite); TTransferEvent = procedure( Sender : TispVM; Mode : TTransferMode) of object; TispVM = class protected fJtag : IJTAG; protected fOnTransfer : TTransferEvent; fTransferMode : TTransferMode; protected fBufTDI : array [0 .. 1023] of byte; // data to send to device fBufTDO : array [0 .. 1023] of byte; // data received from device fBufSMASK : array [0 .. 1023] of byte; fBufMASK : array [0 .. 1023] of byte; fBuffer : array [0 .. 1023] of byte; fBufferSize : integer; fBufferIndex : integer; fMaskTCK : byte; fMaskTMS : byte; fMaskTDI : byte; fMaskTDO : byte; fMaskTRST : byte; fMaskENA : byte; fMaskPWR : byte; fValTMS : boolean; fValTDI : boolean; fValTDO : boolean; fValTRST : boolean; fValENA : boolean; fInitDone : boolean; private function GetData(i: word): byte; procedure SetData(i: word; d: byte); protected procedure Init( BufferSize : word; TCK : byte; TMS : byte; TDI : byte; TDO : byte; TRST : byte; ENA : byte; PWR : byte); procedure SetPin( pin: TPin; Value: byte); procedure Flush; public procedure InitDsoJtag; // prepare for DSO procedure InitPrgJtag; // prepare for JTAG programmer protected fFlowControl : TFlowControl; // Flow control register. fDataType : TDataType; // Data type of the current row. fEndDR : TJTAGState; // The state that the device goes after SDR. fEndIR : TJTAGState; // The state that the device goes after SIR. fHeadDR : word; // The number of lead devices in bypass. fHeadIR : word; // The sum of IR length of lead devices. fTailDR : word; // The number of tail devices in bypass. fTailIR : word; // The sum of IR length of tail devices. fDataSize : word; // The number of bits of data or instruction // to be shifted into or out from the device. fFrequency : word; // The TCK frequency in MHz. fMaxSize : word; // The maximum amount of data needed to hold a row of data. fShiftValue : word; // Stores the LSH or RSH value. fRepeatLoops : word; // Stores the current repeat loop value. fVendor : TVendor; // Stores the current vendor. fCalculatedCRC : word; // Stores the VME file CRC. fCheckSum : cardinal; // Stores the device checksum. fCheckSumIndex : integer; fCurrentJTAGState : TJTAGState; // Stores the current state of the JTAG state machine. // // looping support // fHeapMemory : PByte; // Holds the entire repeat loop. fHeapCounter : word; // Points to the current byte in the repeat loop. fHeapSize : word; // The current size of the repeat loop in bytes. // // intelligent programming support // fIntelDataIndex : word; // Points to the current byte of the intelligent buffer. fIntelBufferSize : word; // Holds the size of the intelligent buffer. // // The maximum size of each respective buffer. These variables are used to write // the HEX files when converting VME to HEX. // fTDOSize : word; fMASKSize : word; fTDISize : word; fDMASKSize : word; fLCOUNTSize : word; fHDRSize : word; fTDRSize : word; fHIRSize : word; fTIRSize : word; fHeapBufferSize : word; // // Variables used to store data // fOutMaskData : PByte; fOutDMaskData : PByte; fInData : PByte; fOutData : PByte; fHIRData : PByte; fTIRData : PByte; fHDRData : PByte; fTDRData : PByte; fIntelBuffer : PByte; // // List to hold all LVDS pairs. // // LVDSPair * ... // count fLVDs : array of TLVDSPair; fStream : TStream; private function GetByte: byte; procedure sclock(n:integer=1); protected function ispVMCode: TReturnCode; function ispVMAmble( OpCode: TOpcode): TReturnCode; function ispVMShift( OpCode: TOpcode): TReturnCode; function ispVMDataSize: word; procedure ispVMDelay( Delay: word); procedure ispVMClocks( Count: word); function ispVMLoop( LoopCount: word): TReturnCode; function ispVMLCount( CountSize: word): TReturnCode; procedure ispVMStateMachine( NextState: TJTAGState); procedure ispVMComment( Size: word); function ispVMProcessLVDS( Count: word):TReturnCode; procedure ispVMHeader( Size: word); function ispVMDataCode: TReturnCode; procedure ispVMData( Data: PByte); function ispVMBitShift( OpCode: TOpCode; Count: word): TReturnCode; procedure ispVMBypass( ScanType: TOpCode; Count: word); function ispVMSend( Count: word): TReturnCode; function ispVMRead( Count: word): TReturnCode; function ispVMReadAndSave( Count: word): TReturnCode; procedure ispVMStart; procedure ispVMEnd; procedure ispVMMemManager( Target: TOpCode; Size: word); public function ispVM( Stream: TStream): TReturnCode; public procedure AfterConstruction; override; public property DataSize: integer read fBufferIndex; property Data[i: word]: byte read GetData write SetData; property JTAG : IJTAG read fJtag write fJtag; property OnTransfer : TTransferEvent read fOnTransfer write fOnTransfer; end; implementation uses Windows, jtag.vme.tools; const JTAGTransitions : array [0..24] of TJTAGTransition = ( ( CurrState : RESET; NextState : RESET; Pattern : $FC; Pulses : 6), ( CurrState : RESET; NextState : IDLE; Pattern : $00; Pulses : 1), ( CurrState : RESET; NextState : DRPAUSE; Pattern : $50; Pulses : 5), ( CurrState : RESET; NextState : IRPAUSE; Pattern : $68; Pulses : 6), ( CurrState : IDLE; NextState : RESET; Pattern : $E0; Pulses : 3), ( CurrState : IDLE; NextState : DRPAUSE; Pattern : $A0; Pulses : 4), ( CurrState : IDLE; NextState : IRPAUSE; Pattern : $D0; Pulses : 5), ( CurrState : IDLE; NextState : DRCAPTURE; Pattern : $80; Pulses : 2), ( CurrState : DRPAUSE; NextState : RESET; Pattern : $F8; Pulses : 5), ( CurrState : DRPAUSE; NextState : IDLE; Pattern : $C0; Pulses : 3), ( CurrState : DRPAUSE; NextState : IRPAUSE; Pattern : $F4; Pulses : 7), ( CurrState : DRPAUSE; NextState : DRPAUSE; Pattern : $E8; Pulses : 6), ( CurrState : DRPAUSE; NextState : DRSHIFT; Pattern : $80; Pulses : 2), ( CurrState : DRPAUSE; NextState : DRCAPTURE; Pattern : $E0; Pulses : 4), ( CurrState : IRPAUSE; NextState : RESET; Pattern : $F8; Pulses : 5), ( CurrState : IRPAUSE; NextState : IDLE; Pattern : $C0; Pulses : 3), ( CurrState : IRPAUSE; NextState : DRPAUSE; Pattern : $E8; Pulses : 6), ( CurrState : IRPAUSE; NextState : DRSHIFT; Pattern : $E0; Pulses : 5), ( CurrState : IRPAUSE; NextState : IRSHIFT; Pattern : $80; Pulses : 2), ( CurrState : IRPAUSE; NextState : DRCAPTURE; Pattern : $E0; Pulses : 4), ( CurrState : DRSHIFT; NextState : IDLE; Pattern : $C0; Pulses : 3), ( CurrState : DRSHIFT; NextState : DRPAUSE; Pattern : $80; Pulses : 2), ( CurrState : IRSHIFT; NextState : IDLE; Pattern : $C0; Pulses : 3), ( CurrState : IRSHIFT; NextState : IRPAUSE; Pattern : $80; Pulses : 2), ( CurrState : DRCAPTURE; NextState : DRPAUSE; Pattern : $80; Pulses : 2) ); var idx : integer; data : array [0..3] of byte; { TvmeProgram } // ================================================================================================ // After Construction // ================================================================================================ procedure TispVM.AfterConstruction; var x: array [0..20] of byte; begin inherited; fEndDR := DRPAUSE; fEndIR := IRPAUSE; fFrequency := 1000; end; // ================================================================================================ // Init // ================================================================================================ procedure TispVM.Init( BufferSize : word; TCK : byte; TMS : byte; TDI : byte; TDO : byte; TRST : byte; ENA : byte; PWR : byte); begin fBufferSize := 504; // if (BufferSize <> 1024) and (BufferSize <> 512) // then fBufferSize := 1024 // else fBufferSize := BufferSize; if TCK <> $FF then fMaskTCK := 1 shl TCK else fMaskTCK := 0; if TMS <> $FF then fMaskTMS := 1 shl TMS else fMaskTMS := 0; if TDI <> $FF then fMaskTDI := 1 shl TDI else fMaskTDI := 0; if TDO <> $FF then fMaskTDO := 1 shl TDO else fMaskTDO := 0; if TRST <> $FF then fMaskTRST := 1 shl TRST else fMaskTRST := 0; if ENA <> $FF then fMaskENA := 1 shl ENA else fMaskENA := 0; if PWR <> $FF then fMaskPWR := 1 shl PWR else fMaskPWR := 0; fInitDone := true; end; // ================================================================================================ // InitDsoJtag // ================================================================================================ procedure TispVM.InitDsoJtag; begin Init(256, 0, 1, 3, 7, $FF, $FF, $FF); end; // ================================================================================================ // InitPrgJtag // ================================================================================================ procedure TispVM.InitPrgJtag; begin Init(256, 0, 1, 7, 3, 5, 4, 6); end; // ================================================================================================ // Get Data // ================================================================================================ function TispVM.GetData(i: word): byte; begin if i < fBufferSize then result := fBuffer[i] else result := 0; end; // ================================================================================================ // Set Data // ================================================================================================ procedure TispVM.SetData(i: word; d: byte); begin if i < fBufferSize then fBuffer[i] := d end; // ================================================================================================ // Load // ================================================================================================ function TispVM.ispVM(Stream: TStream): TReturnCode; var i : integer; b : byte; s : AnsiString; begin if Assigned(Stream) then begin fStream := Stream; fStream.Seek(0, soFromBeginning); b := GetByte; case TOpCode(b) of opFileCRC: begin // ---------------------------------------------- // Read and store the expected CRC to do the // comparison at the end. Only versions 3.0 and // higher support CRC protection. // ---------------------------------------------- fCheckSum := GetByte shl 8; fCheckSum := fCheckSum + GetByte; // ---------------------------------------------- // Read and store the version of the VME file. // Must be version 2.0. // ---------------------------------------------- for i:=0 to 7 do s := s + AnsiChar(GetByte); end; else begin // ------------------------------------------------- // Read and store the version of the VME file. // Must be version 2.0. // ------------------------------------------------- s := AnsiChar(b); for i:=1 to 7 do s := s + AnsiChar(GetByte); end; end; // ------------------------------------------------------------ // Compare the VME file version against the supported version. // ------------------------------------------------------------ result := VME_VersionFailure; if s = '__VME2.0' then result := VME_OK; if s = '__VME3.0' then result := VME_OK; if s = '____12.0' then result := VME_OK; if s = '____12.1' then result := VME_OK; if result <> VME_OK then exit; // ------------------------------------------------------------ // Enable the JTAG port to communicate with the deevice. // Set the JTAG state machine to the RESET state. // ------------------------------------------------------------ ispVMStart; // ------------------------------------------------------------ // Process the VME file. // ------------------------------------------------------------ result := ispVMCode; // ------------------------------------------------------------ // Set the JTAG state machine to RESET state then disable the // the communication with the JTAG port. // ------------------------------------------------------------ ispVMEnd end end; // ================================================================================================ // Get Byte // // Returns a byte to the caller. The returned byte depends on the DataType register. // If the HEAP_IN bit is set, then the byte is returned from the HEAP. // If the LHEAP_IN bit is set, then the byte is returned from the intelligent buffer. // Otherwise, the byte is returned directly from the VME file. // ================================================================================================ function TispVM.GetByte: byte; begin result := 0; if dtHeap in fDataType then begin if fHeapCounter > fHeapSize then result := $FF else begin result := fHeapMemory[fHeapCounter]; INC(fHeapCounter) end; end else if dtLHeap in fDataType then begin if fIntelDataIndex >= fIntelBufferSize then result := $FF else begin result := fIntelBuffer[fIntelDataIndex]; INC(fIntelDataIndex); end; end else begin if Assigned(fStream) then if fStream.Read(result,1) <> 1 then result := $FF end; end; // ================================================================================================ // ispVMCode // // This is the heart of the embedded engine. All the high-level opcodes are extracted here. // Once they have been identified, then it will call other functions to handle the processing. // ================================================================================================ function TispVM.ispVMCode: TReturnCode; var RepeatSize : word; OpCode : TOpcode; State : TJTAGState; Delay : word; Toggle : word; Data : byte; FlowControl : TFlowControl; begin RepeatSize := 0; OpCode := opEndData; result := VME_OK; State := RESET; Delay := 0; Toggle := 0; Data := 0; // --------------------------------------------------------------- // Check the compression flag only if this is the first time // this function is entered. Do not check the compression flag if // it is being called recursively from other functions within // the embedded engine. // --------------------------------------------------------------- if not (dtHeap in fDataType) and not (dtLHeap in fDataType) then begin Data := GetByte; if Data = $F1 then Include( fDataType, dtCompress) else if Data = $F2 then Exclude( fDataType, dtCompress) else begin result := VME_InvalidFile; exit end end; // --------------------------------------------------------------- // Loop through all the VME opcodes. // --------------------------------------------------------------- OpCode := TOpCode(GetByte); while OpCode <> opEndData do begin case OpCode of // -------------------------------------------- // opSTATE // -------------------------------------------- opState: begin State := TJTAGState( GetByte); if Assigned(fJtag) then fJtag.state(State); if (dtLHeap in fDataType) and (State = DRPAUSE) and (fCurrentJTAGState = State) then if Assigned(fJtag) then fJtag.state(DRCAPTURE); ispVMStateMachine(State); end; // -------------------------------------------- // SIR,SDR,XSDR // Shift data into the device. // -------------------------------------------- opSIR,opSDR,opXSDR: begin result := ispVMShift(OpCode); if result <> VME_OK then break; end; // -------------------------------------------- // WAIT // Observe delay. // -------------------------------------------- opWAIT: begin Delay := ispVMDataSize; ispVMDelay(Delay); end; // -------------------------------------------- // TCK // Issue clock toggles. // -------------------------------------------- opTCK: begin Toggle := ispVMDataSize; ispVMClocks(Toggle); end; // -------------------------------------------- // ENDDR,ENDIR // Set the ENDDR,ENDIR // -------------------------------------------- opEndDR: fEndDR := TJTAGState( GetByte); opEndIR: fEndIR := TJTAGState( GetByte); // -------------------------------------------- // HIR,TIR,HDR,TDR // -------------------------------------------- opHIR,opTIR,opHDR,opTDR: begin result := ispVMAmble( OpCode); if result <> VME_OK then break; end; // -------------------------------------------- // MEM // -------------------------------------------- opMEM: begin //OutputDebugString('opMEM'); fMaxSize := ispVMDataSize; end; // -------------------------------------------- // Vendor // -------------------------------------------- opVendor: begin //OutputDebugString('opVendor'); fVendor := TVendor( GetByte); end; // -------------------------------------------- // SETFLOW // Set the flow control. // Flow control determines the personality of // the embedded engine. // // TODO: check this! // -------------------------------------------- opSetFlow: begin OutputDebugString('opSetFlow'); // fFlowControl := fFlowControl + TFlowControl(GetByte); end; opResetFlow: begin OutputDebugString('opResetFlow'); // fFlowControl := fFlowControl + TFlowControl(GetByte); end; // -------------------------------------------- // HEAP // Allocate heap to store loops // -------------------------------------------- opHEAP: begin //OutputDebugString('opHEAP'); OpCode := TOpCode(GetByte); if OpCode <> opSecureHeap then break; fHeapSize := ispVMDataSize; ispVMMemManager( opHEAP, fHeapSize); end; // -------------------------------------------- // REPEAT // -------------------------------------------- opREPEAT: begin //OutputDebugString('opREPEAT'); fRepeatLoops := 0; result := ispVMLoop( ispVMDataSize); if result <> VME_OK then break; end; opENDLOOP: exit; opEndVME : exit; // -------------------------------------------- // SHR,SHL // Right-shift/Left-shift address. // -------------------------------------------- opSHR: begin //OutputDebugString('opSHR'); Include( fFlowControl, fcbShiftRight); fShiftValue := fRepeatLoops * GetByte; end; opSHL: begin //OutputDebugString('opSHL'); Include( fFlowControl, fcbShiftLeft); fShiftValue := fRepeatLoops * GetByte; end; // -------------------------------------------- // FREQUENCY // -------------------------------------------- opFrequency: begin //OutputDebugString('opFREQUENCY'); fFrequency := ispVMDataSize; if fFrequency >= 1000 then begin fFrequency := fFrequency div 1000; if fFrequency = 1 then fFrequency := 1000 end else begin if fFrequency = 0 then fFrequency := 1000 end; end; // -------------------------------------------- // LCOUNT // -------------------------------------------- opLCount: begin //OutputDebugString('opLCOUNT'); result := ispVMLCount( ispVMDataSize); if result <> VME_OK then break end; // -------------------------------------------- // VUES // -------------------------------------------- opVUES: begin //OutputDebugString('opVUES'); Include(FlowControl,fcbVerifyUES); end; // -------------------------------------------- // COMMENT // -------------------------------------------- opComment: begin //OutputDebugString('opCOMMENT'); ispVMComment( ispVMDataSize); end; // -------------------------------------------- // LVDS // -------------------------------------------- opLVDS: begin //OutputDebugString('opLVDS'); ispVMProcessLVDS( ispVMDataSize); end; // -------------------------------------------- // HEADER // -------------------------------------------- opHeader: begin //OutputDebugString('opHEADER'); ispVMHeader( ispVMDataSize); end; // -------------------------------------------- // ispEN // -------------------------------------------- opIspEN: begin OpCode := TOpCode(GetByte); case OpCode of opON : SetPin(pinENA, 1); opOFF : SetPin(pinENA, 0); end; end; // -------------------------------------------- // TRST // -------------------------------------------- opTRST: begin OpCode := TOpCode(GetByte); case OpCode of opON : SetPin(pinTRST, 1); opOFF : SetPin(pinTRST, 0); end; end; else result := VME_InvalidFile end; OpCode := TOpCode(GetByte); end; // // Invalid exit point. // Processing token 'ENDVME' is the only valid // way to exit the embedded engine. // result := VME_InvalidFile; end; // ================================================================================================ // ispVMDataSize // // Returns a VME-encoded number, ususally used to indicate the bitlength of an SIR/SDR command. // ================================================================================================ function TispVM.ispVMDataSize: word; var curr : byte; idx : byte; begin result := 0; idx := 0; curr := GetByte; while curr and $80 <> 0 do begin result := result or ((curr and $7f) shl idx); curr := GetByte; INC( idx, 7) end; result := result or ((curr and $7f) shl idx); end; // ================================================================================================ // ispVMDataCode // // Processes the TDI/TDO/MASK/DMASK etc of an SIR/SDR command. // ================================================================================================ function TispVM.ispVMDataCode: TReturnCode; var DataByte : ShortInt; DataSource : ShortInt; pos : Int64; begin result := VME_OK; if dtHeap in fDataType then DataSource := 1 // data source is memory else DataSource := 0; // data source is file fDataType := fDataType - [dtTDIData, dtTDOData, dtMASKData, dtDMASKData, dtCMASKData]; // -------------------------------------------------------------------- // Iterate through SIR/SDR command and look for TDI, TDO, MASK, etc... // -------------------------------------------------------------------- DataByte := ShortInt(GetByte); while DataByte >= 0 do begin pos := fStream.Position -1; ispVMMemManager( TOpCode(DataByte), fMaxSize); case TOpCode(DataByte) of // ---------------------------------------------------- // TDI // ---------------------------------------------------- opTDI: begin // ----------------------------------------- // Store the maximum size of the TDI buffer. // Used to convert VME to HEX. // ----------------------------------------- if fTDISize <= fDataSize then fTDISize := fDataSize; // ----------------------------------------- // Update DataType register to indicate that // TDI data is currently being used. Process // the data in the VME file into the TDI // buffer. // ----------------------------------------- Include(fDataType, dtTDIData); ispVMData( fInData); end; // ---------------------------------------------------- // TDO // ---------------------------------------------------- opTDO: begin // ----------------------------------------- // Store the maximum size of the TDO buffer. // Used to convert VME to HEX. // ----------------------------------------- if fTDOSize <= fDataSize then fTDOSize := fDataSize; // ----------------------------------------- // Update DataType register to indicate that // TDO data is currently being used. Process // the data in the VME file into the TDO // buffer. // ----------------------------------------- Include(fDataType, dtTDOData); ispVMData( fOutData); end; // ---------------------------------------------------- // XTDO // ---------------------------------------------------- opXTDO: begin // ----------------------------------------- // Store the maximum size of the TDO buffer. // Used to convert VME to HEX. // ----------------------------------------- if fTDOSize <= fDataSize then fTDOSize := fDataSize; // ----------------------------------------- // Update DataType register to indicate that // TDO data is currently being used. Process // the data in the VME file into the TDO // buffer. // ----------------------------------------- Include(fDataType, dtTDOData); end; opMASK: begin // ----------------------------------------- // Store the maximum size of the MASK buffer. // Used to convert VME to HEX. // ----------------------------------------- if fMASKSize <= fDataSize then fMASKSize := fDataSize; // ----------------------------------------- // Update DataType register to indicate that // MASK data is currently being used. Process // the data in the VME file into the MASK // buffer. // ----------------------------------------- Include(fDataType, dtMASKData); ispVMData( fOutMaskData); end; opDMask: begin // ----------------------------------------- // Store the maximum size of the DMASK // buffer. Used to convert VME to HEX. // ----------------------------------------- if fDMASKSize <= fDataSize then fDMASKSize := fDataSize; // ----------------------------------------- // Update DataType register to indicate that // DMASK data is currently being used. // Process the data in the VME file into the // DMASK buffer. // ----------------------------------------- Include(fDataType, dtDMASKData); ispVMData( fOutDMaskData); end; opCMask: begin // ----------------------------------------- // Update DataType register to indicate that // DMASK data is currently being used. // Process the data in the VME file into the // DMASK buffer. // ----------------------------------------- Include(fDataType, dtCMASKData); ispVMData( fOutMaskData); end; opContinue: begin result := VME_OK; exit; end; else begin result := VME_InvalidFile; exit end; end; case TOpCode(DataByte) of opTDI: begin // ----------------------------------------- // Left bit shift. Used when performing // algorithm looping. // ----------------------------------------- if fcbShiftLeft in fFlowControl then begin ispVMBitShift( opSHL, fShiftValue); Exclude( fFlowControl, fcbShiftLeft) end; // ----------------------------------------- // Left bit shift. Used when performing // algorithm looping. // ----------------------------------------- if fcbShiftRight in fFlowControl then begin ispVMBitShift( opSHR, fShiftValue); Exclude( fFlowControl, fcbShiftRight) end; end; end; if DataSource <> 0 then Include( fDataType, dtHeap); DataByte := ShortInt(GetByte); end; if DataSource <> 0 then Include( fDataType, dtHeap); if DataByte < 0 then begin pos := fStream.Position; result := VME_InvalidFile; end else result := VME_OK end; // ================================================================================================ // ispVMData // // Extract one row of data operand from the current data type opcode. Perform the decompression if // necessary. Extra RAM is not required for the decompression process. The decompression scheme // employed in this module is on row by row basis. The format of the data stream: // // [compression code][compressed data stream] // 0x00 --No compression // 0x01 --Compress by 0x00. // Example: // Original stream: 0x000000000000000000000001 // Compressed stream: 0x01000901 // Detail: 0x01 is the code, 0x00 is the key, // 0x09 is the count of 0x00 bytes, // 0x01 is the uncompressed byte. // // 0x02 --Compress by 0xFF. // Example: // Original stream: 0xFFFFFFFFFFFFFFFFFFFFFF01 // Compressed stream: 0x02FF0901 // Detail: 0x02 is the code, 0xFF is the key, // 0x09 is the count of 0xFF bytes, // 0x01 is the uncompressed byte. // // 0x03 // : : // 0xFE -- Compress by nibble blocks. // Example: // Original stream: 0x84210842108421084210 // Compressed stream: 0x0584210 // Detail: 0x05 is the code, means 5 nibbles block. // 0x84210 is the 5 nibble blocks. // The whole row is 80 bits given by fDataSize. // The number of times the block repeat itself // is found by fDataSize/(4*0x05) which is 4. // // 0xFF -- Compress by the most frequently happen byte. // Example: // Original stream: 0x04020401030904040404 // Compressed stream: 0xFF04(0,1,0x02,0,1,0x01,1,0x03,1,0x09,0,0,0) // or: 0xFF044090181C240 // Detail: 0xFF is the code, 0x04 is the key. // a bit of 0 represent the key shall be put into // the current bit position and a bit of 1 // represent copying the next of 8 bits of data // in. // ================================================================================================ procedure TispVM.ispVMData(Data: PByte); var size : word; i, j, m : integer; getData : word; DataByte : byte; FFcount : integer; compress : byte; compr_char : byte; index : integer; compression : ShortInt; pos : Int64; begin size := 0; i := 0; j := 0; m := 0; getData := 0; compr_char := $FF; // --------------------------------------------------------------- // Convert "size in bits" to "size in bytes". // --------------------------------------------------------------- if fDataSize mod 8 > 0 then size := (fDataSize div 8) + 1 else size := (fDataSize div 8); // --------------------------------------------------------------- // If there is a compression, then check if compress by key of // 0x00 or 0xff or by other keys by nibble blocks. // --------------------------------------------------------------- if dtCompress in fDataType then begin compression := 1; compress := GetByte; if (TOpCode(compress) = opVAR) and (dtHeap in fDataType) then begin getData := 1; Exclude( fDataType, dtHeap); compress := GetByte; end; case compress of $00: compression := 0; // No compression $01: compr_char := $00; $02: compr_char := $ff; $ff: begin pos := fStream.Position; i := 8; compr_char := GetByte; pos := fStream.Position; for index := 0 to size-1 do begin Data[index] := 0; if i > 7 then begin DataByte := GetByte; pos := fStream.Position; i := 0; end; if (DataByte shl i) and $80 = $80 then m := 8 else begin Data[index] := compr_char; m := 0; end; INC(i); for j:=0 to m-1 do begin if i > 7 then begin DataByte := GetByte; i := 0; pos := fStream.Position; end; Data[index] := Data[index] or (((DataByte shl i) and $80) shr j); INC(i); end; end; size := 0; pos := fStream.Position; end; else begin for index:=0 to size -1 do Data[index] := 0; for index:=0 to compress -1 do begin if (index mod 2) = 0 then DataByte := GetByte; for i:=0 to ((size*2) div compress) -1 do begin j := index + i * compress; if (j mod 2) <> 0 then if (index mod 2) <> 0 then Data[j div 2] := Data[j div 2] or (DataByte and $0F) else Data[j div 2] := Data[j div 2] shr 4 else if (index mod 2) <> 0 then Data[j div 2] := Data[j div 2] shl 4 else Data[j div 2] := Data[j div 2] and $F0 end; size := 0; end; end; end; end; // Decompress by byte 0x00 or 0xff FFcount := 0; for index := 0 to size -1 do begin if FFcount <= 0 then begin DataByte := GetByte; if (TOpCode(DataByte) = opVar) and (dtHeap in fDataType) and (getData = 0) and not (dtCompress in fDataType) then begin getData := 1; Exclude( fDataType, dtHeap); DataByte := GetByte; end; Data[index] := DataByte; if (compression <> 0) and (DataByte = compr_char) then // compression is on FFcount := ispVMDataSize; // the number of $FF or $00 bytes end else begin DEC(FFcount); Data[index] := compr_char; end; end; if getData <> 0 then Include( fDataType, dtHeap); end; // ================================================================================================ // ispVMShift // // Process the SIR/SDR/XSDR commands. // ================================================================================================ function TispVM.ispVMShift(OpCode: TOpcode): TReturnCode; var DataIndex : word; ReadLoop : word; begin DataIndex := 0; ReadLoop := 0; result := VME_OK; fDataSize := ispVMDataSize; Exclude( fDataType, dtSIRData); Exclude( fDataType, dtSDRData); Exclude( fDataType, dtExpress); // ------------------------------------------------------------------------- // Elsö lepeskent olvassuk be a TDI/TDO/... adatokat a megfelelö bufferekbe. // Ha TDO adatok is vannak specifikalva, akkor a State Machine aktualizalasa // utan toljuk ki a buffer tartalmat, hogy a TDO muvelet a buffer elejen // kezdödhessen. Igy max 512 (1024) byte-os adatot tudunk ellenörizni. // ------------------------------------------------------------------------- result := ispVMDataCode; if result <> VME_OK then begin result := VME_InvalidFile; exit end; if fDataSize > 250 then Exclude( fDataType, dtTDOData); // ------------------------------------------------------------------------- // Move the device state machine and shift in any bypass data. // ------------------------------------------------------------------------- case OpCode of // ------------------------------------------------------------ // SIR // ------------------------------------------------------------ opSIR: begin Include( fDataType, dtSIRData); // -------------------------------------------- // If performing cascading, then go directly // to IRSHIFT. Else go to IRPAUSE before going // to IRSHIFT. // -------------------------------------------- if Assigned( fJtag) then begin if fcbCascade in fFlowControl then fJtag.state(IRSHIFT) else begin fJtag.state(IRPAUSE); fJtag.state(IRSHIFT); if fHeadIR > 0 then begin ispVMBypass( opHIR, fHeadIR); sclock end; end; end; end; // ------------------------------------------------------------ // SDR/XSDR // ------------------------------------------------------------ opSDR, opXSDR: begin Include( fDataType, dtSDRData); if OpCode = opXSDR then Include( fDataType, dtExpress); // --------------------------------------------- // If already in DRSHIFT, then do not move state // or shift in header. This would imply that the // previously shifted frame was a cascaded frame // --------------------------------------------- if fCurrentJTAGState <> DRSHIFT then begin // ------------------------------------------ // If performing cascading, then go directly // to DRSHIFT. Else goto DRPAUSE before going // to DRSHIFT. // ------------------------------------------ if fcbCascade in fFlowControl then begin if fCurrentJTAGState = DRPAUSE then begin ispVMStateMachine( DRSHIFT); // ------------------------------------ // If cascade flag has been set and the // current state is DRPAUSE, this imp- // lies that the first cascaded frame // is about to shifted in. The header // must be shifted prior to shifting // the first cascaded frame. // ------------------------------------ if fHeadDR > 0 then begin ispVMBypass( opHDR, fHeadDR); sclock end; end else ispVMStateMachine( DRSHIFT); end // ------------------------------------------ // No cascading. // ------------------------------------------ else begin ispVMStateMachine( DRPAUSE); ispVMStateMachine( DRSHIFT); if fHeadDR > 0 then begin ispVMBypass( opHDR, fHeadDR); sclock end; end; end; end; else begin result := VME_InvalidFile; exit end; end; // // -------------------------------------------------------------------- // // Read TDI,TDO,MASK data into internal buffers. // // -------------------------------------------------------------------- // result := ispVMDataCode; // // if result <> VME_OK then // begin // result := VME_InvalidFile; // exit // end; // -------------------------------------------------------------------- // If we have TDO data to check, then flush buffer first. // -------------------------------------------------------------------- if dtTDOData in fDataType then Flush; // -------------------------------------------------------------------- // Do shifting, and process TDO or DATA MASK // -------------------------------------------------------------------- if (dtTDOData in fDataType) or (dtDMASKData in fDataType) then begin // DMASK Data if dtDMASKData in fDataType then begin result := ispVMReadAndSave( fDataSize); if result = VME_OK then begin if fTailDR > 0 then begin sclock; ispVMBypass( opTDR, fTailDR); end; ispVMStateMachine( DRPAUSE); ispVMStateMachine( DRSHIFT); if fHeadDR > 0 then begin ispVMBypass( opHDR, fHeadDR); sclock end; for DataIndex:=0 to (fDataSize div 8) do fInData[DataIndex] := fOutData[DataIndex]; Exclude( fDataType, dtTDOData); Exclude( fDataType, dtDMASKData); result := ispVMSend( fDataSize) end; end // TDO Data else begin result := ispVMRead( fDataSize); if (result = VME_VerificationFailure) and (fVendor = vXilinx) then begin for ReadLoop:=0 to 29 do begin result := ispVMRead( fDataSize); if result = VME_OK then break else begin ispVMStateMachine(DRPAUSE); ispVMBypass( opTDR, fTailDR); ispVMStateMachine( fEndDR); ispVMStateMachine( IDLE); ispVMDelay(1000); end; end; end; end; end else // TDI only result := ispVMSend( fDataSize); // ------------------------------------------------------------------------- // Transfer the input data to the output buffer for the next verify. // MoveMem ??? // ------------------------------------------------------------------------- if (dtExpress in fDataType) or (OpCode = opSDR) then if Assigned(fOutData) then for DataIndex:=0 to fDataSize - 1 do fOutData[DataIndex] := fInData[DataIndex]; // ------------------------------------------------------------------------- // Update State Machine // ------------------------------------------------------------------------- case OpCode of opSIR: begin // If not performing cascading, then shift ENDIR if not (fcbCascade in fFlowControl) then begin if fTailIR > 0 then begin sclock; ispVMBypass( opTIR, fTailIR); end; ispVMStateMachine(fEndIR); end; end; opSDR,opXSDR: begin // If not performing cascading, then shift ENDIR if not (fcbCascade in fFlowControl) then begin if fTailDR > 0 then begin sclock; ispVMBypass( opTDR, fTailDR); end; ispVMStateMachine(fEndDR); if dtTDOData in fDataType then Flush; end; end; end; end; // ================================================================================================ // ispVMAmble // // This routine is to extract Header and Trailer parameter for SIR and SDR operations. // // The Header and Trailer parameter are the pre-amble and post-amble bit stream need to be shifted // into TDI or out of TDO of the devices. Mostly is for the purpose of bypassing the leading or // trailing devices. ispVM supports only shifting data into TDI to bypass the devices. // // For a single device, the header and trailer parameters are all set to 0 as default by ispVM. // If it is for multiple devices, the header and trailer value will change as specified by the // VME file. // ================================================================================================ function TispVM.ispVMAmble(OpCode: TOpcode): TReturnCode; var compress: byte; begin compress := 0; fDataSize := ispVMDataSize; if fDataSize > 0 then begin // ------------------------------------------------------------ // Discard the TDI byte and set the compression bit in the data // type register to false if compression is set, because TDI // data after HIR/HDR/TIR/TDR is not compressed. // ------------------------------------------------------------ GetByte; if dtCompress in fDataType then begin compress := 1; Exclude( fDataType, dtCompress); end; end; case OpCode of opHIR: begin // ------------------------------------------------- // Store the maximum size of the HIR buffer. Used to // convert VME to HEX. // ------------------------------------------------- if fHIRSize <= fDataSize then fHIRSize := fDataSize; // ------------------------------------------------- // Assign the HIR value and allocate memory. // ------------------------------------------------- fHeadIR := fDataSize; if fHeadIR > 0 then begin ispVMMemManager( opHIR, fHeadIR); ispVMData( fHIRData); end; end; opTIR: begin // ------------------------------------------------- // Store the maximum size of the TIR buffer. Used to // convert VME to HEX. // ------------------------------------------------- if fTIRSize <= fDataSize then fTIRSize := fDataSize; // ------------------------------------------------- // Assign the TIR value and allocate memory. // ------------------------------------------------- fTailIR := fDataSize; if fTailIR > 0 then begin ispVMMemManager( opTIR, fTailIR); ispVMData( fTIRData); end; end; opHDR: begin // ------------------------------------------------- // Store the maximum size of the HDR buffer. Used to // convert VME to HEX. // ------------------------------------------------- if fHDRSize <= fDataSize then fHDRSize := fDataSize; // ------------------------------------------------- // Assign the HIR value and allocate memory. // ------------------------------------------------- fHeadDR := fDataSize; if fHeadDR > 0 then begin ispVMMemManager( opHDR, fHeadDR); ispVMData( fHDRData); end; end; opTDR: begin // ------------------------------------------------- // Store the maximum size of the TDR buffer. Used to // convert VME to HEX. // ------------------------------------------------- if fTDRSize <= fDataSize then fTDRSize := fDataSize; // ------------------------------------------------- // Assign the TIR value and allocate memory. // ------------------------------------------------- fTailDR := fDataSize; if fTailDR > 0 then begin ispVMMemManager( opTDR, fTailDR); ispVMData( fTDRData); end; end; end; // --------------------------------------------------------------- // Re-enable compression if it was previously set. // --------------------------------------------------------------- if compress <> 0 then Include( fDataType, dtCompress); result := VME_OK; if fDataSize > 0 then begin OpCode := TOpCode( GetByte); if OpCode <> opContinue then result := VME_InvalidFile; end; end; // ================================================================================================ // ispVMLoop // // Perform the function call upon by the REPEAT opcode. Memory is to be allocated to store the // entire loop from REPEAT to ENDLOOP. After the loop is stored then execution begin. The // REPEATLOOP flag is set on the fFlowControl register to indicate the repeat loop is in session // and therefore fetch opcode from the memory instead of from the file. // ================================================================================================ function TispVM.ispVMLoop(LoopCount: word): TReturnCode; var HeapIndex: word; LoopIndex: word; begin HeapIndex := 0; LoopIndex := 0; fShiftValue := 0; result := VME_OK; for HeapIndex:=0 to fHeapSize -1 do fHeapMemory[HeapIndex] := GetByte; if TOpCode(fHeapMemory[HeapIndex-1]) = opEndLoop then begin Include( fFlowControl, fcbRepeatLoop); Include( fDataType, dtHeap); for LoopIndex:=0 to LoopCount -1 do begin fHeapCounter := 0; result := ispVMCode; fRepeatLoops := fRepeatLoops +1; if result <> VME_OK then break; end; Exclude( fFlowControl, fcbRepeatLoop); Exclude( fDataType, dtHeap); end else result := VME_InvalidFile; end; // ================================================================================================ // ispVMBitShift // // Shift the TDI stream left or right by the number of bits. The data in fInData is of the VME // format, so the actual shifting is the reverse of IEEE 1532 or SVF format. // ================================================================================================ function TispVM.ispVMBitShift(OpCode: TOpCode; Count: word): TReturnCode; var i : word; size : word; tmp : word; begin i := 0; result:= VME_OK; if (fDataSize mod 8) > 0 then size := (fDataSize div 8) +1 else size := (fDataSize div 8); case OpCode of // ------------------------------------------------------------ // Right Shift // ------------------------------------------------------------ opSHR: begin while i < size do begin if fInData[i] <> 0 then begin tmp := Count; while tmp > 0 do begin fInData[i] := fInData[i] shl 1; if fInData[i] = 0 then begin DEC(i); fInData[i] := 1; end; DEC(tmp); end; end; INC(i); end; end; // ------------------------------------------------------------ // Left Shift // ------------------------------------------------------------ opSHL: begin while i < size do begin if fInData[i] <> 0 then begin tmp := Count; while tmp > 0 do begin fInData[i] := fInData[i] shr 1; if fInData[i] = 0 then begin DEC(i); fInData[i] := 8; end; DEC(tmp); end; end; INC(i); end; end; // ------------------------------------------------------------ // Invalud operation // ------------------------------------------------------------ else result := VME_InvalidFile end end; // ================================================================================================ // ispVMComment // // Iterate through the comment and ignore it. // ================================================================================================ procedure TispVM.ispVMComment(Size: word); var c: AnsiChar; s: AnsiString; w: WideString; begin while Size > 0 do begin c := AnsiChar(GetByte); s := s + c; DEC(Size) end; w := '| '+s+' |'; // s := s +#13#10; writeln(s); // OutputDebugString(@w[1]); end; // ================================================================================================ // ispVMHeader // // Iterate through the header and ignore it. // ================================================================================================ procedure TispVM.ispVMHeader(Size: word); begin while Size > 0 do begin GetByte; DEC(size) end end; // ================================================================================================ // ispVMLCount // // Process the intelligent programming loops. // ================================================================================================ function TispVM.ispVMLCount(CountSize: word): TReturnCode; var Continue : boolean; BufferIndex : word; CountIndex : word; RepeatHeap : boolean; OpCode : TOpcode; State : TJTAGState; Delay : word; Toggle : word; usByte : byte; begin RepeatHeap := false; fIntelBufferSize := ispVMDataSize; ispVMMemManager(opLHEAP, fIntelBufferSize); // --------------------------------------------------------------- // Store the maximum size of the intelligent buffer. // Used to convert VME to HEX. // --------------------------------------------------------------- if fLCOUNTSize <= fIntelBufferSize then fLCOUNTSize := fIntelBufferSize; // --------------------------------------------------------------- // Copy intel data to the buffer. // --------------------------------------------------------------- for BufferIndex:=0 to fIntelBufferSize -1 do fIntelBuffer[BufferIndex] := GetByte; // --------------------------------------------------------------- // Update data type register. // --------------------------------------------------------------- Include( fDataType, dtLHeap); // --------------------------------------------------------------- // If the HEAP flag is set, tmporarily unset the flag so data will // be retrieved from the status buffer. // --------------------------------------------------------------- if dtHeap in fDataType then begin Exclude( fDataType, dtHeap); RepeatHeap := true; end; // --------------------------------------------------------------- // Iterate through the intelligent programming command. // --------------------------------------------------------------- for CountIndex:=0 to CountSize -1 do begin fIntelDataIndex := 0; OpCode := opEndData; State := RESET; Delay := 0; Toggle := 0; usByte := 0; Continue := true; // -------------------------------------------------- // Begin looping through all the VME opcodes. // -------------------------------------------------- while Continue do begin OpCode := TOpCode(GetByte); case OpCode of opHIR,opTIR,opHDR,opTDR: // Set the header/trailer of device in order // to bypass successfully. ispVMAmble( OpCode); opState: begin // Step the JTAG state machine to DRCAPTURE // to support looping. State := TJTAGState(GetByte); if (dtLHeap in fDataType) and (State = DRPAUSE) and (fCurrentJTAGState = DRPAUSE) then ispVMStateMachine( DRCAPTURE); ispVMStateMachine(State); end; opSIR : result := ispVMShift(OpCode); opSDR : result := ispVMShift(OpCode); opWAIT : ispVMDelay( ispVMDataSize); opTCK : ispVMClocks( ispVMDataSize); opComment : ispVMComment( ispVMDataSize); opENDLOOP : Continue := false; opIspEN: begin OpCode := TOpCode(GetByte); case OpCode of opON : SetPin( pinENA, 0); opOFF : SetPin( pinENA, 0); end; ispVMDelay(1); end; opTRST: begin OpCode := TOpCode(GetByte); case OpCode of opON : SetPin( pinTRST, 0); opOFF : SetPin( pinTRST, 0); end; ispVMDelay(1); end; else result := VME_InvalidFile end; end; if result = VME_OK then break; end; if RepeatHeap then Include( fDataType, dtHeap); Exclude( fDataType, dtLHeap); end; // ================================================================================================ // ispVMClocks // // Applies the specified number of pulses to TCK. // ================================================================================================ procedure TispVM.ispVMClocks(Count: word); var i: integer; begin for i:=0 to Count -1 do sclock end; // ================================================================================================ // ispVMBypass // // This procedure takes care of the HIR, HDR, TIR, TDR for the purpose of putting the other devices // into Bypass mode. The current state is checked to find out if it is at DRPAUSE or IRPAUSE. // If it is at DRPAUSE, perform bypass register scan. // If it is at IRPAUSE, scan into instruction registers the bypass instruction. // ================================================================================================ procedure TispVM.ispVMBypass(ScanType: TOpCode; Count: word); var Index : word; SourceIndex : word; BitState : byte; CurByte : byte; Source : PByte; begin SourceIndex := 0; if Count > 0 then begin case ScanType of opHIR: Source := fHIRData; opTIR: Source := fTIRData; opHDR: Source := fHDRData; opTDR: Source := fTDRData; else Source := nil; end; for Index:=0 to Count -2 do begin if (Index mod 8) = 0 then begin CurByte := Source[SourceIndex]; INC(SourceIndex); end; if (CurByte shl (Index mod 8)) and $80 = $80 then BitState := 1 else BitState := 0; SetPin( pinTDI, BitState); sclock; end; if (Index mod 8) = 0 then CurByte := Source[SourceIndex]; if (CurByte shl (Index mod 8)) and $80 = $80 then BitState := 1 else BitState := 0; SetPin( pinTDI, BitState); end; end; // ================================================================================================ // ispVMStateMachine // // This procedure steps all devices in the daisy chain from a given JTAG state to the next // desirable state. If the next state is TLR, the JTAG state machine is brute forced into // TLR by driving TMS high and pulse TCK 6 times. // ================================================================================================ procedure TispVM.ispVMStateMachine(NextState:TJTAGState); var PathIndex : byte; StateIndex : byte; begin if (fCurrentJTAGState = NextState) and (NextState <> RESET) then exit; for StateIndex:=0 to 24 do if (fCurrentJTAGState = JTAGTransitions[StateIndex].CurrState) and (NextState = JTAGTransitions[StateIndex].NextState) then break; fCurrentJTAGState := NextState; for PathIndex:=0 to JTAGTransitions[StateIndex].Pulses -1 do begin if (JTAGTransitions[StateIndex].Pattern shl PathIndex) and $80 = $80 then SetPin( pinTMS, 1) else SetPin( pinTMS, 0); sclock; end; SetPin( pinTDI, 0); SetPin( pinTMS, 0); end; // ================================================================================================ // ispVMSend // // Send the TDI data stream to devices. The data stream can be instructions or data. // ================================================================================================ function TispVM.ispVMSend(Count: word): TReturnCode; var Index : word; DataIndex: word; CurByte : byte; BitState : byte; begin // if Assigned(fJtag) then // fJtag.xfer( fInData, Count, 1); { DataIndex := 0; for Index:=0 to Count -2 do begin if (Index mod 8) = 0 then begin CurByte := fInData[DataIndex]; INC(DataIndex); end; if (CurByte shl (Index mod 8)) and $80 = $80 then BitState := 1 else BitState := 0; SetPin( pinTDI, BitState); sclock; end; // Take care of the last bit. if (Index mod 8) = 0 then CurByte := fInData[DataIndex]; if (CurByte shl (Index mod 8)) and $80 = $80 then BitState := 1 else BitState := 0; SetPin( pinTDI, BitState); // Clock in last bit for the first n-1 cascaded frames. if fcbCascade in fFlowControl then sclock; } result := VME_OK end; // ================================================================================================ // ispVMRead // // Read the data stream from devices and verify. // ================================================================================================ function TispVM.ispVMRead(Count: word): TReturnCode; var DataSizeIndex : word; ErrorCount : word; LastBitIndex : word; DataByte : byte; MaskByte : byte; InDataByte : byte; CurBit : byte; ByteIndex : byte; BufferIndex : word; DisplayByte : byte; DisplayFlag : boolean; BitState : byte; StrChecksum : array [0..255] of AnsiChar; CalChecksum : boolean; cnt : integer; i : integer; begin ByteIndex := 0; BufferIndex := 0; DisplayByte := 0; DisplayFlag := true; CalChecksum := false; LastBitIndex := Count -1; // --------------------------------------------------------------- // If mask is not all zeros, then set the display flag to 0x00, // otherwise it shall be set to 0x01 to indicate that data read // from the device shall be displayed. // If VME_DEBUG is defined, always display data. // --------------------------------------------------------------- for DataSizeIndex:=0 to ((Count + 7) mod 8) -1 do begin if dtMASKData in fDataType then begin if fOutMaskData[DataSizeIndex] <> 0 then begin DisplayFlag := false; break end; end else if dtCMASKData in fDataType then begin CalChecksum := true; DisplayFlag := false; break end else begin DisplayFlag := false; break end; end; // --------------------------------------------------------------- // Send TDI data out. // --------------------------------------------------------------- fTransferMode := tmRead; result := ispVMSend(Count); exit; // for i:=0 to (Count *2) -1 do // fBuffer[i] := fBuffer[i] and fMaskTDO; // --------------------------------------------------------------- // Begin shifting data in and out of the device. // --------------------------------------------------------------- for DataSizeIndex:=0 to Count -1 do begin if ByteIndex = 0 then begin if dtTDOData in fDataType then DataByte := fOutData[BufferIndex]; if dtMASKData in fDataType then MaskByte := fOutMaskData[BufferIndex] else MaskByte := $FF; if dtCMASKData in fDataType then begin MaskByte := $00; CalChecksum := true; end; if dtTDIData in fDataType then InDataByte := fInData[BufferIndex]; INC(BufferIndex) end; // CurBit := ReadPort; if DisplayFlag then begin DisplayByte := DisplayByte shl 1; DisplayByte := DisplayByte or CurBit; end; // ------------------------------------------------------------ // Check if data read from port matches with expected TDO. // ------------------------------------------------------------ if dtTDOData in fDataType then begin if CalChecksum then begin if CurBit = 1 then fCheckSum := fCheckSum + (1 shl (fCheckSumIndex mod 8)); INC( fCheckSumIndex) end else begin // TODO: b+ end; end; // ------------------------------------------------------------ // Write TDI data to the port. // ------------------------------------------------------------ if (InDataByte shl ByteIndex) and $80 = $80 then BitState := 1 else BitState := 0; SetPin( pinTDI, BitState); if (DataSizeIndex < LastBitIndex) or (fcbCascade in fFlowControl) then sclock; // ------------------------------------------------------------ // Increment the byte index. If it exceeds 7, then resetit back // to zero. // ------------------------------------------------------------ INC(ByteIndex); if ByteIndex > 7 then begin if DisplayFlag then begin // ------------------------------------------------------ // Store displayed data in the TDO buffer. By reusing the // TDO buffer to store displayed data, there is no need // to allocate a buffer simply to hold display data. This // will not cause any false verification errors because // the true TDO byte has already been consumed. // ------------------------------------------------------ fOutData[BufferIndex -1] := DisplayByte; DisplayByte := 0; end; ByteIndex := 0; end else if fDataSize = 1 then begin if DisplayFlag then begin // ------------------------------------------------------ // Store displayed data in the TDO buffer. By reusing the // TDO buffer to store displayed data, there is no need // to allocate a buffer simply to hold display data. This // will not cause any false verification errors because // the true TDO byte has already been consumed. // // Flip DisplayByte and store it in DataByte. // ------------------------------------------------------ DataByte := FlipByte(DisplayByte); fOutData[0] := DataByte; DisplayByte := 0; end; ByteIndex := 0; end; end; // --------------------------------------------------------------- // Display data read from the device. // --------------------------------------------------------------- if DisplayFlag then begin // writeln.... cnt := (fDataSize +7) mod 8; for DataSizeIndex := cnt-1 downto 0 do begin MaskByte := fOutData[DataSizeIndex]; DataByte := FlipByte(MaskByte); // write DataByte end; if fCheckSum <> 0 then begin end; end; if ErrorCount > 0 then begin end; result := VME_OK end; // ================================================================================================ // ispVMReadAndSave // ================================================================================================ function TispVM.ispVMReadAndSave(Count: word): TReturnCode; var DataSizeIndex : word; ErrorCount : word; LastBitIndex : word; OutBitIndex : word; DataByte : byte; DMaskByte : byte; InDataByte : byte; CurBit : byte; ByteIndex : byte; BufferIndex : word; DisplayByte : byte; DisplayFlag : boolean; BitState : byte; StrChecksum : array [0..255] of AnsiChar; CalChecksum : boolean; cnt : integer; i : integer; begin ByteIndex := 0; BufferIndex := 0; DisplayByte := 0; DisplayFlag := true; CalChecksum := false; LastBitIndex := Count -1; // --------------------------------------------------------------- // Iterate through the data bits. // --------------------------------------------------------------- for DataSizeIndex := 0 to Count -1 do begin if ByteIndex = 0 then begin if dtDMASKData in fDataType then DMaskByte := fOutDMaskData[BufferIndex] else DMaskByte := $00; if dtTDIData in fDataType then InDataByte := fInData[BufferIndex]; INC(BufferIndex) end; // CurBit := ReadPort; if (InDataByte shl ByteIndex) and $80 = $80 then DataByte := $01 else DataByte := $00; // initialize the byte to be zero if (OutBitIndex mod 8) = 0 then fOutData[OutBitIndex div 8] := $00; // ------------------------------------------------------------ // Use TDI, DMASK, and device TDO to create new TDI // (actually stored in fOutData). // ------------------------------------------------------------ if (DMaskByte shl ByteIndex) and $80 = $80 then begin if Length( fLVDs) > 0 then for i:=Low(fLVDS) to High(fLVDS) do if fLVDs[i].NegativeIndex = DataSizeIndex then begin fLVDs[i].Update := true; break; end; // DMASK bit is 1, use TDI. if DataByte and $01 = $01 then fOutData[OutBitIndex mod 8] := fOutData[OutBitIndex mod 8] or $01; end else begin // DMASK bit is 0, use TDO. if CurBit and $01 = $01 then fOutData[OutBitIndex mod 8] := fOutData[OutBitIndex mod 8] or $01; end; // ------------------------------------------------------------ // Shift in TDI in order to get TDO out. // ------------------------------------------------------------ INC(OutBitIndex); SetPin( pinTDI, DataByte); if DataSizeIndex < LastBitIndex then sclock; // ------------------------------------------------------------ // Increment the byte index. If it exceeds 7, then reset it // back to zero. // ------------------------------------------------------------ INC(ByteIndex); if ByteIndex >= 8 then ByteIndex := 0; end; // --------------------------------------------------------------- // If fLVDs list exists and pairs needed updating, then update the // negative pair to receive the flipped positive pair value. // Ezt a reszt most kihagyom! Fene tudja mikor kell. // --------------------------------------------------------------- if Length(fLVDs) > 0 then begin for i:=Low(fLVDs) to High(fLVDs) do begin if fLVDs[i].Update then begin // -------------------------------------------- // Read the positive value and invert it. // -------------------------------------------- DataByte := fLVDs[i].PositiveIndex; fLVDs[i].NegativeIndex := not DataByte; // -------------------------------------------- // Get the byte that needs modification. // -------------------------------------------- InDataByte := fOutData[ fLVDs[i].NegativeIndex div 8]; if DataByte <> 0 then begin end; end; end; end; result := VME_OK end; // ================================================================================================ // ispVMStart // // Enable the port to the device and set the state to RESET. // ================================================================================================ procedure TispVM.ispVMStart; begin ispVMStateMachine(RESET); Flush; end; // ================================================================================================ // ispVMEnd // // Set the state of devices to RESET to enable the devices and disable the port. // ================================================================================================ procedure TispVM.ispVMEnd; begin ispVMStateMachine(RESET); Flush; ispVMDelay(1000) end; // ================================================================================================ // ispVMProcessLVDS // ================================================================================================ function TispVM.ispVMProcessLVDS(Count: word): TReturnCode; var i: word; begin // --------------------------------------------------------------- // Allocate memory to hold LVDS pairs. // --------------------------------------------------------------- SetLength( fLVDs, Count); // --------------------------------------------------------------- // Iterate through each given LVDS pair. // --------------------------------------------------------------- for i:=0 to Count -1 do begin fLVDs[i].PositiveIndex := ispVMDataSize; fLVDs[i].NegativeIndex := ispVMDataSize; fLVDs[i].Update := false; end; result := VME_OK end; // ================================================================================================ // ispVMDelay // // Users must implement a delay to observe a_usTimeDelay, where // bit 15 of the a_usTimeDelay defines the unit. // 1 = milliseconds // 0 = microseconds // Example: // a_usTimeDelay = 0x0001 = 1 microsecond delay. // a_usTimeDelay = 0x8001 = 1 millisecond delay. // // This subroutine is called upon to provide a delay from 1 millisecond to a few hundreds // milliseconds each time. // // It is understood that due to a_usTimeDelay is defined as unsigned short, a 16 bits integer, // this function is restricted to produce a delay to 64000 micro-seconds or 32000 milli-second // maximum. The VME file will never pass on to this function a delay time > those maximum number. // If it needs more than those maximum, the VME file will launch the delay function several times // to realize a larger delay time cummulatively. // // It is perfectly alright to provide a longer delay than required. It is not acceptable if the // delay is shorter. // ================================================================================================ procedure TispVM.ispVMDelay(Delay: word); var d: integer; begin if Delay and $8000 = $8000 then d := Delay and $7FFF else d := Delay div 1000; if d = 0 then d := 1; // if Assigned(fJtag) then // fJtag.wait(d); //@ Flush; //@ Sleep(d); end; // ================================================================================================ // SClock // ================================================================================================ procedure TispVM.sclock(n:integer); var data : byte; i : integer; begin data := 0; if fValTMS then data := data or fMaskTMS; if fValTDI then data := data or fMaskTDI; if fValTRST then data := data or fMaskTRST; if fValENA then data := data or fMaskENA; for i:=0 to n-1 do begin if (fBufferSize - fBufferIndex) < 2 then Flush; data := data and not fMaskTCK; fBuffer[fBufferIndex] := data; INC(fBufferIndex); data := data or fMaskTCK; fBuffer[fBufferIndex] := data; INC(fBufferIndex); end; end; // ================================================================================================ // SetPin // ================================================================================================ procedure TispVM.SetPin( pin: TPin; Value: byte); begin case pin of pinTMS : fValTMS := Value <> 0; pinTDI : fValTDI := Value <> 0; pinTRST : fValTRST := Value <> 0; pinENA : fValENA := Value <> 0; end; end; // ================================================================================================ // Flush the buffer // ================================================================================================ procedure TispVM.Flush; begin if fBufferIndex > 0 then if Assigned( fOnTransfer) then fOnTransfer( self, fTransferMode); fBufferIndex := 0; end; // ================================================================================================ // ispVMMemManager // // Allocate memory based on Target. The memory size specified by Size. // ================================================================================================ procedure TispVM.ispVMMemManager(Target: TOpCode; Size: word); begin case Target of opTDI,opXTDI: begin if Assigned(fInData) then FreeMem(fInData); fInData := AllocMem( (Size div 8) +2); end; opTDO,opXTDO: begin if Assigned(fOutData) then FreeMem(fOutData); fOutData := AllocMem( (Size div 8) +2); end; opMASK: begin if Assigned( fOutMaskData) then FreeMem( fOutMaskData); fOutMaskData := AllocMem( (Size div 8) +2); end; opDMASK: begin if Assigned( fOutDMaskData) then FreeMem( fOutDMaskData); fOutDMaskData := AllocMem( (Size div 8) +2); end; opHIR: begin if Assigned( fHIRData) then FreeMem( fHIRData); fHIRData := AllocMem( (Size div 8) +2); end; opTIR: begin if Assigned( fTIRData) then FreeMem( fTIRData); fTIRData := AllocMem( (Size div 8) +2); end; opHDR: begin if Assigned( fHDRData) then FreeMem( fHDRData); fHDRData := AllocMem( (Size div 8) +2); end; opTDR: begin if Assigned( fTDRData) then FreeMem( fTDRData); fTDRData := AllocMem( (Size div 8) +2); end; opHEAP: begin if Assigned( fHeapMemory) then FreeMem( fHeapMemory); fHeapMemory := AllocMem( (Size div 8) +2); end; opLHeap: begin if Assigned( fIntelBuffer) then FreeMem( fIntelBuffer); fIntelBuffer := AllocMem( (Size div 8) +2); end; end; end; initialization end.