Files
bds.mr.jtg/src.jtag/vme/jtag.vme.pas
T
2026-01-08 19:12:06 +01:00

2901 lines
90 KiB
ObjectPascal

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
// kezddhessen. Igy max 512 (1024) byte-os adatot tudunk ellenrizni.
// -------------------------------------------------------------------------
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.