/* Inputs and outputs are chip NOT tester relative */
#include <stdio.h>
#include <ctype.h>
#define LDEBUG 0
#define maxsigs 72
#define SG sigs[i]
#define fpf fprintf
#define foris for(i=0;i<sindex;i++)
#define g_s() get_sym(s,&t)
#define tbase 0x300
#define maxcode 40000
/* Parser constants etc */
char cmt_start_ch = '{',
cmt_end_ch = '}',
line_cmt_ch = '#',
x_id_start_chs[] = {'$','_','\0'},
x_id_chs[] = {'$','_','\0'},
x_space_chs[] = {';',':','@','=','\0'},
op_chs[] = {'+','*','/','\0'};
char *keys[] = { "END", "INPUT", "OUTPUT", "PIN", "BIDIR", "DEFPINS" };
#include "procs5.c"
/* program vars */
int sindex=0, vecnum=0, group=TRUE; long codelen=0l;
typedef enum {snone=0,early,late} stype;
typedef enum {end=0,set_group,get_group,set_dir,clock,newvec} comm;
stype skew=snone;
struct sig { char v,ov,rv,dir,odir,vt, name[N_L]; int pin; } sigs[maxsigs];
struct pinadd {int iaddr,oaddr; byte iv,ov,m,status;} pindata[maxsigs/8];
char code[maxcode];
FILE *fo,*fs;
main(argc,argv)
int argc; char *argv[];
{int i,do_skew=FALSE; long j=0l;
set_hardware();
if (argc<2)
error("USAGE: ctest <designname> [-no_group|-ng] [-l] [-id]");
fin=efopen(cf(argv[1],".vec"),"r");
init();
if (arg_num(argc,argv,"-stdout")) fo=stdout;
else fo= efopen(cf(argv[1],".cv"),"w");
if (arg_num(argc,argv,"-skew"))
{ do_skew=TRUE; fs=fopen(cf(argv[1],".skw"),"w");}
if (arg_num(argc,argv,"-no_group")||arg_num(argc,argv,"-ng"))
group=FALSE;
if (arg_num(argc,argv,"-id")) {printf("Version FEB/5/89\n"); exit(0);}
/*------------------------------------------------------------------*/
expect_sym("DEFPINS");
while (strneq(s,"END") && !feof(fin))
{
g_s();
if (strneq(s,"PIN") && strneq(s,"END"))
error("PIN or END expected in defpins");
else
{
if (strequ(s,"PIN"))
{i=get_int();
if (i>maxsigs || i<=0) error("invalid pin range");
sigs[sindex].pin=i;
g_s();
if (strequ(s,"VSS") || strequ(s,"VDD"))
{ if (strequ(s,"VDD")) {setd(i,'I'); setp(i,'1');}
else {setd(i,'I'); setp(i,'0');}
}
else
{
if (t!=ident) error("Signal name expected");
if (sig_exists(s)) error("Duplicate signal found in sigdefs");
strcpy(sigs[sindex].name,s);
g_s();
if (s[0] != 'I' && s[0] != 'O' && s[0] != 'B')
error("INPUT, OUTPUT, or BIDIR expected");
sigs[sindex].vt = s[0];
sindex++; }}
}
} /* while */
/*------- Output the header ----------------------------------*/
/*
fpf(fo,"# Test Output\n\nDEFPINS\n");
foris fpf(fo," PIN %d %s %c;\n",SG.pin,SG.name,SG.vt);
fpf(fo,"END;\n\n");
pr_header();
*/
/*------- Init the pins ----------------------------------*/
/* init values */
foris { SG.v='-'; SG.dir='-'; SG.odir='-';}
for(i=0;i<=maxsigs/8;i++) pindata[i].ov=0;
foris
switch (SG.vt)
{
case 'O': setd(SG.pin,'O'); break;
case 'B': SG.dir='O'; setd(SG.pin,'O'); break;
}
ssync(); /* get power on */
/*
foris
printf("%s %c %c %c %d\n",SG.name,SG.vt,SG.v,SG.dir,SG.pin);
*/
/*-------- Read and deal with vectors ------------------------------*/
while (!feof(fin)) /* deal with vector */
{
vecnum++;
/* copy old vals */
foris { SG.ov = SG.v; SG.odir = SG.dir;}
if(codelen>maxcode-50) error("cv codelength too long");
putc(newvec,fo); codelen++;
get_vline();
if(!feof(fin))
{assert_vec(snone,0);
strobe_vec();
}
} /* END of vector while */
putc(end,fo); codelen++;
fclose(fo);
if(arg_num(argc,argv,"-l"))
{fin=efopen(cf(argv[1],".cv"),"r");
printf("\n\n CODE LISTING\n ============\n\n");
while(!feof(fin)) code[j++]=getc(fin);
listcode(code);
printf("\n END OF CODE LISTING\n\n");
}
printf("-I- length of compiled code is %d bytes\n",codelen);
fpf(stdout,"-I- %d vectors \n",--vecnum );
} /* main */
/*------------------------------------------------------------------*/
cv(c)
char c;
{ switch (c) {
case 'L': return('0');
case 'H': return('1');
default : return(c);
}
}
vt(c)
char c;
{ c=uc(c);
if (c == 'L' || c == 'H') return('I'); else
{if (c == '0' || c == '1' || c == 'X') return('O');
else return('U'); }}
iv(c)
char c;
{ if(c=='0') return('L'); if(c=='1') return('H'); return(c); }
/*------------------------------------------------------------------*/
get_value()
{ /* fpf(fo,"gv\n"); */
do {
xgetch();
if (ch=='#') { while (ch != '\n') xgetch(); }
if (ch=='{') { while (ch != '}') xgetch(); }
if (ch >= 'a' && ch <= 'z') ch = toupper(ch);
} while (!cinstring(ch,"HL10X") && ch != EOF);
return(ch);
}
/*------------------------------------------------------------------*/
get_vline()
{ int i; char c;
foris
{ c = get_value();
if (SG.vt == 'O' && (c == 'H' || c == 'L'))
error("Expected output value");
if (SG.vt == 'I' && (c == '0' || c == '1' || c == 'X'))
error("Expected input value");
if (SG.vt == 'B') SG.dir = vt(c);
SG.v = cv(c);
} /* for */
}
/*------------------------------------------------------------------*/
assert_vec(skew,pn)
stype skew; int pn;
{ int i=0;
if(skew==early)
{ while(SG.pin!=pn&&i<sindex) i++; printf("eraly\n");
if(SG.dir!=SG.odir) setd(SG.pin,SG.dir);
if(SG.vt=='I'&&SG.v!=SG.ov) setp(SG.pin,SG.v);
if(SG.dir=='I'&&SG.v!=SG.ov) setp(SG.pin,SG.v);
ssync();
}
foris /* assert vals */
if(skew==snone||skew!=snone&&SG.pin!=pn) /* filter the skew sig */
{
if(SG.dir!=SG.odir) setd(SG.pin,SG.dir);
if(SG.vt=='I'&&SG.v!=SG.ov) setp(SG.pin,SG.v);
if(SG.dir=='I'&&SG.v!=SG.ov) setp(SG.pin,SG.v);
}
ssync();
if(skew==late )
{ while(SG.pin!=pn&&i<sindex) i++; printf("late\n");
if(SG.dir!=SG.odir) setd(SG.pin,SG.dir);
if(SG.vt=='I'&&SG.v!=SG.ov) setp(SG.pin,SG.v);
if(SG.dir=='I'&&SG.v!=SG.ov) setp(SG.pin,SG.v);
ssync();
}
}
/*--------------------------------------------------------------------*/
strobe_vec()
{ int i, tsterr=FALSE;
extern char read_pin();
for(i=0;i<=maxsigs/8;i++) pindata[i].status='F';
foris
{/* set mask value */
if((SG.dir!=SG.odir||SG.v!=SG.ov)&&SG.vt!='I' )
if(SG.v=='X'||SG.dir=='I')
{ pindata[(SG.pin-1)/8].m &= ~(1<<(SG.pin-1)%8);
if(LDEBUG) printf("mask on pin %d = %d\n",SG.pin,0);}
else {pindata[(SG.pin-1)/8].m |= 1<<(SG.pin-1)%8;
if(LDEBUG) printf("mask on pin %d = %d\n",SG.pin,1);}
}
foris /* update expected value */
{if(SG.vt!='I'&&SG.dir!='I')
{if(SG.v=='1') pindata[(SG.pin-1)/8].ov |= 1<<(SG.pin-1)%8;
if(SG.v=='0') pindata[(SG.pin-1)/8].ov &= ~(1<<(SG.pin-1)%8);}
}
foris /* read back vals to SG.rv */
if(SG.vt=='O'||SG.dir=='O')
{
SG.rv=read_pin(SG.pin);
if(SG.rv!=SG.v&&SG.v!='X') tsterr = TRUE;
}
/*
foris
if(SG.vt=='I'||SG.dir=='I') fpf(fo,"%c",iv(SG.v));
else
{if(SG.v=='X') fpf(fo,"X"); else fpf(fo,"%c",SG.rv);}
fpf(fo," {%d}\n",vecnum);
if(tsterr)
{
foris
if(SG.v != SG.rv && (SG.vt=='O'||SG.dir=='O') && SG.v!='X')
fpf(fo,"#"); else fpf(fo," ");
fpf(fo,"\n");
fpf(stderr,"fail at vector %d\n",vecnum);
}
*/
}
/*--------------------------------------------------------------------*/
pr_header()
{ int i=0,j=0,l=0;
fpf(fo,"{\n");
foris if(strlen(SG.name)>l) l=strlen(SG.name);
l--;
for(;j<=l;j++)
{ foris if(strlen(SG.name)>j)
fpf(fo,"%c",SG.name[j]); else fpf(fo,"%c",' ');
fpf(fo,"\n");
}
fpf(fo,"}\n");
}
set_hardware()
{ /* maps pin numbers to expander device addresses */
int i=0; /* HARDWARE DEPENDANT ROUTINE */
/* set outputs from tester */
outp(tbase+3,0x80);
outp(tbase+7,0x80);
outp(tbase+0xb,0x80);
/* set inputs to tester */
outp(0x310+0x3,0x9b);
outp(0x310+0x7,0x9b);
outp(0x310+0xb,0x9b);
/* set outputs from tester */
for(i=0 ; i<=2;i++) outp(tbase+i,0xff);
for(i=4 ; i<=6;i++) outp(tbase+i,0xff);
for(i=8 ;i<=10;i++) outp(tbase+i,0xff);
/* set up pindata vals, mask and addresses */
while(i<=maxsigs/8)
{pindata[i].iv=0xff; pindata[i].m=0; pindata[i++].ov=0;}
for(i=0 ;i<= 2;i++) pindata[i].iaddr=i;
for(i=3 ;i<= 5;i++) pindata[i].iaddr=i+1;
for(i=6 ;i<=8 ;i++) pindata[i].iaddr=i+2;
for(i=0 ;i<= 2;i++) pindata[i].oaddr=i+0x10;
for(i=3 ;i<= 5;i++) pindata[i].oaddr=i+0x11;
for(i=6 ;i<= 8;i++) pindata[i].oaddr=i+0x12;
}
fastrun(cs) /* compacted code interpreter */
byte *cs; /* HARDWARE DEPENDENT */
{long i=0l,v=0l; int j; byte rv;
while(cs[i]) /* !end */
{switch((char) cs[i])
{
case set_group: /* set_group|offset|value */
outp(cs[i+1]+tbase,cs[i+2]); i+=3; break;
case get_group: /* get_group|offset|mask|expected_val */
rv=inp(cs[++i]+tbase);
if(rv&cs[i+1] != cs[i+1]&cs[i+2])
fpf(stderr,"fail at vector %d\n",v);
cs[i+2]=rv; i+=3; break;
/* clock|count|offset|val1|val2 */
case clock : for(j=cs[++i];j>0;j--)
{outp(cs[i+1]+tbase,cs[i+2]);
outp(cs[i+1]+tbase,cs[i+3]);}
i+=4; break;
case newvec : v++; i++; break;
default: error("in compacted code interpreter");
}
} /* while */
}
listcode(cs) /* compacted code interpreter */
char *cs;
{long i=0l,v=0l;
while(cs[i]) /* !end */
{switch((char) cs[i])
{
case set_group: printf(" set offset %x to %x \n",cs[i+1],cs[i+2]);
i+=3; break;
case get_group: printf(" get offset %x mask %x exp %x\n",
cs[i+1],cs[i+2],cs[i+3]); i+=4; break;
case clock : printf("clock %x %x %x %x\n",cs[i+1],cs[i+2],
cs[i+3],cs[i+4]); i++; break;
case newvec : printf(" newvec\n"); v++; i++; break;
default: printf("found command %x\n",cs[i]);
error("in compacted code interpreter");
}
} /* while */
}
/*
compress_code(cs)
byte *cs;
{long i=0l,v=0l; int j,num_sets; byte lastmask,maskbeforelast;
while(cs[i])
{ if (cs[i++]==set_group)
{
*/
sig_exists(sg)
char *sg;
{int i;
for(i = 0;i!=sindex && strneq(sg,sigs[i].name);i++) ;
if (strequ(sg,sigs[i].name)) return(TRUE);
else return(FALSE);
}
outp(a,d)
int a; byte d;
{
if(LDEBUG) printf("outp %x %x\n",a,d);
putc(set_group,fo);
putc(a-tbase,fo);
putc(d,fo);
codelen+=3;
}
inp(a)
int a;
{int i=0;
while(i<maxsigs/8 && a != pindata[i].oaddr+tbase) i++;
if(a!=pindata[i].oaddr+tbase) error("inp");
if(pindata[i].m!=0)
{
putc(get_group,fo);
putc(a-tbase,fo);
putc(pindata[i].m,fo);
putc(pindata[i].ov,fo);
if(LDEBUG) printf("inp %x %x %d\n",a,pindata[i].m,i);
}
codelen +=4;
return 0;
}
setp(p,v)
int p; char v;
{p--;
if(v=='1') pindata[p/8].iv=pindata[p/8].iv |1<<p%8;
else pindata[p/8].iv=pindata[p/8].iv & ~(1<<p%8);
if(!group) outp(tbase+pindata[p/8].iaddr,pindata[p/8].iv);
else pindata[p/8].status='T';
if(LDEBUG) printf("set pin %d to %c\n",p+1,v);
}
setd(p,d)
int p; char d;
{
/* printf("set dir %d to %c\n",p,d); */
if(d=='O') setp(p,'1');
if(d=='I') setp(p,'0');
}
char read_pin(p)
int p;
{
p--;
if(pindata[p/8].status=='F') /* check if its already read */
{pindata[p/8].ov=inp(tbase+pindata[p/8].oaddr);
pindata[p/8].status='R';}
if(pindata[p/8].ov & 1<<p%8) return '1';
return '0';
}
ssync() /* output grouped signals for speed */
{int i; /* printf("ssync\n"); */
if(group)
{ for(i=0;i<maxsigs/8;i++)
if(pindata[i].status=='T') outp(tbase+pindata[i].iaddr,pindata[i].iv);
}
}