mirror of
https://github.com/holub/mame
synced 2025-06-25 22:04:15 +03:00
made plaparse less strict about whitespace and ordering, and added .phase keyword
This commit is contained in:
parent
02fc842fe9
commit
301af68a06
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user