/* * pal.c * * pal emulator * AT-8 hardware design * */ #include #include #include "pal.h" /* * globals */ struct pal *phead; /* start of PAL list */ /* * getbit - get an ascii bit (0 or 1) from a JEDEC file */ getbit(datfile) FILE *datfile; { char inchar; char temp[80]; for (inchar = fgetc(datfile); inchar != EOF; inchar = fgetc(datfile)) if ((inchar == '1') || (inchar =='0')) break; else if ((inchar =='L') || (inchar =='l')) fscanf(datfile,"%s",temp); return inchar; } /* * palinit - initialize PAL data structures * * This is the initialization routine which parses a JEDEC file, * determines the file type, reads the device specific chip data, * and initializes the logic arrays for execution. Two data files * are required: the JEDEC file (in UNIX format), and the PAL * definition file. * * At present, a third data file is read - the limit definition * file. This file determines the logic "0" and "1" level for * each input. It is anticipated that this function will become * an intrinsic part of the EPICS record in the future. * */ struct pal * palinit(file,recname,thresh) char *file; char *recname; double thresh[]; { FILE *datfile; char temp[80], jedfile[80], inchar; int i, j, k, l, m, fusenum, itemp, members; unsigned int *elptr, tmask; struct thresh *tptr; struct blk *fptr; static struct pal *curpal; strcpy(jedfile,file); strcat(jedfile,".jed"); printf("palinit - opening JEDEC file %s\n",jedfile); for (i = 0; i < RETRY; i++) if ((datfile = fopen(jedfile, "r")) != NULL) break; if (i == RETRY) { printf("palinit:cannot open JEDEC file %s - aborting\n",jedfile); return (struct pal *)0; } /* * allocate memory for new PAL */ if (!phead) phead = curpal = (struct pal *)malloc(sizeof (struct pal)); else { curpal->flink = (struct pal *)malloc(sizeof (struct pal)); curpal = curpal->flink; } curpal->bptr = (struct blk *)0; curpal->flink = (struct pal *)0; curpal->iptr = (struct palinit *)malloc(sizeof (struct palinit)); curpal->iptr->def = (char *)malloc(strlen(file)+1); strcpy(curpal->iptr->def,file); curpal->recnam = (char *)malloc(strlen(recname)+1); strcpy(curpal->recnam,recname); /* * look for PAL type - this info is marked with the character value 02 */ for (; (inchar = fgetc(datfile)) != EOF;) if (inchar == 2) break; if (inchar == 2) { fscanf(datfile,"%s",temp); curpal->iptr->name = (char *)malloc(strlen(temp)+1); strcpy(curpal->iptr->name,temp); strcpy(temp,file); /* strip off path info from JEDEC input file */ for (i = strlen(temp); i > 0; i--) if (temp[i] == '/') break; if (i) temp[i+1] = NULL; else temp[0] = NULL; curpal->iptr->path = (char *)malloc(strlen(temp)+1); strcpy(curpal->iptr->path,temp); } else if (inchar == EOF) { printf("palinit:cannot find PAL device type in %s - aborting\n",jedfile); return (struct pal *)0; } /* * find PAL device specific data */ if (paldef(curpal)) return (struct pal *)0; /* * load input threshold data */ for (i = j = 0, tptr = curpal->ithresh; i < curpal->inp; i++, tptr++) { tptr->lothresh = thresh[j++]; tptr->hithresh = thresh[j++]; } /* * look for start of fuse data */ for (i = fscanf(datfile,"%s",temp); (i != EOF) && (strcmp(temp,"L0000")); i = fscanf(datfile,"%s",temp)); if (i == EOF) { printf("palinit:cannot find fuse data in %s - aborting\n",jedfile); return (struct pal *)0; } fusenum = 0; /* * initialize fuse data for each pal block */ for (i = 0; i < curpal->blknum; i++) /* for each PAL block */ { if (fusenum != curpal->bptr[i].loc) { for (; fusenum != curpal->bptr[i].loc; fusenum++) if (getbit(datfile) == EOF) { printf("palinit:cannot find start of PAL block %d file %s - aborting\n",i,jedfile); return (struct pal *)0; } } for (j = 0, elptr = curpal->bptr[i].array; j < curpal->bptr[i].blksiz; j++) /* for each block element */ { members = curpal->blkbits/INTBITS; /* # members per element */ if (curpal->blkbits%INTBITS) /* check for partially filled member */ members++; for (k = 0; k < members; k++, elptr++) /* for each element member */ { if (k < curpal->blkbits/INTBITS) /* last member may be partially filled */ itemp = INTBITS; /* if not do 32 bits worth */ else itemp = curpal->blkbits%INTBITS; /* if so how much */ for (l = 0, *elptr = 0; l < itemp; l++) /* do it */ { if ((inchar = getbit(datfile)) == EOF) /* get next data bit */ { printf("palinit:unexpected EOF in JEDEC file (pal blocks)\n"); return (struct pal *)0; } else if (inchar == '0') tmask = 1; /* set bit in element */ else tmask = 0; /* clear bit in element */ *elptr |= tmask<blknum; i++) for (j = 0, elptr = curpal->bptr[i].array; j < curpal->bptr[i].blksiz; j++, elptr++) { for (k = 0, l = 0; k < curpal->blkbits; k++) { if (k > ((INTBITS-1)+(INTBITS*l))) l ++; if (!(*(elptr+l) & (1<<(k-(l*INTBITS))))) break; } if (k == curpal->blkbits) for(m = 0; m < curpal->blkelm; m++) *(elptr + m) = 0; elptr += curpal->blkelm - 1; } /* * determine scan order - initialize list with combinatorial logic first */ for (i = 0, j = 0; i < curpal->blknum; i++) if (curpal->bptr[i].typ == COMBINATORIAL) curpal->scan[j++] = i; for (i = 0; i < curpal->blknum; i++) if (curpal->bptr[i].typ == REGISTERED) curpal->scan[j++] = i; /* * delete uneeded structures */ for (i = 0, fptr = curpal->bptr; i < curpal->blknum; i++, fptr++) { free(fptr->rsel); fptr->rsel = (struct rowsel *)0; } for (i = 0, tptr = curpal->ithresh; i < curpal->inp; i++, tptr++) { free(tptr->rsel); tptr->rsel = (struct rowsel *)0; } free(curpal->iptr); curpal->iptr = (struct palinit *)0; /* * temporary diagnostic - print out PAL info * printf("record name %s\n",curpal->recnam); printf("%d blocks %d bits %d elements %d inputs\n",curpal->blknum,curpal->blkbits, curpal->blkelm,curpal->inp); for (i = 0; i < curpal->blknum; i++) { printf("block %d size %d polarity %d type %d\n",i,curpal->bptr[i].blksiz, curpal->bptr[i].pol,curpal->bptr[i].typ); printf("fuse %d row %d neg offset %d\n",curpal->bptr[i].loc, curpal->bptr[i].row,curpal->bptr[i].nrofst); for (j = 0, elptr = curpal->bptr[i].array; j < curpal->bptr[i].blksiz; j++, elptr++) { for (k = 0, l = 0; k < curpal->blkbits; k++) { if (k > (INTBITS-1)+l) { l += 32; elptr++; } if (*elptr & (1<<(k-l))) printf("1"); else printf("0"); } printf("\n"); } } * end diagnostic */ /* * initialization done */ fclose(datfile); return curpal; } /* * palconfig * * read in device specific configuration information * */ palconfig(datfile, curpal, fusenum) FILE *datfile; struct pal *curpal; int fusenum; { int i, j, k, l, m; struct thresh *tptr; struct blk *fptr; char inchar; if (!strcmp(curpal->iptr->name,"PAL16V8")) { /* * The PAL16V8 has a complex macrocell involving 2 configuration * fuses for feedback, 8 seperate polarity, and 8 seperate type fuses. * Look for polarity data first */ for (; fusenum != curpal->iptr->polloc; fusenum++) if (getbit(datfile) == EOF) { printf("palconfig:cannot find polarity data\n"); return -1; } /* * read in polarity data for each pal block */ for (i = 0; i < curpal->blknum; i++) { if ((inchar = getbit(datfile)) == EOF) { printf("palconfig:unexpected EOF in JEDEC file %s (polarity)\n",curpal->iptr->def); return -1; } else if (inchar == '0') curpal->bptr[i].pol = INVERTED; else curpal->bptr[i].pol = NORMAL; fusenum++; } /* * look for output type data */ for (; fusenum != curpal->iptr->typloc; fusenum++) if (getbit(datfile) == EOF) { printf("palconfig:cannot find type data\n"); return -1; } /* * read in type data for each pal block */ for (i = 0; i < curpal->blknum; i++) { if ((inchar = getbit(datfile)) == EOF) { printf("palconfig:unexpected EOF in JEDEC file %s (type)\n",curpal->iptr->def); return -1; } if (inchar == '1') curpal->bptr[i].typ = COMBINATORIAL; else curpal->bptr[i].typ = REGISTERED; fusenum++; } /* * look for global macrocell configuration data */ for (; fusenum != curpal->iptr->s0; fusenum++) if (getbit(datfile) == EOF) { printf("palconfig:cannot find macrocell data\n"); return -1; } /* * read in global macrocell data */ for (i = 0; i < curpal->iptr->snum; i++) { if ((inchar = getbit(datfile)) == EOF) { printf("palconfig:unexpected EOF in JEDEC file %s (macrocell)\n",curpal->iptr->def); return -1; } if (inchar == '1') curpal->iptr->mc[i] = 1; else curpal->iptr->mc[i] = 0; fusenum++; } /* * determine input fuse assignments */ for (i = 0, tptr = curpal->ithresh; i < curpal->inp; i++, tptr++) if (tptr->rsel->arow != -1) if (curpal->iptr->mc[tptr->rsel->sel] == tptr->rsel->psel) tptr->row = tptr->rsel->prow; else tptr->row = tptr->rsel->arow; else tptr->row = tptr->rsel->prow; /* * determine logic block feedback fuse assignments */ for (i = 0, fptr = curpal->bptr; i < curpal->blknum; i++, fptr++) if (fptr->rsel->arow != -1) if (curpal->iptr->mc[fptr->rsel->sel] == fptr->rsel->psel) fptr->row = fptr->rsel->prow; else fptr->row = fptr->rsel->arow; else fptr->row = fptr->rsel->prow; } else if (!strcmp(curpal->iptr->name,"PAL22V10")) { /* * The 22V10 has a simple macrocell where polarity and type are * controlled by two configuration fuses. * Look for global macrocell configuration data first */ for (; fusenum != curpal->iptr->s0; fusenum++) if (getbit(datfile) == EOF) { printf("palconfig:cannot find macrocell data\n"); return -1; } /* * read in global macrocell data */ for (j = 0; j < curpal->blknum; j++) { for (i = 0, k = 0; i < curpal->iptr->snum; i++, k<<1) { if ((inchar = getbit(datfile)) == EOF) { printf("palconfig:unexpected EOF in JEDEC file %s (macrocell)\n",curpal->iptr->def); return -1; } else if (inchar == '1') k |= 1<bptr[j].pol = NORMAL; else curpal->bptr[j].pol = INVERTED; if (k & 2) curpal->bptr[j].typ = COMBINATORIAL; else curpal->bptr[j].typ = REGISTERED; } /* * determine input fuse assignments */ for (i = 0, tptr = curpal->ithresh; i < curpal->inp; i++, tptr++) tptr->row = tptr->rsel->prow; /* * determine logic block feedback fuse assignments */ for (i = 0, fptr = curpal->bptr; i < curpal->blknum; i++, fptr++) fptr->row = fptr->rsel->prow; } return 0; } /* * pal - PAL emulator * */ pal(pptr,in,inum,result) struct pal *pptr; double in[]; int inum; unsigned int *result; { int i, j; struct thresh *tptr; struct blk *lptr; unsigned int inarray[2]; unsigned int tval; inarray[0] = inarray[1] = tval = 0; if (!pptr) return -1; for (i = 0, tptr = pptr->ithresh; (i < pptr->inp) && (i < inum); i++, tptr++) /* load input bits */ if (in[i] < tptr->lothresh) inbitload(tptr,inarray,0); else if (in[i] > tptr->hithresh) inbitload(tptr,inarray,1); for (i = 0, lptr = pptr->bptr; i < pptr->blknum; i++, lptr++) /* load feedback bits */ if ((!pptr->blktyp) || (!lptr->typ)) /* if not registered 22v10 */ outbitload(lptr,inarray,(*result>>i)&1); /* feedback from VAL field */ else outbitload(lptr,inarray,!((*result>>i)&1)); /* * temporary diagnostic - print out array inputs * for (i = 0, j = 0; i < pptr->blkbits; i++) { if (i > ((INTBITS-1)+(INTBITS*j))) j ++; if (inarray[j] & (1<<(i-(j*INTBITS)))) printf("1"); else printf("0"); } printf("\t"); * end diagnostic */ *result = 0; /* clear VAL field */ for (i = 0, lptr = pptr->bptr + *(pptr->scan); i < pptr->blknum; i++, lptr = pptr->bptr + *(pptr->scan + i)) /* evaluate blocks */ { tval = eval(lptr,inarray,pptr->blkelm); /* evaluate PAL logic block */ *result |= tval<<(*(pptr->scan+i)); /* load bits into VAL */ } return 0; } /* * inbitload - load bits in input array * */ inbitload(tptr,inarray,val) struct thresh *tptr; unsigned int inarray[2]; unsigned int val; { int i; tptr->val = val; if (tptr->row == -1) return 0; if (tptr->row < INTBITS) { inarray[0] |= val<row; inarray[0] |= (!val)<<(tptr->row + tptr->nrofst); } else { i = tptr->row - INTBITS; inarray[1] |= val<nrofst); } return 0; } /* * outbitload - load feedback bits in input array * */ outbitload(lptr,inarray,val) struct blk *lptr; unsigned int inarray[2]; unsigned int val; { int i; if (lptr->row == -1) return 0; if (lptr->row < INTBITS) if (val) { inarray[0] |= val<row; inarray[0] &= (val<<(lptr->row + lptr->nrofst)) ^ 0xffffffff; } else { inarray[0] &= ((!val)<row) ^ 0xffffffff; inarray[0] |= (!val)<<(lptr->row + lptr->nrofst); } else if (val) { i = lptr->row - INTBITS; inarray[1] |= val<nrofst)) ^ 0xffffffff; } else { i = lptr->row - INTBITS; inarray[1] &= ((!val)<nrofst); } return 0; } /* * eval - evaluate logic block * */ eval(lptr,inarray,blkelm) struct blk *lptr; unsigned int inarray[2]; int blkelm; { int i, j; unsigned int *eptr; int tval, t[2]; for (i = tval = 0, eptr = lptr->array; i < lptr->blksiz; i++) { for (j = t[0] = t[1] = 0; j < blkelm; j++, eptr++) if ((inarray[j] & *eptr) == *eptr) { t[j] = 1; if (*eptr) tval = 1; } for (j = 0; j < blkelm; j++) tval &= t[j]; if (tval) { if (lptr->pol == INVERTED) tval = 0; lptr->val = tval; if (lptr->typ == COMBINATORIAL) outbitload(lptr,inarray,lptr->val); return lptr->val; } } if (lptr->pol == INVERTED) tval = 1; lptr->val = tval; if (lptr->typ == COMBINATORIAL) outbitload(lptr,inarray,lptr->val); return lptr->val; }