1334 lines
39 KiB
ObjectPascal
1334 lines
39 KiB
ObjectPascal
unit jtag.svf2;
|
|
|
|
interface
|
|
uses
|
|
Classes,
|
|
jtag.types;
|
|
|
|
type
|
|
TsvfReturnCode =
|
|
(
|
|
SVF_OK = 0,
|
|
SVF_InvalidFile = -1
|
|
);
|
|
|
|
TScan =
|
|
(
|
|
SCAN_HIR,
|
|
SCAN_HDR,
|
|
SCAN_TIR,
|
|
SCAN_TDR,
|
|
SCAN_SIR,
|
|
SCAN_SDR
|
|
);
|
|
|
|
TsvfDataTypeBit =
|
|
(
|
|
dtTDIData, // TDI data is present
|
|
dtTDOData, // TDO data is present
|
|
dtMASKData, // MASK data is present
|
|
dtSMASKData // SMASK data us present
|
|
);
|
|
|
|
TsvfDataType = set of TsvfDataTypeBit;
|
|
|
|
|
|
TjtagSVF = class
|
|
protected
|
|
fStream : TStream;
|
|
fLogLevel : integer;
|
|
|
|
fBuffer : PAnsiChar;
|
|
fBufferIdx : cardinal;
|
|
fBufferSize : cardinal;
|
|
|
|
fJTAG : IJTAG;
|
|
fLog : IJTAGLOG;
|
|
|
|
fDataHIR : TsvfDataType;
|
|
fDataHDR : TsvfDataType;
|
|
fDataTIR : TsvfDataType;
|
|
fDataTDR : TsvfDataType;
|
|
fDataSIR : TsvfDataType;
|
|
fDataSDR : TsvfDataType;
|
|
|
|
protected
|
|
fHIRSize : word;
|
|
fHDRSize : word;
|
|
fTIRSize : word;
|
|
fTDRSize : word;
|
|
fSIRSize : word;
|
|
fSDRSize : word;
|
|
|
|
fHIR_TDIData : PByte;
|
|
fHDR_TDIData : PByte;
|
|
fTIR_TDIData : PByte;
|
|
fTDR_TDIData : PByte;
|
|
fSIR_TDIData : PByte;
|
|
fSDR_TDIData : PByte;
|
|
|
|
fHIR_TDOData : PByte;
|
|
fHDR_TDOData : PByte;
|
|
fTIR_TDOData : PByte;
|
|
fTDR_TDOData : PByte;
|
|
fSIR_TDOData : PByte;
|
|
fSDR_TDOData : PByte;
|
|
|
|
fHIR_MASKData : PByte;
|
|
fHDR_MASKData : PByte;
|
|
fTIR_MASKData : PByte;
|
|
fTDR_MASKData : PByte;
|
|
fSIR_MASKData : PByte;
|
|
fSDR_MASKData : PByte;
|
|
|
|
fHIR_SMASKData : PByte;
|
|
fHDR_SMASKData : PByte;
|
|
fTIR_SMASKData : PByte;
|
|
fTDR_SMASKData : PByte;
|
|
fSIR_SMASKData : PByte;
|
|
fSDR_SMASKData : PByte;
|
|
|
|
fRUN_State : TJTAGState;
|
|
|
|
protected
|
|
|
|
procedure svfMemManager( scan : TScan;
|
|
bits : cardinal);
|
|
|
|
|
|
|
|
private
|
|
function svfPRG : TsvfReturnCode;
|
|
|
|
function svfScan( scan : TScan): TsvfReturnCode;
|
|
|
|
function svfData( buf : PBYTE;
|
|
bits : cardinal): TsvfReturnCode;
|
|
|
|
function svfENDxR : TsvfReturnCode;
|
|
function svfFreq : TsvfReturnCode;
|
|
function svfState : TsvfReturnCode;
|
|
function svfRun : TsvfReturnCode;
|
|
|
|
public
|
|
function SVF( Stream: TStream): TsvfReturnCode;
|
|
|
|
procedure AfterConstruction; override;
|
|
procedure BeforeDestruction; override;
|
|
|
|
public
|
|
property LogLevel : integer read fLogLevel write fLogLevel;
|
|
|
|
property JTAGLOG : IJTAGLOG read fLog write fLog;
|
|
property JTAG : IJTAG read fJTAG write fJTAG;
|
|
end;
|
|
|
|
implementation
|
|
uses
|
|
SysUtils;
|
|
|
|
{ TjtagSVF }
|
|
|
|
// ================================================================================================
|
|
// after construction
|
|
// ================================================================================================
|
|
procedure TjtagSVF.AfterConstruction;
|
|
begin
|
|
fRUN_State := DRPAUSE
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// before destruction
|
|
// ================================================================================================
|
|
procedure TjtagSVF.BeforeDestruction;
|
|
begin
|
|
svfMemManager( SCAN_HIR, 0);
|
|
svfMemManager( SCAN_HDR, 0);
|
|
|
|
svfMemManager( SCAN_TIR, 0);
|
|
svfMemManager( SCAN_TDR, 0);
|
|
|
|
svfMemManager( SCAN_SIR, 0);
|
|
svfMemManager( SCAN_SDR, 0);
|
|
|
|
inherited;
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// svf
|
|
// ================================================================================================
|
|
function TjtagSVF.SVF(Stream: TStream): TsvfReturnCode;
|
|
begin
|
|
if Assigned(Stream) then
|
|
begin
|
|
fBufferIdx := 0;
|
|
fBufferSize := Stream.Size;
|
|
fBuffer := GetMemory( fBufferSize);
|
|
|
|
Stream.Seek( 0,soFromBeginning);
|
|
Stream.Read( fBuffer^, Stream.Size);
|
|
|
|
svfPRG;
|
|
|
|
FreeMemory(fBuffer);
|
|
|
|
fBuffer := nil;
|
|
fBufferIdx := 0
|
|
end;
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// svfPRG
|
|
// ================================================================================================
|
|
function TjtagSVF.svfPRG: TsvfReturnCode;
|
|
var
|
|
tmp: AnsiString;
|
|
|
|
begin
|
|
result := SVF_OK;
|
|
|
|
while true do
|
|
begin
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9,#13,#10]) do
|
|
inc(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
case fBuffer[fBufferIdx] of
|
|
// ----------------------------------------------------
|
|
// comment
|
|
// ----------------------------------------------------
|
|
'!':
|
|
begin
|
|
tmp := '';
|
|
|
|
while (fBufferIdx < fBufferSize) and not (fBuffer[fBufferIdx] in [#13,#10]) do
|
|
begin
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
inc(fBufferIdx);
|
|
end;
|
|
|
|
writeln(tmp);
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#13,#10]) do
|
|
inc(fBufferIdx);
|
|
end;
|
|
|
|
'/':
|
|
begin
|
|
inc( fBufferIdx);
|
|
|
|
if fBuffer[fBufferIdx] = '/' then
|
|
begin
|
|
tmp := '/';
|
|
|
|
while (fBufferIdx < fBufferSize) and not (fBuffer[fBufferIdx] in [#13,#10]) do
|
|
begin
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
inc(fBufferIdx);
|
|
end;
|
|
|
|
writeln(tmp);
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#13,#10]) do
|
|
inc(fBufferIdx);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
// ----------------------------------------------------
|
|
// HIR/HDR
|
|
// ----------------------------------------------------
|
|
'H':
|
|
if fBufferIdx < fBufferSize then
|
|
begin
|
|
case fBuffer[fBufferIdx+1] of
|
|
'I': result := svfScan( SCAN_HIR);
|
|
'D': result := svfScan( SCAN_HDR);
|
|
else result := SVF_InvalidFile;
|
|
end;
|
|
end;
|
|
|
|
// ----------------------------------------------------
|
|
// TIR/TDR
|
|
// ----------------------------------------------------
|
|
// TODO 1 : Implement TRST (xilinx miatt)
|
|
'T':
|
|
if fBufferIdx < fBufferSize then
|
|
begin
|
|
case fBuffer[fBufferIdx+1] of
|
|
'I': result := svfScan( SCAN_TIR);
|
|
'D': result := svfScan( SCAN_TDR);
|
|
else result := SVF_InvalidFile;
|
|
end;
|
|
end;
|
|
|
|
// ----------------------------------------------------
|
|
// SIR/SDR
|
|
// ----------------------------------------------------
|
|
'S':
|
|
if fBufferIdx < fBufferSize then
|
|
begin
|
|
case fBuffer[fBufferIdx+1] of
|
|
'I': result := svfScan( SCAN_SIR);
|
|
'D': result := svfScan( SCAN_SDR);
|
|
'T': result := svfState;
|
|
else result := SVF_InvalidFile;
|
|
end;
|
|
end;
|
|
|
|
// ----------------------------------------------------
|
|
// ENDIR/ENDDR
|
|
// ----------------------------------------------------
|
|
'E':
|
|
if fBufferIdx < fBufferSize then
|
|
begin
|
|
if (fBuffer[fBufferIdx+1] = 'N') and
|
|
(fBuffer[fBufferIdx+2] = 'D') then
|
|
begin
|
|
case fBuffer[fBufferIdx+3] of
|
|
'I': result := svfENDxR;
|
|
'D': result := svfENDxR;
|
|
else result := SVF_InvalidFile
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// ----------------------------------------------------
|
|
// FREQUENCY
|
|
// ----------------------------------------------------
|
|
'F':
|
|
result := svfFreq;
|
|
|
|
// ----------------------------------------------------
|
|
// RUNTEST
|
|
// ----------------------------------------------------
|
|
'R':
|
|
result := svfRun;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// SCAN
|
|
// ================================================================================================
|
|
function TjtagSVF.svfSCAN(scan: TScan): TsvfReturnCode;
|
|
|
|
function reverse( data: PByte; length: integer): string;
|
|
var
|
|
i : integer;
|
|
n : byte;
|
|
|
|
begin
|
|
result := '';
|
|
|
|
for i:=0 to length-1 do
|
|
begin
|
|
n := (data[i] shr 4) and $0f;
|
|
|
|
case n of
|
|
0 : result := '0' + result;
|
|
1 : result := '8' + result;
|
|
2 : result := '4' + result;
|
|
3 : result := 'C' + result;
|
|
4 : result := '2' + result;
|
|
5 : result := 'A' + result;
|
|
6 : result := '6' + result;
|
|
7 : result := 'E' + result;
|
|
8 : result := '1' + result;
|
|
9 : result := '9' + result;
|
|
$a : result := '5' + result;
|
|
$b : result := 'D' + result;
|
|
$c : result := '3' + result;
|
|
$d : result := 'B' + result;
|
|
$e : result := '7' + result;
|
|
$f : result := 'F' + result;
|
|
end;
|
|
|
|
n := (data[i] shr 0) and $0f;
|
|
|
|
case n of
|
|
0 : result := '0' + result;
|
|
1 : result := '8' + result;
|
|
2 : result := '4' + result;
|
|
3 : result := 'C' + result;
|
|
4 : result := '2' + result;
|
|
5 : result := 'A' + result;
|
|
6 : result := '6' + result;
|
|
7 : result := 'E' + result;
|
|
8 : result := '1' + result;
|
|
9 : result := '9' + result;
|
|
$a : result := '5' + result;
|
|
$b : result := 'D' + result;
|
|
$c : result := '3' + result;
|
|
$d : result := 'B' + result;
|
|
$e : result := '7' + result;
|
|
$f : result := 'F' + result;
|
|
end;
|
|
end;
|
|
end;
|
|
var
|
|
bits : cardinal;
|
|
bytes : cardinal;
|
|
|
|
tmp : AnsiString;
|
|
i : integer;
|
|
s : string;
|
|
|
|
sTDI : string;
|
|
sTDO : string;
|
|
|
|
begin
|
|
result := SVF_InvalidFile;
|
|
|
|
if (fBuffer[fBufferIdx+2] = 'R') and (fBuffer[fBufferIdx+3] in [#32,#9]) then
|
|
begin
|
|
INC(fBufferIdx,3);
|
|
|
|
// skip whitespaces
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
// check for digit
|
|
if not (fBuffer[fBufferIdx] in ['0'..'9']) then
|
|
exit;
|
|
|
|
// read size
|
|
bits := 0;
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['0'..'9']) do
|
|
begin
|
|
bits := bits * 10 + ord(fBuffer[fBufferIdx]) - ord('0');
|
|
INC(fBufferIdx);
|
|
end;
|
|
|
|
svfMemManager( scan, bits);
|
|
|
|
// skip whitespaces
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
case scan of
|
|
SCAN_HIR: Exclude( fDataHIR, dtTDOData);
|
|
SCAN_HDR: Exclude( fDataHDR, dtTDOData);
|
|
|
|
SCAN_TIR: Exclude( fDataTIR, dtTDOData);
|
|
SCAN_TDR: Exclude( fDataTDR, dtTDOData);
|
|
|
|
SCAN_SIR: Exclude( fDataSIR, dtTDOData);
|
|
SCAN_SDR: Exclude( fDataSDR, dtTDOData);
|
|
end;
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['T','M','S']) do
|
|
begin
|
|
tmp := '';
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['A'..'Z']) do
|
|
begin
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
inc(fBufferIdx);
|
|
end;
|
|
|
|
case scan of
|
|
SCAN_HIR:
|
|
begin
|
|
if tmp = 'TDI' then Include( fDataHIR, dtTDIData) else
|
|
if tmp = 'TDO' then Include( fDataHIR, dtTDOData) else
|
|
if tmp = 'MASK' then Include( fDataHIR, dtMASKData) else
|
|
if tmp = 'SMASK' then Include( fDataHIR, dtSMASKData) else exit;
|
|
|
|
if tmp = 'TDI' then result := svfData(fHIR_TDIData, bits) else
|
|
if tmp = 'TDO' then result := svfData(fHIR_TDOData, bits) else
|
|
if tmp = 'MASK' then result := svfData(fHIR_MASKData, bits) else
|
|
if tmp = 'SMASK' then result := svfData(fHIR_SMASKData, bits)
|
|
end;
|
|
|
|
SCAN_HDR:
|
|
begin
|
|
if tmp = 'TDI' then Include( fDataHDR, dtTDIData) else
|
|
if tmp = 'TDO' then Include( fDataHDR, dtTDOData) else
|
|
if tmp = 'MASK' then Include( fDataHDR, dtMASKData) else
|
|
if tmp = 'SMASK' then Include( fDataHDR, dtSMASKData) else exit;
|
|
|
|
if tmp = 'TDI' then result := svfData(fHDR_TDIData, bits) else
|
|
if tmp = 'TDO' then result := svfData(fHDR_TDOData, bits) else
|
|
if tmp = 'MASK' then result := svfData(fHDR_MASKData, bits) else
|
|
if tmp = 'SMASK' then result := svfData(fHDR_SMASKData, bits)
|
|
end;
|
|
|
|
SCAN_TIR:
|
|
begin
|
|
if tmp = 'TDI' then Include( fDataTIR, dtTDIData) else
|
|
if tmp = 'TDO' then Include( fDataTIR, dtTDOData) else
|
|
if tmp = 'MASK' then Include( fDataTIR, dtMASKData) else
|
|
if tmp = 'SMASK' then Include( fDataTIR, dtSMASKData) else exit;
|
|
|
|
if tmp = 'TDI' then result := svfData(fTIR_TDIData, bits) else
|
|
if tmp = 'TDO' then result := svfData(fTIR_TDOData, bits) else
|
|
if tmp = 'MASK' then result := svfData(fTIR_MASKData, bits) else
|
|
if tmp = 'SMASK' then result := svfData(fTIR_SMASKData, bits)
|
|
end;
|
|
|
|
SCAN_TDR:
|
|
begin
|
|
if tmp = 'TDI' then Include( fDataTDR, dtTDIData) else
|
|
if tmp = 'TDO' then Include( fDataTDR, dtTDOData) else
|
|
if tmp = 'MASK' then Include( fDataTDR, dtMASKData) else
|
|
if tmp = 'SMASK' then Include( fDataTDR, dtSMASKData) else exit;
|
|
|
|
if tmp = 'TDI' then result := svfData(fTDR_TDIData, bits) else
|
|
if tmp = 'TDO' then result := svfData(fTDR_TDOData, bits) else
|
|
if tmp = 'MASK' then result := svfData(fTDR_MASKData, bits) else
|
|
if tmp = 'SMASK' then result := svfData(fTDR_SMASKData, bits)
|
|
end;
|
|
|
|
SCAN_SIR:
|
|
begin
|
|
if tmp = 'TDI' then Include( fDataSIR, dtTDIData) else
|
|
if tmp = 'TDO' then Include( fDataSIR, dtTDOData) else
|
|
if tmp = 'MASK' then Include( fDataSIR, dtMASKData) else
|
|
if tmp = 'SMASK' then Include( fDataSIR, dtSMASKData) else exit;
|
|
|
|
if tmp = 'TDI' then result := svfData(fSIR_TDIData, bits) else
|
|
if tmp = 'TDO' then result := svfData(fSIR_TDOData, bits) else
|
|
if tmp = 'MASK' then result := svfData(fSIR_MASKData, bits) else
|
|
if tmp = 'SMASK' then result := svfData(fSIR_SMASKData, bits)
|
|
end;
|
|
|
|
SCAN_SDR:
|
|
begin
|
|
if tmp = 'TDI' then Include( fDataSDR, dtTDIData) else
|
|
if tmp = 'TDO' then Include( fDataSDR, dtTDOData) else
|
|
if tmp = 'MASK' then Include( fDataSDR, dtMASKData) else
|
|
if tmp = 'SMASK' then Include( fDataSDR, dtSMASKData) else exit;
|
|
|
|
if tmp = 'TDI' then result := svfData(fSDR_TDIData, bits) else
|
|
if tmp = 'TDO' then result := svfData(fSDR_TDOData, bits) else
|
|
if tmp = 'MASK' then result := svfData(fSDR_MASKData, bits) else
|
|
if tmp = 'SMASK' then result := svfData(fSDR_SMASKData, bits) else exit;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if fBuffer[fBufferIdx] = ';' then
|
|
begin
|
|
INC(fBufferIdx);
|
|
result := SVF_OK;
|
|
end;
|
|
|
|
if Assigned( fJTAG) then
|
|
begin
|
|
bytes := (bits + 7) div 8;
|
|
|
|
case scan of
|
|
SCAN_SIR:
|
|
begin
|
|
writeln( Format('SIR(s) : %s', [reverse(fSIR_TDIData,bytes)]));
|
|
fJTAG.sir( fSIR_TDIData, bits);
|
|
writeln( Format('SIR(r) : %s', [reverse(fSIR_TDIData,bytes)]));
|
|
|
|
if dtTDOData in fDataSIR then
|
|
begin
|
|
writeln( Format('SIR(o) : %s', [reverse(fSIR_TDOData,bytes)]));
|
|
|
|
if dtMASKData in fDataSIR then
|
|
begin
|
|
writeln( Format('SIR(m) : %s', [reverse(fSIR_MASKData,bytes)]));
|
|
|
|
for i:=0 to bytes -1 do
|
|
begin
|
|
fSIR_TDIData[i] := fSIR_TDIData[i] and fSIR_MASKData[i];
|
|
fSIR_TDOData[i] := fSIR_TDOData[i] and fSIR_MASKData[i];
|
|
|
|
if fSIR_TDIData[i] <> fSIR_TDOData[i] then
|
|
begin
|
|
bits := 0;
|
|
end;
|
|
end;
|
|
|
|
writeln( Format('SIR(mr): %s', [reverse(fSIR_TDIData,bytes)]));
|
|
writeln( Format('SIR(mo): %s', [reverse(fSIR_TDOData,bytes)]));
|
|
end;
|
|
end;
|
|
|
|
writeln;
|
|
end;
|
|
|
|
SCAN_SDR:
|
|
begin
|
|
writeln( Format('SDR(s) : %s', [reverse(fSDR_TDIData,bytes)]));
|
|
fJTAG.sdr( fSDR_TDIData, bits);
|
|
writeln( Format('SDR(r) : %s', [reverse(fSDR_TDIData,bytes)]));
|
|
|
|
if dtTDOData in fDataSDR then
|
|
begin
|
|
writeln( Format('SDR(o) : %s', [reverse(fSDR_TDOData,bytes)]));
|
|
|
|
if dtMASKData in fDataSDR then
|
|
begin
|
|
writeln( Format('SDR(m) : %s', [reverse(fSDR_MASKData,bytes)]));
|
|
|
|
for i:=0 to bytes -1 do
|
|
begin
|
|
fSDR_TDIData[i] := fSDR_TDIData[i] and fSDR_MASKData[i];
|
|
fSDR_TDOData[i] := fSDR_TDOData[i] and fSDR_MASKData[i];
|
|
end;
|
|
|
|
sTDI := reverse(fSDR_TDIData,bytes);
|
|
sTDO := reverse(fSDR_TDOData,bytes);
|
|
|
|
writeln( Format('SDR(mr): %s', [sTDI]));
|
|
writeln( Format('SDR(mo): %s', [sTDO]));
|
|
end;
|
|
|
|
s := '';
|
|
|
|
for i:=1 to Length(sTDI) do
|
|
if sTDI[i] <> sTDO[i]
|
|
then s := s + '^'
|
|
else s := s + ' ';
|
|
|
|
if Trim(s) <> '' then
|
|
writeln( Format(' %s', [s]));
|
|
|
|
end;
|
|
|
|
writeln;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
// ================================================================================================
|
|
// ENDIR/ENDDR
|
|
// ================================================================================================
|
|
function TjtagSVF.svfENDxR: TsvfReturnCode;
|
|
var
|
|
state : AnsiChar;
|
|
tmp : AnsiString;
|
|
|
|
begin
|
|
result := SVF_InvalidFile;
|
|
state := '0';
|
|
tmp := '';
|
|
|
|
if (fBuffer[fBufferIdx+4] = 'R') and (fBuffer[fBufferIdx+5] in [#32,#9]) then
|
|
begin
|
|
INC(fBufferIdx,5);
|
|
|
|
// skip whitespaces
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
if not (fBuffer[fBufferIdx] in ['I','D','R']) then
|
|
exit;
|
|
|
|
// read state name
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['A'..'Z']) do
|
|
begin
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
INC(fBufferIdx);
|
|
end;
|
|
|
|
// check state name
|
|
if tmp = 'IRPAUSE' then else
|
|
if tmp = 'DRPAUSE' then else
|
|
if tmp = 'RESET' then else
|
|
if tmp = 'IDLE' then else exit;
|
|
|
|
// skip whitespaces
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
if fBuffer[fBufferIdx] = ';' then
|
|
begin
|
|
inc( fBufferIdx);
|
|
result := SVF_OK
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// FREQUENCY
|
|
// ================================================================================================
|
|
function TjtagSVF.svfFreq: TsvfReturnCode;
|
|
var
|
|
tmp: AnsiString;
|
|
|
|
begin
|
|
result := SVF_InvalidFile;
|
|
tmp := '';
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['A'..'Z']) do
|
|
begin
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
inc(fBufferIdx);
|
|
end;
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
if tmp = 'FREQUENCY' then
|
|
begin
|
|
// just skip for now
|
|
while (fBufferIdx < fBufferSize) and not (fBuffer[fBufferIdx] in [#13,#10]) do
|
|
inc(fBufferIdx);
|
|
end;
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// RUNTEST
|
|
// ================================================================================================
|
|
function TjtagSVF.svfRun: TsvfReturnCode;
|
|
var
|
|
tmp: AnsiString;
|
|
|
|
tck : integer;
|
|
int : integer;
|
|
frc : integer;
|
|
exp : integer;
|
|
|
|
state : TJTAGState;
|
|
save : cardinal;
|
|
|
|
pulses: cardinal;
|
|
burst : WORD;
|
|
|
|
label
|
|
pulse;
|
|
|
|
begin
|
|
result := SVF_InvalidFile;
|
|
tmp := '';
|
|
tck := 0;
|
|
pulses := 0;
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['A'..'Z']) do
|
|
begin
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
inc(fBufferIdx);
|
|
end;
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
if tmp = 'RUNTEST' then
|
|
begin
|
|
// skip whitespaces
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
// get optional state
|
|
state := UNDEF;
|
|
|
|
if fBuffer[fBufferIdx] in ['I','D','R'] then
|
|
begin
|
|
tmp := '';
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['A'..'Z']) do
|
|
begin
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
INC(fBufferIdx);
|
|
end;
|
|
|
|
if tmp = 'DRPAUSE' then state := DRPAUSE else
|
|
if tmp = 'IRPAUSE' then state := IRPAUSE else
|
|
if tmp = 'RESET' then state := RESET else
|
|
if tmp = 'IDLE' then state := IDLE else exit;
|
|
end;
|
|
|
|
// skip whitespaces
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if (fBufferIdx = fBufferSize) or not (fBuffer[fBufferIdx] in ['0'..'9']) then
|
|
exit;
|
|
|
|
save := fBufferIdx; // remember position
|
|
|
|
// get number of TCK pulses or integer part of mintime
|
|
int := 0;
|
|
frc := 0;
|
|
exp := 0;
|
|
tmp := '';
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['0'..'9']) do
|
|
begin
|
|
int := int * 10 + integer(fBuffer[fBufferIdx]) - ord('0');
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
INC(fBufferIdx);
|
|
end;
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
// "run_count run_clk" case
|
|
if fBuffer[fBufferIdx] <> '.' then
|
|
begin
|
|
// skip whitespaces
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
// read 'TCK' or 'SCK'
|
|
if (fBuffer[fBufferIdx+0] in ['T','S']) and
|
|
(fBuffer[fBufferIdx+1] = 'C') and
|
|
(fBuffer[fBufferIdx+2] = 'K') then
|
|
begin
|
|
tck := int;
|
|
int := 0;
|
|
inc(fBufferIdx,3);
|
|
|
|
// skip whitespaces
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
if fBuffer[fBufferIdx] = ';' then
|
|
begin
|
|
result := SVF_OK;
|
|
inc(fBufferIdx);
|
|
goto pulse;
|
|
end;
|
|
end
|
|
|
|
else
|
|
exit;
|
|
end
|
|
|
|
else
|
|
fBufferIdx := save;
|
|
|
|
// read mintime
|
|
int := 0;
|
|
frc := 0;
|
|
exp := 0;
|
|
tmp := '';
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['0'..'9']) do
|
|
begin
|
|
int := int * 10 + integer(fBuffer[fBufferIdx]) - ord('0');
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
INC(fBufferIdx);
|
|
end;
|
|
|
|
if (fBufferIdx = fBufferSize) or (fBuffer[fBufferIdx] <> '.') then
|
|
exit;
|
|
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
inc(fBufferIdx);
|
|
|
|
if (fBufferIdx = fBufferSize) or not (fBuffer[fBufferIdx] in ['0'..'9']) then
|
|
exit;
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['0'..'9']) do
|
|
begin
|
|
frc := frc + integer(fBuffer[fBufferIdx]) - ord('0');
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
INC(fBufferIdx);
|
|
end;
|
|
|
|
// match exponent letter: 'E'
|
|
if (fBufferIdx = fBufferSize) or (fBuffer[fBufferIdx] <> 'E') then
|
|
exit;
|
|
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
inc(fBufferIdx);
|
|
|
|
// match optional sign: ('+' | '-')
|
|
if fBuffer[fBufferIdx] in ['-','+'] then
|
|
begin
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
inc(fBufferIdx);
|
|
end;
|
|
|
|
// match exponent: ('0'..'9')+
|
|
if (fBufferIdx = fBufferSize) or not (fBuffer[fBufferIdx] in ['0'..'9']) then
|
|
exit;
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['0'..'9']) do
|
|
begin
|
|
exp := exp + integer(fBuffer[fBufferIdx]) - ord('0');
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
INC(fBufferIdx);
|
|
end;
|
|
|
|
// skip WS: (' ' | '\t')*
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
pulses := Round(StrToFloat(tmp) / 1e-6);
|
|
|
|
// match second mark: 'SEC'
|
|
if (fBufferIdx = fBufferSize) or (fBuffer[fBufferIdx] <> 'S') then
|
|
exit;
|
|
|
|
tmp := '';
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['S','E','C']) do
|
|
begin
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
INC(fBufferIdx);
|
|
end;
|
|
|
|
if tmp <> 'SEC' then
|
|
exit;
|
|
|
|
// skip WS: (' ' | '\t')*
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
// TODO:maxtime, endstate....
|
|
|
|
|
|
// match instruction terminator: ';'
|
|
if fBuffer[fBufferIdx] <> ';' then
|
|
exit;
|
|
|
|
inc(fBufferIdx);
|
|
|
|
result := SVF_OK;
|
|
|
|
// ------------------------------------------------------------
|
|
// execute command
|
|
// ------------------------------------------------------------
|
|
pulse:
|
|
if Assigned( fJTAG) then
|
|
begin
|
|
pulses := pulses + tck;
|
|
|
|
while(pulses > 0) do
|
|
begin
|
|
if pulses > 50000 then
|
|
begin
|
|
burst := 50000;
|
|
pulses := pulses - 50000
|
|
end
|
|
|
|
else begin
|
|
burst := pulses;
|
|
pulses := 0
|
|
end;
|
|
|
|
fJTAG.run(state,burst);
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
// ================================================================================================
|
|
// STATE
|
|
// ================================================================================================
|
|
function TjtagSVF.svfState : TsvfReturnCode;
|
|
var
|
|
tmp : AnsiString;
|
|
state : TJTAGState;
|
|
|
|
begin
|
|
result := SVF_InvalidFile;
|
|
state := UNDEF;
|
|
tmp := '';
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['A'..'Z']) do
|
|
begin
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
inc(fBufferIdx);
|
|
end;
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
if tmp = 'STATE' then
|
|
begin
|
|
while true do
|
|
begin
|
|
tmp := '';
|
|
|
|
// skip whitespaces
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
// read state name
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['A'..'Z']) do
|
|
begin
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
INC(fBufferIdx);
|
|
end;
|
|
|
|
// check state name
|
|
if tmp = 'IRPAUSE' then state := IRPAUSE else
|
|
if tmp = 'DRPAUSE' then state := DRPAUSE else
|
|
if tmp = 'RESET' then state := RESET else
|
|
if tmp = 'IDLE' then state := IDLE else exit;
|
|
|
|
// skip whitespaces
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
if Assigned(JTAG) then
|
|
JTAG.state(state);
|
|
|
|
if fBuffer[fBufferIdx] = ';' then
|
|
begin
|
|
inc( fBufferIdx);
|
|
result := SVF_OK;
|
|
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// svfData
|
|
// ================================================================================================
|
|
function TjtagSVF.svfData(buf: PBYTE; bits: cardinal): TsvfReturnCode;
|
|
var
|
|
tmp : AnsiString;
|
|
bytes : cardinal;
|
|
count : cardinal;
|
|
b : byte;
|
|
i : integer;
|
|
|
|
function Reverse( c: AnsiChar): BYTE;
|
|
var
|
|
b: BYTE;
|
|
|
|
begin
|
|
Result := 0;
|
|
|
|
case c of
|
|
'0'..'9': b := ord(c) - ord('0');
|
|
'A'..'F': b := ord(c) - ord('A') + 10;
|
|
'a'..'f': b := ord(c) - ord('a') + 10;
|
|
end;
|
|
|
|
if b and $08 = $08 then Result := Result + $01;
|
|
if b and $04 = $04 then Result := Result + $02;
|
|
if b and $02 = $02 then Result := Result + $04;
|
|
if b and $01 = $01 then Result := Result + $08;
|
|
end;
|
|
|
|
begin
|
|
result := SVF_InvalidFile;
|
|
bytes := (bits + 7) div 8;
|
|
|
|
// skip whitespaces
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
if fBuffer[fBufferIdx] <> '(' then
|
|
exit;
|
|
|
|
inc( fBufferIdx);
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
if not (fBuffer[fBufferIdx] in ['0'..'9','A'..'F','a'..'f']) then
|
|
exit;
|
|
|
|
tmp := '';
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in ['0'..'9','A'..'F','a'..'f',#32,#9,#13,#10]) do
|
|
begin
|
|
if fBuffer[fBufferIdx] in ['0'..'9','A'..'F','a'..'f'] then
|
|
tmp := tmp + fBuffer[fBufferIdx];
|
|
|
|
inc(fBufferIdx);
|
|
end;
|
|
|
|
if length(tmp) < (bits + 3) div 4 then
|
|
exit;
|
|
|
|
bytes := 0;
|
|
count := 0;
|
|
|
|
for i:=length(tmp) downto 1 do
|
|
begin
|
|
b := Reverse(tmp[i]);
|
|
|
|
if count mod 2 = 0
|
|
then buf[bytes] := b shl 4
|
|
else buf[bytes] := buf[bytes] + b;
|
|
|
|
if count mod 2 = 1 then
|
|
inc(bytes);
|
|
|
|
inc(count);
|
|
|
|
if count * 4 >= bits then
|
|
break;
|
|
end;
|
|
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
if fBuffer[fBufferIdx] <> ')' then
|
|
exit;
|
|
|
|
inc( fBufferIdx);
|
|
|
|
while (fBufferIdx < fBufferSize) and (fBuffer[fBufferIdx] in [#32,#9,#13,#10]) do
|
|
INC(fBufferIdx);
|
|
|
|
if fBufferIdx = fBufferSize then
|
|
exit;
|
|
|
|
result := SVF_OK
|
|
end;
|
|
|
|
// ================================================================================================
|
|
// svfMemManager
|
|
// ================================================================================================
|
|
procedure TjtagSVF.svfMemManager( scan: TScan; bits: cardinal);
|
|
var
|
|
bytes: cardinal;
|
|
begin
|
|
bytes := (bits + 7) div 8;
|
|
|
|
case scan of
|
|
SCAN_HIR:
|
|
begin
|
|
if (bits = 0) or (bits > fHIRSize) then
|
|
begin
|
|
if Assigned(fHIR_TDIData) then FreeMemory(fHIR_TDIData);
|
|
if Assigned(fHIR_TDOData) then FreeMemory(fHIR_TDOData);
|
|
if Assigned(fHIR_MASKData) then FreeMemory(fHIR_MASKData);
|
|
if Assigned(fHIR_SMASKData) then FreeMemory(fHIR_SMASKData);
|
|
|
|
if bits = 0 then
|
|
begin
|
|
fHIR_TDIData := nil;
|
|
fHIR_TDOData := nil;
|
|
fHIR_MASKData := nil;
|
|
fHIR_SMASKData := nil
|
|
end
|
|
|
|
else begin
|
|
fHIR_TDIData := GetMemory(bytes);
|
|
fHIR_TDOData := GetMemory(bytes);
|
|
fHIR_MASKData := GetMemory(bytes);
|
|
fHIR_SMASKData := GetMemory(bytes)
|
|
end
|
|
end;
|
|
|
|
if fHIRSize <> bits then
|
|
begin
|
|
fHIRSize := bits;
|
|
fDataHIR := []
|
|
end
|
|
end;
|
|
|
|
SCAN_HDR:
|
|
begin
|
|
if (bits = 0) or (bits > fHDRSize) then
|
|
begin
|
|
if Assigned(fHDR_TDIData) then FreeMemory(fHDR_TDIData);
|
|
if Assigned(fHDR_TDOData) then FreeMemory(fHDR_TDOData);
|
|
if Assigned(fHDR_MASKData) then FreeMemory(fHDR_MASKData);
|
|
if Assigned(fHDR_SMASKData) then FreeMemory(fHDR_SMASKData);
|
|
|
|
if bits = 0 then
|
|
begin
|
|
fHDR_TDIData := nil;
|
|
fHDR_TDOData := nil;
|
|
fHDR_MASKData := nil;
|
|
fHDR_SMASKData := nil
|
|
end
|
|
|
|
else begin
|
|
fHDR_TDIData := GetMemory(bytes);
|
|
fHDR_TDOData := GetMemory(bytes);
|
|
fHDR_MASKData := GetMemory(bytes);
|
|
fHDR_SMASKData := GetMemory(bytes)
|
|
end
|
|
end;
|
|
|
|
if fHDRSize <> bits then
|
|
begin
|
|
fHDRSize := bits;
|
|
fDataHDR := []
|
|
end
|
|
end;
|
|
|
|
SCAN_TIR:
|
|
begin
|
|
if (bits = 0) or (bits > fTIRSize) then
|
|
begin
|
|
if Assigned(fTIR_TDIData) then FreeMemory(fTIR_TDIData);
|
|
if Assigned(fTIR_TDOData) then FreeMemory(fTIR_TDOData);
|
|
if Assigned(fTIR_MASKData) then FreeMemory(fTIR_MASKData);
|
|
if Assigned(fTIR_SMASKData) then FreeMemory(fTIR_SMASKData);
|
|
|
|
if bits = 0 then
|
|
begin
|
|
fTIR_TDIData := nil;
|
|
fTIR_TDOData := nil;
|
|
fTIR_MASKData := nil;
|
|
fTIR_SMASKData := nil
|
|
end
|
|
|
|
else begin
|
|
fTIR_TDIData := GetMemory(bytes);
|
|
fTIR_TDOData := GetMemory(bytes);
|
|
fTIR_MASKData := GetMemory(bytes);
|
|
fTIR_SMASKData := GetMemory(bytes)
|
|
end
|
|
end;
|
|
|
|
if fTIRSize <> bits then
|
|
begin
|
|
fTIRSize := bits;
|
|
fDataTIR := []
|
|
end
|
|
end;
|
|
|
|
SCAN_TDR:
|
|
begin
|
|
if (bits = 0) or (bits > fTDRSize) then
|
|
begin
|
|
if Assigned(fTDR_TDIData) then FreeMemory(fTDR_TDIData);
|
|
if Assigned(fTDR_TDOData) then FreeMemory(fTDR_TDOData);
|
|
if Assigned(fTDR_MASKData) then FreeMemory(fTDR_MASKData);
|
|
if Assigned(fTDR_SMASKData) then FreeMemory(fTDR_SMASKData);
|
|
|
|
if bits = 0 then
|
|
begin
|
|
fTDR_TDIData := nil;
|
|
fTDR_TDOData := nil;
|
|
fTDR_MASKData := nil;
|
|
fTDR_SMASKData := nil
|
|
end
|
|
|
|
else begin
|
|
fTDR_TDIData := GetMemory(bytes);
|
|
fTDR_TDOData := GetMemory(bytes);
|
|
fTDR_MASKData := GetMemory(bytes);
|
|
fTDR_SMASKData := GetMemory(bytes)
|
|
end
|
|
end;
|
|
|
|
if fTDRSize <> bits then
|
|
begin
|
|
fTDRSize := bits;
|
|
fDataTDR := []
|
|
end
|
|
end;
|
|
|
|
SCAN_SIR:
|
|
begin
|
|
if (bits = 0) or (bits > fSIRSize) then
|
|
begin
|
|
if Assigned(fSIR_TDIData) then FreeMemory(fSIR_TDIData);
|
|
if Assigned(fSIR_TDOData) then FreeMemory(fSIR_TDOData);
|
|
if Assigned(fSIR_MASKData) then FreeMemory(fSIR_MASKData);
|
|
if Assigned(fSIR_SMASKData) then FreeMemory(fSIR_SMASKData);
|
|
|
|
if bits = 0 then
|
|
begin
|
|
fSIR_TDIData := nil;
|
|
fSIR_TDOData := nil;
|
|
fSIR_MASKData := nil;
|
|
fSIR_SMASKData := nil
|
|
end
|
|
|
|
else begin
|
|
fSIR_TDIData := GetMemory(bytes);
|
|
fSIR_TDOData := GetMemory(bytes);
|
|
fSIR_MASKData := GetMemory(bytes);
|
|
fSIR_SMASKData := GetMemory(bytes)
|
|
end
|
|
end;
|
|
|
|
if fSIRSize <> bits then
|
|
begin
|
|
fSIRSize := bits;
|
|
fDataSIR := []
|
|
end
|
|
end;
|
|
|
|
SCAN_SDR:
|
|
begin
|
|
if (bits = 0) or (bits > fSDRSize) then
|
|
begin
|
|
if Assigned(fSDR_TDIData) then FreeMemory(fSDR_TDIData);
|
|
if Assigned(fSDR_TDOData) then FreeMemory(fSDR_TDOData);
|
|
if Assigned(fSDR_MASKData) then FreeMemory(fSDR_MASKData);
|
|
if Assigned(fSDR_SMASKData) then FreeMemory(fSDR_SMASKData);
|
|
|
|
if bits = 0 then
|
|
begin
|
|
fSDR_TDIData := nil;
|
|
fSDR_TDOData := nil;
|
|
fSDR_MASKData := nil;
|
|
fSDR_SMASKData := nil
|
|
end
|
|
|
|
else begin
|
|
fSDR_TDIData := GetMemory(bytes);
|
|
fSDR_TDOData := GetMemory(bytes);
|
|
fSDR_MASKData := GetMemory(bytes);
|
|
fSDR_SMASKData := GetMemory(bytes)
|
|
end
|
|
end;
|
|
|
|
if fSDRSize <> bits then
|
|
begin
|
|
fSDRSize := bits;
|
|
fDataSDR := []
|
|
end
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
end.
|