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

425 lines
12 KiB
ObjectPascal

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.