made plaparse less strict about whitespace and ordering, and added .phase keyword

This commit is contained in:
hap 2014-11-16 05:01:08 +01:00
parent 02fc842fe9
commit 301af68a06

View File

@ -4,7 +4,9 @@
plaparse.h plaparse.h
Parser for Berkeley standard PLA files into raw fusemaps. Simple parser for Berkeley standard PLA files into raw fusemaps.
It supports no more than one output matrix, and is limited to
keywords: i, o, p, phase, e
***************************************************************************/ ***************************************************************************/
@ -31,9 +33,11 @@
struct parse_info struct parse_info
{ {
UINT32 inputs; UINT32 inputs; /* number of input columns */
UINT32 outputs; UINT32 outputs; /* number of output columns */
UINT32 terms; UINT32 terms; /* number of terms */
UINT32 xorval[JED_MAX_FUSES/64]; /* output polarity */
UINT32 xorptr;
}; };
@ -57,20 +61,22 @@ static int iscrlf(char c)
character stream character stream
-------------------------------------------------*/ -------------------------------------------------*/
static UINT32 suck_number(const UINT8 **psrc) static UINT32 suck_number(const UINT8 **cursrc, const UINT8 *srcend)
{ {
const UINT8 *src = *psrc;
UINT32 value = 0; UINT32 value = 0;
(*cursrc)++;
// find first digit
while (*cursrc < srcend && !iscrlf(**cursrc) && !isdigit(**cursrc))
(*cursrc)++;
// loop over and accumulate digits // loop over and accumulate digits
while (isdigit(*src)) while (isdigit(**cursrc))
{ {
value = value * 10 + *src - '0'; value = value * 10 + (**cursrc) - '0';
src++; (*cursrc)++;
} }
// return a pointer to the string afterwards
*psrc = src;
return value; return value;
} }
@ -81,66 +87,55 @@ static UINT32 suck_number(const UINT8 **psrc)
***************************************************************************/ ***************************************************************************/
/*------------------------------------------------- /*-------------------------------------------------
process_field - process a single field process_terms - process input/output matrix
-------------------------------------------------*/ -------------------------------------------------*/
static void process_field(jed_data *data, const UINT8 *cursrc, const UINT8 *srcend, parse_info *pinfo) static bool process_terms(jed_data *data, const UINT8 **cursrc, const UINT8 *srcend, parse_info *pinfo)
{ {
cursrc++; UINT32 curinput = 0;
UINT32 curoutput = 0;
// switch off of the field type
switch (*cursrc)
{
// number of inputs
case 'i':
cursrc += 2;
pinfo->inputs = suck_number(&cursrc);
if (LOG_PARSE) printf("Inputs: %u\n", pinfo->inputs);
break;
// number of outputs
case 'o':
cursrc += 2;
pinfo->outputs = suck_number(&cursrc);
if (LOG_PARSE) printf("Outputs: %u\n", pinfo->outputs);
break;
// number of product terms
case 'p':
{
cursrc += 2;
pinfo->terms = suck_number(&cursrc);
if (LOG_PARSE) printf("Terms: %u\n", pinfo->terms);
UINT32 curfuse = 0;
bool outputs = false; bool outputs = false;
cursrc++; while (*cursrc < srcend && **cursrc != '.' && **cursrc != '#')
while (cursrc < srcend && *cursrc != '.')
{ {
switch (*cursrc) switch (**cursrc)
{ {
case '-': case '-':
if (!outputs) if (!outputs)
{ {
jed_set_fuse(data, curfuse++, 1); curinput++;
jed_set_fuse(data, curfuse++, 1); jed_set_fuse(data, data->numfuses++, 1);
jed_set_fuse(data, data->numfuses++, 1);
if (LOG_PARSE) printf("11"); if (LOG_PARSE) printf("11");
} }
break; break;
case '~':
if (!outputs)
{
curinput++;
// this product term is inhibited
jed_set_fuse(data, data->numfuses++, 0);
jed_set_fuse(data, data->numfuses++, 0);
if (LOG_PARSE) printf("00");
}
break;
case '1': case '1':
if (outputs) if (outputs)
{ {
jed_set_fuse(data, curfuse++, 0); curoutput++;
jed_set_fuse(data, data->numfuses++, 0);
if (LOG_PARSE) printf("0"); if (LOG_PARSE) printf("0");
} }
else else
{ {
jed_set_fuse(data, curfuse++, 1); curinput++;
jed_set_fuse(data, curfuse++, 0); jed_set_fuse(data, data->numfuses++, 1);
jed_set_fuse(data, data->numfuses++, 0);
if (LOG_PARSE) printf("10"); if (LOG_PARSE) printf("10");
} }
@ -149,45 +144,121 @@ static void process_field(jed_data *data, const UINT8 *cursrc, const UINT8 *srce
case '0': case '0':
if (outputs) if (outputs)
{ {
jed_set_fuse(data, curfuse++, 1); curoutput++;
jed_set_fuse(data, data->numfuses++, 1);
if (LOG_PARSE) printf("1"); if (LOG_PARSE) printf("1");
} }
else else
{ {
jed_set_fuse(data, curfuse++, 0); curinput++;
jed_set_fuse(data, curfuse++, 1); jed_set_fuse(data, data->numfuses++, 0);
jed_set_fuse(data, data->numfuses++, 1);
if (LOG_PARSE) printf("01"); if (LOG_PARSE) printf("01");
} }
break; break;
case ' ': case ' ': case '\t':
if (curinput > 0)
{
outputs = true; outputs = true;
if (LOG_PARSE) printf(" "); if (LOG_PARSE) printf(" ");
}
break;
default:
break; break;
} }
if (iscrlf(*cursrc) && outputs) if (iscrlf(**cursrc) && outputs)
{ {
outputs = false; outputs = false;
if (LOG_PARSE) printf("\n"); if (LOG_PARSE) printf("\n");
if (curinput != pinfo->inputs || curoutput != pinfo->outputs)
return false;
curinput = 0;
curoutput = 0;
} }
cursrc++; (*cursrc)++;
} }
data->numfuses = curfuse; return true;
}
/*-------------------------------------------------
process_field - process a single field
-------------------------------------------------*/
static bool process_field(jed_data *data, const UINT8 **cursrc, const UINT8 *srcend, parse_info *pinfo)
{
(*cursrc)++;
switch (**cursrc)
{
// number of inputs
case 'i':
pinfo->inputs = suck_number(cursrc, srcend);
if (pinfo->inputs == 0 || pinfo->inputs >= (JED_MAX_FUSES/2))
return false;
if (LOG_PARSE) printf("Inputs: %u\n", pinfo->inputs);
break; break;
// number of outputs
case 'o':
pinfo->outputs = suck_number(cursrc, srcend);
if (pinfo->outputs == 0 || pinfo->outputs >= (JED_MAX_FUSES/2))
return false;
if (LOG_PARSE) printf("Outputs: %u\n", pinfo->outputs);
break;
case 'p':
// output polarity (optional)
if ((*cursrc)[1] == 'h' && (*cursrc)[2] == 'a' && (*cursrc)[3] == 's' && (*cursrc)[4] == 'e')
{
if (LOG_PARSE) printf("Phase...\n");
while (*cursrc < srcend && !iscrlf(**cursrc) && pinfo->xorptr < (JED_MAX_FUSES/2))
{
if (**cursrc == '0' || **cursrc == '1')
{
// 0 is negative
if (**cursrc == '0')
pinfo->xorval[pinfo->xorptr/32] |= 1 << (pinfo->xorptr & 31);
pinfo->xorptr++;
} }
// end of file (*cursrc)++;
}
}
// or number of product terms (optional)
else
{
pinfo->terms = suck_number(cursrc, srcend);
if (pinfo->terms == 0 || pinfo->terms >= (JED_MAX_FUSES/2))
return false;
if (LOG_PARSE) printf("Terms: %u\n", pinfo->terms);
}
break;
// end of file (optional)
case 'e': case 'e':
if (LOG_PARSE) printf("End of file\n"); if (LOG_PARSE) printf("End of file\n");
break; break;
default:
return false;
} }
cursrc++; return true;
} }
@ -201,34 +272,53 @@ int pla_parse(const void *data, size_t length, jed_data *result)
{ {
const UINT8 *cursrc = (const UINT8 *)data; const UINT8 *cursrc = (const UINT8 *)data;
const UINT8 *srcend = cursrc + length; const UINT8 *srcend = cursrc + length;
const UINT8 *scan;
parse_info pinfo; parse_info pinfo;
memset(&pinfo, 0, sizeof(pinfo));
result->numfuses = 0; result->numfuses = 0;
memset(result->fusemap, 0x00, sizeof(result->fusemap)); memset(result->fusemap, 0, sizeof(result->fusemap));
while (cursrc < srcend) while (cursrc < srcend)
{ {
if (*cursrc == '#') switch (*cursrc)
{ {
cursrc++; // comment line
case '#':
while (cursrc < srcend && !iscrlf(*cursrc)) while (cursrc < srcend && !iscrlf(*cursrc))
cursrc++; cursrc++;
} break;
else if (*cursrc == '.')
{ // keyword
scan = cursrc; case '.':
while (scan < srcend && !iscrlf(*scan)) if (!process_field(result, &cursrc, srcend, &pinfo))
scan++;
if (scan >= srcend)
return JEDERR_INVALID_DATA; return JEDERR_INVALID_DATA;
break;
process_field(result, cursrc, srcend, &pinfo); // terms
case '0': case '1': case '-': case '~':
if (!process_terms(result, &cursrc, srcend, &pinfo))
return JEDERR_INVALID_DATA;
break;
cursrc = scan + 1; default:
cursrc++;
break;
}
} }
cursrc++; // write output polarity
if (pinfo.xorptr > 0)
{
if (LOG_PARSE) printf("Polarity: ");
for (int i = 0; i < pinfo.outputs; i++)
{
int bit = pinfo.xorval[i/32] >> (i & 31) & 1;
jed_set_fuse(result, result->numfuses++, bit);
if (LOG_PARSE) printf("%d", bit);
}
if (LOG_PARSE) printf("\n");
} }
return JEDERR_NONE; return JEDERR_NONE;