ref: 4b53b584263c8b7ea997d756e9712bf438bc348b
dir: /src/galasm.c/
/******************************************************************************
** galasm.c
*******************************************************************************
**
** description:
**
** This file contains the GAL-assembler.
**
******************************************************************************/
/********************************* includes **********************************/
#include <u.h>
#include <libc.h>
#include <ctype.h>
#include <stdio.h>
#include "galasm.h"
/********************************** defines **********************************/
#define SUFFIX_NON 0 /* possible suffixes */
#define SUFFIX_T 1
#define SUFFIX_R 2
#define SUFFIX_E 3
#define SUFFIX_CLK 4
#define SUFFIX_APRST 5
#define SUFFIX_ARST 6
#define DUMMY_OLMC11 24
#define DUMMY_OLMC12 25
/******************************** variables **********************************/
/* Diese Arrays geben an, in welche Spalte der ent- */
/* sprechende Pin eingekoppelt (bzw. r�ckgekoppelt) */
/* wird. F�r die invertierende Einkopplung ist 1 zu */
/* addieren, um die entsprechende Spalte zu erhalten */
/* -1 hei�t: keine Einkopplung auf Matrix vorhanden */
/* A possible translation (courtesy of Babelfish)
* These arrays indicate, into which column the appropriate pin
* becomes linked (and/or jerk-coupled). For inverting linking
* is to be added 1, in order to receive the appropriate column -1 hei_t
* : no linking on matrix available.
*/
/* Possible interpretation (by me)
* These arrays maps the pins to the fuse matrix. Each integer
* represents the number of the linked column or -1 if that pin
* dosn't link to any column . For inverted signals, the right column
* number can be calculated by adding one to the given number.
*/
/* GAL16V8 */
int PinToFuse16Mode1[20] = { 2, 0, 4, 8, 12, 16, 20, 24, 28, -1,
30, 26, 22, 18, -1, -1, 14, 10, 6, -1 };
int PinToFuse16Mode2[20] = { 2, 0, 4, 8, 12, 16, 20, 24, 28, -1,
30, -1, 26, 22, 18, 14, 10, 6, -1, -1 };
int PinToFuse16Mode3[20] = { -1, 0, 4, 8, 12, 16, 20, 24, 28, -1,
-1, 30, 26, 22, 18, 14, 10, 6, 2, -1 };
/* GAL20V8 */
int PinToFuse20Mode1[24] = { 2, 0, 4, 8,12,16,20,24,28,32,36,-1,
38,34,30,26,22,-1,-1,18,14,10, 6,-1 };
int PinToFuse20Mode2[24] = { 2, 0, 4, 8,12,16,20,24,28,32,36,-1,
38,34,-1,30,26,22,18,14,10,-1, 6,-1 };
int PinToFuse20Mode3[24] = { -1, 0, 4, 8,12,16,20,24,28,32,36,-1,
-1,38,34,30,26,22,18,14,10, 6, 2,-1 };
/* GAL22V10 */
int PinToFuse22V10[24] = { 0, 4, 8,12,16,20,24,28,32,36,40,-1,
42,38,34,30,26,22,18,14,10, 6, 2,-1 };
/* GAL20RA10 */
int PinToFuse20RA10[24] = { -1, 0, 4, 8,12,16,20,24,28,32,36,-1,
-1,38,34,30,26,22,18,14,10, 6, 2,-1 };
/* These arrays show which row is connected to */
/* which OLMC */
int ToOLMC[8] = { 56, 48, 40, 32, 24, 16, 8, 0 };
int ToOLMC22V10[12] = { 122, 111, 98, 83, 66, 49, 34, 21, 10, 1, 0, 131 };
int ToOLMC20RA10[10] = { 72, 64, 56, 48, 40, 32, 24, 16, 8, 0 };
/* this array shows the size of the */
/* 22V10-OLMCs ( AR and SP = 1 ) */
int OLMCSize22V10[12] = { 9, 11, 13, 15, 17, 17, 15, 13, 11, 9, 1, 1 };
/* The last two entries of the 22V10 arrays are for the */
/* AR and SP rows of the 22V10 GAL. This rows are not */
/* connected to an OLMC. But to keep the assembler as */
/* simple as possible, I introduced two "OLMCs" for the */
/* AR and SP. The assembler treads them like real OLMCs. */
/* So don't become confused when OLMC number 11 and 12 */
/* are used as inputs, outputs, pins... by the assembler. */
/* These two OLMCs are just dummy-OLMCs. */
UBYTE PinNames[24][10];
UBYTE PinDecNeg[24];
UBYTE ModeErrorStr[] = "Mode x: Pin xx";
UBYTE *pinnames;
int modus;
int linenum;
UBYTE *actptr, *buffend;
struct JedecStruct Jedec;
struct Pin actPin;
struct GAL_OLMC OLMC[12];
UBYTE *fbuff;
/******************************************************************************
** int AssemblePldFile(char *file)
*******************************************************************************
** input: file The file to be assembled
**
** output: 0: successful
** else: error
**
** remarks: This function does assemble a *.pld file.
******************************************************************************/
int AssemblePldFile(char *file, struct Config *cfg)
{
UBYTE chr;
UBYTE *bool_start, *oldptr;
char prevOp;
char suffix_strn[MAX_SUFFIX_SIZE];
int i = 0, j, k, l = 0, n, m;
int max_chr, pass, pin_num, bool_linenum;
int actOLMC, row_offset, newline, oldline;
int suffix, start_row, max_row, num_of_olmcs;
int gal_type;
int num_of_pins;
int olmc_1st_pin;
int num_of_col,fsize;
{
fsize = FileSize(file);
if((fbuff = malloc(fsize)))
{
if ((ReadFile(file, fsize, fbuff)))
{
actptr = fbuff;
buffend = fbuff+fsize;
linenum = 1;
/* This code generates a warning about exceeding array bounds */
#ifndef IGNOREME /* was #if 0 */
for (n = 0; n < sizeof(Jedec); n++)
{ /* init. JEDEC structure */
if (n < LOGIC22V10_SIZE)
Jedec.GALLogic[n] = 1; /* set fuses */
else
Jedec.GALLogic[n] = 0; /* clear ACW... */
}
#endif
/* I think this is what is intended: GALLogic is set to 1s, rest is cleared */
memset(&Jedec, 0, sizeof(Jedec));
memset(Jedec.GALLogic, 1, sizeof(Jedec.GALLogic));
for (n = 0; n < 12; n++)
{ /* clear OLMC structure */
OLMC[n].Active = 0;
OLMC[n].PinType = 0;
OLMC[n].TriCon = 0;
OLMC[n].Clock = 0;
OLMC[n].ARST = 0;
OLMC[n].APRST = 0;
OLMC[n].FeedBack = 0;
}
/*** get type of GAL ***/
if (strncmp((char *)actptr, "GAL16V8", (usize)7) == 0)
{
num_of_olmcs = 8; /* number of OLMCs */
num_of_pins = 20; /* number of pins */
olmc_1st_pin = 12; /* 1st OLMC pin */
num_of_col = MAX_FUSE_ADR16 + 1; /* number of col. */
gal_type = GAL16V8;
if ((*(actptr+7L) != ' ') && /* Only ' ', newline and tab are valid */
(*(actptr+7L) != 0x0A) && /* after the GAL's name */
(*(actptr+7L) != 0x09)) /* Any other char will produce an error */
{
AsmError(1, 0);
return(-1);
}
}
else
if (strncmp((char *)actptr, "GAL20V8", (usize)7) == 0)
{
num_of_olmcs = 8; /* num of OLMCs */
num_of_pins = 24; /* num of pins */
olmc_1st_pin = 15; /* 1st OLMC pin */
num_of_col = MAX_FUSE_ADR20 + 1;/* num of col */
gal_type = GAL20V8;
if ((*(actptr+7L) != ' ') &&
(*(actptr+7L) != 0x0A) &&
(*(actptr+7L) != 0x09))
{
AsmError(1, 0);
return(-1);
}
}
else
if (strncmp((char *)actptr, "GAL20RA10", (usize)9) == 0)
{
num_of_olmcs = 10;
num_of_pins = 24;
olmc_1st_pin = 14;
num_of_col = MAX_FUSE_ADR20RA10 + 1;
gal_type = GAL20RA10;
if ((*(actptr+9L) != ' ') &&
(*(actptr+9L) != 0x0A) &&
(*(actptr+9L) != 0x09) )
{
AsmError(1, 0);
return(-1);
}
}
else
if (strncmp((char *)actptr, "GAL22V10", (usize)8) == 0)
{
num_of_olmcs = 10;
num_of_pins = 24;
olmc_1st_pin = 14;
num_of_col = MAX_FUSE_ADR22V10 + 1;
gal_type = GAL22V10;
if ((*(actptr+8L) != ' ') &&
(*(actptr+8L) != 0x0A) &&
(*(actptr+8L) != 0x09))
{
AsmError(1, 0);
return(-1);
}
}
else
{
AsmError(1, 0);
return(-1);
}
/*** get the leading 8 bytes of the second ***/
/*** line as signature ***/
if (GetNextLine()) /* end of file? */
{
AsmError(2, 0); /* yes, then error */
return(-1);
}
/* store signature in the */
n = m = 0; /* JEDEC structure */
/* end of signature: after eight */
/* characters, CR or TAB */
while((*actptr != 0x0A) && (*actptr != 0x09) && (n < 8))
{
chr = *actptr;
for (m = 0; m < 8; m++)
Jedec.GALSig[n*8 + m] = (chr >> (7 - m)) & 0x1;
actptr++; /* increment pointer and */
n++; /* character-counter */
if (actptr>buffend) /* end of file ? */
{ /* yes, then error */
AsmError(2, 0);
return(-1);
}
}
/*** get name of pins ***/
/* clear flags for negations */
/* in the pin declaration */
for (n = 0; n < 24; PinDecNeg[n++] = 0);
pinnames = &PinNames[0][0]; /*assembler: pin names in PinNames*/
/* set flag 'not assembled' */
GetNextLine();
for (n = 0; n < num_of_pins; n++)
{
if (GetNextChar()) /* unexpected end of file? */
{ /* yes, then error */
AsmError(2, 0);
return(-1);
}
m = 0;
chr = *actptr; /* get character */
if (IsNEG(chr)) /* is there a negation? */
{
max_chr = 10;
PinDecNeg[n] = 1; /* yes, then set flag */
}
else
max_chr = 9;
if (!(isalpha(chr) || isdigit(chr) || IsNEG(chr)))
{
AsmError(5, 0); /* is character a legal */
return(-1); /* one? */
}
k = 0;
while (isalpha(chr) || isdigit(chr) || IsNEG(chr))
{
if (IsNEG(chr) && k != 0) /* check position of '/' */
{
AsmError(10, 0); /* must be at the beginning */
return(-1); /* of the pin name */
}
k = 1;
actptr++;
if (IsNEG(chr) && (!(isalpha(*actptr) || isdigit(*actptr))))
{
AsmError(3, 0);
return(-1);
}
*(pinnames + n*10 + m) = chr;
m++;
chr = *actptr;
if (m == max_chr) /* check number of characters */
{ /* in this pinname */
AsmError(4, 0);
return(-1); /* error: too many char. */
}
}
*(pinnames+n*10+m) = 0; /* mark end of string */
for (l = 0; l < n; l++) /* pin name twice? */
{
if (strcmp((char *)pinnames+l*10, "NC"))
{
i = j = 0;
if (IsNEG(*(pinnames+l*10))) /* skip negation sign */
i = 1;
if (IsNEG(*(pinnames+n*10)))
j = 1;
if (!strcmp((char *)(pinnames+l*10+i),
(char *)(pinnames+n*10+j)))
{
AsmError(9, 0); /* pin name defined twice */
return(-1);
}
}
}
/* is GND at the GND-pin? */
if (!strcmp((char *)(pinnames + n*10), "GND"))
{
if (n+1 != num_of_pins/2)
{
AsmError(6, 0);
return(-1);
}
}
if (n + 1 == num_of_pins/2)
{
if (strcmp((char *)(pinnames + n*10), "GND"))
{
AsmError(8, 0);
return(-1);
}
}
/* is VCC at the VCC pin? */
if (!strcmp((char *)(pinnames + n*10), "VCC"))
{
if (n+1 != num_of_pins)
{
AsmError(6, 0);
return(-1);
}
}
if (n + 1 == num_of_pins)
{
if (strcmp((char *)(pinnames + n*10), "VCC"))
{
AsmError(7, 0);
return(-1);
}
}
/* AR and SP are key words for 22V10 */
/* they are not allowed in the pin */
/* declaration */
if (gal_type == GAL22V10)
{
if (!strcmp((char *)(pinnames+n*10), "AR"))
{
AsmError(18, 0);
return(-1);
}
if (!strcmp((char *)(pinnames + n*10), "SP"))
{
AsmError(18, 0);
return(-1);
}
}
}
/* Boolean-Equations auswerten:
Dabei werden die Boolean-Equations zweimal untersucht. Beim ersten
Durchlauf werden die OLMC-Pins ausgewertet und die OLMC-Struktur ge-
f�llt. Mit Hilfe dieser Struktur l��t sich auf dem notwendigen Modus
(1, 2 oder 3) schlie�en. Beim zweiten Durchlauf wird dann die
Fuse-Matrix erstellt.
*/
/* Babelfish translation (slightly adapted):
Boolean Equations evaluate:
The Boolean Equations is twice examined.
With the first run the OLMC pins are evaluated and the OLMC structure is filled.
With the help of this structure the correct mode (1, 2 or 3) will be
calculated. With the second run the Fuse matrix is then provided.
*/
if (GetNextChar()) /* end of file? */
{
AsmError(2, 0);
return(-1);
}
/* are there any equations? */
if (!strncmp((char *)actptr, "DESCRIPTION", (usize)11))
{
AsmError(33, 0); /* no, then error */
return(-1);
}
bool_start = actptr; /* set pointer to the beginning of */
bool_linenum = linenum; /* the equations and save line number */
for (pass = 0; pass < 2; pass++) /* this is a two-pass-assembler */
{
if (!cfg->Quiet) printf("Assembler Phase %d for \"%s\"\n", (pass+1), file);
if (pass) /* 2. pass? => make ACW and get */
{ /* the mode for 16V8,20V8 GALs */
modus = 0;
/*** GAL16V8, GAL20V8 ***/
if (gal_type == GAL16V8 || gal_type == GAL20V8)
{
for (n = 0; n < 8; n++) /* examine all OLMCs */
{
if (OLMC[n].PinType == REGOUT) /* is there a registered */
{ /* OLMC?, then GAL's mode */
/* is mode 3 */
if (!modus)
{
modus = MODE3;
Jedec.GALSYN = 0; /* set SYN and AC0 for mode 3 */
Jedec.GALAC0 = 1;
if (cfg->Verbose)
printf("Using %s mode because:\n", GetModeName(modus));
}
pin_num = n + olmc_1st_pin;
if (cfg->Verbose)
printf(" pin %d (%s) is configured as registered output\n",
pin_num, GetPinName(pinnames, pin_num));
}
}
if (!modus) /* still no mode? */
{
for (n = 0; n < 8; n++) /* examine all OLMCs */
{
if (OLMC[n].PinType == TRIOUT) /* is there a tristate */
{ /* OLMC?, then GAL's */
/* mode is mode 2 */
if (!modus)
{
modus = MODE2;
Jedec.GALSYN = 1; /* set SYN, AC0 for mode 2 */
Jedec.GALAC0 = 1;
if (cfg->Verbose)
printf("Using %s mode because:\n", GetModeName(modus));
}
pin_num = n + olmc_1st_pin;
if (cfg->Verbose) {
printf(" pin %d (%s) is configured as tri-state output\n",
pin_num, GetPinName(pinnames, pin_num));
}
}
}
}
if (!modus) /* still no mode? */
{
/* if there is a violation of mode 1, */
/* then use automatically mode 2 */
for (n = 0; n < 8; n++)
{
if (OLMC[n].PinType == INPUT || (OLMC[n].PinType == COM_TRI_OUT && OLMC[n].FeedBack))
{
pin_num = n + olmc_1st_pin;
if ((gal_type == GAL16V8 && (pin_num == 15 || pin_num == 16)) ||
(gal_type == GAL20V8 && (pin_num == 18 || pin_num == 19)))
{
if (!modus)
{
modus = MODE2; /* mode 2 */
Jedec.GALSYN = 1; /* set SYN, AC0 bit */
Jedec.GALAC0 = 1;
if (cfg->Verbose)
printf("Using %s mode because:\n", GetModeName(modus));
}
if (cfg->Verbose)
printf(" pin %d (%s) is configured as %s\n", pin_num,
GetPinName(pinnames, pin_num),
OLMC[n].PinType == INPUT ? "input" : "output with feedback");
}
}
}
}
if (!modus) /* if there is still no mode */
{ /* defined, use mode 1 */
modus = MODE1;
Jedec.GALSYN = 1; /* set SYN and AC0 bit */
Jedec.GALAC0 = 0;
if (cfg->Verbose) {
printf("Defaulting to %s mode\n", GetModeName(modus));
}
}
/* If GAL's mode is mode 1, use all OLMCs which type is */
/* not defined explicitly as combinational outputs. */
/* If GAL's mode is mode 2 or 3, use all OLMCs which type */
/* is not defined explicitly as tristate output which is */
/* always enabled */
for (n = 0; n < 8; n++) /* examine all OLMCs */
{
if (OLMC[n].PinType == COM_TRI_OUT) /* is OLMC's type */
{ /* definded expl. */
if (modus == MODE1) /* mode 1? then comb. output */
OLMC[n].PinType = COMOUT;
else
{
OLMC[n].PinType = TRIOUT; /* mode 2, 3? then */
/* tri. output */
OLMC[n].TriCon = TRI_VCC; /* tristate control */
/* = TRUE */
}
}
}
/* make ACW; (SYN and AC0 are */
/* defined already) */
for (n = 0; n < PT_SIZE; n++) /* set product term disable */
Jedec.GALPT[n] = 1;
/* get AC1 bits */
for (n = 0; n < AC1_SIZE; n++)
{
if (OLMC[n].PinType == INPUT || OLMC[n].PinType == TRIOUT)
Jedec.GALAC1[AC1_SIZE - 1 - n] = 1;
}
for (n = 0; n < XOR_SIZE; n++) /* get XOR bits */
{
if (((OLMC[n].PinType == COMOUT) ||
(OLMC[n].PinType == TRIOUT) ||
(OLMC[n].PinType == REGOUT)) &&
(OLMC[n].Active == ACTIVE_HIGH))
Jedec.GALXOR[XOR_SIZE - 1 - n] = 1;
}
}
/*** GAL22V10 ***/
if (gal_type == GAL22V10)
{
for (n = 0; n < 10; n++)
{
if (OLMC[n].PinType == COM_TRI_OUT) /* output can be */
OLMC[n].PinType = TRIOUT; /* tristate or */
/* register */
if (((OLMC[n].PinType == COMOUT) ||
(OLMC[n].PinType == TRIOUT) ||
(OLMC[n].PinType == REGOUT)) &&
(OLMC[n].Active == ACTIVE_HIGH))
Jedec.GALXOR[9 - n] = 1;
/* get AC1 bits (S1) */
if (OLMC[n].PinType == INPUT || OLMC[n].PinType == TRIOUT)
Jedec.GALS1[9 - n] = 1;
}
}
/*** GAL20RA10 ***/
if (gal_type == GAL20RA10)
{
/* get XOR bits (S0) */
for (n = 0; n < 10; n++)
{
if (OLMC[n].PinType == COM_TRI_OUT) /* output can be */
OLMC[n].PinType = TRIOUT; /* tristate or */
/* register */
if (((OLMC[n].PinType == COMOUT) ||
(OLMC[n].PinType == TRIOUT) ||
(OLMC[n].PinType == REGOUT)) &&
(OLMC[n].Active == ACTIVE_HIGH))
Jedec.GALXOR[9 - n] = 1;
}
}
}
if(pass)
{
if(!cfg->Quiet) {
printf("GAL%s", GetGALName(gal_type));
if (gal_type == GAL16V8 || gal_type == GAL20V8)
printf("; Operation mode: %s", GetModeName(modus));
printf("; Security fuse %s\n", cfg->JedecSecBit ? "on" : "off");
}
}
actptr = bool_start;
linenum = bool_linenum;
newline = linenum;
goto label1; /* Shit, don't blame me for the gotos. */
/* I know, goto is a very bad command in C */
/* and in the most other languages. But it */
/* is very hard to remove them in this case. */
loop1:
if (GetNextChar()) /* end of file? */
{
AsmError(2, 0);
return(-1);
}
suffix = SUFFIX_NON;
if (*actptr == '.') /* is there a suffix? */
{ /* yes, then get the string */
actptr++;
if (gal_type == GAL22V10 &&
(actPin.p_Pin == 24 || actPin.p_Pin == 25))
{
AsmError(39, 0); /* no suffix allowed at */
return(-1); /* AR and SP */
}
n = 0;
while (isalpha(*actptr)) /* copy suffix string into */
{ /* suffix array */
if (n < MAX_SUFFIX_SIZE)
suffix_strn[n++] = *actptr++;
else
{ /* string too long, then */
AsmError(13, 0); /* unknown suffix */
return(-1);
}
}
suffix_strn[n] = 0; /* mark end of string */
if (suffix_strn[0] == 'T') suffix = SUFFIX_T;
else if (suffix_strn[0] == 'R') suffix = SUFFIX_R;
else if (suffix_strn[0] == 'E') suffix = SUFFIX_E;
else if (!strcmp(&suffix_strn[0], "CLK")) suffix = SUFFIX_CLK;
else if (!strcmp(&suffix_strn[0], "ARST")) suffix = SUFFIX_ARST;
else if (!strcmp(&suffix_strn[0], "APRST")) suffix = SUFFIX_APRST;
else
{
AsmError(13, 0); /* unknown suffix */
return(-1);
}
/* check whether suffix is */
/* allowed or not */
if (gal_type != GAL20RA10)
{
switch (suffix)
{
case SUFFIX_CLK:
AsmError(34, 0); /* no .CLK allowed */
return(-1);
break;
case SUFFIX_ARST:
AsmError(35, 0); /* .ARST is not allowed */
return(-1);
break;
case SUFFIX_APRST:
AsmError(36, 0); /* .APRST is not allowed */
return(-1);
break;
}
}
if (GetNextChar()) /* end of file? */
{
AsmError(2, 0);
return(-1);
}
}
actOLMC = (int)actPin.p_Pin; /* save offset of OLMC */
if (gal_type == GAL16V8)
actOLMC -= 12;
else
if (gal_type == GAL20V8)
actOLMC -= 15;
else
actOLMC -= 14;
row_offset = 0; /* offset for OR at OLMC*/
prevOp = 0; /* previous operator */
if (!pass) /* is this pass 1? */
{ /* is pin a OLMC pin? */
if (((gal_type == GAL16V8) &&
(actPin.p_Pin >= 12) && (actPin.p_Pin <= 19)) ||
((gal_type == GAL20V8) &&
(actPin.p_Pin >= 15) && (actPin.p_Pin <= 22)) ||
((gal_type == GAL22V10) &&
(actPin.p_Pin >= 14) && (actPin.p_Pin <= DUMMY_OLMC12)) ||
((gal_type == GAL20RA10) &&
(actPin.p_Pin >= 14) && (actPin.p_Pin <= 23)))
{
switch (gal_type) /* get OLMC number */
{
case GAL16V8:
n = actPin.p_Pin - 12;
break;
case GAL20V8:
n = actPin.p_Pin - 15;
break;
case GAL22V10:
case GAL20RA10:
n = actPin.p_Pin - 14;
break;
}
switch (suffix)
{
case SUFFIX_R: /* output definition */
case SUFFIX_T:
case SUFFIX_NON:
if (!OLMC[n].PinType || OLMC[n].PinType == INPUT)
{
if (actPin.p_Neg) /* get pin's activation */
OLMC[n].Active = ACTIVE_LOW;
else
OLMC[n].Active = ACTIVE_HIGH;
if (suffix == SUFFIX_T)
OLMC[n].PinType = TRIOUT; /* tri. output */
if (suffix == SUFFIX_R)
OLMC[n].PinType = REGOUT; /* reg. output */
if (suffix == SUFFIX_NON) /* type of output is */
OLMC[n].PinType = COM_TRI_OUT; /* not defined */
/* explicitly */
}
else
{
if (gal_type == GAL22V10 && (n == 10 || n == 11))
{
AsmError(40, 0); /* AR or SP is defined */
return(-1); /* twice */
}
else
{
AsmError(16, 0); /* pin is defined twice as */
return(-1); /* output */
}
}
break;
case SUFFIX_E:
if (actPin.p_Neg) /* negation of the trisate */
{ /* control is not allowed */
AsmError(19, 0);
return(-1);
}
if (OLMC[n].TriCon) /* tri. control twice? */
{ /* yes, then error */
AsmError(22, 0);
return(-1);
}
OLMC[n].TriCon = TRICON; /* set the flag that there is */
/* a tri. control equation */
if (!OLMC[n].PinType || OLMC[n].PinType == INPUT)
{
AsmError(17, 0); /* the sequence must be output */
return(-1); /* followed by the tri. control */
}
if (OLMC[n].PinType == REGOUT &&
(gal_type == GAL16V8 || gal_type == GAL20V8))
{
AsmError(23, 0); /* GAL16V8/20V8: tristate control */
return(-1); /* for reg. output is not allowed */
}
if (OLMC[n].PinType == COM_TRI_OUT)
{ /* no tristate .T? */
AsmError(24, 0); /* then error */
return(-1);
}
break;
case SUFFIX_CLK:
if (actPin.p_Neg) /* negation of the .CLK */
{ /* control is not allowed */
AsmError(19, 0);
return(-1);
}
if (OLMC[n].PinType == NOTUSED)
{
AsmError(42, 0); /* sequence must be: output */
return(-1); /* def., .CLK definition */
}
if (OLMC[n].Clock)
{ /* is .CLK defined twice? */
AsmError(45, 0); /* yes, then error */
return(-1);
}
OLMC[n].Clock = 1; /* set flag that there is */
/* a .CLK equation */
if (OLMC[n].PinType != REGOUT)
{
AsmError(48, 0); /* no .CLK allowed when */
return(-1); /* output is not registered */
}
break;
case SUFFIX_ARST:
if (actPin.p_Neg)
{ /* negation of the .ARST */
AsmError(19, 0); /* control is not allowed */
return(-1);
}
if (OLMC[n].PinType == NOTUSED)
{
AsmError(43, 0); /* sequence must be: output */
return(-1); /* def., .ARST definition */
}
if (OLMC[n].ARST)
{ /* is .ARST defined twice? */
AsmError(46, 0); /* yes, then error */
return(-1);
}
OLMC[n].ARST = 1; /* set flag that there is */
/* a .ARST equation */
if (OLMC[n].PinType != REGOUT)
{
AsmError(48, 0); /* no .CLK allowed when */
return(-1); /* output is not registered */
}
break;
case SUFFIX_APRST:
if (actPin.p_Neg)
{ /* negation of the .APRST */
AsmError(19, 0); /* control is not allowed */
return(-1);
}
if (OLMC[n].PinType == NOTUSED)
{
AsmError(44, 0); /* sequence must be: output */
return(-1); /* def., .APRST definition */
}
if (OLMC[n].APRST)
{ /* is .APRST defined twice? */
AsmError(47, 0); /* yes, then error */
return(-1);
}
OLMC[n].APRST = 1; /* set flag that there is */
/* a .APRST equation */
if (OLMC[n].PinType != REGOUT)
{
AsmError(48, 0); /* no .CLK allowed when */
return(-1); /* output is not registered */
}
break;
}
}
else
{
AsmError(15, 0); /* pin can't be programmed */
return(-1); /* as output */
}
}
start_row = max_row = 0;
switch (gal_type)
{ /* get first the row of the */
case GAL16V8: /* OLMC and the number of */
case GAL20V8: /* rows which areavailable */
start_row = ToOLMC[actOLMC];
max_row = 8;
break;
case GAL22V10:
start_row = ToOLMC22V10[actOLMC];
max_row = OLMCSize22V10[actOLMC];
break;
case GAL20RA10:
start_row = ToOLMC20RA10[actOLMC];
max_row = 8;
break;
}
if (*actptr != '=') /* '=' ? */
{ /* no, then error */
AsmError(14, 0);
return(-1);
}
loop2:
actptr++;
if (GetNextChar())
{ /* end of file? */
AsmError(2, 0); /* yes, then error */
return(-1);
}
oldptr = actptr; /* save pointer */
IsPinName(pinnames, num_of_pins);
if (gal_type == GAL22V10 && !actPin.p_Pin)
{ /* AR and SP is not allowed */
Is_AR_SP(oldptr); /* in terms of an equation */
if (actPin.p_Pin)
{ /* when used, then error */
AsmError(31, 0);
return(-1);
}
}
if (!actPin.p_Pin)
{ /* pin name? */
AsmError(11, 0); /* no, then error */
return(-1);
}
if (actPin.p_Pin == NC_PIN)
{ /* NC used as pin name? */
AsmError(12, 0); /* yes, then error */
return(-1);
}
if (IsNEG(*(pinnames+(long)((actPin.p_Pin - 1)*10))))
actPin.p_Neg = !actPin.p_Neg; /* consider negation in the */
/* pin declartion */
oldline = linenum;
if (GetNextChar())
{ /* end of file? */
AsmError(2, 0); /* yes, then error */
return(-1);
}
newline = linenum;
linenum = oldline;
if (!pass) /* is this pass 1?*/
{
if (((gal_type == GAL16V8) && /* is this pin an OLMC pin? */
(actPin.p_Pin >= 12) && (actPin.p_Pin <= 19)) ||
((gal_type == GAL20V8) &&
(actPin.p_Pin >= 15) && (actPin.p_Pin <= 22)) ||
((gal_type == GAL22V10) &&
(actPin.p_Pin >= 14) && (actPin.p_Pin <= DUMMY_OLMC12)) ||
((gal_type == GAL20RA10) &&
(actPin.p_Pin >= 14) && (actPin.p_Pin <= 23)) )
{
switch (gal_type) /* get OLMC number */
{
case GAL16V8:
n = actPin.p_Pin - 12;
break;
case GAL20V8:
n = actPin.p_Pin - 15;
break;
case GAL22V10:
case GAL20RA10:
n = actPin.p_Pin - 14;
break;
}
if (!OLMC[n].PinType) /* is OLMC's type already */
OLMC[n].PinType = INPUT; /* defined? no, then use */
/* it as input */
OLMC[n].FeedBack = YES; /* if a OLMC pin is used within an */
} /* equation, a feedback is needed */
}
/* in pass 2 we have to make the fuse matrix */
if (pass)
{
switch (gal_type) /* get row offset */
{
case GAL16V8:
case GAL20V8:
if (suffix == SUFFIX_E) /* when tristate control use */
row_offset = 0; /* first row (=> offset = 0) */
else
if (!row_offset) /*is offset of rows still equal 0?*/
if (modus != MODE1 &&
OLMC[actOLMC].PinType != REGOUT)
row_offset = 1; /* then init. row-offset */
break;
case GAL22V10:
if (suffix == SUFFIX_E) /* enable is the first row */
row_offset = 0; /* of the OLMC */
else
{
if (actOLMC == 10 || actOLMC == 11)
row_offset = 0; /* AR, SP?, then no offset */
else
if (!row_offset) /* output starts at the */
row_offset = 1; /* second row => offset = 1 */
}
break;
case GAL20RA10:
switch (suffix)
{
case SUFFIX_E: /* enable is the first row */
row_offset = 0; /* of the OLMC */
break;
case SUFFIX_CLK: /* Clock is the second row */
row_offset = 1; /* of the OLMC */
break;
case SUFFIX_ARST: /* AReset is the third row */
row_offset = 2; /* of the OLMC */
break;
case SUFFIX_APRST: /* APreset is the fourth row */
row_offset = 3; /* of the OLMC */
break;
default: /* output equation starts */
if (row_offset <= 3) /* at the fifth row */
row_offset = 4;
}
break;
}
pin_num = actPin.p_Pin;
/* is there a valuation of GAL's mode? */
if (gal_type == GAL16V8 || gal_type == GAL20V8)
{
if (modus == MODE2) /* valuation of mode 2? */
{
if (gal_type == GAL16V8 && (pin_num == 12 || pin_num == 19))
{
AsmError(20, 0);
return(-1);
}
if (gal_type == GAL20V8 && (pin_num == 15 || pin_num == 22))
{
AsmError(21, 0);
return(-1);
}
}
if (modus == MODE3) /* valuation of mode 3? */
{
if (gal_type == GAL16V8 && (pin_num == 1 || pin_num == 11))
{
AsmError(26, 0);
return(-1);
}
if (gal_type == GAL20V8 && (pin_num == 1 || pin_num == 13))
{
AsmError(27, 0);
return(-1);
}
}
}
if (gal_type == GAL20RA10) /* valuation of 20RA10? */
{
if (pin_num == 1) /* pin 1 is reserved for */
{ /* /PL (preload) */
AsmError(37, 0);
return(-1);
}
if (pin_num == 13)
{ /* pin 13 is reserved for */
AsmError(38, 0); /* /OE (output enable) */
return(-1);
}
}
/* if GND, set row equal 0 */
if (pin_num == num_of_pins || pin_num == num_of_pins/2)
{
if (actPin.p_Neg)
{ /* /VCC and /GND are not allowed */
AsmError(25, 0);
return(-1);
}
if (!prevOp && !IsAND(*actptr) && !IsOR(*actptr))
{
if (pin_num == num_of_pins/2)
{
m = (start_row + row_offset) * num_of_col;
/* set row equal 0 */
for (n = m; n < m+num_of_col; Jedec.GALLogic[n++] = 0);
}
}
else
{
AsmError(28, 0);
return(-1);
}
}
else
{
if (suffix == SUFFIX_E || suffix == SUFFIX_CLK ||
suffix == SUFFIX_ARST || suffix == SUFFIX_APRST ||
(gal_type == GAL22V10 && (actOLMC == 10 || actOLMC == 11)))
{
if (IsOR(prevOp))
{ /* max. one product term */
AsmError(29, 0); /* for CLK, ARST, APRST, E */
return(-1); /* and 22V10: AR, SP */
}
SetAND(start_row + row_offset, pin_num, actPin.p_Neg, gal_type);
}
else
{
if (IsOR(prevOp))
{ /* OR operation? yes, then */
row_offset++; /* take the next row */
if (row_offset == max_row)
{ /* too many ORs?*/
AsmError(30, 0);
return(-1);
}
}
/* set ANDs */
SetAND(start_row + row_offset, pin_num, actPin.p_Neg, gal_type);
}
}
/* are there any more terms? */
if (!IsOR(*actptr) && !IsAND(*actptr) && suffix != SUFFIX_E &&
suffix != SUFFIX_CLK && suffix != SUFFIX_ARST &&
suffix != SUFFIX_APRST)
{
/* no?, then set unused */
row_offset++; /* rows of the OLMX */
/* equal 0 */
if (row_offset != max_row)
{
m = (start_row + row_offset) * num_of_col;
for (n = m; n < m + (max_row - row_offset)*num_of_col; n++)
Jedec.GALLogic[n] = 0;
}
}
}
linenum = newline;
if (IsOR(*actptr) || IsAND(*actptr))
{
prevOp = *actptr;
goto loop2;
}
if (strncmp((char *)actptr, "DESCRIPTION", (usize)11))
{
label1:
linenum = newline;
oldptr = actptr;
IsPinName(pinnames, num_of_pins);
if (gal_type == GAL22V10 && !actPin.p_Pin)
{ /* no pin name? then */
Is_AR_SP(oldptr); /* check whether name */
/* is AR or SP */
if (actPin.p_Pin && actPin.p_Neg)
{ /* but no negation of */
AsmError(32, 0); /* AR or SP */
return(-1);
}
}
if (!actPin.p_Pin)
{ /* pin name? */
AsmError(11, 0); /* no, then error */
return(-1);
}
if (actPin.p_Pin == NC_PIN)
{ /* NC used as pin name? */
AsmError(12, 0); /* yes, then error */
return(-1);
}
if (IsNEG(*(pinnames+(long)((actPin.p_Pin-1)*10))))
actPin.p_Neg = !actPin.p_Neg; /* negation at pin declaration */
goto loop1;
}
}
/* set fuse matrix of unused OLMCs and of OLMCs */
/* which are programmed as input equal 0 */
for (n = 0; n < num_of_olmcs; n++)
{
if (OLMC[n].PinType == NOTUSED || OLMC[n].PinType == INPUT)
{
int i = 0;
switch (gal_type)
{ /* get first row of the */
case GAL16V8: /* OLMC and the number of */
case GAL20V8: /* rows which are available */
l = ToOLMC[n];
i = 8;
break;
case GAL22V10:
l = ToOLMC22V10[n];
i = OLMCSize22V10[n];
break;
case GAL20RA10:
l = ToOLMC20RA10[n];
i = 8;
break;
}
l = l * num_of_col;
m = l + i * num_of_col;
for (k = l; k < m; k++)
Jedec.GALLogic[k] = 0;
}
}
if (gal_type == GAL22V10)
{ /* if AR or SP is not defined, */
/* set corresponding row equal 0 */
if (!OLMC[10].PinType) /* set row of AR equal 0 */
for (n = 0; n < num_of_col; Jedec.GALLogic[n++] = 0);
if (!OLMC[11].PinType) /* set row of SP equal 0 */
for (n = 5764; n < 5764 + num_of_col; Jedec.GALLogic[n++] = 0);
}
if (gal_type == GAL20RA10)
{ /* set unused CLK, ARST */
/* and APRST equal 0 */
for (n = 0; n < num_of_olmcs; n++) /* examine all OLMCs */
{
if (OLMC[n].PinType != NOTUSED) /* is OLMC used? */
{
if (OLMC[n].PinType == REGOUT && !OLMC[n].Clock)
{
AsmError(41, n + 14); /* register output */
return(-1); /* needs clock definition */
}
if (!OLMC[n].Clock)
{ /* is clock unused? */
l = (ToOLMC20RA10[n] + 1) * num_of_col; /* then clear */
/* the row */
for (k = l; k < l + num_of_col; k++)
Jedec.GALLogic[k] = 0;
}
if (OLMC[n].PinType == REGOUT)
{
if (!OLMC[n].ARST)
{ /* is ARST unused? */
l = (ToOLMC20RA10[n] + 2) * num_of_col;
for (k = l; k < l + num_of_col; k++)
Jedec.GALLogic[k] = 0;
}
if (!OLMC[n].APRST)
{ /* is APRST unused? */
l = (ToOLMC20RA10[n] + 3) * num_of_col;
for (k = l; k < l + num_of_col; k++)
Jedec.GALLogic[k] = 0;
}
}
}
}
}
/* now the JEDEC structure is ready */
/* (be happy, it was a hard task) */
/* set flag, so that we can see that */
/* this file is assembled succesfully */
free(fbuff);
/*** now make the selected files ***/
/* Obtain the filename without the extension */
{
char *base; int l;
if((base = GetBaseName(file)))
{
#define extman(p,l,a,b,c) { p[l-2] = a; base[l-1] = b; base[l-0] = c; }
l = (strlen(base) - 1);
base[l-3] = '.';
extman(base,l,'j','e','d');
WriteJedecFile(base, gal_type, cfg);
extman(base,l,'f','u','s');
if(cfg->GenFuse) WriteFuseFile(base, gal_type);
extman(base,l,'p','i','n');
if(cfg->GenPin ) WritePinFile (base, gal_type);
extman(base,l,'c','h','p');
if(cfg->GenChip) WriteChipFile(base, gal_type);
free(base);
}
else
{
ErrorReq(2);
return(-2);
}
return(0); /* there was no error */
}
}
else
{
ErrorReq(3); /* read error */
free(fbuff);
return(-2);
}
}
else
{
ErrorReq(2); /* no more free memory */
return(-2);
}
}
}
/******************************************************************************
** SetAND()
*******************************************************************************
** input: row row in which the AND should be set
** pinnum pin which should be ANDed
** negation 0: pin without negation
** 1: pin with negation sign (/)
**
** output: none
**
** remarks: sets an AND (=0) in the fuse matrix
******************************************************************************/
void SetAND(int row, int pinnum, int negation, int gal_type)
{
int column = 0;
int numofcol = 0;
switch (gal_type)
{
case GAL16V8:
if (modus == MODE1)
column = PinToFuse16Mode1[pinnum - 1];
if (modus == MODE2)
column = PinToFuse16Mode2[pinnum - 1];
if (modus == MODE3)
column = PinToFuse16Mode3[pinnum - 1];
numofcol = MAX_FUSE_ADR16 + 1;
break;
case GAL20V8:
if (modus == MODE1)
column = PinToFuse20Mode1[pinnum - 1];
if (modus == MODE2)
column = PinToFuse20Mode2[pinnum - 1];
if (modus == MODE3)
column = PinToFuse20Mode3[pinnum - 1];
numofcol = MAX_FUSE_ADR20 + 1;
break;
case GAL22V10:
column = PinToFuse22V10[pinnum - 1];
/* is it a registered OLMC pin that is active high? */
/* Yes, then correct the negation */
if ((pinnum >= 14 && pinnum <= 23) && !Jedec.GALS1[23 - pinnum] && Jedec.GALXOR[23 - pinnum])
{
negation = negation ? 0 : 1;
}
numofcol = MAX_FUSE_ADR22V10 + 1;
break;
case GAL20RA10:
column = PinToFuse20RA10[pinnum - 1];
numofcol = MAX_FUSE_ADR20RA10 + 1;
break;
}
Jedec.GALLogic[row*numofcol + column + negation] = 0;
}
/******************************************************************************
** IsPinName()
*******************************************************************************
** input: *pinnames pointer to the pinnames array
** numofpins number of pins (20 or 24, depends on the type of GAL)
**
** global: actptr pointer to the first character of the pinname
** actPin.p_Pin: number of pin or NC_PIN; 0: no pin
** actPin.p_Neg: pinname with '/' = 1; without '/' = 0
**
** output: none
**
** remarks: This function tests whether actptr points to a pinname or not
******************************************************************************/
void IsPinName(UBYTE *pinnames, int numofpins)
{
int i, k, n;
UBYTE *oldactptr;
actPin.p_Neg = 0; /* install structure for pin */
actPin.p_Pin = 0;
if (IsNEG(*actptr))
{ /* negation? */
actptr++;
actPin.p_Neg = 1;
}
n = 0; /* get length of pin name */
oldactptr = actptr;
while (isalpha(*actptr) || isdigit(*actptr))
{
actptr++;
n++;
}
if (n) {
if ((n == 2 ) && !strncmp((char *)oldactptr, "NC", (usize)2))
actPin.p_Pin = NC_PIN; /* NC pin*/
else
for (k = 0; k < numofpins; k++)
{ /* examine whole list of pin names */
i = 0;
if (IsNEG(*(pinnames+k*10)))
i = 1;
/* are the string sizes equal? */
if (n == strlen((char *)(pinnames+k*10+i)))
if (!(strncmp((char *)oldactptr, (char *)(pinnames+k*10+i),
(usize)n))) /* yes, then compare these strings */
{
actPin.p_Pin = k + 1;
break;
}
}
}
}
/******************************************************************************
** Is_AR_SP()
*******************************************************************************
** input: *ptr pointer to the first character of the pinname
**
** output: none
** global actPin.p_Pin: 23: AR, 24: SP, 0: no AR, SP
** actPin.p_Neg: pinname with '/' = 1; without '/' = 0
**
** remarks: This function tests whether actptr points to a AR or SP
******************************************************************************/
void Is_AR_SP(UBYTE *ptr)
{
int n;
UBYTE *oldptr;
actPin.p_Neg = 0; /* install structure for pin */
actPin.p_Pin = 0;
if (IsNEG(*ptr))
{ /* negation? */
ptr++;
actPin.p_Neg = 1;
}
n = 0; /* get length of pin name */
oldptr = ptr;
while (isalpha(*ptr) || isdigit(*ptr))
{
ptr++;
n++;
}
/* assign AR to "OLMC 11" ("pin 24") and */
if (n) /* assign SP to "OLMC 12" ("pin 25") */
{
if ((n == 2 ) && !strncmp((char *)oldptr, "AR", (usize)2))
actPin.p_Pin = DUMMY_OLMC11;
if ((n == 2 ) && !strncmp((char *)oldptr, "SP", (usize)2))
actPin.p_Pin = DUMMY_OLMC12;
}
}
/******************************************************************************
** GetNextChar()
*******************************************************************************
** input: none
**
** output: 0: character found, actptr points to it
** 1: no character found
**
** remarks: searchs the next character which is no comment, space, TAB, LF
******************************************************************************/
int GetNextChar(void)
{
for(;;)
{
switch (*actptr)
{
case 0x0A: /* LineFeed */
actptr++;
linenum++;
break;
case ' ': /* space */
case 0x09: /* TAB */
actptr++;
break;
case ';': /* comment found? */
if (GetNextLine()) /* then skip rest of line */
return(0);
break;
default:
/* was there a character? */
if (*actptr > ' ' && *actptr <= '~')
return(0);
else
actptr++;
}
if (actptr > buffend) /* end of file? */
return(1);
}
}
/******************************************************************************
** GetNextLine()
*******************************************************************************
** input: none
**
** output: 0: line found, actptr points to this line
** 1: end of file reached
**
** remarks: gets pointer to next line
******************************************************************************/
int GetNextLine(void)
{
for(;;)
{
if (*actptr == 0x0A)
{
actptr++;
linenum++;
return(0);
}
if (actptr > buffend) /* end of file? */
return(1);
actptr++;
}
}
/******************************************************************************
** IsOR()
*******************************************************************************
** input: none
**
** output: 1: chr is a OR
** 0: chr is no OR
**
** remarks: checks whether or not chr is a OR sign or not
******************************************************************************/
int IsOR(char chr)
{
if (chr == '+' || chr == '#')
return(1);
else
return(0);
}
/******************************************************************************
** IsAND()
*******************************************************************************
** input: none
**
** output: 1: chr is a AND
** 0: chr is no AND
**
** remarks: checks whether or not chr is a AND sign or not
******************************************************************************/
int IsAND(char chr)
{
if (chr == '*' || chr == '&')
return(1);
else
return(0);
}
/******************************************************************************
** IsNEG()
*******************************************************************************
** input: none
**
** output: 1: chr is a negation sign
** 0: chr is no negation sign
**
** remarks: checks whether or not chr is a negation sign or not
******************************************************************************/
int IsNEG(char chr)
{
if (chr == '/' || chr == '!')
return(1);
else
return(0);
}
/********************************************************/
/* the following routines are for the creation of the */
/* documentation files */
/********************************************************/
int GetPinNum(int gal_type)
{
if(gal_type == GAL16V8) return(20);
return(24);
}
/******************************************************************************
** WriteChipFile(char *filename, int gal_type)
*******************************************************************************
** input: gal type
** filename
**
** output: none
**
** remarks: make chip file
******************************************************************************/
void WriteChipFile(char *filename, int gal_type)
{
FILE *fp;
int n;
int num_of_pins = GetPinNum(gal_type);
if ((fp = fopen(filename, (char *)"w")))
{
fprintf(fp, "\n\n");
WriteSpaces(fp, 31);
if (gal_type == GAL16V8)
fprintf(fp, " GAL16V8\n\n");
if (gal_type == GAL20V8)
fprintf(fp, " GAL20V8\n\n");
if (gal_type == GAL22V10)
fprintf(fp, " GAL22V10\n\n");
if (gal_type == GAL20RA10)
fprintf(fp, "GAL20RA10\n\n");
WriteSpaces(fp, 26);
fprintf(fp,"-------\\___/-------\n");
for (n = 0; n < num_of_pins/2; n++)
{
WriteSpaces(fp, 25 - (int)strlen((char *)(pinnames+n*10)));
fprintf(fp,"%s | %2d %2d | %s\n", pinnames + n*10,
n+1, num_of_pins-n, pinnames+(num_of_pins-n-1)*10);
if (n < num_of_pins/2 - 1)
{
WriteSpaces(fp, 26);
fprintf(fp, "| |\n");
}
}
WriteSpaces(fp, 26);
fprintf(fp, "-------------------\n");
if (fclose(fp) == EOF)
{
ErrorReq(8); /* can't close file */
return;
}
}
}
/******************************************************************************
** WritePinFile(char �*filename, int gal_type)
*******************************************************************************
** input: gal type
** filename
**
** output: none
**
** remarks: make pin file
******************************************************************************/
void WritePinFile(char *filename, int gal_type)
{
FILE *fp;
int k, n, flag;
int num_of_pins = GetPinNum(gal_type);
if ((fp = fopen(filename, (char *)"w")))
{
fprintf(fp, "\n\n");
fprintf(fp, " Pin # | Name | Pin Type\n");
fprintf(fp, "-----------------------------\n");
for (n = 1; n <= num_of_pins; n++)
{
fprintf(fp," %2d | ",n);
fprintf(fp,"%s",pinnames+(n-1)*10);
WriteSpaces(fp, 9-(int)strlen((char *)(pinnames+(n-1)*10)));
flag = 0;
if (n == num_of_pins/2)
{
fprintf(fp,"| GND\n");
flag = 1;
}
if (n == num_of_pins)
{
fprintf(fp,"| VCC\n\n");
flag = 1;
}
if (gal_type == GAL16V8 || gal_type == GAL20V8)
{
if (modus == MODE3 && n == 1)
{
fprintf(fp, "| Clock\n");
flag = 1;
}
if (modus == MODE3)
{
if (gal_type == GAL16V8 && n == 11)
{
fprintf(fp, "| /OE\n");
flag = 1;
}
if (gal_type == GAL20V8 && n == 13)
{
fprintf(fp, "| /OE\n");
flag = 1;
}
}
}
if (gal_type == GAL22V10 && n == 1)
{
fprintf(fp, "| Clock/Input\n");
flag = 1;
}
/* OLMC pin?*/
if ((gal_type == GAL16V8 && n >= 12 && n <= 19) ||
(gal_type == GAL20V8 && n >= 15 && n <= 22) ||
(gal_type == GAL20RA10 && n >= 14 && n <= 23) ||
(gal_type == GAL22V10 && n >= 14 && n <= 23))
{
if (gal_type == GAL16V8)
k = n - 12;
else
if (gal_type == GAL20V8)
k = n - 15;
else
k = n - 14;
if (OLMC[k].PinType != INPUT)
if (OLMC[k].PinType)
fprintf(fp,"| Output\n");
else
fprintf(fp,"| NC\n");
else
fprintf(fp,"| Input\n");
}
else
{
if (!flag)
fprintf(fp,"| Input\n");
}
}
if (fclose(fp) == EOF)
{
ErrorReq(8); /* can't close file */
return;
}
}
else
{
ErrorReq(13);
return;
}
}
/******************************************************************************
** WriteRow()
*******************************************************************************
** input: *fp pointer to the file handle
** row number of row which should be written
**
** output: none
**
** remarks: writes a row of an OLMC to the file characterized by the file
** handle fp
******************************************************************************/
void WriteRow(FILE *fp, int row, int num_of_col)
{
int col;
fprintf(fp, "\n%3d ", row); /* print row number */
for (col = 0; col < num_of_col; col++)
{ /* print fuses of */
if (!((col) % 4)) /* a row */
fprintf(fp, " ");
if (Jedec.GALLogic[row*num_of_col + col])
fprintf(fp, "-");
else
fprintf(fp, "x");
}
}
/******************************************************************************
** WriteChipFile(char *filename, int gal_type)
*******************************************************************************
** input: gal type
** filename
**
** output: none
**
** remarks: make fuse file
******************************************************************************/
void WriteFuseFile(char *filename, int gal_type)
{
FILE *fp;
int row, pin, n, numofOLMCs, numofrows, olmc;
int num_of_col = 0;
switch(gal_type)
{
case GAL16V8: num_of_col = MAX_FUSE_ADR16 + 1; break;
case GAL20V8: num_of_col = MAX_FUSE_ADR20 + 1; break;
case GAL20RA10: num_of_col = MAX_FUSE_ADR20RA10 + 1; break;
case GAL22V10: num_of_col = MAX_FUSE_ADR22V10 + 1; break;
}
if ((fp = fopen(filename, (char *)"w")))
{
if (gal_type == GAL16V8)
{
pin = 19;
numofOLMCs = 8;
}
else
if (gal_type == GAL20V8)
{
pin = 22;
numofOLMCs = 8;
}
else
{ /* 22V10, 20RA10 */
pin = 23;
numofOLMCs = 10;
}
row = 0;
for (olmc = 0; olmc < numofOLMCs; olmc++)
{
if (gal_type == GAL22V10 && olmc == 0)
{ /* AR when 22V10 */
fprintf(fp, "\n\nAR");
WriteRow(fp, row, num_of_col);
row++;
}
if (gal_type == GAL22V10) /* get number of rows */
numofrows = OLMCSize22V10[olmc]; /* of an OLMC */
else
numofrows = 8;
fprintf(fp, "\n\nPin %2d = ", pin); /* print pin */
fprintf(fp, "%s", pinnames + (pin - 1)*10);
WriteSpaces(fp, 13-(int)strlen((char *)(pinnames+(pin-1)*10)));
if (gal_type == GAL16V8)
fprintf(fp, "XOR = %1d AC1 = %1d", Jedec.GALXOR[19-pin],
Jedec.GALAC1[19 - pin]);
else
if (gal_type == GAL20V8)
fprintf(fp, "XOR = %1d AC1 = %1d",
Jedec.GALXOR[22 - pin], Jedec.GALAC1[22 - pin]);
else
if (gal_type == GAL22V10)
fprintf(fp, "S0 = %1d S1 = %1d",
Jedec.GALXOR[23 - pin], Jedec.GALS1[23 - pin]);
else
if (gal_type == GAL20RA10)
fprintf(fp, "S0 = %1d",
Jedec.GALXOR[23 - pin]);
for (n = 0; n < numofrows; n++)
{ /* print all fuses of an OLMC */
WriteRow(fp, row, num_of_col);
row++;
}
if (gal_type == GAL22V10 && olmc == 9)
{ /* SP when 22V10 */
fprintf(fp, "\n\nSP");
WriteRow(fp, row, num_of_col);
}
pin--;
}
fprintf(fp, "\n\n");
if (fclose(fp) == EOF)
{
ErrorReq(8); /* can't close file */
return;
}
}
else
{
ErrorReq(13);
return;
}
}
/******************************************************************************
** WriteSpaces()
*******************************************************************************
** input: *fp pointer to the file handle of the file
** numof number of spaces to be written to the file
**
** output: none
**
** remarks: write "numof" spaces to the file characterized by *fp
******************************************************************************/
void WriteSpaces(FILE *fp, int numof)
{
int n;
for (n = 0; n < numof; n++)
fprintf(fp, " ");
}
/******************************************************************************
** AsmError()
*******************************************************************************
** input: errornum number of error to be printed
** pinnum = 0: print "Error in line linnum:" ...
** > 0: print "Pin pinnum:" ...
**
** output: none
**
** remarks: print error messages of the GAL-assembler and free
** the memory allocated by the file buffer
******************************************************************************/
void AsmError(int errornum, int pinnum)
{
free(fbuff);
if (!pinnum)
printf("Error in line %d: ", linenum);
else
printf("Error, pin %d: ", pinnum);
printf("%s\n", AsmErrorArray[errornum]);
}
/******************************************************************************
** main
*******************************************************************************
**
** options:
**
** -s Enable security fuse
** -c Disable .chp file output
** -f Disable .fus file output
** -p Disable .pin file output
** -a Restrict checksum to the fuse array only
** -w Force <CR><LF> line endings for .jed file overriding platform default
** -v Verbose output
**
**
**
******************************************************************************/
int main(int argc, char *argv[])
{
int rc;
char *p;
struct Config cfg;
cfg.GenFuse = TRUE;
cfg.GenChip = TRUE;
cfg.GenPin = TRUE;
cfg.JedecSecBit = FALSE;
cfg.JedecFuseChk = FALSE;
cfg.ForceCRLF = FALSE;
cfg.Verbose = FALSE;
cfg.Quiet = FALSE;
p = argv[1];
while(argc > 1 && (p[0] == '-' || (isalpha(p[1]) && (argc != 2))))
{
switch(p[1])
{
case 's':
case 'S':
cfg.JedecSecBit = TRUE;
break;
case 'c':
case 'C':
cfg.GenChip = FALSE;
break;
case 'f':
case 'F':
cfg.GenFuse = FALSE;
break;
case 'p':
case 'P':
cfg.GenPin = FALSE;
break;
case 'a':
case 'A':
cfg.JedecFuseChk = TRUE;
break;
case 'w':
case 'W':
cfg.ForceCRLF = TRUE;
break;
case 'v':
case 'V':
cfg.Verbose = TRUE;
break;
case 'h':
case 'H':
case '?':
printf("Usage:\ngalasm [-scfpawv] <filename>\n");
printf( "-s Enable security fuse\n"
"-c Do not create the .chp file\n"
"-f Do not create the .fus file\n"
"-p Do not create the .pin file\n"
"-a Restrict checksum to the fuse array only\n"
"-w Force <CR><LF> line endings for .jed file overriding platform default\n"
"-v Verbose output\n");
exits(0);
case 'q':
case 'Q':
cfg.Quiet = TRUE;
break;
case '-':
case '\0':
argc--;
argv++;
goto opt_done;
default:
goto usage;
}
if(!isalpha(p[2]))
{
argc--;
argv++;
p = argv[1];
}
else
p++;
}
opt_done:
if (!cfg.Quiet) printf( "galasm 2.1, Portable GAL Assembler\n"
"Copyright (c) 1998-2003 Alessandro Zummo. All Rights Reserved\n"
"Original sources Copyright (c) 1991-96 Christian Habermann\n\n");
if(argc != 2)
{
usage:
printf("Usage:\ngalasm [-scfpawv] <filename>\n");
printf("Type galasm -h for help\n");
exits("Usage");
}
rc = AssemblePldFile(argv[1], &cfg);
if(rc != 0) {
printf("Assembling failed.\n");
exits(smprint("Assembly return: %d", rc));
}
else
if (!cfg.Quiet) printf("Assembling successfully completed.\n");
exits(0);
}