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;
} }
@ -80,114 +86,179 @@ static UINT32 suck_number(const UINT8 **psrc)
CORE IMPLEMENTATION CORE IMPLEMENTATION
***************************************************************************/ ***************************************************************************/
/*-------------------------------------------------
process_terms - process input/output matrix
-------------------------------------------------*/
static bool process_terms(jed_data *data, const UINT8 **cursrc, const UINT8 *srcend, parse_info *pinfo)
{
UINT32 curinput = 0;
UINT32 curoutput = 0;
bool outputs = false;
while (*cursrc < srcend && **cursrc != '.' && **cursrc != '#')
{
switch (**cursrc)
{
case '-':
if (!outputs)
{
curinput++;
jed_set_fuse(data, data->numfuses++, 1);
jed_set_fuse(data, data->numfuses++, 1);
if (LOG_PARSE) printf("11");
}
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':
if (outputs)
{
curoutput++;
jed_set_fuse(data, data->numfuses++, 0);
if (LOG_PARSE) printf("0");
}
else
{
curinput++;
jed_set_fuse(data, data->numfuses++, 1);
jed_set_fuse(data, data->numfuses++, 0);
if (LOG_PARSE) printf("10");
}
break;
case '0':
if (outputs)
{
curoutput++;
jed_set_fuse(data, data->numfuses++, 1);
if (LOG_PARSE) printf("1");
}
else
{
curinput++;
jed_set_fuse(data, data->numfuses++, 0);
jed_set_fuse(data, data->numfuses++, 1);
if (LOG_PARSE) printf("01");
}
break;
case ' ': case '\t':
if (curinput > 0)
{
outputs = true;
if (LOG_PARSE) printf(" ");
}
break;
default:
break;
}
if (iscrlf(**cursrc) && outputs)
{
outputs = false;
if (LOG_PARSE) printf("\n");
if (curinput != pinfo->inputs || curoutput != pinfo->outputs)
return false;
curinput = 0;
curoutput = 0;
}
(*cursrc)++;
}
return true;
}
/*------------------------------------------------- /*-------------------------------------------------
process_field - process a single field process_field - process a single field
-------------------------------------------------*/ -------------------------------------------------*/
static void process_field(jed_data *data, const UINT8 *cursrc, const UINT8 *srcend, parse_info *pinfo) static bool process_field(jed_data *data, const UINT8 **cursrc, const UINT8 *srcend, parse_info *pinfo)
{ {
cursrc++; (*cursrc)++;
// switch off of the field type switch (**cursrc)
switch (*cursrc)
{ {
// number of inputs // number of inputs
case 'i': case 'i':
cursrc += 2; pinfo->inputs = suck_number(cursrc, srcend);
pinfo->inputs = suck_number(&cursrc); if (pinfo->inputs == 0 || pinfo->inputs >= (JED_MAX_FUSES/2))
return false;
if (LOG_PARSE) printf("Inputs: %u\n", pinfo->inputs); if (LOG_PARSE) printf("Inputs: %u\n", pinfo->inputs);
break; break;
// number of outputs // number of outputs
case 'o': case 'o':
cursrc += 2; pinfo->outputs = suck_number(cursrc, srcend);
pinfo->outputs = suck_number(&cursrc); if (pinfo->outputs == 0 || pinfo->outputs >= (JED_MAX_FUSES/2))
return false;
if (LOG_PARSE) printf("Outputs: %u\n", pinfo->outputs); if (LOG_PARSE) printf("Outputs: %u\n", pinfo->outputs);
break; break;
// number of product terms
case 'p': case 'p':
{ // output polarity (optional)
cursrc += 2; if ((*cursrc)[1] == 'h' && (*cursrc)[2] == 'a' && (*cursrc)[3] == 's' && (*cursrc)[4] == 'e')
pinfo->terms = suck_number(&cursrc);
if (LOG_PARSE) printf("Terms: %u\n", pinfo->terms);
UINT32 curfuse = 0;
bool outputs = false;
cursrc++;
while (cursrc < srcend && *cursrc != '.')
{ {
switch (*cursrc) if (LOG_PARSE) printf("Phase...\n");
while (*cursrc < srcend && !iscrlf(**cursrc) && pinfo->xorptr < (JED_MAX_FUSES/2))
{ {
case '-': if (**cursrc == '0' || **cursrc == '1')
if (!outputs)
{ {
jed_set_fuse(data, curfuse++, 1); // 0 is negative
jed_set_fuse(data, curfuse++, 1); if (**cursrc == '0')
pinfo->xorval[pinfo->xorptr/32] |= 1 << (pinfo->xorptr & 31);
if (LOG_PARSE) printf("11"); pinfo->xorptr++;
} }
break;
(*cursrc)++;
case '1':
if (outputs)
{
jed_set_fuse(data, curfuse++, 0);
if (LOG_PARSE) printf("0");
}
else
{
jed_set_fuse(data, curfuse++, 1);
jed_set_fuse(data, curfuse++, 0);
if (LOG_PARSE) printf("10");
}
break;
case '0':
if (outputs)
{
jed_set_fuse(data, curfuse++, 1);
if (LOG_PARSE) printf("1");
}
else
{
jed_set_fuse(data, curfuse++, 0);
jed_set_fuse(data, curfuse++, 1);
if (LOG_PARSE) printf("01");
}
break;
case ' ':
outputs = true;
if (LOG_PARSE) printf(" ");
break;
} }
if (iscrlf(*cursrc) && outputs)
{
outputs = false;
if (LOG_PARSE) printf("\n");
}
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;
data->numfuses = curfuse; if (LOG_PARSE) printf("Terms: %u\n", pinfo->terms);
}
break; break;
}
// end of file // 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
while (cursrc < srcend && !iscrlf(*cursrc)) case '#':
while (cursrc < srcend && !iscrlf(*cursrc))
cursrc++;
break;
// keyword
case '.':
if (!process_field(result, &cursrc, srcend, &pinfo))
return JEDERR_INVALID_DATA;
break;
// terms
case '0': case '1': case '-': case '~':
if (!process_terms(result, &cursrc, srcend, &pinfo))
return JEDERR_INVALID_DATA;
break;
default:
cursrc++; cursrc++;
break;
} }
else if (*cursrc == '.') }
// write output polarity
if (pinfo.xorptr > 0)
{
if (LOG_PARSE) printf("Polarity: ");
for (int i = 0; i < pinfo.outputs; i++)
{ {
scan = cursrc; int bit = pinfo.xorval[i/32] >> (i & 31) & 1;
while (scan < srcend && !iscrlf(*scan)) jed_set_fuse(result, result->numfuses++, bit);
scan++; if (LOG_PARSE) printf("%d", bit);
if (scan >= srcend)
return JEDERR_INVALID_DATA;
process_field(result, cursrc, srcend, &pinfo);
cursrc = scan + 1;
} }
if (LOG_PARSE) printf("\n");
cursrc++;
} }
return JEDERR_NONE; return JEDERR_NONE;