commit a30568e2a9e9e1bf17d81faf8d8866d240780e4d Author: Róka Miklós Date: Thu Jan 8 19:12:06 2026 +0100 Initial check in diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ddfb82f --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.dcu +*.exe +*.res + +*.identcache +*.local +*.dsk +*.dsv + diff --git a/doc/svf.pdf b/doc/svf.pdf new file mode 100644 index 0000000..ab421f1 Binary files /dev/null and b/doc/svf.pdf differ diff --git a/doc/xapp503.pdf b/doc/xapp503.pdf new file mode 100644 index 0000000..2707fb6 Binary files /dev/null and b/doc/xapp503.pdf differ diff --git a/prj.jtag/Delphi12Athens/mr.jtag.dpk b/prj.jtag/Delphi12Athens/mr.jtag.dpk new file mode 100644 index 0000000..7506c04 --- /dev/null +++ b/prj.jtag/Delphi12Athens/mr.jtag.dpk @@ -0,0 +1,58 @@ +package mr.jtag; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS ON} +{$RANGECHECKS ON} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE DEBUG} +{$ENDIF IMPLICITBUILDING} +{$LIBVERSION '290'} +{$IMPLICITBUILD ON} + +requires + rtl, + vcl; + +contains + jtag.bstream in '..\..\src.jtag\jtag.bstream.pas', + jtag.types in '..\..\src.jtag\jtag.types.pas', + jtag.svfAstComment in '..\..\src.jtag\svf\jtag.svfAstComment.pas', + jtag.svfAstEndDR in '..\..\src.jtag\svf\jtag.svfAstEndDR.pas', + jtag.svfAstEndIR in '..\..\src.jtag\svf\jtag.svfAstEndIR.pas', + jtag.svfAstFreq in '..\..\src.jtag\svf\jtag.svfAstFreq.pas', + jtag.svfAstNode in '..\..\src.jtag\svf\jtag.svfAstNode.pas', + jtag.svfAstPrint in '..\..\src.jtag\svf\jtag.svfAstPrint.pas', + jtag.svfAstRuntest in '..\..\src.jtag\svf\jtag.svfAstRuntest.pas', + jtag.svfAstScan in '..\..\src.jtag\svf\jtag.svfAstScan.pas', + jtag.svfAstState in '..\..\src.jtag\svf\jtag.svfAstState.pas', + jtag.svfFreq in '..\..\src.jtag\svf\jtag.svfFreq.pas', + jtag.svfLex in '..\..\src.jtag\svf\jtag.svfLex.pas', + jtag.svfPar in '..\..\src.jtag\svf\jtag.svfPar.pas', + jtag.svfProgram in '..\..\src.jtag\svf\jtag.svfProgram.pas', + jtag.svfLexer in '..\..\src.jtag\svf\grammar\jtag.svfLexer.pas', + jtag.svfLexerTokens in '..\..\src.jtag\svf\grammar\jtag.svfLexerTokens.pas', + jtag.svfParser in '..\..\src.jtag\svf\grammar\jtag.svfParser.pas', + jtag.svfParserTokens in '..\..\src.jtag\svf\grammar\jtag.svfParserTokens.pas', + jtag.svfScanLexer in '..\..\src.jtag\svf\grammar\jtag.svfScanLexer.pas', + jtag.svfScanLexerTokens in '..\..\src.jtag\svf\grammar\jtag.svfScanLexerTokens.pas'; + +end. diff --git a/prj.jtag/Delphi12Athens/mr.jtag.dproj b/prj.jtag/Delphi12Athens/mr.jtag.dproj new file mode 100644 index 0000000..e33922a --- /dev/null +++ b/prj.jtag/Delphi12Athens/mr.jtag.dproj @@ -0,0 +1,1025 @@ + + + {170520DD-7A28-4FC8-B9F7-197528EE4BC3} + mr.jtag.dpk + 20.3 + VCL + True + Debug + Win32 + mr.jtag + 1 + Package + + + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + ..\..\dcu\Delphi12Athens\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + true + true + System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) + mr_jtag + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 290 + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + + + DEBUG;$(DCC_Define) + true + false + true + true + true + true + true + + + false + true + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + true + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + Base + + + Cfg_1 + Base + + + Cfg_2 + Base + + + + Delphi.Personality.12 + Package + + + + mr.jtag.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + + + true + + + + + true + + + + + true + + + + + mr.jtag.bpl + true + + + + + 1 + + + 0 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-anydpi-v21 + 1 + + + res\drawable-anydpi-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values-v31 + 1 + + + res\values-v31 + 1 + + + + + res\values-v35 + 1 + + + res\values-v35 + 1 + + + + + res\drawable-anydpi-v26 + 1 + + + res\drawable-anydpi-v26 + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-anydpi-v33 + 1 + + + res\drawable-anydpi-v33 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-night-v21 + 1 + + + res\values-night-v21 + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable-anydpi-v24 + 1 + + + res\drawable-anydpi-v24 + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-night-anydpi-v21 + 1 + + + res\drawable-night-anydpi-v21 + 1 + + + + + res\drawable-anydpi-v31 + 1 + + + res\drawable-anydpi-v31 + 1 + + + + + res\drawable-night-anydpi-v31 + 1 + + + res\drawable-night-anydpi-v31 + 1 + + + + + 1 + + + 1 + + + 0 + + + + + 1 + .framework + + + 1 + .framework + + + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 1 + + + 1 + + + + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + + + + + + + + + + + + + True + False + False + + + 12 + + + + + diff --git a/src.jtag/jtag.bstream.pas b/src.jtag/jtag.bstream.pas new file mode 100644 index 0000000..6f046c6 --- /dev/null +++ b/src.jtag/jtag.bstream.pas @@ -0,0 +1,1128 @@ +unit jtag.bstream; + +interface + +uses + Classes, + Types, + jtag.svfAstScan, + jtag.svfAstRuntest, + jtag.svfAstState; + +type + TjtagBStream = class; + + TjtagCepMode = (cmNone, cmRead, cmWrite); + + TjtagTapState = (stInvalid, stReset, stIdle, stDrScan, stIrScan, + stDrCapture, stIrCapture, stDrShift, stIrShift, stDrExit1, stIrExit1, + stDrPause, stIrPause, stDrExit2, stIrExit2, stDrUpdate, stIrUpdate); + + TjtagOnFullEvent = procedure(Sender: TjtagBStream; + CEPMode: TjtagCepMode) of object; + + TjtagOnDumpEvent = procedure( Sender: TjtagBStream; Data: string) of object; + + TjtagBStream = class + protected + fBufTDI: array [0 .. 1023] of byte; + fBufTDO: array [0 .. 1023] of byte; + fBufSMASK: array [0 .. 1023] of byte; + fBufMASK: array [0 .. 1023] of byte; + + fInitDone: boolean; + fBufferSize: word; + fBuffer: array [0 .. 1023] of byte; + fCursor : word; + fCursorR : word; + + fEndDR: TjtagTapState; + fEndIR: TjtagTapState; + + fMaskTCK: byte; + fMaskTMS: byte; + fMaskTDI: byte; + fMaskTDO: byte; + fMaskTRST: byte; + fMaskENA: byte; + fMaskPWR: byte; + + // current value of the pins + fValTCK: byte; + fValTMS: byte; + fValTDI: byte; + fValTDO: byte; + fValTRST: byte; + fValENA: byte; + fValPWR: byte; + + fCEPMode: TjtagCepMode; + + fLastCEPMode: TjtagCepMode; + fLastWrite: integer; + + // events + fOnFull: TjtagOnFullEvent; + fOnDump: TjtagOnDumpEvent; + + // ------------------------------------------------------------ + // JTAG TAP state machine + // ------------------------------------------------------------ + protected + fState: TjtagTapState; + + function FlipByte( Data: byte): byte; + + + // ------------------------------------------------------------ + public + procedure SendBit(TDI: byte; TMS: byte); + + procedure SendByte(Value: byte; length: byte; last: boolean = false); + overload; + + procedure SendByte(TDI: byte; TDO: byte; SMASK: byte; MASK: byte; + length: word; last: boolean = false); overload; + + function ReceiveByte(length: byte): byte; + + // ------------------------------------------------------------ + // Property handlers + // ------------------------------------------------------------ + private + function GetData(i: word): byte; + procedure SetData(i: word; d: byte); + + procedure SetState(newState: TjtagTapState); + procedure SetEndDR(Value: TjtagTapState); + procedure SetEndIR(Value: TjtagTapState); + + + + protected + procedure Init(BufferSize: word; TCK: byte; TMS: byte; TDI: byte; + TDO: byte; TRST: byte; ENA: byte; PWR: byte); + + public + procedure InitDsoJtag; + procedure InitPrgJtag; + + procedure Clear; + procedure Emit; + procedure Pulse(n: cardinal = 1); + procedure Flush; + + protected + fBufHIR: array [0 .. 255] of byte; + fBufTIR: array [0 .. 255] of byte; + fBufHDR: array [0 .. 255] of byte; + fBufTDR: array [0 .. 255] of byte; + + fLenHIR: integer; + fLenTIR: integer; + fLenHDR: integer; + fLenTDR: integer; + + fBitHIR: integer; + fBitTIR: integer; + fBitHDR: integer; + fBitTDR: integer; + + procedure SendHTIDR(stmt: TsvfAstScan); + + public + procedure Send(stmt: TsvfAstScan); overload; + procedure Send(stmt: TsvfAstRuntest); overload; + procedure Send(stmt: TsvfAstState); overload; + + public + procedure AfterConstruction; override; + procedure BeforeDestruction; override; + + public + property Size: word read fBufferSize; + property DataSize: word read fCursor; + property Data[i: word]: byte read GetData write SetData; + + property CEPMode: TjtagCepMode read fCEPMode write fCEPMode; + + property State: TjtagTapState read fState write SetState; + property EndDR: TjtagTapState read fEndDR write SetEndDR; + property EndIR: TjtagTapState read fEndIR write SetEndIR; + + property TCK: byte read fValTCK write fValTCK; + property TMS: byte read fValTMS write fValTMS; + property TDI: byte read fValTDI write fValTDI; + property TRST: byte read fValTRST write fValTRST; + property ENA: byte read fValENA write fValENA; + + public + property OnFull: TjtagOnFullEvent read fOnFull write fOnFull; + property OnDump: TjtagOnDumpEvent read fOnDump write fOnDump; + + end; + +implementation + +uses + Vcl.Forms, + Windows, + SysUtils; + +{ TjtagBStream } + +{ TjtagBStream } + +// @@@: Construction/destruction ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Construction/destruction +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ================================================================================================ +// AfterConstruction +// ================================================================================================ +procedure TjtagBStream.AfterConstruction; +begin + inherited; + + fMaskTCK := 0; + fMaskTMS := 0; + fMaskTDI := 0; + fMaskTDO := 0; + fMaskTRST := 0; + fMaskENA := 0; + fMaskPWR := 0; + + fCursor := 0; + fState := stInvalid; + + fEndDR := stIdle; + fEndIR := stIdle; + + fLastWrite := 0; + fCEPMode := cmNone; +end; + +// ================================================================================================ +// BeforeDestruction +// ================================================================================================ +procedure TjtagBStream.BeforeDestruction; +begin + + inherited; +end; + +// ================================================================================================ +// Init +// ================================================================================================ +procedure TjtagBStream.Init(BufferSize: word; TCK, TMS, TDI, TDO, TRST, ENA, + 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 TjtagBStream.InitDsoJtag; +begin + Init(256, 0, 1, 3, 7, $FF, $FF, $FF); +end; + +// ================================================================================================ +// InitPrgJtag +// ================================================================================================ +procedure TjtagBStream.InitPrgJtag; +begin + Init(256, 0, 1, 7, 3, 5, 4, 6); +end; + + +// @@@: JTAG TAP state machine interface ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// JTAG TAP state machine interface +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ================================================================================================ +// State +// ================================================================================================ +procedure TjtagBStream.SetState(newState: TjtagTapState); +var + i: integer; + rc: boolean; + +begin + rc := true; + + // ----------------------------------------------------- + // xxx -> RESET + // ----------------------------------------------------- + if newState = stReset then + for i := 0 to 4 do + SendBit(0, 1) + + // ----------------------------------------------------- + // IDLE + // ----------------------------------------------------- + else if newState = stIdle then + begin + case fState of + stReset: + begin + SendBit(0, 0); + end; + + stDrShift, stDrPause, stIrShift, stIrPause: + begin + SendBit(0, 1); + SendBit(0, 1); + SendBit(0, 0); + end; + + stDrExit1, stIrExit1: + begin + SendBit(0, 1); + SendBit(0, 0); + end; + + else + rc := false; + end; + end + + // ----------------------------------------------------- + // DRSHIFT + // ----------------------------------------------------- + else if newState = stDrShift then + begin + case fState of + stReset: + begin + SendBit(0, 0); // IDLE + SendBit(0, 1); // DRSELECT + SendBit(0, 0); // DRCAPTURE + SendBit(0, 0); // DRSHIFT + end; + + stIdle: + begin + SendBit(0, 1); // DRSELECT + SendBit(0, 0); // DRCAPTURE + SendBit(0, 0); // DRSHIFT + end; + + stDrPause: + begin + SendBit(0, 1); // DREXIT2 + SendBit(0, 0); // DRSHIFT + end; + + else + rc := false; + end; + end + + // ----------------------------------------------------- + // IRSHIFT + // ----------------------------------------------------- + else if newState = stIrShift then + begin + case fState of + stReset: + begin + SendBit(0, 0); // IDLE + SendBit(0, 1); // DRSELECT + SendBit(0, 1); // IRSELECT + SendBit(0, 0); // IRCAPTURE + SendBit(0, 0); // IRSHIFT + end; + + stIdle: + begin + SendBit(0, 1); // DRSELECT + SendBit(0, 1); // IRSELECT + SendBit(0, 0); // IRCAPTURE + SendBit(0, 0); // IRSHIFT + end; + + stIrPause: + begin + SendBit(0, 1); // IREXIT2 + SendBit(0, 0); // IRSHIFT + end; + + else + rc := false; + end; + end + + // ----------------------------------------------------- + // DRPAUSE + // ----------------------------------------------------- + else if newState = stDrPause then + begin + case fState of + stReset: + begin + SendBit(0, 0); // IDLE + SendBit(0, 1); // DRSELECT + SendBit(0, 0); // DRCAPTURE + SendBit(0, 1); // DREXIT1 + SendBit(0, 0); // DRPAUSE + end; + + stIdle: + begin + SendBit(0, 1); // DRSELECT + SendBit(0, 0); // DRCAPTURE + SendBit(0, 1); // DREXIT1 + SendBit(0, 0); // DRPAUSE + end; + + stDrShift: + begin + SendBit(0, 1); // DREXIT1 + SendBit(0, 0); // DRPAUSE + end; + + else + rc := false; + end; + end + + // ----------------------------------------------------- + // IRPAUSE + // ----------------------------------------------------- + else if newState = stIrPause then + begin + case fState of + stReset: + begin + SendBit(0, 0); // IDLE + SendBit(0, 1); // DRSELECT + SendBit(0, 1); // IRSELECT + SendBit(0, 0); // IRCAPTURE + SendBit(0, 1); // IREXIT1 + SendBit(0, 0); // IRPAUSE + end; + + stIdle: + begin + SendBit(0, 1); // DRSELECT + SendBit(0, 1); // IRSELECT + SendBit(0, 0); // IRCAPTURE + SendBit(0, 1); // IREXIT1 + SendBit(0, 0); // IRPAUSE + end; + + stIrShift: + begin + SendBit(0, 1); // IREXIT1 + SendBit(0, 0); // IRPAUSE + end; + + else + rc := false; + end; + end; + + if rc then + fState := newState; +end; + +// ================================================================================================ +// Pulse +// ================================================================================================ +procedure TjtagBStream.Pulse(n: cardinal); +var + i: cardinal; + +begin + for i := 0 to n - 1 do + begin + fValTCK := 0; + Emit; + fValTCK := 1; + Emit; + end; +end; + +// ================================================================================================ +// Emit +// ================================================================================================ +procedure TjtagBStream.Emit; +var + b: byte; + +begin + b := 0; + + if fValTCK <> 0 then + b := b or fMaskTCK; + if fValTMS <> 0 then + b := b or fMaskTMS; + if fValTDI <> 0 then + b := b or fMaskTDI; + if fValTRST <> 0 then + b := b or fMaskTRST; + if fValENA = 0 then + b := b or fMaskENA; + + fBuffer[fCursor] := b; + INC(fCursor); + + if fCursor > fBufferSize - 1 then + Flush; +end; + +// ================================================================================================ +// Flush +// ================================================================================================ +procedure TjtagBStream.Flush; +begin + if Assigned(fOnFull) then + fOnFull(self, fCEPMode); + + fCursor := 0; + fCursorR := 0; +end; + +function TjtagBStream.FlipByte(Data: byte): byte; +var + i: integer; + +begin + result := 0; + + for i:=0 to 7 do + begin + result := result shl 1; + + if Data and $01 = $01 then + result := result or $1; + + Data := Data shr 1; + end; +end; + +// ================================================================================================ +// Clear +// ================================================================================================ +procedure TjtagBStream.Clear; +var + i: integer; + b: byte; + +begin + b := 0; + + if fValTCK <> 0 then + b := b or fMaskTCK; + if fValTMS <> 0 then + b := b or fMaskTMS; + if fValTDI <> 0 then + b := b or fMaskTDI; + if fValTRST <> 0 then + b := b or fMaskTRST; + if fValENA <> 0 then + b := b or fMaskENA; + + for i := 0 to 1023 do + fBuffer[i] := b; + + fCursor := 0; +end; + +// ================================================================================================ +// SendBit +// ================================================================================================ +procedure TjtagBStream.SendBit(TDI: byte; TMS: byte); +begin + fValTDI := TDI; + fValTMS := TMS; + + Pulse; +end; + +// ================================================================================================ +// SendByte +// +// Send entire byte to the device. If 'last' is 1, TMS will be high for the last bit transmitted, +// forcing transition to EXIT1 state. From EXIT1 state the TAP state will be moved to the specified +// end state, automatically. +// ================================================================================================ +procedure TjtagBStream.SendByte(Value: byte; length: byte; last: boolean); +var + i: integer; + xtdi: byte; + xtms: byte; + val: byte; + +begin + val := Value; + + if (length > 0) and (length < 9) then + begin + for i := 0 to length - 1 do + begin +// xtdi := val and $01; +// val := val shr 1; + + if val and $80 = $80 + then xtdi := 1 + else xtdi := 0; + + val := val shl 1; + + if last and (i = length - 1) + then xtms := 1 + else xtms := 0; + + SendBit(xtdi, xtms); + end; + + if last then + begin + if fState = stDrShift then + begin + fState := stDrExit1; + SetState(fEndDR); + end + + else if fState = stIrShift then + begin + fState := stIrExit1; + SetState(fEndIR); + end + end + end +end; + +// ================================================================================================ +// SendByte +// +// Send entire byte to the device. If 'last' is 1, TMS will be high for the last bit transmitted, +// forcing transition to EXIT1 state. From EXIT1 state the TAP state will be moved to the specified +// end state, automatically. +// ================================================================================================ +procedure TjtagBStream.SendByte(TDI: byte; TDO: byte; SMASK: byte; MASK: byte; + length: word; last: boolean = false); + +begin + +end; + +// ================================================================================================ +// ReceiveByte +// ================================================================================================ +function TjtagBStream.ReceiveByte(length: byte): byte; +var + i: integer; + +begin + result := 0; + + for i := 0 to length - 1 do + begin + if (fBuffer[fCursorR] and fMaskTDO) <> 0 then + result := result or (1 shl i); + + INC(fCursorR, 2); + end; +end; + + +// @@@: Property Handlers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Property Handlers +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ================================================================================================ +// GetData +// ================================================================================================ +function TjtagBStream.GetData(i: word): byte; +begin + if i < 1024 then + result := fBuffer[i] + else + result := 0; +end; + +// ================================================================================================ +// SetData +// ================================================================================================ +procedure TjtagBStream.SetData(i: word; d: byte); +begin + if i < 1024 then + fBuffer[i] := d; +// fBuffer[i] := d and fMaskTDO; + + fCursor := 0; +end; + +// ================================================================================================ +// SetEndDR +// ================================================================================================ +procedure TjtagBStream.SetEndDR(Value: TjtagTapState); +begin + if Value in [stReset, stIdle, stDrPause] then + fEndDR := Value; +end; + +// ================================================================================================ +// SetEndIR +// ================================================================================================ +procedure TjtagBStream.SetEndIR(Value: TjtagTapState); +begin + if Value in [stReset, stIdle, stIrPause] then + fEndIR := Value; +end; + + + +// @@@: Send SVF statements +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Send SVF statements +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +// ================================================================================================ +// SendHTIDR +// ================================================================================================ +procedure TjtagBStream.SendHTIDR(stmt: TsvfAstScan); +var + i: integer; + +begin + // ------------------------------------------- + // Header Instruction Register + // ------------------------------------------- + if stmt.Inst = 'HIR' then + begin + fLenHIR := stmt.LenTDI; + fBitHIR := stmt.Bits; + + for i := 0 to fLenHIR - 1 do + fBufHIR[i] := stmt.DataTDI[i] + + // if stmt.LenTDI = stmt.LenSMASK + // then for i:=0 to fLenHIR -1 do fBufHIR[i] := stmt.DataTDI[i] and stmt.DataSMASK[i] + // else for i:=0 to fLenHIR -1 do fBufHIR[i] := stmt.DataTDI[i] + end + + // ------------------------------------------- + // Trailer Instruction Register + // ------------------------------------------- + else if stmt.Inst = 'TIR' then + begin + fLenTIR := stmt.LenTDI; + fBitTIR := stmt.Bits; + + for i := 0 to fLenTIR - 1 do + fBufTIR[i] := stmt.DataTDI[i] + + // if stmt.LenTDI = stmt.LenSMASK + // then for i:=0 to fLenTIR -1 do fBufTIR[i] := stmt.DataTDI[i] and stmt.DataSMASK[i] + // else for i:=0 to fLenTIR -1 do fBufTIR[i] := stmt.DataTDI[i] + end + + // ------------------------------------------- + // Header Data Register + // ------------------------------------------- + else if stmt.Inst = 'HDR' then + begin + fLenHDR := stmt.LenTDI; + fBitHDR := stmt.Bits; + + for i := 0 to fLenHDR - 1 do + fBufHDR[i] := stmt.DataTDI[i] + + // if stmt.LenTDI = stmt.LenSMASK + // then for i:=0 to fLenHDR -1 do fBufHDR[i] := stmt.DataTDI[i] and stmt.DataSMASK[i] + // else for i:=0 to fLenHDR -1 do fBufHDR[i] := stmt.DataTDI[i] + end + + // ------------------------------------------- + // Trailer Data Register + // ------------------------------------------- + else if stmt.Inst = 'TDR' then + begin + fLenTDR := stmt.LenTDI; + fBitTDR := stmt.Bits; + + for i := 0 to fLenTDR - 1 do + fBufTDR[i] := stmt.DataTDI[i] + + // if stmt.LenTDI = stmt.LenSMASK + // then for i:=0 to fLenTDR -1 do fBufTDR[i] := stmt.DataTDI[i] and stmt.DataSMASK[i] + // else for i:=0 to fLenTDR -1 do fBufTDR[i] := stmt.DataTDI[i] + end +end; + +// ================================================================================================ +// SCAN +// +// Note: Scan statements may define TDO values to check the result from the device. The data length +// of these kind of statements must be less then 512 bits. The checking of the result will be +// done in thos routine, because the bstream will be fulshed before data sending, so the +// buffer will contain the data that must be checked. The event handler must fill then data +// buffer with the readed data. +// ================================================================================================ +procedure TjtagBStream.Send(stmt: TsvfAstScan); +var + i: integer; + n: integer; + b: integer; + l: boolean; + s: string; + t: string; + + x1: byte; + x2: byte; + + zm : boolean; + d : boolean; + +begin + if (stmt.Inst = 'HIR') or + (stmt.Inst = 'TIR') or + (stmt.Inst = 'HDR') or + (stmt.Inst = 'TDR') then + SendHTIDR(stmt) + + // --------------------------------------------------------------- + // SIR + // --------------------------------------------------------------- + else if stmt.Inst = 'SIR' then + begin + // ---------------------------------------- + // Move to IRSHIFT + // ---------------------------------------- + fCEPMode := cmWrite; + State := stIrShift; + + // ---------------------------------------- + // If output checking is necessary, then + // first flush the stream. + // All SIR statement that needs checking + // must fit in one package. + // ---------------------------------------- + if stmt.LenTDI = stmt.LenTDO then + begin + Flush; + fCEPMode := cmRead; + end; + + // ---------------------------------------- + // Send HIR + // ---------------------------------------- + b := fBitHIR mod 8; + if b = 0 then + b := 8; + + for i := 0 to fLenHIR - 1 do + if i <> fLenHIR - 1 then + SendByte(fBufHIR[i], 8) + else + SendByte(fBufHIR[i], b); + + // ---------------------------------------- + // Send SIR + // ---------------------------------------- + b := stmt.Bits mod 8; + if b = 0 then + b := 8; + + l := fBitTIR = 0; + n := (stmt.Bits +7) div 8; +// for i := 0 to stmt.LenTDI - 1 do + + for i := 0 to n - 1 do + if i <> n - 1 + then SendByte(stmt.DataTDI[i], 8) + else SendByte(stmt.DataTDI[i], b, l); + + // ---------------------------------------- + // Send TIR + // ---------------------------------------- + b := fBitTIR mod 8; + if b = 0 then + b := 8; + + for i := 0 to fLenTIR - 1 do + if i <> fLenTIR - 1 + then SendByte(fBufTIR[i], 8) + else SendByte(fBufTIR[i], b, true); + + // ---------------------------------------- + if stmt.LenTDI = stmt.LenTDO then + begin + Flush; + + // ------------------------------------- + // Skip head data + // ------------------------------------- + b := fBitHIR mod 8; + if b = 0 then + b := 8; + + for i := 0 to fLenHIR - 1 do + if i <> fLenHIR - 1 + then ReceiveByte(8) + else ReceiveByte(b); + + // ------------------------------------- + // Check result + // fBuffer contains the readed data. + // ------------------------------------- + for i := 0 to stmt.LenTDI - 1 do + begin + if stmt.LenMASK = stmt.LenTDI then + begin + x1 := ReceiveByte(8) and stmt.DataMASK[i]; + x2 := stmt.DataTDO[i] and stmt.DataMASK[i]; + end + + else + begin + x1 := ReceiveByte(8); + x2 := stmt.DataTDO[i]; + end; + + s := Format('SIR:[%2.2x, %2.2x]', [x1, x2]); + + if Assigned(OnDump) then + OnDump( self, s); + + Application.ProcessMessages; + end; + + fCEPMode := cmWrite; + end; + end + + // --------------------------------------------------------------- + // SDR + // --------------------------------------------------------------- + else if stmt.Inst = 'SDR' then + begin + n := (stmt.Bits +7) div 8; + + // ---------------------------------------- + // Move to DRSHIFT + // ---------------------------------------- + fCEPMode := cmWrite; + State := stDrShift; + + // ---------------------------------------- + // If output checking is necessary, then + // first flush the stream. + // All SDR statement that needs checking + // can fit in one package. + // ---------------------------------------- + if stmt.LenTDI = stmt.LenTDO then + begin + Flush; + fCEPMode := cmRead; + end; + + // ---------------------------------------- + // Send HDR + // ---------------------------------------- + b := fBitHDR mod 8; + if b = 0 then + b := 8; + + for i := 0 to fLenHDR - 1 do + if i <> fLenHDR - 1 + then SendByte(fBufHDR[i], 8) + else SendByte(fBufHDR[i], b); + + // ---------------------------------------- + // Send SDR + // ---------------------------------------- + b := stmt.Bits mod 8; + if b = 0 then + b := 8; + + l := fBitTDR = 0; + +// for i := 0 to stmt.LenTDI - 1 do + for i := 0 to n - 1 do + begin + if i <> n - 1 + then SendByte(stmt.DataTDI[i], 8) + else SendByte(stmt.DataTDI[i], b, l); + + Application.ProcessMessages; + end; + + // ---------------------------------------- + // Send TDR + // ---------------------------------------- + b := fBitTDR mod 8; + if b = 0 then + b := 8; + + for i := 0 to fLenTDR - 1 do + if i <> fLenTDR - 1 + then SendByte(fBufTDR[i], 8) + else SendByte(fBufTDR[i], b, true); + + // ---------------------------------------- + // Check result if any + // ---------------------------------------- + if (stmt.LenTDI = stmt.LenTDO) and (stmt.LenTDI < 129)then + begin + Flush; + + // ------------------------------------- + // Skip head data + // ------------------------------------- + b := fBitHDR mod 8; + if b = 0 then + b := 8; + + for i := 0 to fBitHDR - 1 do + if i <> n - 1 + then x1 := ReceiveByte(8) + else x1 := ReceiveByte(b); + + // ------------------------------------- + // Check result + // fBuffer contains the readed data. + // ------------------------------------- + s := ''; + t := ''; + + // ------------------------------------- + // If MASK is 0000...00 then don't mask + // the data. In this case, the data must + // be dumped only. + // It is a Read operation without check! + // ------------------------------------- + zm := false; + + if stmt.LenMASK = stmt.LenTDO then + begin + zm := true; + + for i:=0 to n-1 do + if stmt.DataMASK[i] <> 0 then + begin + zm := false; + break; + end; + end; + + for i := 0 to n - 1 do + begin + if (stmt.LenSMASK = stmt.LenTDI) and (not zm) + then x1 := ReceiveByte(8) and FlipByte(stmt.DataSMASK[i]) + else x1 := ReceiveByte(8); + + if (stmt.LenMASK = stmt.LenTDO) and (not zm) + then x2 := stmt.DataTDO[i] and FlipByte(stmt.DataMASK[i]) + else x2 := stmt.DataTDO[i]; + + s := Format('%2.2x',[(x1)]) +s; + t := Format('%2.2x',[(x2)]) +t; + + Application.ProcessMessages; + end; + + if Assigned(fOnDump) then + begin + // if mask is zero, then simply dump data ... + if zm then + fOnDump( self, s) + + // ... else check for difference + else begin + d := false; + + for i:=1 to Length(s) do + begin + x1 := ord(s[i]); + x2 := ord(t[i]); + + if ((x1 and x2) <> x2) and (x2 <> 0) then + begin + d := true; + break + end; + end; + + if d then + begin + fOnDump(self,':: '+t); + fOnDump(self,'>> '+s); + end; + end; + end; + + fCEPMode := cmWrite; + end; + + Application.ProcessMessages; + end +end; + +// ================================================================================================ +// RUNTEST +// ================================================================================================ +procedure TjtagBStream.Send(stmt: TsvfAstRuntest); +begin + Pulse(StrToInt(stmt.RunCount)); +end; + +// ================================================================================================ +// STATE +// ================================================================================================ +procedure TjtagBStream.Send(stmt: TsvfAstState); +var + i: integer; + +begin + for i := 0 to stmt.StateCount - 1 do + begin + case stmt.States[i] of + 0: State := jtag.bstream.stReset; + 1: State := jtag.bstream.stIdle; + end + end; +end; + +end. diff --git a/src.jtag/jtag.types.pas b/src.jtag/jtag.types.pas new file mode 100644 index 0000000..91e7a5b --- /dev/null +++ b/src.jtag/jtag.types.pas @@ -0,0 +1,48 @@ +unit jtag.types; + +interface + +type + // ========================================================================= + // Keep this values synchronized with "tri.h" !!!! + // ========================================================================= + TJTAGState = + ( + TS_RESET = 0, + TS_IDLE = 1, + TS_IRPAUSE = 2, + TS_DRPAUSE = 3, + TS_IRSHIFT = 4, + TS_DRSHIFT = 5, + TS_DRCAPT = 6, + TS_IREXIT1 = 7, + TS_DREXIT1 = 8, + + TS_UNDEF = $FF + ); + + IJTAG = interface + procedure init; + procedure trst( value : BYTE); + procedure ena( value : BYTE); + + procedure endir( state : TJTAGState); + procedure enddr( state : TJTAGState); + procedure state( state : TJTAGState); + + procedure sir( data : PBYTE; length: WORD); + procedure sdr( data : PBYTE; length: WORD); + + procedure run( state : TJTAGState; count: WORD); + + procedure test; + end; + + IJTAGLOG = interface + procedure info( msg : string); + procedure warning( msg : string); + end; + +implementation + +end. diff --git a/src.jtag/svf/grammar/jtag.svfLexer.g b/src.jtag/svf/grammar/jtag.svfLexer.g new file mode 100644 index 0000000..dafe65d --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfLexer.g @@ -0,0 +1,247 @@ +unit jtag.svfLexer; + +// ---------------------------------------------------------------------------- +// This section is used for generating "uses" clause in the unit 'svfLexer'. +// Every unit name must be terminated with ';' +// e.g: +// +// uses +// { +// Classes; +// SysUtils; +// } +// ---------------------------------------------------------------------------- +uses +{ +} + +// ---------------------------------------------------------------------------- +// This section is used for generating "const" clause in the unit 'svfLexer'. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +//const +//{ +//} + +// ---------------------------------------------------------------------------- +// This section is used for generating "type" clause in the unit 'svfLexer'. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +type +{ +} + +// ============================================================================ +// Lexer class declaration +// ============================================================================ +lexer TsvfLexer; +// ---------------------------------------------------------------------------- +// Lexer options +// ---------------------------------------------------------------------------- +options +{ + k = 2; + exportVocab = jtag.svfLexer; + caseSensitive = false; +} + +// ---------------------------------------------------------------------------- +// Lexer tokens. Usualy string literals. +// ---------------------------------------------------------------------------- +tokens +{ + // ------------ + // SVF Commands + // ------------ + "ENDDR"; + "ENDIR"; + "FREQUENCY"; + "HDR"; + "HIR"; + "PIO"; + "PIOMAP"; + "RUNTEST"; + "SDR"; + "SIR"; + "STATE"; + "TDR"; + "TIR"; + "TRST"; + + // ------------ + // TAP States + // ------------ + "RESET"; + "IDLE"; + + "DRSELECT"; + "DRCAPTURE"; + "DRSHIFT"; + "DRPAUSE"; + "DREXIT1"; + "DREXIT2"; + "DRUPDATE"; + + "IRSELECT"; + "IRCAPTURE"; + "IRSHIFT"; + "IRPAUSE"; + "IREXIT1"; + "IREXIT2"; + "IRUPDATE"; + + "HZ"; + "TDI"; + "TDO"; + "MASK"; + "SMASK"; + + "IN"; + "OUT"; + "INOUT"; + + "SEC"; + "MAXIMUM"; + "ENDSTATE"; + "TCK"; + "SCK"; + + "ON"; + "OFF"; + "Z"; + "ABSENT"; + + INT; + FLOAT; +} + +// ---------------------------------------------------------------------------- +// Lexer member declarations. +// All user defined member declarations should be placed here. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +memberdecl +{ + protected + fOnNewline : TNotifyEvent; + + public + property OnNewline : TNotifyEvent read fOnNewline write fOnNewline; +} + +// ============================================================================ +// Begin rule definitions +// +// Remember: All lexer rule names must begin with UPPERCASE letter! +// ============================================================================ +SEMI : ';'; +LPAREN : '('; +RPAREN : ')'; + +ID +options +{ + testLiterals = true; +} + : ('A'..'Z' | 'a'..'z') ('A'..'Z' | 'a'..'z' | '0'..'9')* +; + +NUMBER + : + DIGITS { _ttype := TT_INT; } + ( '.' DIGITS { _ttype := TT_FLOAT;} )? + ( EXP (SIGN)? DIGITS { _ttype := TT_FLOAT;} )? + ; + +protected +VECTOR + : + 'H' | 'L' | 'Z' | 'U' | 'D' | 'X' | + 'h' | 'l' | 'z' | 'u' | 'd' | 'x' + ; + +protected +EXP + : 'E' | 'e' + ; + +protected +SIGN + : '+' | '-' + ; + +protected DIGIT : '0'..'9'; +protected DIGITS : (DIGIT)+ ; + +//protected XDIGIT : 'a'..'f' | 'A'..'F' | '0'..'9'; +//protected XDIGITS : (XDIGIT)+ ; + + + + +// ---------------------------------------------------------------------------- +// SLCOMMENT +// ---------------------------------------------------------------------------- +SLCOMMENT + : + ("//" | '!') + ( ~( '\r' | '\n') )* + ( + options + { + generateAmbigWarnings = false; + } + : '\r' '\n' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + | '\r' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + | '\n' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + ) + { + _ttype := TT_SKIP; + } + ; + +// ---------------------------------------------------------------------------- +// NEWLINE +// ---------------------------------------------------------------------------- +NEWLINE + : + ( + options + { + generateAmbigWarnings = false; + } + : '\r' '\n' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + | '\r' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + | '\n' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + ) + { + _ttype := TT_SKIP; + } + ; + +// ---------------------------------------------------------------------------- +// WHITESPACE +// ---------------------------------------------------------------------------- +WHITESPACE + : + ( + ' ' + | '\t' { tab; } + ) + { + _ttype := TT_SKIP; + } + ; + +// ============================================================================ +// End rule definitions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// This section is used for generating member defintions in the unit 'svfLexer'. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +memberdef +{ +} + diff --git a/src.jtag/svf/grammar/jtag.svfLexer.pas b/src.jtag/svf/grammar/jtag.svfLexer.pas new file mode 100644 index 0000000..7b5d396 --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfLexer.pas @@ -0,0 +1,785 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 2.1.0.0r +// Grammar: jtag.svfLexer.g +// ============================================================================ +unit jtag.svfLexer; + +interface + +uses + System.Classes, + dpgrtl.lexer, + dpgrtl.types, + jtag.svfLexerTokens, + SysUtils; + +type + // ========================================================================= + // Type declarations from grammar. + // ========================================================================= + + // ========================================================================= + // Class TsvfLexer declaration + // ========================================================================= + TsvfLexer = class( TLexer) + + protected + fOnNewline : TNotifyEvent; + + public + property OnNewline : TNotifyEvent read fOnNewline write fOnNewline; + + protected // Internals + procedure initialize; override; + + public // Protected grammar rules + // Must callable from parser too + procedure mDIGITS ( pCreate: boolean); + procedure mEXP ( pCreate: boolean); + procedure mSIGN ( pCreate: boolean); + procedure mVECTOR ( pCreate: boolean); + procedure mDIGIT ( pCreate: boolean); + + public // Public grammar rules + procedure mSEMI ( pCreate: boolean); + procedure mLPAREN ( pCreate: boolean); + procedure mRPAREN ( pCreate: boolean); + procedure mID ( pCreate: boolean); + procedure mNUMBER ( pCreate: boolean); + procedure mSLCOMMENT ( pCreate: boolean); + procedure mNEWLINE ( pCreate: boolean); + procedure mWHITESPACE ( pCreate: boolean); + + public + function NextToken: IToken; override; + end; + +implementation +uses + dpgrtl.exception, + dpgrtl.token; + + +// ============================================================================ +// mSEMI +// ============================================================================ +procedure TsvfLexer.mSEMI( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_SEMI; + + match(';'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mLPAREN +// ============================================================================ +procedure TsvfLexer.mLPAREN( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_LPAREN; + + match('('); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mRPAREN +// ============================================================================ +procedure TsvfLexer.mRPAREN( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_RPAREN; + + match(')'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mID +// ============================================================================ +procedure TsvfLexer.mID( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_ID; + + if (( LA(1) in ['A'..'Z'])) then + begin + match( ['A'..'Z']); + end + + else if (( LA(1) in ['a'..'z'])) then + begin + match( ['a'..'z']); + end + + else + Raise EMismatchedChar.Create( LA(1), ['A'..'Z','a'..'z'], InputState.FileName, InputState.Line, InputState.Column); + + while(true) do + begin + if (( LA(1) in ['A'..'Z'])) then + begin + match( ['A'..'Z']); + end + + else if (( LA(1) in ['a'..'z'])) then + begin + match( ['a'..'z']); + end + + else if (( LA(1) in ['0'..'9'])) then + begin + match( ['0'..'9']); + end + + else + break; + end; + + _ttype := TestLiteral( _ttype); + + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mNUMBER +// ============================================================================ +procedure TsvfLexer.mNUMBER( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_NUMBER; + + mDIGITS(false); + _ttype := TT_INT; + if (( LA(1) in ['.'])) then + begin + match('.'); + mDIGITS(false); + _ttype := TT_FLOAT; + end; + if (( LA(1) in ['E','e'])) then + begin + mEXP(false); + if (( LA(1) in ['+','-'])) then + begin + mSIGN(false); + end; + mDIGITS(false); + _ttype := TT_FLOAT; + end; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mDIGITS +// ============================================================================ +procedure TsvfLexer.mDIGITS( pCreate: boolean); +var + _begin: integer; + _cnt_18: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_DIGITS; + + _cnt_18 := 0; + + while(true) do + begin + if (( LA(1) in ['0'..'9'])) then + begin + mDIGIT(false); + end + + else + begin + if _cnt_18 >= 1 then + break + else + Raise EMismatchedChar.Create( LA(1), ['0'..'9'], InputState.FileName, InputState.Line, InputState.Column); + end; + + INC(_cnt_18); + end; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mEXP +// ============================================================================ +procedure TsvfLexer.mEXP( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_EXP; + + if (( LA(1) in ['E'])) then + begin + match('E'); + end + + else if (( LA(1) in ['e'])) then + begin + match('e'); + end + + else + Raise EMismatchedChar.Create( LA(1), ['E','e'], InputState.FileName, InputState.Line, InputState.Column); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mSIGN +// ============================================================================ +procedure TsvfLexer.mSIGN( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_SIGN; + + if (( LA(1) in ['+'])) then + begin + match('+'); + end + + else if (( LA(1) in ['-'])) then + begin + match('-'); + end + + else + Raise EMismatchedChar.Create( LA(1), ['+','-'], InputState.FileName, InputState.Line, InputState.Column); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mVECTOR +// ============================================================================ +procedure TsvfLexer.mVECTOR( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_VECTOR; + + if (( LA(1) in ['H'])) then + begin + match('H'); + end + + else if (( LA(1) in ['L'])) then + begin + match('L'); + end + + else if (( LA(1) in ['Z'])) then + begin + match('Z'); + end + + else if (( LA(1) in ['U'])) then + begin + match('U'); + end + + else if (( LA(1) in ['D'])) then + begin + match('D'); + end + + else if (( LA(1) in ['X'])) then + begin + match('X'); + end + + else if (( LA(1) in ['h'])) then + begin + match('h'); + end + + else if (( LA(1) in ['l'])) then + begin + match('l'); + end + + else if (( LA(1) in ['z'])) then + begin + match('z'); + end + + else if (( LA(1) in ['u'])) then + begin + match('u'); + end + + else if (( LA(1) in ['d'])) then + begin + match('d'); + end + + else if (( LA(1) in ['x'])) then + begin + match('x'); + end + + else + Raise EMismatchedChar.Create( LA(1), ['D','H','L','U','X','Z','d','h','l','u','x','z'], InputState.FileName, InputState.Line, InputState.Column); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mDIGIT +// ============================================================================ +procedure TsvfLexer.mDIGIT( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_DIGIT; + + match( ['0'..'9']); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mSLCOMMENT +// ============================================================================ +procedure TsvfLexer.mSLCOMMENT( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_SLCOMMENT; + + if (( LA(1) in ['/'])) then + begin + match('//'); + end + + else if (( LA(1) in ['!'])) then + begin + match('!'); + end + + else + Raise EMismatchedChar.Create( LA(1), ['!','/'], InputState.FileName, InputState.Line, InputState.Column); + + while(true) do + begin + if (( LA(1) in [#1..#9,#11..#12,#14..#255])) then + begin + match( [#1..#9,#11..#12,#14..#255]); + end + + else + break; + end; + + if (( LA(1) in [#13]) and (LA(2) in [#10])) then + begin + match(#13); + match(#10); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else + Raise EMismatchedChar.Create( LA(1), [#10,#13], InputState.FileName, InputState.Line, InputState.Column); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mNEWLINE +// ============================================================================ +procedure TsvfLexer.mNEWLINE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_NEWLINE; + + if (( LA(1) in [#13]) and (LA(2) in [#10])) then + begin + match(#13); + match(#10); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else + Raise EMismatchedChar.Create( LA(1), [#10,#13], InputState.FileName, InputState.Line, InputState.Column); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mWHITESPACE +// ============================================================================ +procedure TsvfLexer.mWHITESPACE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_WHITESPACE; + + if (( LA(1) in [' '])) then + begin + match(' '); + end + + else if (( LA(1) in [#9])) then + begin + match(#9); + tab; + end + + else + Raise EMismatchedChar.Create( LA(1), [#9,' '], InputState.FileName, InputState.Line, InputState.Column); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ---------------------------------------------------------------------------- +// NextToken +// ---------------------------------------------------------------------------- +function TsvfLexer.NextToken : IToken; +var + _first : TCharSet; + +begin + _first := [#9..#10,#13,' '..'!','('..')','/'..'9',';','A'..'Z','a'..'z']; + + while( true) do + begin + ResetText; + + try + if (( LA(1) in [';'])) then + begin + mSEMI(true); + result := ReturnToken; + end + + else if (( LA(1) in ['('])) then + begin + mLPAREN(true); + result := ReturnToken; + end + + else if (( LA(1) in [')'])) then + begin + mRPAREN(true); + result := ReturnToken; + end + + else if (( LA(1) in ['A'..'Z','a'..'z'])) then + begin + mID(true); + result := ReturnToken; + end + + else if (( LA(1) in ['0'..'9'])) then + begin + mNUMBER(true); + result := ReturnToken; + end + + else if (( LA(1) in ['!','/'])) then + begin + mSLCOMMENT(true); + result := ReturnToken; + end + + else if (( LA(1) in [#10,#13])) then + begin + mNEWLINE(true); + result := ReturnToken; + end + + else if (( LA(1) in [#9,' '])) then + begin + mWHITESPACE(true); + result := ReturnToken; + end + + else + begin + if LA(1) = EOF_CHAR then + begin + uponEof; + result := TToken.Create(TT_EOF); + end + + else + Raise EMismatchedChar.Create(LA(1), _first, InputState.FileName, InputState.Line, InputState.Column); + end; + + // -------------------------------------------------------------- + // If we found a SKIP token, then try again... + // -------------------------------------------------------------- + if result = nil then + continue; + + // -------------------------------------------------------------- + // Now we have a valid token, so exit the function + // -------------------------------------------------------------- + break; + + except + Raise; + end; + end; +end; + +// ---------------------------------------------------------------------------- +// InitLiterals +// ---------------------------------------------------------------------------- +procedure TsvfLexer.initialize; +begin + fCaseSensitive := false; + fLiterals.CaseSensitive := false; + + fLiterals['drselect' ] := 20; + fLiterals['pio' ] := 9; + fLiterals['mask' ] := 37; + fLiterals['absent' ] := 50; + fLiterals['idle' ] := 19; + fLiterals['drupdate' ] := 26; + fLiterals['tdo' ] := 36; + fLiterals['hdr' ] := 7; + fLiterals['ircapture' ] := 28; + fLiterals['enddr' ] := 4; + fLiterals['out' ] := 40; + fLiterals['drpause' ] := 23; + fLiterals['off' ] := 48; + fLiterals['tir' ] := 16; + fLiterals['drexit2' ] := 25; + fLiterals['irupdate' ] := 33; + fLiterals['tdr' ] := 15; + fLiterals['on' ] := 47; + fLiterals['inout' ] := 41; + fLiterals['sdr' ] := 12; + fLiterals['irexit1' ] := 31; + fLiterals['state' ] := 14; + fLiterals['drexit1' ] := 24; + fLiterals['irpause' ] := 30; + fLiterals['endir' ] := 5; + fLiterals['drshift' ] := 22; + fLiterals['maximum' ] := 43; + fLiterals['tdi' ] := 35; + fLiterals['frequency' ] := 6; + fLiterals['hir' ] := 8; + fLiterals['hz' ] := 34; + fLiterals['runtest' ] := 11; + fLiterals['smask' ] := 38; + fLiterals['in' ] := 39; + fLiterals['tck' ] := 45; + fLiterals['z' ] := 49; + fLiterals['reset' ] := 18; + fLiterals['sck' ] := 46; + fLiterals['sir' ] := 13; + fLiterals['irselect' ] := 27; + fLiterals['trst' ] := 17; + fLiterals['irshift' ] := 29; + fLiterals['irexit2' ] := 32; + fLiterals['endstate' ] := 44; + fLiterals['drcapture' ] := 21; + fLiterals['piomap' ] := 10; + fLiterals['sec' ] := 42; +end; + +end. diff --git a/src.jtag/svf/grammar/jtag.svfLexerTokens.pas b/src.jtag/svf/grammar/jtag.svfLexerTokens.pas new file mode 100644 index 0000000..a51cb84 --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfLexerTokens.pas @@ -0,0 +1,77 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 2.1.0.0r +// Grammar: jtag.svfLexer.g +// ============================================================================ +unit jtag.svfLexerTokens; + +interface + +const + LT_DRSELECT = 20; + LT_PIO = 9; + LT_MASK = 37; + LT_ABSENT = 50; + TT_ID = 56; + TT_NEWLINE = 64; + TT_EOF = 1; + TT_SEMI = 53; + TT_DIGIT = 61; + LT_IDLE = 19; + LT_DRUPDATE = 26; + LT_TDO = 36; + LT_HDR = 7; + LT_IRCAPTURE = 28; + LT_ENDDR = 4; + LT_OUT = 40; + LT_DRPAUSE = 23; + LT_OFF = 48; + LT_TIR = 16; + LT_DREXIT2 = 25; + TT_SIGN = 60; + LT_IRUPDATE = 33; + LT_TDR = 15; + TT_RPAREN = 55; + LT_ON = 47; + LT_INOUT = 41; + LT_SDR = 12; + LT_IREXIT1 = 31; + LT_STATE = 14; + TT_DIGITS = 62; + LT_DREXIT1 = 24; + LT_IRPAUSE = 30; + TT_SLCOMMENT = 63; + LT_ENDIR = 5; + LT_DRSHIFT = 22; + LT_MAXIMUM = 43; + LT_TDI = 35; + LT_FREQUENCY = 6; + LT_HIR = 8; + LT_HZ = 34; + LT_RUNTEST = 11; + LT_SMASK = 38; + LT_IN = 39; + LT_TCK = 45; + LT_Z = 49; + LT_RESET = 18; + TT_INT = 51; + LT_SCK = 46; + TT_FLOAT = 52; + TT_VECTOR = 58; + LT_SIR = 13; + TT_EXP = 59; + LT_IRSELECT = 27; + LT_TRST = 17; + LT_IRSHIFT = 29; + TT_LPAREN = 54; + TT_NUMBER = 57; + LT_IREXIT2 = 32; + TT_WHITESPACE = 65; + LT_ENDSTATE = 44; + LT_DRCAPTURE = 21; + LT_PIOMAP = 10; + LT_SEC = 42; + +implementation +end. diff --git a/src.jtag/svf/grammar/jtag.svfLexerTokens.txt b/src.jtag/svf/grammar/jtag.svfLexerTokens.txt new file mode 100644 index 0000000..a075a89 --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfLexerTokens.txt @@ -0,0 +1,65 @@ +// $Delphi Parser Generator: jtag.svfLexer.g -> jtag.svfLexer.gTokens.txt$ +TsvfLexer +LT_DRSELECT="DRSELECT"=20 +LT_PIO="PIO"=9 +LT_MASK="MASK"=37 +LT_ABSENT="ABSENT"=50 +TT_ID=56 +TT_NEWLINE=64 +TT_EOF=1 +TT_SEMI=53 +TT_DIGIT=61 +LT_IDLE="IDLE"=19 +LT_DRUPDATE="DRUPDATE"=26 +LT_TDO="TDO"=36 +LT_HDR="HDR"=7 +LT_IRCAPTURE="IRCAPTURE"=28 +LT_ENDDR="ENDDR"=4 +LT_OUT="OUT"=40 +LT_DRPAUSE="DRPAUSE"=23 +LT_OFF="OFF"=48 +LT_TIR="TIR"=16 +LT_DREXIT2="DREXIT2"=25 +TT_SIGN=60 +LT_IRUPDATE="IRUPDATE"=33 +LT_TDR="TDR"=15 +TT_RPAREN=55 +LT_ON="ON"=47 +LT_INOUT="INOUT"=41 +LT_SDR="SDR"=12 +LT_IREXIT1="IREXIT1"=31 +LT_STATE="STATE"=14 +TT_DIGITS=62 +LT_DREXIT1="DREXIT1"=24 +LT_IRPAUSE="IRPAUSE"=30 +TT_SLCOMMENT=63 +LT_ENDIR="ENDIR"=5 +LT_DRSHIFT="DRSHIFT"=22 +LT_MAXIMUM="MAXIMUM"=43 +LT_TDI="TDI"=35 +LT_FREQUENCY="FREQUENCY"=6 +LT_HIR="HIR"=8 +LT_HZ="HZ"=34 +LT_RUNTEST="RUNTEST"=11 +LT_SMASK="SMASK"=38 +LT_IN="IN"=39 +LT_TCK="TCK"=45 +LT_Z="Z"=49 +LT_RESET="RESET"=18 +TT_INT=51 +LT_SCK="SCK"=46 +TT_FLOAT=52 +TT_VECTOR=58 +LT_SIR="SIR"=13 +TT_EXP=59 +LT_IRSELECT="IRSELECT"=27 +LT_TRST="TRST"=17 +LT_IRSHIFT="IRSHIFT"=29 +TT_LPAREN=54 +TT_NUMBER=57 +LT_IREXIT2="IREXIT2"=32 +TT_WHITESPACE=65 +LT_ENDSTATE="ENDSTATE"=44 +LT_DRCAPTURE="DRCAPTURE"=21 +LT_PIOMAP="PIOMAP"=10 +LT_SEC="SEC"=42 diff --git a/src.jtag/svf/grammar/jtag.svfParser.g b/src.jtag/svf/grammar/jtag.svfParser.g new file mode 100644 index 0000000..902138f --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfParser.g @@ -0,0 +1,376 @@ +unit jtag.svfParser; + +// ---------------------------------------------------------------------------- +// This section is used for generating "uses" clause in the unit 'svfParser'. +// Every unit name must be terminated with ';' +// e.g: +// +// uses +// { +// Classes; +// SysUtils; +// } +// ---------------------------------------------------------------------------- +uses +{ + jtag.svfScanLexer; + + jtag.svfProgram; + jtag.svfAstNode; + jtag.svfAstEndDR; + jtag.svfAstEndIR; + jtag.svfAstState; + jtag.svfAstScan; + jtag.svfAstRuntest; + + dpgrtl.tokenbuffer; + dpgrtl.parserstate; +} + +// ---------------------------------------------------------------------------- +// This section is used for generating "const" clause in the unit 'svfParser'. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +//const +//{ +//} + +// ---------------------------------------------------------------------------- +// This section is used for generating "type" clause in the unit 'svfParser'. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +type +{ +} + +// ============================================================================ +// Parser class declaration +// ============================================================================ +parser TsvfParser; +// ---------------------------------------------------------------------------- +// Parser options +// ---------------------------------------------------------------------------- +options +{ + k = 2; + importVocab = jtag.svfScanLexer; + exportVocab = jtag.svfParser; +} + +// ---------------------------------------------------------------------------- +// Parser member declarations. +// All user defined member declarations should be placed here. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +memberdecl +{ + protected + fProgram : TsvfProgram; + + fScanLexer : TsvfScanLexer; + fOldPS : IParserState; + fNewPS : IParserState; + + public + procedure AfterConstruction; override; + procedure BeforeDestruction; override; + + protected + procedure AddENDDR( Value : byte); + procedure AddENDIR( Value : byte); + procedure AddFREQ( t : IToken); +} + +// ============================================================================ +// Begin rule definitions +// +// Remember: All parser rule names must begin with LOWERCASE letter! +// ============================================================================ +svf[scan: TsvfScanLexer] returns [TsvfProgram] +local +{ + ntb : ITokenBuffer; +} +{ + fScanLexer := scan; + + ntb := TTokenBuffer.Create( fScanLexer); + fOldPS := InputState; + fNewPS := TParserState.Create( ntb); +} + : + (command SEMI)* + + { + result := fProgram; + } + ; + + +command +local +{ + xstate : byte; + sstate : byte; + trst : AnsiString; + s : AnsiString; + astScan : TsvfAstScan; + astState : TsvfAstState; + astRun : TsvfAstRuntest; +} +{ + xstate := stNONDEF; // intermediate state + sstate := stNONDEF; // stable state + trst := ''; + + t := nil; + n := nil; +} + : + "ENDDR" sstate=stable_state { AddENDDR( sstate); } + | "ENDIR" sstate=stable_state { AddENDIR( sstate); } + + + | (t:"HDR" | t:"HIR" | t:"TDR" | t:"TIR" | t:"SDR" | t:"SIR" ) n:INT + { + astScan := TsvfAstScan.Create( t.TokenText, n.TokenText); + } + ( + ("TDI" scandata[0,astScan]) + | ("TDO" scandata[1,astScan]) + | ("MASK" scandata[2,astScan]) + | ("SMASK" scandata[3,astScan]) + )* + + { + fProgram.AddStatement( astScan); + } + + // ----------------------------------------------------- + // STATE + // ----------------------------------------------------- + | "STATE" + { + astState := TsvfAstState.Create; + astState.BeginData; + } + + ( + xstate=state + { + astState.AddState( xstate); + } + )* + + sstate=stable_state + { + astState.AddState( sstate); + astState.EndData; + + fProgram.AddStatement( astState); + } + + // --------------------------------------------------------------- + // RUNTEST + // --------------------------------------------------------------- + | "RUNTEST" + { + astRun := TsvfAstRuntest.Create; + astRun.BeginData; + } + + ( + sstate=stable_state + { + astRun.RunState := sstate; + } + )? + + ( + t:INT s=run_clk + { + astRun.RunCount := t.Tokentext; + astRun.RunClock := s; + } + + ( + (t:INT | t:FLOAT) "SEC" + { + astRun.MinTime := t.TokenText; + } + ( + "MAXIMUM" t:INT "SEC" + { + astRun.MaxTime := t.Tokentext; + } + )? + )? + + | + (t:INT | t:FLOAT) "SEC" + { + astRun.MinTime := t.TokenText; + } + ( + "MAXIMUM" t:INT "SEC" + { + astRun.MaxTime := t.Tokentext; + } + )? + ) + + ( + "ENDSTATE" sstate=stable_state + { + astRun.EndState := sstate; + } + )? + + { + astRun.EndData; + fProgram.AddStatement( astRun); + } + + // --------------------------- + // Not implemented commands... + // --------------------------- + | "TRST" trst=trst_val + | "FREQUENCY" f:FLOAT "HZ" + | "PIO" VECTOR + | "PIOMAP" LPAREN (direction ID)+ RPAREN + ; + +run_clk returns [AnsiString] + : + "TCK" { result := 'TCK'; } + | "SCK" { result := 'SCK'; } + ; + +trst_val returns [AnsiString] + : + "ON" { result := 'ON'; } + | "OFF" { result := 'OFF'; } + | "Z" { result := 'Z'; } + | "ABSENT" { result := 'ABSENT'; } + ; + +state returns [byte] + : + "RESET" { result := stRESET; } + | "IDLE" { result := stIDLE; } + + | "DRSELECT" { result := stDRSELECT; } + | "DRCAPTURE" { result := stDRCAPTURE; } + | "DRSHIFT" { result := stDRSHIFT; } + | "DRPAUSE" { result := stDRPAUSE; } + | "DREXIT1" { result := stDREXIT1; } + | "DREXIT2" { result := stDREXIT2; } + | "DRUPDATE" { result := stDRUPDATE; } + + | "IRSELECT" { result := stIRSELECT; } + | "IRCAPTURE" { result := stIRCAPTURE; } + | "IRSHIFT" { result := stIRSHIFT; } + | "IRPAUSE" { result := stIRPAUSE; } + | "IREXIT1" { result := stIREXIT1; } + | "IREXIT2" { result := stIREXIT2; } + | "IRUPDATE" { result := stIRUPDATE; } + ; + + +stable_state returns [byte] + : + "RESET" { result := stRESET; } + | "IDLE" { result := stIDLE; } + | "DRPAUSE" { result := stDRPAUSE; } + | "IRPAUSE" { result := stIRPAUSE; } + ; + +// ============================================================================ +// This is the tricky part... Use another lexer for scandata parsing. +// ============================================================================ +scandata [idx: byte; scan: TsvfAstScan] +: + LPAREN + { + InputState := fNewPS; + scan.BeginData; + } + + ( + t:XDIGITS + { + case idx of + 0: scan.AddTDI( t.TokenText); + 1: scan.AddTDO( t.TokenText); + 2: scan.AddMASK( t.TokenText); + 3: scan.AddSMASK( t.TokenText); + end; + } + )+ + + RPAREN + { + scan.EndData; + InputState := fOldPS; + } + ; + +direction + : + "IN" | "OUT" | "INOUT" + ; + +// ============================================================================ +// End rule definitions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// This section is used for generating member defintions in the unit 'svfParser'. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +memberdef +{ +// ============================================================================ +// AfterConstruction +// ============================================================================ +procedure TsvfParser.AfterConstruction; +begin + fProgram := TsvfProgram.Create; +end; + +// ============================================================================ +// BeforeDestruction +// ============================================================================ +procedure TsvfParser.BeforeDestruction; +begin + fProgram.Free; +end; + + + + +// ============================================================================ +// ENDDR +// ============================================================================ +procedure TsvfParser.AddENDDR( Value: byte); +begin + fProgram.AddStatement( TsvfAstEndDR.Create( Value)); +end; + +// ============================================================================ +// ENDIR +// ============================================================================ +procedure TsvfParser.AddENDIR( Value: byte); +begin + fProgram.AddStatement( TsvfAstEndIR.Create( Value)); +end; + +// ============================================================================ +// FREQUENCY +// ============================================================================ +procedure TsvfParser.AddFREQ( t: IToken); +begin +end; + +} + diff --git a/src.jtag/svf/grammar/jtag.svfParser.pas b/src.jtag/svf/grammar/jtag.svfParser.pas new file mode 100644 index 0000000..7045301 --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfParser.pas @@ -0,0 +1,688 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 2.1.0.0r +// Grammar: jtag.svfParser.g +// ============================================================================ +unit jtag.svfParser; + +interface + +uses + Classes, + dpgrtl.llkparser, + dpgrtl.parserstate, + dpgrtl.tokenbuffer, + dpgrtl.types, + jtag.svfAstEndDR, + jtag.svfAstEndIR, + jtag.svfAstNode, + jtag.svfAstRuntest, + jtag.svfAstScan, + jtag.svfAstState, + jtag.svfParserTokens, + jtag.svfProgram, + jtag.svfScanLexer, + SysUtils; + +type + // ========================================================================= + // Type declarations from grammar. + // ========================================================================= + + // ========================================================================= + // Class TsvfParser declaration + // ========================================================================= + TsvfParser = class( TLLkParser) + + protected + fProgram : TsvfProgram; + + fScanLexer : TsvfScanLexer; + fOldPS : IParserState; + fNewPS : IParserState; + + public + procedure AfterConstruction; override; + procedure BeforeDestruction; override; + + protected + procedure AddENDDR( Value : byte); + procedure AddENDIR( Value : byte); + procedure AddFREQ( t : IToken); + + public // Public grammar rules + function svf ( scan: TsvfScanLexer): TsvfProgram; + procedure command ; + function stable_state : byte; + procedure scandata ( idx: byte; scan: TsvfAstScan); + function state : byte; + function run_clk : AnsiString; + function trst_val : AnsiString; + procedure direction ; + + end; + +implementation +uses + dpgrtl.exception, + dpgrtl.token; + + +// ============================================================================ +// svf +// ============================================================================ +function TsvfParser.svf( scan: TsvfScanLexer): TsvfProgram; +var + ntb : ITokenBuffer; + +begin + + fScanLexer := scan; + + ntb := TTokenBuffer.Create( fScanLexer); + fOldPS := InputState; + fNewPS := TParserState.Create( ntb); + + + while(true) do + begin + if (( LA(1) in [LT_ENDDR..LT_TRST])) then + begin + command; + match(TT_SEMI); + end + + else + break; + end; + + result := fProgram; +end; + +// ============================================================================ +// command +// ============================================================================ +procedure TsvfParser.command; +var + _cnt_23: integer; + f: IToken; + n: IToken; + t: IToken; + xstate : byte; + sstate : byte; + trst : AnsiString; + s : AnsiString; + astScan : TsvfAstScan; + astState : TsvfAstState; + astRun : TsvfAstRuntest; + +begin + + xstate := stNONDEF; // intermediate state + sstate := stNONDEF; // stable state + trst := ''; + + t := nil; + n := nil; + + if (( LA(1) in [LT_ENDDR])) then + begin + match(LT_ENDDR); + sstate := stable_state; + AddENDDR( sstate); + end + + else if (( LA(1) in [LT_ENDIR])) then + begin + match(LT_ENDIR); + sstate := stable_state; + AddENDIR( sstate); + end + + else if (( LA(1) in [LT_HDR..LT_HIR,LT_SDR..LT_SIR,LT_TDR..LT_TIR])) then + begin + if (( LA(1) in [LT_HDR])) then + begin + t := LT(1); + match(LT_HDR); + end + + else if (( LA(1) in [LT_HIR])) then + begin + t := LT(1); + match(LT_HIR); + end + + else if (( LA(1) in [LT_TDR])) then + begin + t := LT(1); + match(LT_TDR); + end + + else if (( LA(1) in [LT_TIR])) then + begin + t := LT(1); + match(LT_TIR); + end + + else if (( LA(1) in [LT_SDR])) then + begin + t := LT(1); + match(LT_SDR); + end + + else if (( LA(1) in [LT_SIR])) then + begin + t := LT(1); + match(LT_SIR); + end + + else + Raise EMismatchedToken.Create( LT(1), [LT_HDR..LT_HIR,LT_SDR..LT_SIR,LT_TDR..LT_TIR], InputState.FileName); + n := LT(1); + match(TT_INT); + astScan := TsvfAstScan.Create( t.TokenText, n.TokenText); + + while(true) do + begin + if (( LA(1) in [LT_TDI])) then + begin + match(LT_TDI); + scandata(0,astScan); + end + + else if (( LA(1) in [LT_TDO])) then + begin + match(LT_TDO); + scandata(1,astScan); + end + + else if (( LA(1) in [LT_MASK])) then + begin + match(LT_MASK); + scandata(2,astScan); + end + + else if (( LA(1) in [LT_SMASK])) then + begin + match(LT_SMASK); + scandata(3,astScan); + end + + else + break; + end; + + fProgram.AddStatement( astScan); + end + + else if (( LA(1) in [LT_STATE])) then + begin + match(LT_STATE); + astState := TsvfAstState.Create; + astState.BeginData; + + while(true) do + begin + if (( LA(1) in [LT_RESET..LT_IRUPDATE]) and (LA(2) in [LT_RESET..LT_IRUPDATE])) then + begin + xstate := state; + astState.AddState( xstate); + end + + else + break; + end; + + sstate := stable_state; + astState.AddState( sstate); + astState.EndData; + + fProgram.AddStatement( astState); + end + + else if (( LA(1) in [LT_RUNTEST])) then + begin + match(LT_RUNTEST); + astRun := TsvfAstRuntest.Create; + astRun.BeginData; + if (( LA(1) in [LT_RESET..LT_IDLE,LT_DRPAUSE,LT_IRPAUSE])) then + begin + sstate := stable_state; + astRun.RunState := sstate; + end; + if (( LA(1) in [TT_INT]) and (LA(2) in [LT_TCK..LT_SCK])) then + begin + t := LT(1); + match(TT_INT); + s := run_clk; + astRun.RunCount := t.Tokentext; + astRun.RunClock := s; + if (( LA(1) in [TT_INT..TT_FLOAT])) then + begin + if (( LA(1) in [TT_INT])) then + begin + t := LT(1); + match(TT_INT); + end + + else if (( LA(1) in [TT_FLOAT])) then + begin + t := LT(1); + match(TT_FLOAT); + end + + else + Raise EMismatchedToken.Create( LT(1), [TT_INT..TT_FLOAT], InputState.FileName); + match(LT_SEC); + astRun.MinTime := t.TokenText; + if (( LA(1) in [LT_MAXIMUM])) then + begin + match(LT_MAXIMUM); + t := LT(1); + match(TT_INT); + match(LT_SEC); + astRun.MaxTime := t.Tokentext; + end; + end; + end + + else if (( LA(1) in [TT_INT..TT_FLOAT]) and (LA(2) in [LT_SEC])) then + begin + if (( LA(1) in [TT_INT])) then + begin + t := LT(1); + match(TT_INT); + end + + else if (( LA(1) in [TT_FLOAT])) then + begin + t := LT(1); + match(TT_FLOAT); + end + + else + Raise EMismatchedToken.Create( LT(1), [TT_INT..TT_FLOAT], InputState.FileName); + match(LT_SEC); + astRun.MinTime := t.TokenText; + if (( LA(1) in [LT_MAXIMUM])) then + begin + match(LT_MAXIMUM); + t := LT(1); + match(TT_INT); + match(LT_SEC); + astRun.MaxTime := t.Tokentext; + end; + end + + else + Raise EMismatchedToken.Create( LT(1), [TT_INT..TT_FLOAT], InputState.FileName); + if (( LA(1) in [LT_ENDSTATE])) then + begin + match(LT_ENDSTATE); + sstate := stable_state; + astRun.EndState := sstate; + end; + astRun.EndData; + fProgram.AddStatement( astRun); + end + + else if (( LA(1) in [LT_TRST])) then + begin + match(LT_TRST); + trst := trst_val; + end + + else if (( LA(1) in [LT_FREQUENCY])) then + begin + match(LT_FREQUENCY); + f := LT(1); + match(TT_FLOAT); + match(LT_HZ); + end + + else if (( LA(1) in [LT_PIO])) then + begin + match(LT_PIO); + match(TT_VECTOR); + end + + else if (( LA(1) in [LT_PIOMAP])) then + begin + match(LT_PIOMAP); + match(TT_LPAREN); + _cnt_23 := 0; + + while(true) do + begin + if (( LA(1) in [LT_IN..LT_INOUT])) then + begin + direction; + match(TT_ID); + end + + else + begin + if _cnt_23 >= 1 then + break + else + Raise EMismatchedToken.Create( LT(1), [LT_IN..LT_INOUT], InputState.FileName); + end; + + INC(_cnt_23); + end; + match(TT_RPAREN); + end + + else + Raise EMismatchedToken.Create( LT(1), [LT_ENDDR..LT_TRST], InputState.FileName); +end; + +// ============================================================================ +// stable_state +// ============================================================================ +function TsvfParser.stable_state: byte; +begin + + if (( LA(1) in [LT_RESET])) then + begin + match(LT_RESET); + result := stRESET; + end + + else if (( LA(1) in [LT_IDLE])) then + begin + match(LT_IDLE); + result := stIDLE; + end + + else if (( LA(1) in [LT_DRPAUSE])) then + begin + match(LT_DRPAUSE); + result := stDRPAUSE; + end + + else if (( LA(1) in [LT_IRPAUSE])) then + begin + match(LT_IRPAUSE); + result := stIRPAUSE; + end + + else + Raise EMismatchedToken.Create( LT(1), [LT_RESET..LT_IDLE,LT_DRPAUSE,LT_IRPAUSE], InputState.FileName); +end; + +// ============================================================================ +// scandata +// ============================================================================ +procedure TsvfParser.scandata( idx: byte; scan: TsvfAstScan); +var + _cnt_30: integer; + t: IToken; + +begin + + match(TT_LPAREN); + InputState := fNewPS; + scan.BeginData; + _cnt_30 := 0; + + while(true) do + begin + if (( LA(1) in [TT_XDIGITS])) then + begin + t := LT(1); + match(TT_XDIGITS); + case idx of + 0: scan.AddTDI( t.TokenText); + 1: scan.AddTDO( t.TokenText); + 2: scan.AddMASK( t.TokenText); + 3: scan.AddSMASK( t.TokenText); + end; + end + + else + begin + if _cnt_30 >= 1 then + break + else + Raise EMismatchedToken.Create( LT(1), [TT_XDIGITS], InputState.FileName); + end; + + INC(_cnt_30); + end; + match(TT_RPAREN); + scan.EndData; + InputState := fOldPS; +end; + +// ============================================================================ +// state +// ============================================================================ +function TsvfParser.state: byte; +begin + + if (( LA(1) in [LT_RESET])) then + begin + match(LT_RESET); + result := stRESET; + end + + else if (( LA(1) in [LT_IDLE])) then + begin + match(LT_IDLE); + result := stIDLE; + end + + else if (( LA(1) in [LT_DRSELECT])) then + begin + match(LT_DRSELECT); + result := stDRSELECT; + end + + else if (( LA(1) in [LT_DRCAPTURE])) then + begin + match(LT_DRCAPTURE); + result := stDRCAPTURE; + end + + else if (( LA(1) in [LT_DRSHIFT])) then + begin + match(LT_DRSHIFT); + result := stDRSHIFT; + end + + else if (( LA(1) in [LT_DRPAUSE])) then + begin + match(LT_DRPAUSE); + result := stDRPAUSE; + end + + else if (( LA(1) in [LT_DREXIT1])) then + begin + match(LT_DREXIT1); + result := stDREXIT1; + end + + else if (( LA(1) in [LT_DREXIT2])) then + begin + match(LT_DREXIT2); + result := stDREXIT2; + end + + else if (( LA(1) in [LT_DRUPDATE])) then + begin + match(LT_DRUPDATE); + result := stDRUPDATE; + end + + else if (( LA(1) in [LT_IRSELECT])) then + begin + match(LT_IRSELECT); + result := stIRSELECT; + end + + else if (( LA(1) in [LT_IRCAPTURE])) then + begin + match(LT_IRCAPTURE); + result := stIRCAPTURE; + end + + else if (( LA(1) in [LT_IRSHIFT])) then + begin + match(LT_IRSHIFT); + result := stIRSHIFT; + end + + else if (( LA(1) in [LT_IRPAUSE])) then + begin + match(LT_IRPAUSE); + result := stIRPAUSE; + end + + else if (( LA(1) in [LT_IREXIT1])) then + begin + match(LT_IREXIT1); + result := stIREXIT1; + end + + else if (( LA(1) in [LT_IREXIT2])) then + begin + match(LT_IREXIT2); + result := stIREXIT2; + end + + else if (( LA(1) in [LT_IRUPDATE])) then + begin + match(LT_IRUPDATE); + result := stIRUPDATE; + end + + else + Raise EMismatchedToken.Create( LT(1), [LT_RESET..LT_IRUPDATE], InputState.FileName); +end; + +// ============================================================================ +// run_clk +// ============================================================================ +function TsvfParser.run_clk: AnsiString; +begin + + if (( LA(1) in [LT_TCK])) then + begin + match(LT_TCK); + result := 'TCK'; + end + + else if (( LA(1) in [LT_SCK])) then + begin + match(LT_SCK); + result := 'SCK'; + end + + else + Raise EMismatchedToken.Create( LT(1), [LT_TCK..LT_SCK], InputState.FileName); +end; + +// ============================================================================ +// trst_val +// ============================================================================ +function TsvfParser.trst_val: AnsiString; +begin + + if (( LA(1) in [LT_ON])) then + begin + match(LT_ON); + result := 'ON'; + end + + else if (( LA(1) in [LT_OFF])) then + begin + match(LT_OFF); + result := 'OFF'; + end + + else if (( LA(1) in [LT_Z])) then + begin + match(LT_Z); + result := 'Z'; + end + + else if (( LA(1) in [LT_ABSENT])) then + begin + match(LT_ABSENT); + result := 'ABSENT'; + end + + else + Raise EMismatchedToken.Create( LT(1), [LT_ON..LT_ABSENT], InputState.FileName); +end; + +// ============================================================================ +// direction +// ============================================================================ +procedure TsvfParser.direction; +begin + + if (( LA(1) in [LT_IN])) then + begin + match(LT_IN); + end + + else if (( LA(1) in [LT_OUT])) then + begin + match(LT_OUT); + end + + else if (( LA(1) in [LT_INOUT])) then + begin + match(LT_INOUT); + end + + else + Raise EMismatchedToken.Create( LT(1), [LT_IN..LT_INOUT], InputState.FileName); +end; + +// ============================================================================ +// AfterConstruction +// ============================================================================ +procedure TsvfParser.AfterConstruction; +begin + fProgram := TsvfProgram.Create; +end; + +// ============================================================================ +// BeforeDestruction +// ============================================================================ +procedure TsvfParser.BeforeDestruction; +begin + fProgram.Free; +end; + + + + +// ============================================================================ +// ENDDR +// ============================================================================ +procedure TsvfParser.AddENDDR( Value: byte); +begin + fProgram.AddStatement( TsvfAstEndDR.Create( Value)); +end; + +// ============================================================================ +// ENDIR +// ============================================================================ +procedure TsvfParser.AddENDIR( Value: byte); +begin + fProgram.AddStatement( TsvfAstEndIR.Create( Value)); +end; + +// ============================================================================ +// FREQUENCY +// ============================================================================ +procedure TsvfParser.AddFREQ( t: IToken); +begin +end; +end. diff --git a/src.jtag/svf/grammar/jtag.svfParserTokens.pas b/src.jtag/svf/grammar/jtag.svfParserTokens.pas new file mode 100644 index 0000000..baa35e2 --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfParserTokens.pas @@ -0,0 +1,79 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 2.1.0.0r +// Grammar: jtag.svfParser.g +// ============================================================================ +unit jtag.svfParserTokens; + +interface + +const + LT_DRSELECT = 20; + LT_PIO = 9; + LT_MASK = 37; + LT_ABSENT = 50; + TT_ID = 56; + TT_NEWLINE = 64; + TT_EOF = 1; + TT_SEMI = 53; + TT_DIGIT = 61; + LT_TDO = 36; + LT_DRUPDATE = 26; + LT_OUT = 40; + LT_HDR = 7; + LT_OFF = 48; + LT_IRCAPTURE = 28; + LT_ENDDR = 4; + LT_DRPAUSE = 23; + LT_IDLE = 19; + TT_XDIGIT = 66; + LT_TIR = 16; + LT_DREXIT2 = 25; + TT_SIGN = 60; + LT_IRUPDATE = 33; + TT_RPAREN = 55; + LT_TDR = 15; + LT_ON = 47; + LT_INOUT = 41; + LT_SDR = 12; + LT_IREXIT1 = 31; + LT_STATE = 14; + TT_DIGITS = 62; + LT_DREXIT1 = 24; + LT_IRPAUSE = 30; + TT_SLCOMMENT = 63; + LT_ENDIR = 5; + LT_DRSHIFT = 22; + LT_MAXIMUM = 43; + LT_SMASK = 38; + LT_FREQUENCY = 6; + LT_TCK = 45; + LT_HZ = 34; + LT_RUNTEST = 11; + LT_HIR = 8; + LT_IN = 39; + TT_INT = 51; + LT_Z = 49; + LT_TDI = 35; + LT_RESET = 18; + LT_SCK = 46; + TT_VECTOR = 58; + TT_XDIGITS = 67; + LT_SIR = 13; + TT_EXP = 59; + LT_IRSELECT = 27; + LT_TRST = 17; + LT_IRSHIFT = 29; + TT_FLOAT = 52; + TT_LPAREN = 54; + TT_NUMBER = 57; + LT_IREXIT2 = 32; + TT_WHITESPACE = 65; + LT_ENDSTATE = 44; + LT_PIOMAP = 10; + LT_DRCAPTURE = 21; + LT_SEC = 42; + +implementation +end. diff --git a/src.jtag/svf/grammar/jtag.svfParserTokens.txt b/src.jtag/svf/grammar/jtag.svfParserTokens.txt new file mode 100644 index 0000000..0e68129 --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfParserTokens.txt @@ -0,0 +1,67 @@ +// $Delphi Parser Generator: jtag.svfParser.g -> jtag.svfParser.gTokens.txt$ +TsvfParser +LT_DRSELECT="DRSELECT"=20 +LT_PIO="PIO"=9 +LT_MASK="MASK"=37 +LT_ABSENT="ABSENT"=50 +TT_ID=56 +TT_NEWLINE=64 +TT_EOF=1 +TT_SEMI=53 +TT_DIGIT=61 +LT_TDO="TDO"=36 +LT_DRUPDATE="DRUPDATE"=26 +LT_OUT="OUT"=40 +LT_HDR="HDR"=7 +LT_OFF="OFF"=48 +LT_IRCAPTURE="IRCAPTURE"=28 +LT_ENDDR="ENDDR"=4 +LT_DRPAUSE="DRPAUSE"=23 +LT_IDLE="IDLE"=19 +TT_XDIGIT=66 +LT_TIR="TIR"=16 +LT_DREXIT2="DREXIT2"=25 +TT_SIGN=60 +LT_IRUPDATE="IRUPDATE"=33 +TT_RPAREN=55 +LT_TDR="TDR"=15 +LT_ON="ON"=47 +LT_INOUT="INOUT"=41 +LT_SDR="SDR"=12 +LT_IREXIT1="IREXIT1"=31 +LT_STATE="STATE"=14 +TT_DIGITS=62 +LT_DREXIT1="DREXIT1"=24 +LT_IRPAUSE="IRPAUSE"=30 +TT_SLCOMMENT=63 +LT_ENDIR="ENDIR"=5 +LT_DRSHIFT="DRSHIFT"=22 +LT_MAXIMUM="MAXIMUM"=43 +LT_SMASK="SMASK"=38 +LT_FREQUENCY="FREQUENCY"=6 +LT_TCK="TCK"=45 +LT_HZ="HZ"=34 +LT_RUNTEST="RUNTEST"=11 +LT_HIR="HIR"=8 +LT_IN="IN"=39 +TT_INT=51 +LT_Z="Z"=49 +LT_TDI="TDI"=35 +LT_RESET="RESET"=18 +LT_SCK="SCK"=46 +TT_VECTOR=58 +TT_XDIGITS=67 +LT_SIR="SIR"=13 +TT_EXP=59 +LT_IRSELECT="IRSELECT"=27 +LT_TRST="TRST"=17 +LT_IRSHIFT="IRSHIFT"=29 +TT_FLOAT=52 +TT_LPAREN=54 +TT_NUMBER=57 +LT_IREXIT2="IREXIT2"=32 +TT_WHITESPACE=65 +LT_ENDSTATE="ENDSTATE"=44 +LT_PIOMAP="PIOMAP"=10 +LT_DRCAPTURE="DRCAPTURE"=21 +LT_SEC="SEC"=42 diff --git a/src.jtag/svf/grammar/jtag.svfScanLexer.g b/src.jtag/svf/grammar/jtag.svfScanLexer.g new file mode 100644 index 0000000..c5e387f --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfScanLexer.g @@ -0,0 +1,137 @@ +unit jtag.svfScanLexer; + +// ---------------------------------------------------------------------------- +// This section is used for generating "uses" clause in the unit 'svfScanLexer'. +// Every unit name must be terminated with ';' +// e.g: +// +// uses +// { +// Classes; +// SysUtils; +// } +// ---------------------------------------------------------------------------- +uses +{ +} + +// ---------------------------------------------------------------------------- +// This section is used for generating "type" clause in the unit 'svfScanLexer'. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +type +{ +} + +// ============================================================================ +// Lexer class declaration +// ============================================================================ +lexer TsvfScanLexer; +// ---------------------------------------------------------------------------- +// Lexer options +// ---------------------------------------------------------------------------- +options +{ + k = 2; + importVocab = jtag.svfLexer; + exportVocab = jtag.svfScanLexer; + caseSensitive = false; +} + +// ---------------------------------------------------------------------------- +// Lexer tokens. Usualy string literals. +// ---------------------------------------------------------------------------- +tokens +{ +} + +// ---------------------------------------------------------------------------- +// Lexer member declarations. +// All user defined member declarations should be placed here. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +memberdecl +{ + protected + fOnNewline : TNotifyEvent; + + public + property OnNewline : TNotifyEvent read fOnNewline write fOnNewline; +} + +// ============================================================================ +// Begin rule definitions +// +// Remember: All lexer rule names must begin with UPPERCASE letter! +// ============================================================================ +RPAREN: ')'; + +protected XDIGIT: '0'..'9' | 'a'..'f' | 'A'..'F' ; +XDIGITS: (XDIGIT)+; + +// ---------------------------------------------------------------------------- +// SLCOMMENT +// ---------------------------------------------------------------------------- +SLCOMMENT + : + "//" + ( ~( '\r' | '\n') )* + ( + options + { + generateAmbigWarnings = false; + } + : '\r' '\n' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + | '\r' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + | '\n' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + ) + { + _ttype := TT_SKIP; + } + ; + +// ---------------------------------------------------------------------------- +// NEWLINE +// ---------------------------------------------------------------------------- +NEWLINE + : + ( + options + { + generateAmbigWarnings = false; + } + : '\r' '\n' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + | '\r' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + | '\n' { newLine; if Assigned( fOnNewline) then fOnNewline(self); } + ) + { + _ttype := TT_SKIP; + } + ; + +// ---------------------------------------------------------------------------- +// WHITESPACE +// ---------------------------------------------------------------------------- +WHITESPACE + : + ( + ' ' + | '\t' { tab; } + ) + { + _ttype := TT_SKIP; + } + ; + +// ============================================================================ +// End rule definitions +// ============================================================================ + +// ---------------------------------------------------------------------------- +// This section is used for generating member defintions in the unit 'svfScanLexer'. +// The content of the section is verbatim copied into the generated code. +// ---------------------------------------------------------------------------- +memberdef +{ +} + diff --git a/src.jtag/svf/grammar/jtag.svfScanLexer.pas b/src.jtag/svf/grammar/jtag.svfScanLexer.pas new file mode 100644 index 0000000..f87ad1b --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfScanLexer.pas @@ -0,0 +1,448 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 2.1.0.0r +// Grammar: jtag.svfscanLexer.g +// ============================================================================ +unit jtag.svfScanLexer; + +interface + +uses + Classes, + dpgrtl.lexer, + dpgrtl.types, + jtag.svfScanLexerTokens, + SysUtils; + +type + // ========================================================================= + // Type declarations from grammar. + // ========================================================================= + + // ========================================================================= + // Class TsvfScanLexer declaration + // ========================================================================= + TsvfScanLexer = class( TLexer) + + protected + fOnNewline : TNotifyEvent; + + public + property OnNewline : TNotifyEvent read fOnNewline write fOnNewline; + + protected // Internals + procedure initialize; override; + + public // Protected grammar rules + // Must callable from parser too + procedure mXDIGIT ( pCreate: boolean); + + public // Public grammar rules + procedure mRPAREN ( pCreate: boolean); + procedure mXDIGITS ( pCreate: boolean); + procedure mSLCOMMENT ( pCreate: boolean); + procedure mNEWLINE ( pCreate: boolean); + procedure mWHITESPACE ( pCreate: boolean); + + public + function NextToken: IToken; override; + end; + +implementation +uses + dpgrtl.exception, + dpgrtl.token; + + +// ============================================================================ +// mRPAREN +// ============================================================================ +procedure TsvfScanLexer.mRPAREN( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_RPAREN; + + match(')'); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mXDIGIT +// ============================================================================ +procedure TsvfScanLexer.mXDIGIT( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_XDIGIT; + + if (( LA(1) in ['0'..'9'])) then + begin + match( ['0'..'9']); + end + + else if (( LA(1) in ['a'..'f'])) then + begin + match( ['a'..'f']); + end + + else if (( LA(1) in ['A'..'F'])) then + begin + match( ['A'..'F']); + end + + else + Raise EMismatchedChar.Create( LA(1), ['0'..'9','A'..'F','a'..'f'], InputState.FileName, InputState.Line, InputState.Column); + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mXDIGITS +// ============================================================================ +procedure TsvfScanLexer.mXDIGITS( pCreate: boolean); +var + _begin: integer; + _cnt_5: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_XDIGITS; + + _cnt_5 := 0; + + while(true) do + begin + if (( LA(1) in ['0'..'9','A'..'F','a'..'f'])) then + begin + mXDIGIT(false); + end + + else + begin + if _cnt_5 >= 1 then + break + else + Raise EMismatchedChar.Create( LA(1), ['0'..'9','A'..'F','a'..'f'], InputState.FileName, InputState.Line, InputState.Column); + end; + + INC(_cnt_5); + end; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mSLCOMMENT +// ============================================================================ +procedure TsvfScanLexer.mSLCOMMENT( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_SLCOMMENT; + + match('//'); + + while(true) do + begin + if (( LA(1) in [#1..#9,#11..#12,#14..#255])) then + begin + match( [#1..#9,#11..#12,#14..#255]); + end + + else + break; + end; + + if (( LA(1) in [#13]) and (LA(2) in [#10])) then + begin + match(#13); + match(#10); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else + Raise EMismatchedChar.Create( LA(1), [#10,#13], InputState.FileName, InputState.Line, InputState.Column); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mNEWLINE +// ============================================================================ +procedure TsvfScanLexer.mNEWLINE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_NEWLINE; + + if (( LA(1) in [#13]) and (LA(2) in [#10])) then + begin + match(#13); + match(#10); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else if (( LA(1) in [#13])) then + begin + match(#13); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else if (( LA(1) in [#10])) then + begin + match(#10); + newLine; if Assigned( fOnNewline) then fOnNewline(self); + end + + else + Raise EMismatchedChar.Create( LA(1), [#10,#13], InputState.FileName, InputState.Line, InputState.Column); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ============================================================================ +// mWHITESPACE +// ============================================================================ +procedure TsvfScanLexer.mWHITESPACE( pCreate: boolean); +var + _begin: integer; + _save: integer; + _token: IToken; + _ttype: integer; + +begin + _begin := Length( TokenText) +1; + _token := nil; + _ttype := TT_WHITESPACE; + + if (( LA(1) in [' '])) then + begin + match(' '); + end + + else if (( LA(1) in [#9])) then + begin + match(#9); + tab; + end + + else + Raise EMismatchedChar.Create( LA(1), [#9,' '], InputState.FileName, InputState.Line, InputState.Column); + _ttype := TT_SKIP; + + if (_ttype <> TT_SKIP) and (pCreate = true) then + begin + _token := makeToken( _ttype); + _token.TokenText := Copy( TokenText, _begin, Length(TokenText)-_begin+1); + end; + + ReturnToken := _token; +end; + +// ---------------------------------------------------------------------------- +// NextToken +// ---------------------------------------------------------------------------- +function TsvfScanLexer.NextToken : IToken; +var + _first : TCharSet; + +begin + _first := [#9..#10,#13,' ',')','/'..'9','A'..'F','a'..'f']; + + while( true) do + begin + ResetText; + + try + if (( LA(1) in [')'])) then + begin + mRPAREN(true); + result := ReturnToken; + end + + else if (( LA(1) in ['0'..'9','A'..'F','a'..'f'])) then + begin + mXDIGITS(true); + result := ReturnToken; + end + + else if (( LA(1) in ['/'])) then + begin + mSLCOMMENT(true); + result := ReturnToken; + end + + else if (( LA(1) in [#10,#13])) then + begin + mNEWLINE(true); + result := ReturnToken; + end + + else if (( LA(1) in [#9,' '])) then + begin + mWHITESPACE(true); + result := ReturnToken; + end + + else + begin + if LA(1) = EOF_CHAR then + begin + uponEof; + result := TToken.Create(TT_EOF); + end + + else + Raise EMismatchedChar.Create(LA(1), _first, InputState.FileName, InputState.Line, InputState.Column); + end; + + // -------------------------------------------------------------- + // If we found a SKIP token, then try again... + // -------------------------------------------------------------- + if result = nil then + continue; + + // -------------------------------------------------------------- + // Now we have a valid token, so exit the function + // -------------------------------------------------------------- + break; + + except + Raise; + end; + end; +end; + +// ---------------------------------------------------------------------------- +// InitLiterals +// ---------------------------------------------------------------------------- +procedure TsvfScanLexer.initialize; +begin + fCaseSensitive := false; + fLiterals.CaseSensitive := false; + + fLiterals['drselect' ] := 20; + fLiterals['pio' ] := 9; + fLiterals['mask' ] := 37; + fLiterals['absent' ] := 50; + fLiterals['drupdate' ] := 26; + fLiterals['idle' ] := 19; + fLiterals['out' ] := 40; + fLiterals['hdr' ] := 7; + fLiterals['ircapture' ] := 28; + fLiterals['enddr' ] := 4; + fLiterals['off' ] := 48; + fLiterals['drpause' ] := 23; + fLiterals['tdo' ] := 36; + fLiterals['tir' ] := 16; + fLiterals['drexit2' ] := 25; + fLiterals['irupdate' ] := 33; + fLiterals['tdr' ] := 15; + fLiterals['sdr' ] := 12; + fLiterals['inout' ] := 41; + fLiterals['on' ] := 47; + fLiterals['irexit1' ] := 31; + fLiterals['state' ] := 14; + fLiterals['drexit1' ] := 24; + fLiterals['irpause' ] := 30; + fLiterals['endir' ] := 5; + fLiterals['drshift' ] := 22; + fLiterals['maximum' ] := 43; + fLiterals['tdi' ] := 35; + fLiterals['frequency' ] := 6; + fLiterals['hir' ] := 8; + fLiterals['hz' ] := 34; + fLiterals['runtest' ] := 11; + fLiterals['smask' ] := 38; + fLiterals['in' ] := 39; + fLiterals['tck' ] := 45; + fLiterals['z' ] := 49; + fLiterals['reset' ] := 18; + fLiterals['sck' ] := 46; + fLiterals['sir' ] := 13; + fLiterals['irselect' ] := 27; + fLiterals['trst' ] := 17; + fLiterals['irshift' ] := 29; + fLiterals['irexit2' ] := 32; + fLiterals['endstate' ] := 44; + fLiterals['drcapture' ] := 21; + fLiterals['piomap' ] := 10; + fLiterals['sec' ] := 42; +end; + +end. diff --git a/src.jtag/svf/grammar/jtag.svfScanLexerTokens.pas b/src.jtag/svf/grammar/jtag.svfScanLexerTokens.pas new file mode 100644 index 0000000..dd72ffe --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfScanLexerTokens.pas @@ -0,0 +1,79 @@ +// ============================================================================ +// This file is generated by the Delphi Parser Generator. +// ---------------------------------------------------------------------------- +// DPG version: 2.1.0.0r +// Grammar: jtag.svfscanLexer.g +// ============================================================================ +unit jtag.svfScanLexerTokens; + +interface + +const + LT_DRSELECT = 20; + LT_PIO = 9; + LT_MASK = 37; + LT_ABSENT = 50; + TT_ID = 56; + TT_NEWLINE = 64; + TT_EOF = 1; + TT_SEMI = 53; + TT_DIGIT = 61; + LT_DRUPDATE = 26; + LT_IDLE = 19; + LT_OUT = 40; + LT_HDR = 7; + LT_IRCAPTURE = 28; + LT_ENDDR = 4; + LT_OFF = 48; + LT_DRPAUSE = 23; + LT_TDO = 36; + TT_XDIGIT = 66; + LT_TIR = 16; + LT_DREXIT2 = 25; + TT_SIGN = 60; + LT_IRUPDATE = 33; + LT_TDR = 15; + TT_RPAREN = 55; + LT_SDR = 12; + LT_INOUT = 41; + LT_ON = 47; + LT_IREXIT1 = 31; + LT_STATE = 14; + TT_DIGITS = 62; + LT_DREXIT1 = 24; + LT_IRPAUSE = 30; + TT_SLCOMMENT = 63; + LT_ENDIR = 5; + LT_DRSHIFT = 22; + LT_MAXIMUM = 43; + LT_TDI = 35; + LT_FREQUENCY = 6; + LT_HIR = 8; + LT_HZ = 34; + LT_RUNTEST = 11; + LT_SMASK = 38; + LT_IN = 39; + LT_TCK = 45; + LT_Z = 49; + LT_RESET = 18; + TT_INT = 51; + LT_SCK = 46; + TT_FLOAT = 52; + TT_VECTOR = 58; + LT_SIR = 13; + TT_EXP = 59; + LT_IRSELECT = 27; + LT_TRST = 17; + LT_IRSHIFT = 29; + TT_XDIGITS = 67; + TT_LPAREN = 54; + TT_NUMBER = 57; + LT_IREXIT2 = 32; + TT_WHITESPACE = 65; + LT_ENDSTATE = 44; + LT_DRCAPTURE = 21; + LT_PIOMAP = 10; + LT_SEC = 42; + +implementation +end. diff --git a/src.jtag/svf/grammar/jtag.svfScanLexerTokens.txt b/src.jtag/svf/grammar/jtag.svfScanLexerTokens.txt new file mode 100644 index 0000000..65cf0c6 --- /dev/null +++ b/src.jtag/svf/grammar/jtag.svfScanLexerTokens.txt @@ -0,0 +1,67 @@ +// $Delphi Parser Generator: jtag.svfscanLexer.g -> jtag.svfscanLexer.gTokens.txt$ +TsvfScanLexer +LT_DRSELECT="DRSELECT"=20 +LT_PIO="PIO"=9 +LT_MASK="MASK"=37 +LT_ABSENT="ABSENT"=50 +TT_ID=56 +TT_NEWLINE=64 +TT_EOF=1 +TT_SEMI=53 +TT_DIGIT=61 +LT_DRUPDATE="DRUPDATE"=26 +LT_IDLE="IDLE"=19 +LT_OUT="OUT"=40 +LT_HDR="HDR"=7 +LT_IRCAPTURE="IRCAPTURE"=28 +LT_ENDDR="ENDDR"=4 +LT_OFF="OFF"=48 +LT_DRPAUSE="DRPAUSE"=23 +LT_TDO="TDO"=36 +TT_XDIGIT=66 +LT_TIR="TIR"=16 +LT_DREXIT2="DREXIT2"=25 +TT_SIGN=60 +LT_IRUPDATE="IRUPDATE"=33 +LT_TDR="TDR"=15 +TT_RPAREN=55 +LT_SDR="SDR"=12 +LT_INOUT="INOUT"=41 +LT_ON="ON"=47 +LT_IREXIT1="IREXIT1"=31 +LT_STATE="STATE"=14 +TT_DIGITS=62 +LT_DREXIT1="DREXIT1"=24 +LT_IRPAUSE="IRPAUSE"=30 +TT_SLCOMMENT=63 +LT_ENDIR="ENDIR"=5 +LT_DRSHIFT="DRSHIFT"=22 +LT_MAXIMUM="MAXIMUM"=43 +LT_TDI="TDI"=35 +LT_FREQUENCY="FREQUENCY"=6 +LT_HIR="HIR"=8 +LT_HZ="HZ"=34 +LT_RUNTEST="RUNTEST"=11 +LT_SMASK="SMASK"=38 +LT_IN="IN"=39 +LT_TCK="TCK"=45 +LT_Z="Z"=49 +LT_RESET="RESET"=18 +TT_INT=51 +LT_SCK="SCK"=46 +TT_FLOAT=52 +TT_VECTOR=58 +LT_SIR="SIR"=13 +TT_EXP=59 +LT_IRSELECT="IRSELECT"=27 +LT_TRST="TRST"=17 +LT_IRSHIFT="IRSHIFT"=29 +TT_XDIGITS=67 +TT_LPAREN=54 +TT_NUMBER=57 +LT_IREXIT2="IREXIT2"=32 +TT_WHITESPACE=65 +LT_ENDSTATE="ENDSTATE"=44 +LT_DRCAPTURE="DRCAPTURE"=21 +LT_PIOMAP="PIOMAP"=10 +LT_SEC="SEC"=42 diff --git a/src.jtag/svf/jtag.svfAstComment.pas b/src.jtag/svf/jtag.svfAstComment.pas new file mode 100644 index 0000000..e14109c --- /dev/null +++ b/src.jtag/svf/jtag.svfAstComment.pas @@ -0,0 +1,37 @@ +unit jtag.svfAstComment; + +interface +uses + jtag.svfAstNode; + +type + TsvfAstComment = class( TsvfAstNode) + private + fComment : AnsiString; + + public + function AsText: AnsiString; override; + + public + constructor Create(Comment: AnsiString); + + public + property Comment : AnsiString read fComment; + + end; + +implementation + +{ TsvfAstEndDR } + +function TsvfAstComment.AsText: AnsiString; +begin + result := fComment; +end; + +constructor TsvfAstComment.Create(Comment: AnsiString); +begin + fComment := Comment +#13#10 +end; + +end. diff --git a/src.jtag/svf/jtag.svfAstEndDR.pas b/src.jtag/svf/jtag.svfAstEndDR.pas new file mode 100644 index 0000000..df05e9b --- /dev/null +++ b/src.jtag/svf/jtag.svfAstEndDR.pas @@ -0,0 +1,57 @@ +unit jtag.svfAstEndDR; + +interface +uses + jtag.svfAstNode, + jtag.svfLex; + +type + TsvfAstEndDR = class( TsvfAstNode) + private + fState : byte; + + public + function AsText: AnsiString; override; + public + constructor Create(State: byte); + + public + property State: byte read fState; + + end; + +implementation +uses + System.SysUtils, + jtag.svfProgram; + +{ TsvfAstEndDR } + +// ================================================================================================ +// Constructor +// ================================================================================================ +constructor TsvfAstEndDR.Create(State: byte); +begin + inherited Create; + fState := State; +end; + +// ================================================================================================ +// As Text +// ================================================================================================ +function TsvfAstEndDR.AsText: AnsiString; +var + s: AnsiString; + +begin + case fState of + stRESET : s := 'RESET'; + stIDLE : s := 'IDLE'; + stDRPAUSE : s := 'DRPAUSE'; + stIRPAUSE : s := 'IRPAUSE'; + end; + + result := 'ENDDR ' +s+ ';' +#13#10; +end; + +end. diff --git a/src.jtag/svf/jtag.svfAstEndIR.pas b/src.jtag/svf/jtag.svfAstEndIR.pas new file mode 100644 index 0000000..e190ffb --- /dev/null +++ b/src.jtag/svf/jtag.svfAstEndIR.pas @@ -0,0 +1,56 @@ +unit jtag.svfAstEndIR; + +interface +uses + jtag.svfAstNode, + jtag.svfLex; + +type + TsvfAstEndIR = class( TsvfAstNode) + private + fState : byte; + fStateX : TTokenType; + + public + function AsText: AnsiString; override; + + public + constructor Create(State: byte); + + public + property State: byte read fState; + + end; + + +implementation +uses + System.sysutils, + jtag.svfProgram; + +{ TsvfAstEndIR } + +constructor TsvfAstEndIR.Create(State: byte); +begin + inherited Create; + fState := State; +end; + + +function TsvfAstEndIR.AsText: AnsiString; +var + s: AnsiString; + +begin + case fState of + stRESET : s := 'RESET'; + stIDLE : s := 'IDLE'; + stDRPAUSE : s := 'DRPAUSE'; + stIRPAUSE : s := 'IRPAUSE'; + end; + + result := 'ENDIR ' +s+ ';' +#13#10; +end; + + +end. diff --git a/src.jtag/svf/jtag.svfAstFreq.pas b/src.jtag/svf/jtag.svfAstFreq.pas new file mode 100644 index 0000000..33cf4db --- /dev/null +++ b/src.jtag/svf/jtag.svfAstFreq.pas @@ -0,0 +1,37 @@ +unit jtag.svfAstFreq; + +interface +uses + jtag.svfAstNode; + +type + TsvfAstFreq = class( TsvfAstNode) + private + fFrequency: double; + + public + function AsText: AnsiString; override; + public + constructor Create(Freq: double); + + public + property Frequency : double read fFrequency; + end; + +implementation +uses + System.SysUtils; + +{ TsvfAstFreq } + +function TsvfAstFreq.AsText: AnsiString; +begin + result := Format('FREQUENCY %8.4e HZ;',[fFrequency])+#13#10; +end; + +constructor TsvfAstFreq.Create(Freq: double); +begin + fFrequency := Freq +end; + +end. diff --git a/src.jtag/svf/jtag.svfAstNode.pas b/src.jtag/svf/jtag.svfAstNode.pas new file mode 100644 index 0000000..b444a61 --- /dev/null +++ b/src.jtag/svf/jtag.svfAstNode.pas @@ -0,0 +1,22 @@ +unit jtag.svfAstNode; + +interface + +type + TsvfAstNode = class + + + public + function AsText: AnsiString; virtual; + end; + +implementation + +{ TsvfAstNode } + +function TsvfAstNode.AsText: AnsiString; +begin + result := ''; +end; + +end. diff --git a/src.jtag/svf/jtag.svfAstPrint.pas b/src.jtag/svf/jtag.svfAstPrint.pas new file mode 100644 index 0000000..aa7b570 --- /dev/null +++ b/src.jtag/svf/jtag.svfAstPrint.pas @@ -0,0 +1,34 @@ +unit jtag.svfAstPrint; + +interface +uses + jtag.svfAstNode; + +type + TsvfAstPrint = class( TsvfAstNode) + public + Text : AnsiString; + + public + constructor Create( AText: AnsiString); + function AsText: AnsiString; override; + end; + + +implementation +uses + System.AnsiStrings; + +{ TsvfAstPrint } + +function TsvfAstPrint.AsText: AnsiString; +begin + result := Text +end; + +constructor TsvfAstPrint.Create( AText: AnsiString); +begin + Text := AnsiReplaceText(AText, '"', ''); +end; + +end. diff --git a/src.jtag/svf/jtag.svfAstRuntest.pas b/src.jtag/svf/jtag.svfAstRuntest.pas new file mode 100644 index 0000000..3022442 --- /dev/null +++ b/src.jtag/svf/jtag.svfAstRuntest.pas @@ -0,0 +1,110 @@ +unit jtag.svfAstRuntest; + +interface +uses + jtag.svfAstNode; + +type + TsvfAstRuntest = class( TsvfAstNode) + private + fAllowData : boolean; + + public + RunClock : AnsiString; + RunCount : AnsiString; + MinTime : AnsiString; + MaxTime : AnsiString; + RunState : byte; + EndState : byte; + + public + constructor Create; + function AsText: AnsiString; override; + + public + procedure BeginData; + procedure EndData; + end; + +implementation +uses + jtag.svfProgram; + +{ TsvfAstRuntest } + +// @@@: Constructor/destructor ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Constructor/destructor +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ====================================================================================== +// Constructor +// ====================================================================================== +constructor TsvfAstRuntest.Create; +begin + inherited; + + fAllowData := false; + + RunClock := 'TCK'; + RunCount := ''; + MinTime := ''; + MaxTime := ''; + RunState := 1; + EndState := $FF; +end; + +// ====================================================================================== +// BeginData +// ====================================================================================== +procedure TsvfAstRuntest.BeginData; +begin + fAllowData := true; +end; + +// ====================================================================================== +// EndData +// ====================================================================================== +procedure TsvfAstRuntest.EndData; +begin + fAllowData := false; +end; + +// ================================================================================================ +// As Text +// ================================================================================================ +function TsvfAstRuntest.AsText: AnsiString; +begin + result := 'RUNTEST'; + + if RunClock <> ''then + result := result +' '+ RunCount +' '+ RunClock; + + if MinTime <> '' then + result := result +' '+ MinTime +' SEC'; + + if MaxTime <> '' then + result := result +' MAXIMUM '+ MaxTime +' SEC'; + + if EndState <> $FF then + begin + result := result +' ENDSTATE '; + + case EndState of + stRESET : result := result +'RESET'; + stIDLE : result := result +'IDLE'; + stDRPAUSE : result := result +'DRPAUSE'; + stIRPAUSE : result := result +'IRPAUSE'; + else result := result +'InVaLiD'; + end; + end; + + result := result +';' +#13#10#13#10; +end; + + +end. diff --git a/src.jtag/svf/jtag.svfAstScan.pas b/src.jtag/svf/jtag.svfAstScan.pas new file mode 100644 index 0000000..b216fa3 --- /dev/null +++ b/src.jtag/svf/jtag.svfAstScan.pas @@ -0,0 +1,438 @@ +unit jtag.svfAstScan; + +interface +uses + System.SysUtils, + jtag.svfAstNode; + +type + TsvfAstScan = class( TsvfAstNode) + + private + fInst : AnsiString; + fLength : integer; + fBytes : integer; + fNibbles : integer; // memory size in 4 bit nibbles + + fDataTDI : PByte; + fDataTDO : PByte; + fDataMASK : PByte; + fDataSMASK : PByte; + + + fLenTDI : integer; + fLenTDO : integer; + fLenMASK : integer; + fLenSMASK : integer; + + fCursor : integer; + fCursorN : integer; // Cursor in 4 bit nibbles for data input + + strict private + function GetDataTDI : pByteArray; + function GetDataTDO : pByteArray; + function GetDataMASK : pByteArray; + function GetDataSMASK : pByteArray; + + public + function AsText: AnsiString; override; + + public + constructor Create( Inst: AnsiString; Length: AnsiString); + destructor Destroy; override; + + public + procedure AddTDI( Data: AnsiString); + procedure AddTDO( Data: AnsiString); + procedure AddMASK( Data: AnsiString); + procedure AddSMASK( Data: AnsiString); + + procedure BeginData; + procedure EndData; + + public + property Inst : AnsiString read fInst; + property Bits : integer read fLength; + property Bytes : integer read fBytes; + + property DataTDI : PByteArray read GetDataTDI; + property DataTDO : PByteArray read GetDataTDO; + property DataMASK : PByteArray read GetDataMASK; + property DataSMASK: PByteArray read GetDataSMASK; + + property LenTDI : integer read fLenTDI; + property LenTDO : integer read fLenTDO; + property LenMASK : integer read fLenMASK; + property LenSMASK : integer read fLenSMASK; + + end; + +implementation +uses + Winapi.Windows, +// Dialogs, + jtag.svfProgram; + +{ TsvfAstScan } + +function hex2bin( hex: AnsiChar): byte; +begin + case hex of + '0'..'9': result := ord(hex) -ord('0'); + 'a'..'f': result := ord(hex) -ord('a') +10; + 'A'..'F': result := ord(hex) -ord('A') +10; + else result := 0; + end; +end; + +function hex2rbin( hex: AnsiChar): byte; +begin + case hex of + '0': result := $0; + '1': result := $8; + '2': result := $4; + '3': result := $C; + '4': result := $2; + '5': result := $A; + '6': result := $6; + '7': result := $E; + '8': result := $1; + '9': result := $9; + + 'A','a': result := $5; + 'B','b': result := $D; + 'C','c': result := $3; + 'D','d': result := $B; + 'E','e': result := $7; + 'F','f': result := $F; + else result := 0; + end; +end; + +// ================================================================================================ +// Constructor +// ================================================================================================ +constructor TsvfAstScan.Create(Inst: AnsiString; Length: AnsiString); +begin + fInst := Inst; + fLength := StrToIntDef( Length, 0); + fBytes := ((fLength +7) div 8); + fNibbles := ((fLength +3) div 4); + + + fDataTDI := nil; + fDataTDO := nil; + fDataMASK := nil; + fDataSMASK := nil; +end; + + +// ================================================================================================ +// Destructor +// ================================================================================================ +destructor TsvfAstScan.Destroy; +begin + if Assigned( fDataTDI) then FreeMem( fDataTDI); + if Assigned( fDataTDO) then FreeMem( fDataTDO); + if Assigned( fDataMASK) then FreeMem( fDataMASK); + if Assigned( fDataSMASK) then FreeMem( fDataSMASK); + + inherited; +end; + +// ================================================================================================ +// BeginData +// ================================================================================================ +procedure TsvfAstScan.BeginData; +begin +end; + +// ================================================================================================ +// EndData +// ================================================================================================ +procedure TsvfAstScan.EndData; +begin +end; + +// ================================================================================================ +// GetDataTDI +// ================================================================================================ +function TsvfAstScan.GetDataTDI: pByteArray; +begin + result := PByteArray( fDataTDI); +end; + +// ================================================================================================ +// GetDataTDO +// ================================================================================================ +function TsvfAstScan.GetDataTDO: pByteArray; +begin + result := PByteArray( fDataTDO); +end; + +// ================================================================================================ +// GetDataMASK +// ================================================================================================ +function TsvfAstScan.GetDataMASK: pByteArray; +begin + result := PByteArray( fDataMASK); +end; + +// ================================================================================================ +// GetDataSMASK +// ================================================================================================ +function TsvfAstScan.GetDataSMASK: pByteArray; +begin + result := PByteArray( fDataSMASK); +end; + +// ================================================================================================ +// AddTDI +// +// Note: The TDI stream can have an arbitrary length. +// ================================================================================================ +procedure TsvfAstScan.AddTDI( Data: AnsiString); +var + i : integer; + +begin + i := 1; + + if not Assigned( fDataTDI) then + begin + fLenTDI := 0; + fCursor := fBytes -1; + fCursorN := fNibbles -1; + fDataTDI := AllocMem( fBytes); + end; + + while i <= Length(Data) do + begin + if fCursorN mod 2 <> 0 + then DataTDI[fCursorN div 2] := hex2rbin(Data[i]) + else DataTDI[fCursorN div 2] := (hex2rbin(Data[i]) shl 4) or DataTDI[fCursorN div 2]; + + DEC(fCursorN); + + INC(fLenTDI); + INC(i); + +// DataTDI[fCursor] := (hex2bin(Data[i]) shl 4) or hex2bin(Data[i+1]);; + +// DEC(fCursor); +// INC(fLenTDI); + +// INC(i, 2); + end; +end; + +// ================================================================================================ +// AddTDO +// ================================================================================================ +procedure TsvfAstScan.AddTDO( Data: AnsiString); +var + i: integer; + +begin + i := 1; + + if not Assigned( fDataTDO) then + begin + fLenTDO := 0; + fCursor := fBytes -1; + fCursorN := fNibbles -1; + fDataTDO := AllocMem( fBytes); + end; + + while i <= Length(Data) do + begin + if fCursorN mod 2 <> 0 + then DataTDO[fCursorN div 2] := hex2bin(Data[i]) shl 4 + else DataTDO[fCursorN div 2] := hex2bin(Data[i]) or (byte(DataTDO[fCursorN div 2])); + + DEC(fCursorN); + + INC(fLenTDO); + INC(i); + +// DataTDO[fCursor] := (hex2bin(Data[i]) shl 4) or hex2bin(Data[i+1]);; +// +// DEC(fCursor); +// INC(fLenTDO); +// +// INC(i); + end; +end; + +// ================================================================================================ +// AddSMASK +// ================================================================================================ +procedure TsvfAstScan.AddSMASK( Data: AnsiString); +var + i: integer; + +begin + i := 1; + + if not Assigned( fDataSMASK) then + begin + fLenSMASK := 0; + fCursor := fBytes-1; + fCursorN := fNibbles -1; + fDataSMASK := AllocMem( fBytes); + end; + + while i <= Length(Data) do + begin + if fCursorN mod 2 <> 0 + then DataSMASK[fCursorN div 2] := hex2rbin(Data[i]) + else DataSMASK[fCursorN div 2] := (hex2rbin(Data[i]) shl 4) or DataSMASK[fCursorN div 2]; + + DEC(fCursorN); + + INC(fLenSMASK); + INC(i); + +// DataSMASK[fCursor] := (hex2bin(Data[i]) shl 4) or hex2bin(Data[i+1]);; +// DataTDI [fCursor] := DataTDI[fCursor] and DataSMASK[fCursor]; +// +// DEC(fCursor); +// INC(fLenSMASK); +// +// INC(i, 2); + end; +end; + +// ================================================================================================ +// AddMASK +// ================================================================================================ +procedure TsvfAstScan.AddMASK( Data: AnsiString); +var + i: integer; + +begin + i := 1; + + if not Assigned( fDataMASK) then + begin + fLenMASK := 0; + fCursor := fBytes -1; + fCursorN := fNibbles -1; + fDataMASK := AllocMem( fBytes); + end; + + while i <= Length(Data) do + begin + if fCursorN mod 2 <> 0 + then DataMASK[fCursorN div 2] := hex2rbin(Data[i]) + else DataMASK[fCursorN div 2] := (hex2rbin(Data[i]) shl 4) or DataMASK[fCursorN div 2]; + + DEC(fCursorN); + + INC(fLenMASK); + INC(i); + +// DataMASK[fCursor] := (hex2bin(Data[i]) shl 4) or hex2bin(Data[i+1]);; +// +// DEC(fCursor); +// INC(fLenMASK); +// +// INC(i, 2); + end; +end; + +// ================================================================================================ +// AsText +// ================================================================================================ +function TsvfAstScan.AsText: AnsiString; + +const + spc = ' '; + + + function DumpData( PrefixLength: integer; + DataName : AnsiString; + Data : PByte; + DataLength : integer): AnsiString; + var + i : integer; + cnt: integer; + ptr: PByte; + b : byte; + s : AnsiChar; + + + begin + cnt := 0; + ptr := Data; + result := Format( '%-7s(',[DataName]); + + for i:= 0 to DataLength-1 do + begin + if i mod 2 = 0 + then b := (ptr^ shr 4) and $0f + else b := (ptr^ shr 0) and $0f; + + case b of + $0: s := '0'; $1: s := '1'; $2: s := '2'; $3: s := '3'; + $4: s := '4'; $5: s := '5'; $6: s := '6'; $7: s := '7'; + $8: s := '8'; $9: s := '9'; $a: s := 'A'; $b: s := 'B'; + $c: s := 'C'; $d: s := 'D'; $e: s := 'E'; $f: s := 'F'; + end; + + result := result +s; + + if cnt = 60 then + begin + result := result +#13#10+ Copy(spc,1,PrefixLength+8); + cnt := 0; + end; + + INC(cnt); + + if i mod 2 = 1 then + INC(ptr); + end; + + result := result +')'; + end; + + +var + s: AnsiString; + + + +begin + if fLenTDI > 0 + then result := Format('%3s %-8d',[fInst, fLength]) + else result := Format('%3s %d', [fInst, fLength]); + + if fLength > 0 then + begin + if fLenTDI > 0 then + result := result + DumpData( 12, 'TDI', fDataTDI, fLenTDI); + + if fLenSMASK > 0 then + begin + result := result + #13#10+ Copy( spc, 1, 12); + result := result + DumpData( 12, 'SMASK', fDataSMASK, fLenSMASK); + end; + + if fLenTDO > 0 then + begin + result := result + #13#10+ Copy( spc, 1, 12); + result := result + DumpData( 12, 'TDO', fDataTDO, fLenTDO); + end; + + if fLenMASK > 0 then + begin + result := result + #13#10+ Copy( spc, 1, 12); + result := result + DumpData( 12, 'MASK', fDataMASK, fLenMASK); + end; + end; + + result := result +';' +#13#10; +end; + +end. diff --git a/src.jtag/svf/jtag.svfAstState.pas b/src.jtag/svf/jtag.svfAstState.pas new file mode 100644 index 0000000..37b92dd --- /dev/null +++ b/src.jtag/svf/jtag.svfAstState.pas @@ -0,0 +1,168 @@ +unit jtag.svfAstState; + +interface +uses + jtag.svfAstNode; + +type + TsvfAstState = class( TsvfAstNode) + private + fStates : array[0..255] of byte; + fCursor : integer; + fAllowData : boolean; + + function GetStateCount: integer; + function GetState(i:integer): byte; + + public + constructor Create; + + public + function AsText: AnsiString; override; + + procedure BeginData; + procedure EndData; + + procedure AddState( State: byte); + + public + property StateCount : integer read GetStateCount; + property States[i:integer] : byte read GetState; + end; + +implementation +uses + jtag.svfProgram; + +{ TsvfAstState } + +// @@@: Constructor/destructor ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Constructor/destructor +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ====================================================================================== +// Constructor +// ====================================================================================== +constructor TsvfAstState.Create; +begin + fCursor := 0; + fAllowData := false; +end; + +// @@@: Property Handlers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Property Handlers +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ====================================================================================== +// GetStateCount +// ====================================================================================== +function TsvfAstState.GetStateCount: integer; +begin + result := fCursor; +end; + +// ====================================================================================== +// GetState +// ====================================================================================== +function TsvfAstState.GetState(i:integer): byte; +begin + if (i>=0) and (i; + + TAnsiCharSet = set of AnsiChar; + + TsvfMode = ( SVF, HEX); + + TsvfLEX = class + private + fBuffer : PAnsiChar; + fStart : PAnsiChar; + fForward : PAnsiChar; + + fToken : TsvfToken; + fMode : TsvfMode; + + fLiterals: TTokenMap; + + private + procedure InitLiterals; + function CheckLiteral( ttext: AnsiString; ttype: TTokenType): TTokenType; + + function MakeToken( ttype : TTokenType; + ttext : AnsiString): TsvfToken; + + + public + function NextToken : TsvfToken; + + + + public + constructor Create( Stream: TStream); + destructor Destroy; override; + end; + +implementation +uses + WinAPI.Windows, + System.SysUtils; + +{ TsvfLEX } + +// ================================================================================================ +// Constructor +// ================================================================================================ +constructor TsvfLEX.Create(Stream: TStream); +var + size : Int64; + token : TsvfToken; + +begin + InitLiterals; + + if Assigned( Stream) then + begin + size := Stream.Size - Stream.Position; + fBuffer := GetMemory(size+1); + + Stream.Read(fBuffer^, size); + + fMode := SVF; + fStart := fBuffer; + fForward := fBuffer; + fBuffer[size] := #0; + end +end; + +destructor TsvfLEX.Destroy; +begin + FreeAndNil(fLiterals); + inherited; +end; + + + +// @@@: Internals +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Internals +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// MakeToken +// ================================================================================================ +function TsvfLEX.MakeToken(ttype: TTokenType; ttext: AnsiString): TsvfToken; +begin + result := TsvfToken.Create; + + with result do + begin + TokenType := ttype; + + if TokenType in [TT_COMMENT,TT_STRING] + then TokenText := ttext + else TokenText := UpperCase(ttext); + end +end; + +// ================================================================================================ +// InitLiterals +// ================================================================================================ +procedure TsvfLEX.InitLiterals; +begin + fLiterals := TTokenMap.Create; + + fLiterals.Add('HIR', LT_HIR ); + fLiterals.Add('HDR', LT_HDR ); + fLiterals.Add('TIR', LT_TIR ); + fLiterals.Add('TDR', LT_TDR ); + fLiterals.Add('SIR', LT_SIR ); + fLiterals.Add('SDR', LT_SDR ); + fLiterals.Add('TDI', LT_TDI ); + fLiterals.Add('TDO', LT_TDO ); + fLiterals.Add('MASK', LT_MASK ); + fLiterals.Add('SMASK', LT_SMASK ); + + fLiterals.Add('FREQUENCY', LT_FREQUENCY ); + fLiterals.Add('HZ', LT_HZ ); + + fLiterals.Add('PIO', LT_PIO ); + fLiterals.Add('PIOMAP', LT_PIOMAP ); + + fLiterals.Add('RUNTEST', LT_RUNTEST ); + fLiterals.Add('TCK', LT_TCK ); + fLiterals.Add('SCK', LT_SCK ); + fLiterals.Add('SEC', LT_SEC ); + fLiterals.Add('MAXIMUM', LT_MAXIMUM ); + fLiterals.Add('ENDSTATE', LT_ENDSTATE ); + + fLiterals.Add('ENDIR', LT_ENDIR ); + fLiterals.Add('ENDDR', LT_ENDDR ); + fLiterals.Add('STATE', LT_STATE ); + + fLiterals.Add('RESET', LT_RESET ); + fLiterals.Add('IDLE', LT_IDLE ); + + fLiterals.Add('DRSELECT', LT_DRSELECT ); + fLiterals.Add('DRCAPTURE', LT_DRCAPTURE ); + fLiterals.Add('DRSHIFT', LT_DRSHIFT ); + fLiterals.Add('DRUPDATE', LT_DRUPDATE ); + fLiterals.Add('DRPAUSE', LT_DRPAUSE ); + fLiterals.Add('DREXIT1', LT_DREXIT1 ); + fLiterals.Add('DREXIT2', LT_DREXIT2 ); + + fLiterals.Add('IRSELECT', LT_IRSELECT ); + fLiterals.Add('IRCAPTURE', LT_DRCAPTURE ); + fLiterals.Add('IRSHIFT', LT_IRSHIFT ); + fLiterals.Add('IRUPDATE', LT_IRUPDATE ); + fLiterals.Add('IRPAUSE', LT_IRPAUSE ); + fLiterals.Add('IREXIT1', LT_IREXIT1 ); + fLiterals.Add('IREXIT2', LT_IREXIT2 ); + + fLiterals.Add('IN', LT_IN ); + fLiterals.Add('OUT', LT_OUT ); + fLiterals.Add('INOUT', LT_INOUT ); + + fLiterals.Add('TRST', LT_TRST ); + fLiterals.Add('ON', LT_ON ); + fLiterals.Add('OFF', LT_OFF ); + fLiterals.Add('Z', LT_Z ); + fLiterals.Add('ABSENT', LT_ABSENT ); + + fLiterals.Add('PRINT', LT_PRINT ); +end; + +// ================================================================================================ +// CheckLiteral +// ================================================================================================ +function TsvfLEX.CheckLiteral(ttext: AnsiString; ttype: TTokenType): TTokenType; +begin + result := ttype; + fLiterals.TryGetValue(ttext, result); +end; + + + +// @@@: Interface +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Interface +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ================================================================================================ +// NextToken +// ================================================================================================ +function TsvfLEX.NextToken: TsvfToken; + + function GetTokenText: AnsiString; + begin + SetLength( result, fForward-fStart); + MoveMemory( @result[1], fStart, fForward-fStart); + end; + +var + ttext : AnsiString; + ttype : TTokenType; + +begin + while true do + begin + result := nil; + fForward := fStart; + + if fMode = HEX then + case fForward^ of + // ---------------------------------------------------- + // HEX digits + // ---------------------------------------------------- + '0'..'9','a'..'f','A'..'F': + begin + INC(fForward); + + while fForward^ in ['0'..'9','a'..'f','A'..'F'] do + INC(fForward); + + result := MakeToken( TT_HEX, GetTokenText); + fStart := fForward; + end; + + // ---------------------------------------------------- + // HEX end + // ---------------------------------------------------- + ')': + begin + fMode := SVF; + INC(fForward); + + result := MakeToken( TT_RPAREN, ''); + fStart := fForward; + end; + + // ---------------------------------------------------- + // SPACE,TAB + // ---------------------------------------------------- + #32, #9: INC(fStart); + + // ---------------------------------------------------- + // CR/LF + // ---------------------------------------------------- + #13,#10: + begin + INC(fStart); + + while fStart^ in [#13,#10] do + INC(fStart) + end; + + // ---------------------------------------------------- + // Invalid char + // ---------------------------------------------------- + else + ; + end + + else + case fForward^ of + // ---------------------------------------------------- + // String + // ---------------------------------------------------- + '"': + begin + INC(fForward); + + while not (fForward^ in ['"',#13,#10]) do + INC(fForward); + + if fForward^ = '"' then + INC(fForward); + + result := MakeToken( TT_STRING, GetTokenText); + fStart := fForward; + end; + + // ---------------------------------------------------- + // semicolon + // ---------------------------------------------------- + ';': + begin + INC(fForward); + + result := MakeToken( TT_SEMI, ';'); + fStart := fForward; + end; + + // ---------------------------------------------------- + // comment + // ---------------------------------------------------- + '!','/': + begin + if fForward^ = '/' then + begin + INC(fForward); + + if fForward^ <> '/' then + ; //raise + end; + + INC(fForward); + + while not (fForward^ in [#13,#10]) do + INC(fForward); + + result := MakeToken( TT_COMMENT, GetTokenText); + fStart := fForward; + end; + + // ---------------------------------------------------- + // id + // ---------------------------------------------------- + 'a'..'z','A'..'Z': + begin + INC(fForward); + + while fForward^ in ['a'..'z','A'..'Z'] do + INC(fForward); + + ttext := GetTokenText; + ttype := CheckLiteral( ttext, TT_ID); + result := MakeToken( ttype, ttext); + fStart := fForward; + end; + + // ---------------------------------------------------- + // number + // ---------------------------------------------------- + '0'..'9': + begin + INC(fForward); + + while fForward^ in ['0'..'9'] do + INC(fForward); + + if fForward^ = '.' then + begin + INC(fForward); + + while fForward^ in ['0'..'9'] do + INC(fForward) + end; + + if fForward^ in ['e','E'] then + begin + INC(fForward); + + if fForward^ in ['+','-'] then + begin + INC(fForward); + + if fForward^ in ['0'..'9'] then + begin + INC(fForward); + + while fForward^ in ['0'..'9'] do + INC(fForward); + end + + else + // raise + end + else + ; // raise + + end; + + result := MakeToken( TT_NUMBER, GetTokenText); + fStart := fForward; + end; + + // ---------------------------------------------------- + // HEX start + // ---------------------------------------------------- + '(': + begin + fMode := HEX; + INC(fForward); + + result := MakeToken( TT_LPAREN, ''); + fStart := fForward; + end; + + // ---------------------------------------------------- + // WS,CR/LF + // ---------------------------------------------------- + #32, #9: INC(fStart); + + #13,#10: + begin + INC(fStart); + + while fStart^ in [#13,#10] do + INC(fStart) + end; + + // ---------------------------------------------------- + // EOF + // ---------------------------------------------------- + #0: + begin + result := MakeToken( TT_EOF, ''); + fStart := fForward; + end; + + // ---------------------------------------------------- + // invalid + // ---------------------------------------------------- + else + begin + fStart := 0; + break; + end; + end; + + + if Assigned(result) then + break; + end; +end; + + + +end. diff --git a/src.jtag/svf/jtag.svfPar.pas b/src.jtag/svf/jtag.svfPar.pas new file mode 100644 index 0000000..7d718d2 --- /dev/null +++ b/src.jtag/svf/jtag.svfPar.pas @@ -0,0 +1,424 @@ +unit jtag.svfPar; + +interface +uses + jtag.svfLex, + jtag.svfProgram; + +type + TsvfPar = class + private + fLex : TsvfLex; + fPrg : TsvfProgram; + + protected + function Match( ttype : TTokenType; dispose: boolean=true):TsvfToken; overload; + function Match( ttypes : TTokenTypes; dispose: boolean=true):TsvfToken; overload; + + public + function SvfProgram: TsvfProgram; + + public + constructor Create( Lex: TsvfLex); + destructor Destroy; override; + end; + +implementation +uses + System.SysUtils, + jtag.svfAstEndDR, + jtag.svfAstEndIR, + jtag.svfAstFreq, + jtag.svfAstRuntest, + jtag.svfAstScan, + jtag.svfAstState, + jtag.svfAstPrint, + jtag.svfAstComment; + + +{ TsvfPar } + +constructor TsvfPar.Create(Lex: TsvfLex); +begin + inherited Create; + + fLex := Lex; + fPrg := TsvfProgram.Create; +end; + +destructor TsvfPar.Destroy; +begin + inherited; +end; + +// ================================================================================================ +// Match token +// ================================================================================================ +function TsvfPar.Match( ttype: TTokenType; dispose: boolean):TsvfToken; +var + t: TsvfToken; + +begin + t := fLex.NextToken; + + if t.TokenType = ttype then + if dispose + then t.Free + else result := t + else + raise Exception.Create('Unexpected token'); +end; + +// ================================================================================================ +// Match tokens +// ================================================================================================ +function TsvfPar.Match(ttypes: TTokenTypes; dispose: boolean): TsvfToken; +var + token: TsvfToken; + +begin + result := nil; + token := fLex.NextToken; + + if token.TokenType in ttypes then + if dispose + then token.Free + else result := token + else + raise Exception.Create('Unexpected token'); +end; + + +// ================================================================================================ +// SVF Program +// ================================================================================================ +function TsvfPar.SvfProgram : TsvfProgram; + + function EndState( ttype: TTokenType): byte; + begin + case ttype of + LT_IDLE : result := stIDLE; + LT_RESET : result := stRESET; + LT_IRPAUSE : result := stIRPAUSE; + LT_DRPAUSE : result := stDRPAUSE; + + else + raise Exception.Create('Invalid end state'); + end; + end; + + function RunState( ttype: TTokenType): byte; + begin + case ttype of + LT_IDLE : result := stIDLE; + LT_RESET : result := stRESET; + LT_IRPAUSE : result := stIRPAUSE; + LT_DRPAUSE : result := stDRPAUSE; + + else + raise Exception.Create('Invalid run state'); + end; + end; + + function GenState( ttype: TTokenType): byte; + begin + case ttype of + LT_RESET : result := stRESET; + LT_IDLE : result := stIDLE; + + LT_DRSELECT : result := stDRSELECT; + LT_DRCAPTURE: result := stDRCAPTURE; + LT_DRSHIFT : result := stDRSHIFT; + LT_DREXIT1 : result := stDREXIT1; + LT_DRPAUSE : result := stDRPAUSE; + LT_DREXIT2 : result := stDREXIT2; + LT_DRUPDATE : result := stDRUPDATE; + + LT_IRSELECT : result := stIRSELECT; + LT_IRCAPTURE: result := stIRCAPTURE; + LT_IRSHIFT : result := stIRSHIFT; + LT_IREXIT1 : result := stIREXIT1; + LT_IRPAUSE : result := stIRPAUSE; + LT_IREXIT2 : result := stIREXIT2; + LT_IRUPDATE : result := stIRUPDATE; + + else + raise Exception.Create('Invalid run state'); + end; + end; + +var + cmd: TsvfToken; + p1 : TsvfToken; + p2 : TsvfToken; + p3 : TsvfToken; + + f : double; + scan : TsvfAstScan; + run : TsvfAstRuntest; + st : TsvfAstState; + + tt1 : TTokenTypes; + tt2 : TTokenTypes; + tt1s : TTokenTypes; + +begin + result := nil; + scan := nil; + + tt1 := [LT_DRSELECT .. LT_DRPAUSE]; + tt2 := [LT_RESET .. LT_DRPAUSE]; + tt1s := [LT_DRSELECT .. LT_DRPAUSE,TT_SEMI]; + + + if Assigned(fLex) then + begin + while true do + begin + p1 := nil; + p2 := nil; + p3 := nil; + cmd := fLex.NextToken; + + case cmd.TokenType of + // ---------------------------------------------------------------- + // PRINT + // ---------------------------------------------------------------- + LT_PRINT: + begin + p1 := Match(TT_STRING, false); + fPrg.AddStatement( TsvfAstPrint.Create(p1.TokenText)); + p1.Free + end; + + + // ---------------------------------------------------------------- + // ENDIR, ENDDR + // ---------------------------------------------------------------- + LT_ENDIR,LT_ENDDR: + begin + p1 := Match([LT_RESET,LT_IDLE,LT_DRPAUSE,LT_IRPAUSE],false); + Match(TT_SEMI); + + case cmd.TokenType of + LT_ENDIR: fPrg.AddStatement( TsvfAstEndIR.Create(EndState(p1.TokenType))); + LT_ENDDR: fPrg.AddStatement( TsvfAstEndDR.Create(EndState(p1.TokenType))); + end; + + p1.Free + end; + + // ---------------------------------------------------------------- + // FREQUENCY + // ---------------------------------------------------------------- + LT_FREQUENCY: + begin + f := 1E6; + p1 := Match([TT_NUMBER,TT_SEMI],false); + + if p1.TokenType <> TT_SEMI then + begin + Match(LT_HZ); + Match(TT_SEMI); + + f := StrToFloat(p1.TokenText); + end; + + fPrg.AddStatement( TsvfAstFreq.Create( f)); + + p1.Free + end; + + // ---------------------------------------------------------------- + // HIR,HDR,TIR,TDR,SIR,SDR + // ---------------------------------------------------------------- + LT_HIR,LT_HDR,LT_TIR,LT_TDR,LT_SIR,LT_SDR: + begin + p1 := Match( TT_NUMBER, false); + p2 := Match( [LT_TDI,LT_TDO,LT_MASK,LT_SMASK,TT_SEMI], false); + + scan := TsvfAstScan.Create(cmd.TokenText, p1.TokenText); + + while p2.TokenType <> TT_SEMI do + begin + Match(TT_LPAREN); + + scan.BeginData; + + while true do + begin + p3 := Match( [TT_HEX,TT_RPAREN],false); + + if p3.TokenType = TT_RPAREN then + begin + scan.EndData; + + p3.Free; + break; + end; + + case p2.TokenType of + LT_TDI : scan.AddTDI( p3.TokenText); + LT_TDO : scan.AddTDO( p3.TokenText); + LT_MASK : scan.AddMASK( p3.TokenText); + LT_SMASK : scan.AddSMASK( p3.TokenText); + end; + + p3.Free; + end; + + p2.Free; + p2 := Match( [LT_TDI,LT_TDO,LT_MASK,LT_SMASK,TT_SEMI], false); + end; + + FreeAndNil(p2); + FreeAndNil(p1); + + fPrg.AddStatement(scan); + end; + + // ---------------------------------------------------------------- + // RUNTEST + // ---------------------------------------------------------------- + LT_RUNTEST: + begin + run := TsvfAstRuntest.Create; + + p1 := nil; + p2 := fLex.NextToken; + + if p2.TokenType <> TT_NUMBER then + begin + p1 := p2; + p2 := Match( TT_NUMBER, false); + end; + + if Assigned(p1) then + run.RunState:= RunState(p1.TokenType); + + p3 := Match( [LT_SCK,LT_TCK,LT_SEC], false); + + if p3.TokenType in [LT_SCK,LT_TCK] then + begin + run.RunClock := p3.TokenText; + run.RunCount := p2.TokenText; + end + + else begin + run.MinTime := p2.TokenText; + end; + + FreeAndNil(p3); + FreeAndNil(p2); + FreeAndNil(p1); + + p1 := Match( [TT_NUMBER,LT_MAXIMUM,LT_ENDSTATE,TT_SEMI], false); + + if p1.TokenType = TT_NUMBER then + begin + Match(LT_SEC); + run.MinTime := p1.TokenText; + + FreeAndNil(p1); + p1 := Match([LT_MAXIMUM,LT_ENDSTATE,TT_SEMI],false) + end; + + if p1.TokenType = LT_MAXIMUM then + begin + Match(LT_SEC); + run.MaxTime := p1.TokenText; + + FreeAndNil(p1); + p1 := Match([LT_ENDSTATE,TT_SEMI],false); + end; + + if p1.TokenType = LT_ENDSTATE then + begin + p2 := Match(tt2,false); + run.EndState := EndState(p2.TokenType); + + FreeAndNil(p2); + FreeAndNil(p1); + + p1 := Match(TT_SEMI, false); + end; + + FreeAndNil(p1); + + fPrg.AddStatement(run); + end; + + + // ---------------------------------------------------------------- + // STATE + // ---------------------------------------------------------------- + LT_STATE: + begin + st := TsvfAstState.Create; + p1 := Match( tt1,false); + + st.BeginData; + + while p1.TokenType <> TT_SEMI do + begin + st.AddState(GenState(p1.TokenType)); + + // stable state can be followed with SEMI + if p1.TokenType in tt2 then + begin + p1.Free; + p1 := Match( tt1s,false); + end + + else begin + p1.Free; + p1 := Match( tt1,false); + end; + end; + + FreeAndNil(p1); + + st.EndData; + fPrg.AddStatement(st); + end; + + // ---------------------------------------------------------------- + // TRST + // ---------------------------------------------------------------- + LT_TRST: + begin + p1 := Match( [LT_ON,LT_OFF,LT_Z,LT_ABSENT],false); + Match(TT_SEMI); + + // ... + + p1.Free + end; + + // ---------------------------------------------------------------- + // Comment + // ---------------------------------------------------------------- + TT_COMMENT: + begin + fPrg.AddStatement( TsvfAstComment.Create(cmd.TokenText)); + end; + + + // ---------------------------------------------------------------- + // End Of File + // ---------------------------------------------------------------- + TT_EOF: + begin + cmd.Free; + break; + end; + end; + + cmd.Free; + end; + + result := fPrg; + end; +end; + +end. diff --git a/src.jtag/svf/jtag.svfProgram.pas b/src.jtag/svf/jtag.svfProgram.pas new file mode 100644 index 0000000..ba722d5 --- /dev/null +++ b/src.jtag/svf/jtag.svfProgram.pas @@ -0,0 +1,155 @@ +unit jtag.svfProgram; + +interface +uses + jtag.svfAstNode, + System.Contnrs; + +const + stRESET = 0; + stIDLE = 1; + + stDRSELECT = 2; + stDRCAPTURE = 3; + stDRSHIFT = 4; + stDRPAUSE = 5; + stDREXIT1 = 6; + stDREXIT2 = 7; + stDRUPDATE = 8; + + stIRSELECT = 9; + stIRCAPTURE = 10; + stIRSHIFT = 11; + stIRPAUSE = 12; + stIREXIT1 = 13; + stIREXIT2 = 14; + stIRUPDATE = 15; + + stNONDEF = $ff; + +type + TsvfProgram = class + private + fStatements : TObjectList; + + function GetStatementCount : integer; + function GetStatement(i: integer): TsvfAstNode; + + public + procedure AddStatement( Stmt: TsvfAstNode); + + public + constructor Create; + destructor Destroy; override; + + procedure Dump( FileName: string); + + public + property StatementCount : integer read GetStatementCount; + property Statements[i: integer] : TsvfAstNode read GetStatement; + + end; + +implementation +uses + System.Classes; + +{ TsvfProgram } + +// @@@: Constructor/destructor ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Constructor/destructor +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ====================================================================================== +// Constructor +// ====================================================================================== +constructor TsvfProgram.Create; +begin + inherited; + fStatements := TObjectList.Create( true); +end; + +// ====================================================================================== +// Destructor +// ====================================================================================== +destructor TsvfProgram.Destroy; +begin + fStatements.Free; + inherited; +end; + +// @@@: Interface +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Interface +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ====================================================================================== +// AddStatement +// ====================================================================================== +procedure TsvfProgram.AddStatement(Stmt: TsvfAstNode); +begin + fStatements.Add( Stmt); +end; + +// ================================================================================================ +// Dump +// ================================================================================================ +procedure TsvfProgram.Dump(FileName: string); +var + i : integer; + s : AnsiString; + stm : TMemoryStream; + + +begin + stm := TMemoryStream.Create; + + for i:=0 to StatementCount -1 do + begin + s := Statements[i].AsText; + stm.Write(s[1], Length(s)); + end; + + stm.SaveToFile(FileName); + stm.Free +end; + + +// @@@: Property Handlers +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Property Handlers +// +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// ====================================================================================== +// GetStatementCount +// ====================================================================================== +function TsvfProgram.GetStatementCount: integer; +begin + result := fStatements.Count; +end; + +// ====================================================================================== +// GetStatement +// ====================================================================================== +function TsvfProgram.GetStatement(i: integer): TsvfAstNode; +begin + if (i>=0) and (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. diff --git a/src.jtag/vme/jtag.vme.pas b/src.jtag/vme/jtag.vme.pas new file mode 100644 index 0000000..2173f51 --- /dev/null +++ b/src.jtag/vme/jtag.vme.pas @@ -0,0 +1,2900 @@ +unit jtag.vme; + +interface +uses + jtag.types, + Classes; + +const + VME_VERSION_NUMBER = '12.1'; + + // + // Maximum declarations + // + VMEHEXMAX = 60000; // The hex file is split 60k per file + SCANMAX = 64000; // The maximum SDR/SIR burst + + // + // Supported JTAG state transitions + // + +type + TJTAGTransition = packed record + CurrState : TJTAGState; // Transition from this state. + NextState : TJTAGState; // Transition to this state. + Pattern : byte; // The targetory of TMS + Pulses : byte; // The number of steps. + end; + + // + // Flow control register nit definitions. A set bit indicates + // that the register currently exhibits the corresponding mode. + // + TFlowControlBit = + ( + fcbIntelPrgm, // Intelligent programming is in effect. + fcbCascade, // Currently splitting large SDR. + fcbRepeatLoop, // Currently executing a repeat loop. + fcbShiftRight, // The next data stream needs a right shift. + fcbShiftLeft, // The next data stream needs a right left. + fcbVerifyUES // Continue if fail is in effect. + ); + + TFlowControl = set of TFlowControlBit; + + // + // DataType register bit definitions. A set bit indicates that the + // register currently holds the corresponding type of data. + // + TDataTypeBit = + ( + dtExpress, // Simultaneous program and verify. + dtCompress, // Data is compressed + dtSIRData, // SIR is the active SVF command. + dtSDRData, // SDR is the active SVF command. + dtTDIData, // TDI data is present. + dtTDOData, // TDO data is present. + dtMASKData, // MASK data is present. + dtCRCData, // CRC data is present. + dtHeap, // Data is from the heap. + dtLHeap, // Data is from intel data buffer. + dtVariable, // Data is from a declared variable. + dtCMASKData, // CMASK data is present. + dtDMASKData, // DMASK data is present. + dtRMASKData, // RMASK data is present, + dtREADData // READ data is present. + ); + + TDataType = set of TDataTypeBit; + + TVendor = + ( + vLattice = 1, + vAltera = 2, + vXilinx = 3 + ); + + + // + // Opcode definitions + // + TOpcode = + ( + opEndData = $00, // The end of the current SDR data stream. + opRunTest = $01, // The duration to stay at the stable state. + opEndDR = $02, // The stable state after SDR. + opEndIR = $03, // The stable state after SIR. + opEndState = $04, // The stable state after RUNTEST. + opTRST = $05, // Assert the TRST pin. + opHIR = $06, // The sum of the IR bits of the leading devices. + opTIR = $07, // The sum of the IR bits of the trailing devices. + opHDR = $08, // The number of leading devices. + opTDR = $09, // The number of trailing devices. + opIspEN = $0a, // Assert the ispEN pin. + opFrequency = $0b, // The maximum clock rate to run the JTAG state machine. + opState = $10, // Move to the next stable(?) state. + opSIR = $11, // The instruction stream follows. + opSDR = $12, // The data stream follows. + opTDI = $13, // The following data stream feeds into device. + opTDO = $14, // The following data stream is compared against the device. + opMASK = $15, // The following data stream is used as a mask. + opXSDR = $16, // The following data stream is for simultaneous program and verify. + opXTDI = $17, // The following data stream is for shift in only. It must be stored + // for the next XSDR. + opXTDO = $18, // There is no data stream. The data stream was stored from the + // previous XTDI. + opMEM = $19, // The maximum memory needed to allocate in order to hold one row of data. + opWAIT = $1A, // The duration of delay to observe. + opTCK = $1B, // The number of TCK pulses. + opSEC = $1C, // The delay time in seconds that must be observed. + opSMASK = $1D, // The mask for TDI data. + opMAX = $1E, // The absolute maximum wait time. + opON = $1F, // Assert the targeted pin. + opOFF = $20, // Deassert the targeted pin. + opSHR = $23, // Set the flow control register for right shift. + opSHL = $24, // Set the flow control register for left shift. + opSetFlow = $30, // Change the flow control register. + opResetFlow = $31, // Clear the flow control register. + opHEAP = $32, // The memory size needed to hold one loop. + opREPEAT = $33, // The beginning of the loop. + opLeftParen = $35, // The beginning of data following the loop. + opVAR = $55, // Placeholder for loop data. + opCRC = $47, // The following data stream is used for CRC calculation. + opCMask = $48, // The following data steram is used as a mask for CRC calculation. + opRMask = $49, // The following data stream is used as a mask for read and save. + opREAD = $50, // The following data stream is used for read and save. + opVendor = $56, // Vendor code. + opENDLOOP = $59, // The end of the repeat loop. + opSecureHeap= $60, // Used to secure the HEAP opcode. + opVUES = $61, // Support continue if fail. + opDMask = $62, // The following data stream is used for dynamic I/O. + opComment = $63, // Support SVF comments in the VME file. + opHeader = $64, // Support header in VME file. + opFileCRC = $65, // Support crc-protected VME file. + opLCount = $66, // Support intelligent programming. + opLDelay = $67, // Support intelligent programming. + opLSDR = $68, // Support intelligent programming. + opLHeap = $69, // Memory needed to hold intelligent data buffer. + opContinue = $70, // Allow continuation. + opLVDS = $71, // Support LVDS. + opEndVME = $7F, // End of the VME file. + opEndFile = $FF // End of file. + ); + + TReturnCode = + ( + VME_OK = 0, + VME_VerificationFailure = -1, + VME_FileReadFailure = -2, + VME_VersionFailure = -3, + VME_InvalidFile = -4, + VME_ArgumentFailure = -5, + VME_CRCFailure = -5 + ); + + TLVDSPair = packed record + PositiveIndex : word; + NegativeIndex : word; + Update : boolean; + end; + +type + TispVM = class; + + TPin = (pinTCK,pinTMS,pinTDI,pinTDO,pinTRST,pinENA); + + TTransferMode = (tmNone, tmRead, tmWrite); + + TTransferEvent = procedure( Sender : TispVM; + Mode : TTransferMode) of object; + + + + TispVM = class + protected + fJtag : IJTAG; + + protected + fOnTransfer : TTransferEvent; + fTransferMode : TTransferMode; + + protected + fBufTDI : array [0 .. 1023] of byte; // data to send to device + fBufTDO : array [0 .. 1023] of byte; // data received from device + fBufSMASK : array [0 .. 1023] of byte; + fBufMASK : array [0 .. 1023] of byte; + + fBuffer : array [0 .. 1023] of byte; + fBufferSize : integer; + fBufferIndex : integer; + + fMaskTCK : byte; + fMaskTMS : byte; + fMaskTDI : byte; + fMaskTDO : byte; + fMaskTRST : byte; + fMaskENA : byte; + fMaskPWR : byte; + + fValTMS : boolean; + fValTDI : boolean; + fValTDO : boolean; + fValTRST : boolean; + fValENA : boolean; + + fInitDone : boolean; + + private + function GetData(i: word): byte; + procedure SetData(i: word; d: byte); + + protected + procedure Init( BufferSize : word; + TCK : byte; + TMS : byte; + TDI : byte; + TDO : byte; + TRST : byte; + ENA : byte; + PWR : byte); + + procedure SetPin( pin: TPin; Value: byte); + procedure Flush; + + public + procedure InitDsoJtag; // prepare for DSO + procedure InitPrgJtag; // prepare for JTAG programmer + + + + protected + fFlowControl : TFlowControl; // Flow control register. + fDataType : TDataType; // Data type of the current row. + + fEndDR : TJTAGState; // The state that the device goes after SDR. + fEndIR : TJTAGState; // The state that the device goes after SIR. + + fHeadDR : word; // The number of lead devices in bypass. + fHeadIR : word; // The sum of IR length of lead devices. + + fTailDR : word; // The number of tail devices in bypass. + fTailIR : word; // The sum of IR length of tail devices. + + fDataSize : word; // The number of bits of data or instruction + // to be shifted into or out from the device. + + fFrequency : word; // The TCK frequency in MHz. + fMaxSize : word; // The maximum amount of data needed to hold a row of data. + fShiftValue : word; // Stores the LSH or RSH value. + fRepeatLoops : word; // Stores the current repeat loop value. + fVendor : TVendor; // Stores the current vendor. + fCalculatedCRC : word; // Stores the VME file CRC. + fCheckSum : cardinal; // Stores the device checksum. + fCheckSumIndex : integer; + + fCurrentJTAGState : TJTAGState; // Stores the current state of the JTAG state machine. + + // + // looping support + // + fHeapMemory : PByte; // Holds the entire repeat loop. + fHeapCounter : word; // Points to the current byte in the repeat loop. + fHeapSize : word; // The current size of the repeat loop in bytes. + + // + // intelligent programming support + // + fIntelDataIndex : word; // Points to the current byte of the intelligent buffer. + fIntelBufferSize : word; // Holds the size of the intelligent buffer. + + // + // The maximum size of each respective buffer. These variables are used to write + // the HEX files when converting VME to HEX. + // + fTDOSize : word; + fMASKSize : word; + fTDISize : word; + fDMASKSize : word; + fLCOUNTSize : word; + + fHDRSize : word; + fTDRSize : word; + fHIRSize : word; + fTIRSize : word; + + fHeapBufferSize : word; + + // + // Variables used to store data + // + fOutMaskData : PByte; + fOutDMaskData : PByte; + + fInData : PByte; + fOutData : PByte; + fHIRData : PByte; + fTIRData : PByte; + fHDRData : PByte; + fTDRData : PByte; + + fIntelBuffer : PByte; + + + // + // List to hold all LVDS pairs. + // + // LVDSPair * ... + // count + fLVDs : array of TLVDSPair; + + fStream : TStream; + + private + function GetByte: byte; + procedure sclock(n:integer=1); + + protected + function ispVMCode: TReturnCode; + + function ispVMAmble( OpCode: TOpcode): TReturnCode; + function ispVMShift( OpCode: TOpcode): TReturnCode; + + function ispVMDataSize: word; + procedure ispVMDelay( Delay: word); + procedure ispVMClocks( Count: word); + function ispVMLoop( LoopCount: word): TReturnCode; + function ispVMLCount( CountSize: word): TReturnCode; + + procedure ispVMStateMachine( NextState: TJTAGState); + + procedure ispVMComment( Size: word); + function ispVMProcessLVDS( Count: word):TReturnCode; + procedure ispVMHeader( Size: word); + + function ispVMDataCode: TReturnCode; + procedure ispVMData( Data: PByte); + + function ispVMBitShift( OpCode: TOpCode; Count: word): TReturnCode; + + procedure ispVMBypass( ScanType: TOpCode; Count: word); + function ispVMSend( Count: word): TReturnCode; + function ispVMRead( Count: word): TReturnCode; + function ispVMReadAndSave( Count: word): TReturnCode; + + procedure ispVMStart; + procedure ispVMEnd; + + procedure ispVMMemManager( Target: TOpCode; Size: word); + + public + function ispVM( Stream: TStream): TReturnCode; + + public + procedure AfterConstruction; override; + + public + property DataSize: integer read fBufferIndex; + property Data[i: word]: byte read GetData write SetData; + + property JTAG : IJTAG read fJtag write fJtag; + + property OnTransfer : TTransferEvent read fOnTransfer write fOnTransfer; + end; + +implementation +uses + Windows, + jtag.vme.tools; + +const + JTAGTransitions : array [0..24] of TJTAGTransition = + ( + ( CurrState : RESET; NextState : RESET; Pattern : $FC; Pulses : 6), + ( CurrState : RESET; NextState : IDLE; Pattern : $00; Pulses : 1), + ( CurrState : RESET; NextState : DRPAUSE; Pattern : $50; Pulses : 5), + ( CurrState : RESET; NextState : IRPAUSE; Pattern : $68; Pulses : 6), + + ( CurrState : IDLE; NextState : RESET; Pattern : $E0; Pulses : 3), + ( CurrState : IDLE; NextState : DRPAUSE; Pattern : $A0; Pulses : 4), + ( CurrState : IDLE; NextState : IRPAUSE; Pattern : $D0; Pulses : 5), + ( CurrState : IDLE; NextState : DRCAPTURE; Pattern : $80; Pulses : 2), + + ( CurrState : DRPAUSE; NextState : RESET; Pattern : $F8; Pulses : 5), + ( CurrState : DRPAUSE; NextState : IDLE; Pattern : $C0; Pulses : 3), + ( CurrState : DRPAUSE; NextState : IRPAUSE; Pattern : $F4; Pulses : 7), + ( CurrState : DRPAUSE; NextState : DRPAUSE; Pattern : $E8; Pulses : 6), + ( CurrState : DRPAUSE; NextState : DRSHIFT; Pattern : $80; Pulses : 2), + ( CurrState : DRPAUSE; NextState : DRCAPTURE; Pattern : $E0; Pulses : 4), + + ( CurrState : IRPAUSE; NextState : RESET; Pattern : $F8; Pulses : 5), + ( CurrState : IRPAUSE; NextState : IDLE; Pattern : $C0; Pulses : 3), + ( CurrState : IRPAUSE; NextState : DRPAUSE; Pattern : $E8; Pulses : 6), + ( CurrState : IRPAUSE; NextState : DRSHIFT; Pattern : $E0; Pulses : 5), + ( CurrState : IRPAUSE; NextState : IRSHIFT; Pattern : $80; Pulses : 2), + ( CurrState : IRPAUSE; NextState : DRCAPTURE; Pattern : $E0; Pulses : 4), + + ( CurrState : DRSHIFT; NextState : IDLE; Pattern : $C0; Pulses : 3), + ( CurrState : DRSHIFT; NextState : DRPAUSE; Pattern : $80; Pulses : 2), + + ( CurrState : IRSHIFT; NextState : IDLE; Pattern : $C0; Pulses : 3), + ( CurrState : IRSHIFT; NextState : IRPAUSE; Pattern : $80; Pulses : 2), + + ( CurrState : DRCAPTURE; NextState : DRPAUSE; Pattern : $80; Pulses : 2) + ); + + +var + idx : integer; + data : array [0..3] of byte; + +{ TvmeProgram } + +// ================================================================================================ +// After Construction +// ================================================================================================ +procedure TispVM.AfterConstruction; +var + x: array [0..20] of byte; + +begin + inherited; + + fEndDR := DRPAUSE; + fEndIR := IRPAUSE; + + fFrequency := 1000; +end; + + +// ================================================================================================ +// Init +// ================================================================================================ +procedure TispVM.Init( BufferSize : word; + TCK : byte; + TMS : byte; + TDI : byte; + TDO : byte; + TRST : byte; + ENA : byte; + PWR : byte); +begin + fBufferSize := 504; + // if (BufferSize <> 1024) and (BufferSize <> 512) + // then fBufferSize := 1024 + // else fBufferSize := BufferSize; + + if TCK <> $FF then fMaskTCK := 1 shl TCK else fMaskTCK := 0; + if TMS <> $FF then fMaskTMS := 1 shl TMS else fMaskTMS := 0; + if TDI <> $FF then fMaskTDI := 1 shl TDI else fMaskTDI := 0; + if TDO <> $FF then fMaskTDO := 1 shl TDO else fMaskTDO := 0; + if TRST <> $FF then fMaskTRST := 1 shl TRST else fMaskTRST := 0; + if ENA <> $FF then fMaskENA := 1 shl ENA else fMaskENA := 0; + if PWR <> $FF then fMaskPWR := 1 shl PWR else fMaskPWR := 0; + + fInitDone := true; +end; + +// ================================================================================================ +// InitDsoJtag +// ================================================================================================ +procedure TispVM.InitDsoJtag; +begin + Init(256, 0, 1, 3, 7, $FF, $FF, $FF); +end; + +// ================================================================================================ +// InitPrgJtag +// ================================================================================================ +procedure TispVM.InitPrgJtag; +begin + Init(256, 0, 1, 7, 3, 5, 4, 6); +end; + +// ================================================================================================ +// Get Data +// ================================================================================================ +function TispVM.GetData(i: word): byte; +begin + if i < fBufferSize + then result := fBuffer[i] + else result := 0; +end; + +// ================================================================================================ +// Set Data +// ================================================================================================ +procedure TispVM.SetData(i: word; d: byte); +begin + if i < fBufferSize then + fBuffer[i] := d +end; + + + + + + + + + + + + + + + + + + + +// ================================================================================================ +// Load +// ================================================================================================ +function TispVM.ispVM(Stream: TStream): TReturnCode; +var + i : integer; + b : byte; + s : AnsiString; + +begin + if Assigned(Stream) then + begin + fStream := Stream; + fStream.Seek(0, soFromBeginning); + + b := GetByte; + + case TOpCode(b) of + opFileCRC: + begin + // ---------------------------------------------- + // Read and store the expected CRC to do the + // comparison at the end. Only versions 3.0 and + // higher support CRC protection. + // ---------------------------------------------- + fCheckSum := GetByte shl 8; + fCheckSum := fCheckSum + GetByte; + + // ---------------------------------------------- + // Read and store the version of the VME file. + // Must be version 2.0. + // ---------------------------------------------- + for i:=0 to 7 do + s := s + AnsiChar(GetByte); + end; + + else begin + // ------------------------------------------------- + // Read and store the version of the VME file. + // Must be version 2.0. + // ------------------------------------------------- + s := AnsiChar(b); + + for i:=1 to 7 do + s := s + AnsiChar(GetByte); + end; + end; + + // ------------------------------------------------------------ + // Compare the VME file version against the supported version. + // ------------------------------------------------------------ + result := VME_VersionFailure; + + if s = '__VME2.0' then result := VME_OK; + if s = '__VME3.0' then result := VME_OK; + if s = '____12.0' then result := VME_OK; + if s = '____12.1' then result := VME_OK; + + if result <> VME_OK then + exit; + + // ------------------------------------------------------------ + // Enable the JTAG port to communicate with the deevice. + // Set the JTAG state machine to the RESET state. + // ------------------------------------------------------------ + ispVMStart; + + // ------------------------------------------------------------ + // Process the VME file. + // ------------------------------------------------------------ + result := ispVMCode; + + // ------------------------------------------------------------ + // Set the JTAG state machine to RESET state then disable the + // the communication with the JTAG port. + // ------------------------------------------------------------ + ispVMEnd + end +end; + +// ================================================================================================ +// Get Byte +// +// Returns a byte to the caller. The returned byte depends on the DataType register. +// If the HEAP_IN bit is set, then the byte is returned from the HEAP. +// If the LHEAP_IN bit is set, then the byte is returned from the intelligent buffer. +// Otherwise, the byte is returned directly from the VME file. +// ================================================================================================ +function TispVM.GetByte: byte; +begin + result := 0; + + if dtHeap in fDataType then + begin + if fHeapCounter > fHeapSize then + result := $FF + + else begin + result := fHeapMemory[fHeapCounter]; + INC(fHeapCounter) + end; + end + + else if dtLHeap in fDataType then + begin + if fIntelDataIndex >= fIntelBufferSize then + result := $FF + + else begin + result := fIntelBuffer[fIntelDataIndex]; + INC(fIntelDataIndex); + end; + end + + else begin + if Assigned(fStream) then + if fStream.Read(result,1) <> 1 then + result := $FF + end; +end; + + + + +// ================================================================================================ +// ispVMCode +// +// This is the heart of the embedded engine. All the high-level opcodes are extracted here. +// Once they have been identified, then it will call other functions to handle the processing. +// ================================================================================================ +function TispVM.ispVMCode: TReturnCode; +var + RepeatSize : word; + OpCode : TOpcode; + State : TJTAGState; + + Delay : word; + Toggle : word; + Data : byte; + FlowControl : TFlowControl; + +begin + RepeatSize := 0; + OpCode := opEndData; + result := VME_OK; + State := RESET; + Delay := 0; + Toggle := 0; + Data := 0; + + // --------------------------------------------------------------- + // Check the compression flag only if this is the first time + // this function is entered. Do not check the compression flag if + // it is being called recursively from other functions within + // the embedded engine. + // --------------------------------------------------------------- + if not (dtHeap in fDataType) and not (dtLHeap in fDataType) then + begin + Data := GetByte; + + if Data = $F1 then + Include( fDataType, dtCompress) + else if Data = $F2 then + Exclude( fDataType, dtCompress) + + else begin + result := VME_InvalidFile; + exit + end + end; + + // --------------------------------------------------------------- + // Loop through all the VME opcodes. + // --------------------------------------------------------------- + OpCode := TOpCode(GetByte); + + while OpCode <> opEndData do + begin + case OpCode of + // -------------------------------------------- + // opSTATE + // -------------------------------------------- + opState: + begin + State := TJTAGState( GetByte); + + if Assigned(fJtag) then + fJtag.state(State); + + if (dtLHeap in fDataType) and (State = DRPAUSE) and (fCurrentJTAGState = State) then + if Assigned(fJtag) then + fJtag.state(DRCAPTURE); + + ispVMStateMachine(State); + end; + + // -------------------------------------------- + // SIR,SDR,XSDR + // Shift data into the device. + // -------------------------------------------- + opSIR,opSDR,opXSDR: + begin + result := ispVMShift(OpCode); + + if result <> VME_OK then + break; + end; + + // -------------------------------------------- + // WAIT + // Observe delay. + // -------------------------------------------- + opWAIT: + begin + Delay := ispVMDataSize; + ispVMDelay(Delay); + end; + + // -------------------------------------------- + // TCK + // Issue clock toggles. + // -------------------------------------------- + opTCK: + begin + Toggle := ispVMDataSize; + ispVMClocks(Toggle); + end; + + // -------------------------------------------- + // ENDDR,ENDIR + // Set the ENDDR,ENDIR + // -------------------------------------------- + opEndDR: fEndDR := TJTAGState( GetByte); + opEndIR: fEndIR := TJTAGState( GetByte); + + // -------------------------------------------- + // HIR,TIR,HDR,TDR + // -------------------------------------------- + opHIR,opTIR,opHDR,opTDR: + begin + result := ispVMAmble( OpCode); + + if result <> VME_OK then + break; + end; + + // -------------------------------------------- + // MEM + // -------------------------------------------- + opMEM: + begin + //OutputDebugString('opMEM'); + fMaxSize := ispVMDataSize; + end; + + // -------------------------------------------- + // Vendor + // -------------------------------------------- + opVendor: + begin + //OutputDebugString('opVendor'); + fVendor := TVendor( GetByte); + end; + + // -------------------------------------------- + // SETFLOW + // Set the flow control. + // Flow control determines the personality of + // the embedded engine. + // + // TODO: check this! + // -------------------------------------------- + opSetFlow: + begin + OutputDebugString('opSetFlow'); + // fFlowControl := fFlowControl + TFlowControl(GetByte); + end; + + opResetFlow: + begin + OutputDebugString('opResetFlow'); + // fFlowControl := fFlowControl + TFlowControl(GetByte); + end; + + // -------------------------------------------- + // HEAP + // Allocate heap to store loops + // -------------------------------------------- + opHEAP: + begin + //OutputDebugString('opHEAP'); + + OpCode := TOpCode(GetByte); + + if OpCode <> opSecureHeap then + break; + + fHeapSize := ispVMDataSize; + ispVMMemManager( opHEAP, fHeapSize); + end; + + // -------------------------------------------- + // REPEAT + // -------------------------------------------- + opREPEAT: + begin + //OutputDebugString('opREPEAT'); + + fRepeatLoops := 0; + result := ispVMLoop( ispVMDataSize); + + if result <> VME_OK then + break; + end; + + opENDLOOP: exit; + opEndVME : exit; + + // -------------------------------------------- + // SHR,SHL + // Right-shift/Left-shift address. + // -------------------------------------------- + opSHR: + begin + //OutputDebugString('opSHR'); + + Include( fFlowControl, fcbShiftRight); + fShiftValue := fRepeatLoops * GetByte; + end; + + opSHL: + begin + //OutputDebugString('opSHL'); + + Include( fFlowControl, fcbShiftLeft); + fShiftValue := fRepeatLoops * GetByte; + end; + + // -------------------------------------------- + // FREQUENCY + // -------------------------------------------- + opFrequency: + begin + //OutputDebugString('opFREQUENCY'); + + fFrequency := ispVMDataSize; + + if fFrequency >= 1000 then + begin + fFrequency := fFrequency div 1000; + + if fFrequency = 1 then + fFrequency := 1000 + end + + else begin + if fFrequency = 0 then + fFrequency := 1000 + end; + end; + + // -------------------------------------------- + // LCOUNT + // -------------------------------------------- + opLCount: + begin + //OutputDebugString('opLCOUNT'); + + result := ispVMLCount( ispVMDataSize); + + if result <> VME_OK then + break + end; + + // -------------------------------------------- + // VUES + // -------------------------------------------- + opVUES: + begin + //OutputDebugString('opVUES'); + + Include(FlowControl,fcbVerifyUES); + end; + + // -------------------------------------------- + // COMMENT + // -------------------------------------------- + opComment: + begin + //OutputDebugString('opCOMMENT'); + + + ispVMComment( ispVMDataSize); + end; + + // -------------------------------------------- + // LVDS + // -------------------------------------------- + opLVDS: + begin + //OutputDebugString('opLVDS'); + + ispVMProcessLVDS( ispVMDataSize); + end; + + // -------------------------------------------- + // HEADER + // -------------------------------------------- + opHeader: + begin + //OutputDebugString('opHEADER'); + + ispVMHeader( ispVMDataSize); + end; + + // -------------------------------------------- + // ispEN + // -------------------------------------------- + opIspEN: + begin + OpCode := TOpCode(GetByte); + + case OpCode of + opON : SetPin(pinENA, 1); + opOFF : SetPin(pinENA, 0); + end; + end; + + // -------------------------------------------- + // TRST + // -------------------------------------------- + opTRST: + begin + OpCode := TOpCode(GetByte); + + case OpCode of + opON : SetPin(pinTRST, 1); + opOFF : SetPin(pinTRST, 0); + end; + end; + + else + result := VME_InvalidFile + end; + + OpCode := TOpCode(GetByte); + end; + + // + // Invalid exit point. + // Processing token 'ENDVME' is the only valid + // way to exit the embedded engine. + // + result := VME_InvalidFile; +end; + +// ================================================================================================ +// ispVMDataSize +// +// Returns a VME-encoded number, ususally used to indicate the bitlength of an SIR/SDR command. +// ================================================================================================ +function TispVM.ispVMDataSize: word; +var + curr : byte; + idx : byte; + +begin + result := 0; + idx := 0; + curr := GetByte; + + while curr and $80 <> 0 do + begin + result := result or ((curr and $7f) shl idx); + curr := GetByte; + + INC( idx, 7) + end; + + result := result or ((curr and $7f) shl idx); +end; + + + +// ================================================================================================ +// ispVMDataCode +// +// Processes the TDI/TDO/MASK/DMASK etc of an SIR/SDR command. +// ================================================================================================ +function TispVM.ispVMDataCode: TReturnCode; +var + DataByte : ShortInt; + DataSource : ShortInt; + pos : Int64; + +begin + result := VME_OK; + + if dtHeap in fDataType + then DataSource := 1 // data source is memory + else DataSource := 0; // data source is file + + fDataType := fDataType - [dtTDIData, dtTDOData, dtMASKData, dtDMASKData, dtCMASKData]; + + + // -------------------------------------------------------------------- + // Iterate through SIR/SDR command and look for TDI, TDO, MASK, etc... + // -------------------------------------------------------------------- + DataByte := ShortInt(GetByte); + + while DataByte >= 0 do + begin + pos := fStream.Position -1; + + ispVMMemManager( TOpCode(DataByte), fMaxSize); + + case TOpCode(DataByte) of + // ---------------------------------------------------- + // TDI + // ---------------------------------------------------- + opTDI: + begin + // ----------------------------------------- + // Store the maximum size of the TDI buffer. + // Used to convert VME to HEX. + // ----------------------------------------- + if fTDISize <= fDataSize then + fTDISize := fDataSize; + + // ----------------------------------------- + // Update DataType register to indicate that + // TDI data is currently being used. Process + // the data in the VME file into the TDI + // buffer. + // ----------------------------------------- + Include(fDataType, dtTDIData); + ispVMData( fInData); + end; + + // ---------------------------------------------------- + // TDO + // ---------------------------------------------------- + opTDO: + begin + // ----------------------------------------- + // Store the maximum size of the TDO buffer. + // Used to convert VME to HEX. + // ----------------------------------------- + if fTDOSize <= fDataSize then + fTDOSize := fDataSize; + + // ----------------------------------------- + // Update DataType register to indicate that + // TDO data is currently being used. Process + // the data in the VME file into the TDO + // buffer. + // ----------------------------------------- + Include(fDataType, dtTDOData); + ispVMData( fOutData); + end; + + // ---------------------------------------------------- + // XTDO + // ---------------------------------------------------- + opXTDO: + begin + // ----------------------------------------- + // Store the maximum size of the TDO buffer. + // Used to convert VME to HEX. + // ----------------------------------------- + if fTDOSize <= fDataSize then + fTDOSize := fDataSize; + + // ----------------------------------------- + // Update DataType register to indicate that + // TDO data is currently being used. Process + // the data in the VME file into the TDO + // buffer. + // ----------------------------------------- + Include(fDataType, dtTDOData); + end; + + opMASK: + begin + // ----------------------------------------- + // Store the maximum size of the MASK buffer. + // Used to convert VME to HEX. + // ----------------------------------------- + if fMASKSize <= fDataSize then + fMASKSize := fDataSize; + + // ----------------------------------------- + // Update DataType register to indicate that + // MASK data is currently being used. Process + // the data in the VME file into the MASK + // buffer. + // ----------------------------------------- + Include(fDataType, dtMASKData); + ispVMData( fOutMaskData); + end; + + opDMask: + begin + // ----------------------------------------- + // Store the maximum size of the DMASK + // buffer. Used to convert VME to HEX. + // ----------------------------------------- + if fDMASKSize <= fDataSize then + fDMASKSize := fDataSize; + + // ----------------------------------------- + // Update DataType register to indicate that + // DMASK data is currently being used. + // Process the data in the VME file into the + // DMASK buffer. + // ----------------------------------------- + Include(fDataType, dtDMASKData); + ispVMData( fOutDMaskData); + end; + + opCMask: + begin + // ----------------------------------------- + // Update DataType register to indicate that + // DMASK data is currently being used. + // Process the data in the VME file into the + // DMASK buffer. + // ----------------------------------------- + Include(fDataType, dtCMASKData); + ispVMData( fOutMaskData); + end; + + opContinue: + begin + result := VME_OK; + exit; + end; + + else + begin + result := VME_InvalidFile; + exit + end; + end; + + case TOpCode(DataByte) of + opTDI: + begin + // ----------------------------------------- + // Left bit shift. Used when performing + // algorithm looping. + // ----------------------------------------- + if fcbShiftLeft in fFlowControl then + begin + ispVMBitShift( opSHL, fShiftValue); + Exclude( fFlowControl, fcbShiftLeft) + end; + + // ----------------------------------------- + // Left bit shift. Used when performing + // algorithm looping. + // ----------------------------------------- + if fcbShiftRight in fFlowControl then + begin + ispVMBitShift( opSHR, fShiftValue); + Exclude( fFlowControl, fcbShiftRight) + end; + end; + end; + + if DataSource <> 0 then + Include( fDataType, dtHeap); + + DataByte := ShortInt(GetByte); + end; + + if DataSource <> 0 then + Include( fDataType, dtHeap); + + if DataByte < 0 then + begin + pos := fStream.Position; + result := VME_InvalidFile; + end + else + result := VME_OK +end; + +// ================================================================================================ +// ispVMData +// +// Extract one row of data operand from the current data type opcode. Perform the decompression if +// necessary. Extra RAM is not required for the decompression process. The decompression scheme +// employed in this module is on row by row basis. The format of the data stream: +// +// [compression code][compressed data stream] +// 0x00 --No compression +// 0x01 --Compress by 0x00. +// Example: +// Original stream: 0x000000000000000000000001 +// Compressed stream: 0x01000901 +// Detail: 0x01 is the code, 0x00 is the key, +// 0x09 is the count of 0x00 bytes, +// 0x01 is the uncompressed byte. +// +// 0x02 --Compress by 0xFF. +// Example: +// Original stream: 0xFFFFFFFFFFFFFFFFFFFFFF01 +// Compressed stream: 0x02FF0901 +// Detail: 0x02 is the code, 0xFF is the key, +// 0x09 is the count of 0xFF bytes, +// 0x01 is the uncompressed byte. +// +// 0x03 +// : : +// 0xFE -- Compress by nibble blocks. +// Example: +// Original stream: 0x84210842108421084210 +// Compressed stream: 0x0584210 +// Detail: 0x05 is the code, means 5 nibbles block. +// 0x84210 is the 5 nibble blocks. +// The whole row is 80 bits given by fDataSize. +// The number of times the block repeat itself +// is found by fDataSize/(4*0x05) which is 4. +// +// 0xFF -- Compress by the most frequently happen byte. +// Example: +// Original stream: 0x04020401030904040404 +// Compressed stream: 0xFF04(0,1,0x02,0,1,0x01,1,0x03,1,0x09,0,0,0) +// or: 0xFF044090181C240 +// Detail: 0xFF is the code, 0x04 is the key. +// a bit of 0 represent the key shall be put into +// the current bit position and a bit of 1 +// represent copying the next of 8 bits of data +// in. + +// ================================================================================================ +procedure TispVM.ispVMData(Data: PByte); +var + size : word; + i, j, m : integer; + getData : word; + DataByte : byte; + FFcount : integer; + compress : byte; + compr_char : byte; + index : integer; + compression : ShortInt; + pos : Int64; + +begin + size := 0; + i := 0; + j := 0; + m := 0; + getData := 0; + compr_char := $FF; + + // --------------------------------------------------------------- + // Convert "size in bits" to "size in bytes". + // --------------------------------------------------------------- + if fDataSize mod 8 > 0 + then size := (fDataSize div 8) + 1 + else size := (fDataSize div 8); + + // --------------------------------------------------------------- + // If there is a compression, then check if compress by key of + // 0x00 or 0xff or by other keys by nibble blocks. + // --------------------------------------------------------------- + if dtCompress in fDataType then + begin + compression := 1; + compress := GetByte; + + if (TOpCode(compress) = opVAR) and (dtHeap in fDataType) then + begin + getData := 1; + + Exclude( fDataType, dtHeap); + compress := GetByte; + end; + + case compress of + $00: compression := 0; // No compression + $01: compr_char := $00; + $02: compr_char := $ff; + + $ff: + begin + pos := fStream.Position; + + i := 8; + compr_char := GetByte; + pos := fStream.Position; + + for index := 0 to size-1 do + begin + Data[index] := 0; + + if i > 7 then + begin + DataByte := GetByte; + pos := fStream.Position; + i := 0; + end; + + if (DataByte shl i) and $80 = $80 then + m := 8 + else begin + Data[index] := compr_char; + m := 0; + end; + + INC(i); + + for j:=0 to m-1 do + begin + if i > 7 then + begin + DataByte := GetByte; + i := 0; + pos := fStream.Position; + end; + + Data[index] := Data[index] or (((DataByte shl i) and $80) shr j); + INC(i); + end; + end; + + size := 0; + pos := fStream.Position; + end; + + else + begin + for index:=0 to size -1 do + Data[index] := 0; + + for index:=0 to compress -1 do + begin + if (index mod 2) = 0 then + DataByte := GetByte; + + for i:=0 to ((size*2) div compress) -1 do + begin + j := index + i * compress; + + if (j mod 2) <> 0 then + if (index mod 2) <> 0 + then Data[j div 2] := Data[j div 2] or (DataByte and $0F) + else Data[j div 2] := Data[j div 2] shr 4 + else + if (index mod 2) <> 0 + then Data[j div 2] := Data[j div 2] shl 4 + else Data[j div 2] := Data[j div 2] and $F0 + end; + + size := 0; + end; + end; + end; + end; + + // Decompress by byte 0x00 or 0xff + FFcount := 0; + + for index := 0 to size -1 do + begin + if FFcount <= 0 then + begin + DataByte := GetByte; + + if (TOpCode(DataByte) = opVar) and (dtHeap in fDataType) and (getData = 0) and not (dtCompress in fDataType) then + begin + getData := 1; + Exclude( fDataType, dtHeap); + DataByte := GetByte; + end; + + Data[index] := DataByte; + + if (compression <> 0) and (DataByte = compr_char) then // compression is on + FFcount := ispVMDataSize; // the number of $FF or $00 bytes + end + + else begin + DEC(FFcount); + Data[index] := compr_char; + end; + end; + + if getData <> 0 then + Include( fDataType, dtHeap); +end; + + +// ================================================================================================ +// ispVMShift +// +// Process the SIR/SDR/XSDR commands. +// ================================================================================================ +function TispVM.ispVMShift(OpCode: TOpcode): TReturnCode; +var + DataIndex : word; + ReadLoop : word; + +begin + DataIndex := 0; + ReadLoop := 0; + result := VME_OK; + fDataSize := ispVMDataSize; + + Exclude( fDataType, dtSIRData); + Exclude( fDataType, dtSDRData); + Exclude( fDataType, dtExpress); + + + // ------------------------------------------------------------------------- + // Elsö lepeskent olvassuk be a TDI/TDO/... adatokat a megfelelö bufferekbe. + // Ha TDO adatok is vannak specifikalva, akkor a State Machine aktualizalasa + // utan toljuk ki a buffer tartalmat, hogy a TDO muvelet a buffer elejen + // kezdödhessen. Igy max 512 (1024) byte-os adatot tudunk ellenörizni. + // ------------------------------------------------------------------------- + result := ispVMDataCode; + + if result <> VME_OK then + begin + result := VME_InvalidFile; + exit + end; + + if fDataSize > 250 then + Exclude( fDataType, dtTDOData); + + + + // ------------------------------------------------------------------------- + // Move the device state machine and shift in any bypass data. + // ------------------------------------------------------------------------- + case OpCode of + // ------------------------------------------------------------ + // SIR + // ------------------------------------------------------------ + opSIR: + begin + Include( fDataType, dtSIRData); + + // -------------------------------------------- + // If performing cascading, then go directly + // to IRSHIFT. Else go to IRPAUSE before going + // to IRSHIFT. + // -------------------------------------------- + if Assigned( fJtag) then + begin + if fcbCascade in fFlowControl then + fJtag.state(IRSHIFT) + + else begin + fJtag.state(IRPAUSE); + fJtag.state(IRSHIFT); + + if fHeadIR > 0 then + begin + ispVMBypass( opHIR, fHeadIR); + sclock + end; + end; + end; + + end; + + // ------------------------------------------------------------ + // SDR/XSDR + // ------------------------------------------------------------ + opSDR, opXSDR: + begin + Include( fDataType, dtSDRData); + + if OpCode = opXSDR then + Include( fDataType, dtExpress); + + // --------------------------------------------- + // If already in DRSHIFT, then do not move state + // or shift in header. This would imply that the + // previously shifted frame was a cascaded frame + // --------------------------------------------- + if fCurrentJTAGState <> DRSHIFT then + begin + // ------------------------------------------ + // If performing cascading, then go directly + // to DRSHIFT. Else goto DRPAUSE before going + // to DRSHIFT. + // ------------------------------------------ + if fcbCascade in fFlowControl then + begin + if fCurrentJTAGState = DRPAUSE then + begin + ispVMStateMachine( DRSHIFT); + + // ------------------------------------ + // If cascade flag has been set and the + // current state is DRPAUSE, this imp- + // lies that the first cascaded frame + // is about to shifted in. The header + // must be shifted prior to shifting + // the first cascaded frame. + // ------------------------------------ + if fHeadDR > 0 then + begin + ispVMBypass( opHDR, fHeadDR); + sclock + end; + end + + else + ispVMStateMachine( DRSHIFT); + end + + // ------------------------------------------ + // No cascading. + // ------------------------------------------ + else begin + ispVMStateMachine( DRPAUSE); + ispVMStateMachine( DRSHIFT); + + if fHeadDR > 0 then + begin + ispVMBypass( opHDR, fHeadDR); + sclock + end; + end; + end; + end; + + else + begin + result := VME_InvalidFile; + exit + end; + end; + +// // -------------------------------------------------------------------- +// // Read TDI,TDO,MASK data into internal buffers. +// // -------------------------------------------------------------------- +// result := ispVMDataCode; +// +// if result <> VME_OK then +// begin +// result := VME_InvalidFile; +// exit +// end; + + // -------------------------------------------------------------------- + // If we have TDO data to check, then flush buffer first. + // -------------------------------------------------------------------- + if dtTDOData in fDataType then + Flush; + + // -------------------------------------------------------------------- + // Do shifting, and process TDO or DATA MASK + // -------------------------------------------------------------------- + if (dtTDOData in fDataType) or (dtDMASKData in fDataType) then + begin + // DMASK Data + if dtDMASKData in fDataType then + begin + result := ispVMReadAndSave( fDataSize); + + if result = VME_OK then + begin + if fTailDR > 0 then + begin + sclock; + ispVMBypass( opTDR, fTailDR); + end; + + ispVMStateMachine( DRPAUSE); + ispVMStateMachine( DRSHIFT); + + if fHeadDR > 0 then + begin + ispVMBypass( opHDR, fHeadDR); + sclock + end; + + for DataIndex:=0 to (fDataSize div 8) do + fInData[DataIndex] := fOutData[DataIndex]; + + Exclude( fDataType, dtTDOData); + Exclude( fDataType, dtDMASKData); + + result := ispVMSend( fDataSize) + end; + end + + // TDO Data + else begin + result := ispVMRead( fDataSize); + + if (result = VME_VerificationFailure) and (fVendor = vXilinx) then + begin + for ReadLoop:=0 to 29 do + begin + result := ispVMRead( fDataSize); + + if result = VME_OK then + break + + else begin + ispVMStateMachine(DRPAUSE); + ispVMBypass( opTDR, fTailDR); + ispVMStateMachine( fEndDR); + ispVMStateMachine( IDLE); + ispVMDelay(1000); + end; + end; + end; + end; + end + + else // TDI only + result := ispVMSend( fDataSize); + + + // ------------------------------------------------------------------------- + // Transfer the input data to the output buffer for the next verify. + // MoveMem ??? + // ------------------------------------------------------------------------- + if (dtExpress in fDataType) or (OpCode = opSDR) then + if Assigned(fOutData) then + for DataIndex:=0 to fDataSize - 1 do + fOutData[DataIndex] := fInData[DataIndex]; + + // ------------------------------------------------------------------------- + // Update State Machine + // ------------------------------------------------------------------------- + case OpCode of + opSIR: + begin + // If not performing cascading, then shift ENDIR + if not (fcbCascade in fFlowControl) then + begin + if fTailIR > 0 then + begin + sclock; + ispVMBypass( opTIR, fTailIR); + end; + + ispVMStateMachine(fEndIR); + end; + end; + + opSDR,opXSDR: + begin + // If not performing cascading, then shift ENDIR + if not (fcbCascade in fFlowControl) then + begin + if fTailDR > 0 then + begin + sclock; + ispVMBypass( opTDR, fTailDR); + end; + + ispVMStateMachine(fEndDR); + + if dtTDOData in fDataType then + Flush; + end; + + end; + end; +end; + +// ================================================================================================ +// ispVMAmble +// +// This routine is to extract Header and Trailer parameter for SIR and SDR operations. +// +// The Header and Trailer parameter are the pre-amble and post-amble bit stream need to be shifted +// into TDI or out of TDO of the devices. Mostly is for the purpose of bypassing the leading or +// trailing devices. ispVM supports only shifting data into TDI to bypass the devices. +// +// For a single device, the header and trailer parameters are all set to 0 as default by ispVM. +// If it is for multiple devices, the header and trailer value will change as specified by the +// VME file. +// ================================================================================================ +function TispVM.ispVMAmble(OpCode: TOpcode): TReturnCode; +var + compress: byte; + +begin + compress := 0; + fDataSize := ispVMDataSize; + + if fDataSize > 0 then + begin + // ------------------------------------------------------------ + // Discard the TDI byte and set the compression bit in the data + // type register to false if compression is set, because TDI + // data after HIR/HDR/TIR/TDR is not compressed. + // ------------------------------------------------------------ + GetByte; + + if dtCompress in fDataType then + begin + compress := 1; + Exclude( fDataType, dtCompress); + end; + end; + + case OpCode of + opHIR: + begin + // ------------------------------------------------- + // Store the maximum size of the HIR buffer. Used to + // convert VME to HEX. + // ------------------------------------------------- + if fHIRSize <= fDataSize then + fHIRSize := fDataSize; + + // ------------------------------------------------- + // Assign the HIR value and allocate memory. + // ------------------------------------------------- + fHeadIR := fDataSize; + + if fHeadIR > 0 then + begin + ispVMMemManager( opHIR, fHeadIR); + ispVMData( fHIRData); + end; + end; + + opTIR: + begin + // ------------------------------------------------- + // Store the maximum size of the TIR buffer. Used to + // convert VME to HEX. + // ------------------------------------------------- + if fTIRSize <= fDataSize then + fTIRSize := fDataSize; + + // ------------------------------------------------- + // Assign the TIR value and allocate memory. + // ------------------------------------------------- + fTailIR := fDataSize; + + if fTailIR > 0 then + begin + ispVMMemManager( opTIR, fTailIR); + ispVMData( fTIRData); + end; + end; + + opHDR: + begin + // ------------------------------------------------- + // Store the maximum size of the HDR buffer. Used to + // convert VME to HEX. + // ------------------------------------------------- + if fHDRSize <= fDataSize then + fHDRSize := fDataSize; + + // ------------------------------------------------- + // Assign the HIR value and allocate memory. + // ------------------------------------------------- + fHeadDR := fDataSize; + + if fHeadDR > 0 then + begin + ispVMMemManager( opHDR, fHeadDR); + ispVMData( fHDRData); + end; + end; + + opTDR: + begin + // ------------------------------------------------- + // Store the maximum size of the TDR buffer. Used to + // convert VME to HEX. + // ------------------------------------------------- + if fTDRSize <= fDataSize then + fTDRSize := fDataSize; + + // ------------------------------------------------- + // Assign the TIR value and allocate memory. + // ------------------------------------------------- + fTailDR := fDataSize; + + if fTailDR > 0 then + begin + ispVMMemManager( opTDR, fTailDR); + ispVMData( fTDRData); + end; + end; + end; + + // --------------------------------------------------------------- + // Re-enable compression if it was previously set. + // --------------------------------------------------------------- + if compress <> 0 then + Include( fDataType, dtCompress); + + result := VME_OK; + + if fDataSize > 0 then + begin + OpCode := TOpCode( GetByte); + + if OpCode <> opContinue then + result := VME_InvalidFile; + end; +end; + +// ================================================================================================ +// ispVMLoop +// +// Perform the function call upon by the REPEAT opcode. Memory is to be allocated to store the +// entire loop from REPEAT to ENDLOOP. After the loop is stored then execution begin. The +// REPEATLOOP flag is set on the fFlowControl register to indicate the repeat loop is in session +// and therefore fetch opcode from the memory instead of from the file. +// ================================================================================================ +function TispVM.ispVMLoop(LoopCount: word): TReturnCode; +var + HeapIndex: word; + LoopIndex: word; + +begin + HeapIndex := 0; + LoopIndex := 0; + fShiftValue := 0; + result := VME_OK; + + for HeapIndex:=0 to fHeapSize -1 do + fHeapMemory[HeapIndex] := GetByte; + + if TOpCode(fHeapMemory[HeapIndex-1]) = opEndLoop then + begin + Include( fFlowControl, fcbRepeatLoop); + Include( fDataType, dtHeap); + + for LoopIndex:=0 to LoopCount -1 do + begin + fHeapCounter := 0; + result := ispVMCode; + fRepeatLoops := fRepeatLoops +1; + + if result <> VME_OK then + break; + end; + + Exclude( fFlowControl, fcbRepeatLoop); + Exclude( fDataType, dtHeap); + end + + else + result := VME_InvalidFile; +end; + +// ================================================================================================ +// ispVMBitShift +// +// Shift the TDI stream left or right by the number of bits. The data in fInData is of the VME +// format, so the actual shifting is the reverse of IEEE 1532 or SVF format. +// ================================================================================================ +function TispVM.ispVMBitShift(OpCode: TOpCode; Count: word): TReturnCode; +var + i : word; + size : word; + tmp : word; + +begin + i := 0; + result:= VME_OK; + + if (fDataSize mod 8) > 0 + then size := (fDataSize div 8) +1 + else size := (fDataSize div 8); + + case OpCode of + // ------------------------------------------------------------ + // Right Shift + // ------------------------------------------------------------ + opSHR: + begin + while i < size do + begin + if fInData[i] <> 0 then + begin + tmp := Count; + + while tmp > 0 do + begin + fInData[i] := fInData[i] shl 1; + + if fInData[i] = 0 then + begin + DEC(i); + fInData[i] := 1; + end; + + DEC(tmp); + end; + end; + + INC(i); + end; + end; + + + // ------------------------------------------------------------ + // Left Shift + // ------------------------------------------------------------ + opSHL: + begin + while i < size do + begin + if fInData[i] <> 0 then + begin + tmp := Count; + + while tmp > 0 do + begin + fInData[i] := fInData[i] shr 1; + + if fInData[i] = 0 then + begin + DEC(i); + fInData[i] := 8; + end; + + DEC(tmp); + end; + end; + + INC(i); + end; + end; + + // ------------------------------------------------------------ + // Invalud operation + // ------------------------------------------------------------ + else + result := VME_InvalidFile + end +end; + +// ================================================================================================ +// ispVMComment +// +// Iterate through the comment and ignore it. +// ================================================================================================ +procedure TispVM.ispVMComment(Size: word); +var + c: AnsiChar; + s: AnsiString; + w: WideString; + +begin + while Size > 0 do + begin + c := AnsiChar(GetByte); + s := s + c; + + DEC(Size) + end; + + w := '| '+s+' |'; + +// s := s +#13#10; + + writeln(s); +// OutputDebugString(@w[1]); +end; + +// ================================================================================================ +// ispVMHeader +// +// Iterate through the header and ignore it. +// ================================================================================================ +procedure TispVM.ispVMHeader(Size: word); +begin + while Size > 0 do + begin + GetByte; + DEC(size) + end +end; + +// ================================================================================================ +// ispVMLCount +// +// Process the intelligent programming loops. +// ================================================================================================ +function TispVM.ispVMLCount(CountSize: word): TReturnCode; +var + Continue : boolean; + BufferIndex : word; + CountIndex : word; + + RepeatHeap : boolean; + OpCode : TOpcode; + + State : TJTAGState; + Delay : word; + Toggle : word; + usByte : byte; + +begin + RepeatHeap := false; + fIntelBufferSize := ispVMDataSize; + + ispVMMemManager(opLHEAP, fIntelBufferSize); + + // --------------------------------------------------------------- + // Store the maximum size of the intelligent buffer. + // Used to convert VME to HEX. + // --------------------------------------------------------------- + if fLCOUNTSize <= fIntelBufferSize then + fLCOUNTSize := fIntelBufferSize; + + // --------------------------------------------------------------- + // Copy intel data to the buffer. + // --------------------------------------------------------------- + for BufferIndex:=0 to fIntelBufferSize -1 do + fIntelBuffer[BufferIndex] := GetByte; + + // --------------------------------------------------------------- + // Update data type register. + // --------------------------------------------------------------- + Include( fDataType, dtLHeap); + + // --------------------------------------------------------------- + // If the HEAP flag is set, tmporarily unset the flag so data will + // be retrieved from the status buffer. + // --------------------------------------------------------------- + if dtHeap in fDataType then + begin + Exclude( fDataType, dtHeap); + RepeatHeap := true; + end; + + // --------------------------------------------------------------- + // Iterate through the intelligent programming command. + // --------------------------------------------------------------- + for CountIndex:=0 to CountSize -1 do + begin + fIntelDataIndex := 0; + OpCode := opEndData; + State := RESET; + Delay := 0; + Toggle := 0; + usByte := 0; + Continue := true; + + // -------------------------------------------------- + // Begin looping through all the VME opcodes. + // -------------------------------------------------- + while Continue do begin + OpCode := TOpCode(GetByte); + + case OpCode of + opHIR,opTIR,opHDR,opTDR: + // Set the header/trailer of device in order + // to bypass successfully. + ispVMAmble( OpCode); + + opState: + begin + // Step the JTAG state machine to DRCAPTURE + // to support looping. + State := TJTAGState(GetByte); + + if (dtLHeap in fDataType) and (State = DRPAUSE) and (fCurrentJTAGState = DRPAUSE) then + ispVMStateMachine( DRCAPTURE); + + ispVMStateMachine(State); + end; + + opSIR : result := ispVMShift(OpCode); + opSDR : result := ispVMShift(OpCode); + + opWAIT : ispVMDelay( ispVMDataSize); + opTCK : ispVMClocks( ispVMDataSize); + opComment : ispVMComment( ispVMDataSize); + + opENDLOOP : Continue := false; + + opIspEN: + begin + OpCode := TOpCode(GetByte); + + case OpCode of + opON : SetPin( pinENA, 0); + opOFF : SetPin( pinENA, 0); + end; + + ispVMDelay(1); + end; + + opTRST: + begin + OpCode := TOpCode(GetByte); + + case OpCode of + opON : SetPin( pinTRST, 0); + opOFF : SetPin( pinTRST, 0); + end; + + ispVMDelay(1); + end; + + else + result := VME_InvalidFile + end; + end; + + if result = VME_OK then + break; + end; + + if RepeatHeap then + Include( fDataType, dtHeap); + + Exclude( fDataType, dtLHeap); +end; + +// ================================================================================================ +// ispVMClocks +// +// Applies the specified number of pulses to TCK. +// ================================================================================================ +procedure TispVM.ispVMClocks(Count: word); +var + i: integer; + +begin + for i:=0 to Count -1 do + sclock +end; + +// ================================================================================================ +// ispVMBypass +// +// This procedure takes care of the HIR, HDR, TIR, TDR for the purpose of putting the other devices +// into Bypass mode. The current state is checked to find out if it is at DRPAUSE or IRPAUSE. +// If it is at DRPAUSE, perform bypass register scan. +// If it is at IRPAUSE, scan into instruction registers the bypass instruction. +// ================================================================================================ +procedure TispVM.ispVMBypass(ScanType: TOpCode; Count: word); +var + Index : word; + SourceIndex : word; + BitState : byte; + CurByte : byte; + Source : PByte; + +begin + SourceIndex := 0; + + if Count > 0 then + begin + case ScanType of + opHIR: Source := fHIRData; + opTIR: Source := fTIRData; + opHDR: Source := fHDRData; + opTDR: Source := fTDRData; + else Source := nil; + end; + + for Index:=0 to Count -2 do + begin + if (Index mod 8) = 0 then + begin + CurByte := Source[SourceIndex]; + INC(SourceIndex); + end; + + if (CurByte shl (Index mod 8)) and $80 = $80 + then BitState := 1 + else BitState := 0; + + SetPin( pinTDI, BitState); + sclock; + end; + + if (Index mod 8) = 0 then + CurByte := Source[SourceIndex]; + + if (CurByte shl (Index mod 8)) and $80 = $80 + then BitState := 1 + else BitState := 0; + + SetPin( pinTDI, BitState); + end; +end; + +// ================================================================================================ +// ispVMStateMachine +// +// This procedure steps all devices in the daisy chain from a given JTAG state to the next +// desirable state. If the next state is TLR, the JTAG state machine is brute forced into +// TLR by driving TMS high and pulse TCK 6 times. +// ================================================================================================ +procedure TispVM.ispVMStateMachine(NextState:TJTAGState); +var + PathIndex : byte; + StateIndex : byte; + +begin + if (fCurrentJTAGState = NextState) and (NextState <> RESET) then + exit; + + for StateIndex:=0 to 24 do + if (fCurrentJTAGState = JTAGTransitions[StateIndex].CurrState) and + (NextState = JTAGTransitions[StateIndex].NextState) then + break; + + fCurrentJTAGState := NextState; + + for PathIndex:=0 to JTAGTransitions[StateIndex].Pulses -1 do + begin + if (JTAGTransitions[StateIndex].Pattern shl PathIndex) and $80 = $80 + then SetPin( pinTMS, 1) + else SetPin( pinTMS, 0); + + sclock; + end; + + SetPin( pinTDI, 0); + SetPin( pinTMS, 0); +end; + +// ================================================================================================ +// ispVMSend +// +// Send the TDI data stream to devices. The data stream can be instructions or data. +// ================================================================================================ +function TispVM.ispVMSend(Count: word): TReturnCode; +var + Index : word; + DataIndex: word; + CurByte : byte; + BitState : byte; + +begin +// if Assigned(fJtag) then +// fJtag.xfer( fInData, Count, 1); + +{ + DataIndex := 0; + + for Index:=0 to Count -2 do + begin + if (Index mod 8) = 0 then + begin + CurByte := fInData[DataIndex]; + INC(DataIndex); + end; + + if (CurByte shl (Index mod 8)) and $80 = $80 + then BitState := 1 + else BitState := 0; + + SetPin( pinTDI, BitState); + sclock; + end; + + // Take care of the last bit. + if (Index mod 8) = 0 then + CurByte := fInData[DataIndex]; + + if (CurByte shl (Index mod 8)) and $80 = $80 + then BitState := 1 + else BitState := 0; + + SetPin( pinTDI, BitState); + + // Clock in last bit for the first n-1 cascaded frames. + if fcbCascade in fFlowControl then + sclock; +} + result := VME_OK +end; + +// ================================================================================================ +// ispVMRead +// +// Read the data stream from devices and verify. +// ================================================================================================ +function TispVM.ispVMRead(Count: word): TReturnCode; +var + DataSizeIndex : word; + ErrorCount : word; + LastBitIndex : word; + DataByte : byte; + MaskByte : byte; + InDataByte : byte; + CurBit : byte; + ByteIndex : byte; + BufferIndex : word; + DisplayByte : byte; + DisplayFlag : boolean; + BitState : byte; + + StrChecksum : array [0..255] of AnsiChar; + CalChecksum : boolean; + + cnt : integer; + i : integer; + +begin + ByteIndex := 0; + BufferIndex := 0; + DisplayByte := 0; + DisplayFlag := true; + CalChecksum := false; + LastBitIndex := Count -1; + + // --------------------------------------------------------------- + // If mask is not all zeros, then set the display flag to 0x00, + // otherwise it shall be set to 0x01 to indicate that data read + // from the device shall be displayed. + // If VME_DEBUG is defined, always display data. + // --------------------------------------------------------------- + for DataSizeIndex:=0 to ((Count + 7) mod 8) -1 do + begin + if dtMASKData in fDataType then + begin + if fOutMaskData[DataSizeIndex] <> 0 then + begin + DisplayFlag := false; + break + end; + end + + else if dtCMASKData in fDataType then + begin + CalChecksum := true; + DisplayFlag := false; + break + end + + else begin + DisplayFlag := false; + break + end; + end; + + // --------------------------------------------------------------- + // Send TDI data out. + // --------------------------------------------------------------- + fTransferMode := tmRead; + result := ispVMSend(Count); + + exit; +// for i:=0 to (Count *2) -1 do +// fBuffer[i] := fBuffer[i] and fMaskTDO; + + + + + + + + + // --------------------------------------------------------------- + // Begin shifting data in and out of the device. + // --------------------------------------------------------------- + for DataSizeIndex:=0 to Count -1 do + begin + if ByteIndex = 0 then + begin + if dtTDOData in fDataType then + DataByte := fOutData[BufferIndex]; + + if dtMASKData in fDataType + then MaskByte := fOutMaskData[BufferIndex] + else MaskByte := $FF; + + if dtCMASKData in fDataType then + begin + MaskByte := $00; + CalChecksum := true; + end; + + if dtTDIData in fDataType then + InDataByte := fInData[BufferIndex]; + + INC(BufferIndex) + end; + +// CurBit := ReadPort; + + if DisplayFlag then + begin + DisplayByte := DisplayByte shl 1; + DisplayByte := DisplayByte or CurBit; + end; + + // ------------------------------------------------------------ + // Check if data read from port matches with expected TDO. + // ------------------------------------------------------------ + if dtTDOData in fDataType then + begin + if CalChecksum then + begin + if CurBit = 1 then + fCheckSum := fCheckSum + (1 shl (fCheckSumIndex mod 8)); + + INC( fCheckSumIndex) + end + + else begin + // TODO: b+ + end; + end; + + // ------------------------------------------------------------ + // Write TDI data to the port. + // ------------------------------------------------------------ + if (InDataByte shl ByteIndex) and $80 = $80 + then BitState := 1 + else BitState := 0; + + SetPin( pinTDI, BitState); + + if (DataSizeIndex < LastBitIndex) or (fcbCascade in fFlowControl) then + sclock; + + // ------------------------------------------------------------ + // Increment the byte index. If it exceeds 7, then resetit back + // to zero. + // ------------------------------------------------------------ + INC(ByteIndex); + + if ByteIndex > 7 then + begin + if DisplayFlag then + begin + // ------------------------------------------------------ + // Store displayed data in the TDO buffer. By reusing the + // TDO buffer to store displayed data, there is no need + // to allocate a buffer simply to hold display data. This + // will not cause any false verification errors because + // the true TDO byte has already been consumed. + // ------------------------------------------------------ + fOutData[BufferIndex -1] := DisplayByte; + DisplayByte := 0; + end; + + ByteIndex := 0; + end + + else if fDataSize = 1 then + begin + if DisplayFlag then + begin + // ------------------------------------------------------ + // Store displayed data in the TDO buffer. By reusing the + // TDO buffer to store displayed data, there is no need + // to allocate a buffer simply to hold display data. This + // will not cause any false verification errors because + // the true TDO byte has already been consumed. + // + // Flip DisplayByte and store it in DataByte. + // ------------------------------------------------------ + DataByte := FlipByte(DisplayByte); + fOutData[0] := DataByte; + DisplayByte := 0; + end; + + ByteIndex := 0; + end; + end; + + // --------------------------------------------------------------- + // Display data read from the device. + // --------------------------------------------------------------- + if DisplayFlag then + begin + // writeln.... + + cnt := (fDataSize +7) mod 8; + + for DataSizeIndex := cnt-1 downto 0 do + begin + MaskByte := fOutData[DataSizeIndex]; + DataByte := FlipByte(MaskByte); + + // write DataByte + end; + + if fCheckSum <> 0 then + begin + + end; + end; + + if ErrorCount > 0 then + begin + + end; + + result := VME_OK +end; + +// ================================================================================================ +// ispVMReadAndSave +// ================================================================================================ +function TispVM.ispVMReadAndSave(Count: word): TReturnCode; +var + DataSizeIndex : word; + ErrorCount : word; + LastBitIndex : word; + OutBitIndex : word; + DataByte : byte; + DMaskByte : byte; + InDataByte : byte; + CurBit : byte; + ByteIndex : byte; + BufferIndex : word; + DisplayByte : byte; + DisplayFlag : boolean; + BitState : byte; + + StrChecksum : array [0..255] of AnsiChar; + CalChecksum : boolean; + + cnt : integer; + i : integer; + +begin + + ByteIndex := 0; + BufferIndex := 0; + DisplayByte := 0; + DisplayFlag := true; + CalChecksum := false; + LastBitIndex := Count -1; + + // --------------------------------------------------------------- + // Iterate through the data bits. + // --------------------------------------------------------------- + for DataSizeIndex := 0 to Count -1 do + begin + if ByteIndex = 0 then + begin + if dtDMASKData in fDataType + then DMaskByte := fOutDMaskData[BufferIndex] + else DMaskByte := $00; + + if dtTDIData in fDataType + then InDataByte := fInData[BufferIndex]; + + INC(BufferIndex) + end; + +// CurBit := ReadPort; + if (InDataByte shl ByteIndex) and $80 = $80 + then DataByte := $01 + else DataByte := $00; + + // initialize the byte to be zero + if (OutBitIndex mod 8) = 0 then + fOutData[OutBitIndex div 8] := $00; + + // ------------------------------------------------------------ + // Use TDI, DMASK, and device TDO to create new TDI + // (actually stored in fOutData). + // ------------------------------------------------------------ + if (DMaskByte shl ByteIndex) and $80 = $80 then + begin + if Length( fLVDs) > 0 then + for i:=Low(fLVDS) to High(fLVDS) do + if fLVDs[i].NegativeIndex = DataSizeIndex then + begin + fLVDs[i].Update := true; + break; + end; + + // DMASK bit is 1, use TDI. + if DataByte and $01 = $01 then + fOutData[OutBitIndex mod 8] := fOutData[OutBitIndex mod 8] or $01; + end + + else begin + // DMASK bit is 0, use TDO. + if CurBit and $01 = $01 then + fOutData[OutBitIndex mod 8] := fOutData[OutBitIndex mod 8] or $01; + end; + + // ------------------------------------------------------------ + // Shift in TDI in order to get TDO out. + // ------------------------------------------------------------ + INC(OutBitIndex); + SetPin( pinTDI, DataByte); + + if DataSizeIndex < LastBitIndex then + sclock; + + // ------------------------------------------------------------ + // Increment the byte index. If it exceeds 7, then reset it + // back to zero. + // ------------------------------------------------------------ + INC(ByteIndex); + + if ByteIndex >= 8 then + ByteIndex := 0; + end; + + // --------------------------------------------------------------- + // If fLVDs list exists and pairs needed updating, then update the + // negative pair to receive the flipped positive pair value. + // Ezt a reszt most kihagyom! Fene tudja mikor kell. + // --------------------------------------------------------------- + if Length(fLVDs) > 0 then + begin + for i:=Low(fLVDs) to High(fLVDs) do + begin + if fLVDs[i].Update then + begin + // -------------------------------------------- + // Read the positive value and invert it. + // -------------------------------------------- + DataByte := fLVDs[i].PositiveIndex; + fLVDs[i].NegativeIndex := not DataByte; + + // -------------------------------------------- + // Get the byte that needs modification. + // -------------------------------------------- + InDataByte := fOutData[ fLVDs[i].NegativeIndex div 8]; + + if DataByte <> 0 then + begin + + end; + + end; + end; + end; + + result := VME_OK +end; + + + + +// ================================================================================================ +// ispVMStart +// +// Enable the port to the device and set the state to RESET. +// ================================================================================================ +procedure TispVM.ispVMStart; +begin + ispVMStateMachine(RESET); + Flush; +end; + +// ================================================================================================ +// ispVMEnd +// +// Set the state of devices to RESET to enable the devices and disable the port. +// ================================================================================================ +procedure TispVM.ispVMEnd; +begin + ispVMStateMachine(RESET); + Flush; + + ispVMDelay(1000) +end; + + +// ================================================================================================ +// ispVMProcessLVDS +// ================================================================================================ +function TispVM.ispVMProcessLVDS(Count: word): TReturnCode; +var + i: word; + +begin + // --------------------------------------------------------------- + // Allocate memory to hold LVDS pairs. + // --------------------------------------------------------------- + SetLength( fLVDs, Count); + + // --------------------------------------------------------------- + // Iterate through each given LVDS pair. + // --------------------------------------------------------------- + for i:=0 to Count -1 do + begin + fLVDs[i].PositiveIndex := ispVMDataSize; + fLVDs[i].NegativeIndex := ispVMDataSize; + fLVDs[i].Update := false; + end; + + result := VME_OK +end; +// ================================================================================================ +// ispVMDelay +// +// Users must implement a delay to observe a_usTimeDelay, where +// bit 15 of the a_usTimeDelay defines the unit. +// 1 = milliseconds +// 0 = microseconds +// Example: +// a_usTimeDelay = 0x0001 = 1 microsecond delay. +// a_usTimeDelay = 0x8001 = 1 millisecond delay. +// +// This subroutine is called upon to provide a delay from 1 millisecond to a few hundreds +// milliseconds each time. +// +// It is understood that due to a_usTimeDelay is defined as unsigned short, a 16 bits integer, +// this function is restricted to produce a delay to 64000 micro-seconds or 32000 milli-second +// maximum. The VME file will never pass on to this function a delay time > those maximum number. +// If it needs more than those maximum, the VME file will launch the delay function several times +// to realize a larger delay time cummulatively. +// +// It is perfectly alright to provide a longer delay than required. It is not acceptable if the +// delay is shorter. +// ================================================================================================ +procedure TispVM.ispVMDelay(Delay: word); +var + d: integer; + +begin + if Delay and $8000 = $8000 + then d := Delay and $7FFF + else d := Delay div 1000; + + if d = 0 then + d := 1; + +// if Assigned(fJtag) then +// fJtag.wait(d); + +//@ Flush; +//@ Sleep(d); +end; + +// ================================================================================================ +// SClock +// ================================================================================================ +procedure TispVM.sclock(n:integer); +var + data : byte; + i : integer; + +begin + data := 0; + + if fValTMS then data := data or fMaskTMS; + if fValTDI then data := data or fMaskTDI; + if fValTRST then data := data or fMaskTRST; + if fValENA then data := data or fMaskENA; + + for i:=0 to n-1 do + begin + if (fBufferSize - fBufferIndex) < 2 then + Flush; + + data := data and not fMaskTCK; + fBuffer[fBufferIndex] := data; + INC(fBufferIndex); + + data := data or fMaskTCK; + fBuffer[fBufferIndex] := data; + INC(fBufferIndex); + end; +end; + +// ================================================================================================ +// SetPin +// ================================================================================================ +procedure TispVM.SetPin( pin: TPin; Value: byte); +begin + case pin of + pinTMS : fValTMS := Value <> 0; + pinTDI : fValTDI := Value <> 0; + pinTRST : fValTRST := Value <> 0; + pinENA : fValENA := Value <> 0; + end; +end; + +// ================================================================================================ +// Flush the buffer +// ================================================================================================ +procedure TispVM.Flush; +begin + if fBufferIndex > 0 then + if Assigned( fOnTransfer) then + fOnTransfer( self, fTransferMode); + + fBufferIndex := 0; +end; + + +// ================================================================================================ +// ispVMMemManager +// +// Allocate memory based on Target. The memory size specified by Size. +// ================================================================================================ +procedure TispVM.ispVMMemManager(Target: TOpCode; Size: word); +begin + case Target of + opTDI,opXTDI: + begin + if Assigned(fInData) then + FreeMem(fInData); + + fInData := AllocMem( (Size div 8) +2); + end; + + opTDO,opXTDO: + begin + if Assigned(fOutData) then + FreeMem(fOutData); + + fOutData := AllocMem( (Size div 8) +2); + end; + + opMASK: + begin + if Assigned( fOutMaskData) then + FreeMem( fOutMaskData); + + fOutMaskData := AllocMem( (Size div 8) +2); + end; + + opDMASK: + begin + if Assigned( fOutDMaskData) then + FreeMem( fOutDMaskData); + + fOutDMaskData := AllocMem( (Size div 8) +2); + end; + + opHIR: + begin + if Assigned( fHIRData) then + FreeMem( fHIRData); + + fHIRData := AllocMem( (Size div 8) +2); + end; + + opTIR: + begin + if Assigned( fTIRData) then + FreeMem( fTIRData); + + fTIRData := AllocMem( (Size div 8) +2); + end; + + opHDR: + begin + if Assigned( fHDRData) then + FreeMem( fHDRData); + + fHDRData := AllocMem( (Size div 8) +2); + end; + + opTDR: + begin + if Assigned( fTDRData) then + FreeMem( fTDRData); + + fTDRData := AllocMem( (Size div 8) +2); + end; + + opHEAP: + begin + if Assigned( fHeapMemory) then + FreeMem( fHeapMemory); + + fHeapMemory := AllocMem( (Size div 8) +2); + end; + + opLHeap: + begin + if Assigned( fIntelBuffer) then + FreeMem( fIntelBuffer); + + fIntelBuffer := AllocMem( (Size div 8) +2); + end; + end; +end; + + + +initialization + +end. diff --git a/src.jtag/vme/jtag.vme.tools.pas b/src.jtag/vme/jtag.vme.tools.pas new file mode 100644 index 0000000..8b62865 --- /dev/null +++ b/src.jtag/vme/jtag.vme.tools.pas @@ -0,0 +1,46 @@ +unit jtag.vme.tools; + +interface + +function FlipByte( Data: byte): byte; +function FlipWord( Data: word): word; + +implementation + +function FlipByte( Data: byte): byte; +var + i: integer; + +begin + result := 0; + + for i:=0 to 7 do + begin + result := result shl 1; + + if Data and $01 = $01 then + result := result or $1; + + Data := Data shr 1; + end; +end; + +function FlipWord( Data: word): word; +var + i: integer; + +begin + result := 0; + + for i:=0 to 15 do + begin + result := result shl 1; + + if Data and $01 = $01 then + result := result or $1; + + Data := Data shr 1; + end; +end; + +end.