static void process_field(jed_data *data, const UINT8 *cursrc, const UINT8 *srcend, UINT16 *checksum) { /* switch off of the field type */ switch (*cursrc) { case 'Q': cursrc++; switch (*cursrc) { /* number of fuses */ case 'F': cursrc++; data->numfuses = suck_number(&cursrc); break; } break; /* default fuse state (0 or 1) */ case 'F': cursrc++; if (LOG_PARSE) printf("F%c\n", *cursrc); if (*cursrc == '0') memset(data->fusemap, 0x00, sizeof(data->fusemap)); else memset(data->fusemap, 0xff, sizeof(data->fusemap)); break; /* fuse states */ case 'L': { UINT32 curfuse; /* read the fuse number */ cursrc++; curfuse = suck_number(&cursrc); if (LOG_PARSE) printf("L%d\n", curfuse); /* read digits, skipping delimiters */ for ( ; cursrc < srcend; cursrc++) if (*cursrc == '0' || *cursrc == '1') { jed_set_fuse(data, curfuse, *cursrc - '0'); if (LOG_PARSE) printf(" fuse %d = %d\n", curfuse, 0); if (curfuse >= data->numfuses) data->numfuses = curfuse + 1; curfuse++; } break; } /* fuse checksum */ case 'C': cursrc++; if (cursrc < srcend + 4 && ishex(cursrc[0]) && ishex(cursrc[1]) && ishex(cursrc[2]) && ishex(cursrc[3])) *checksum = (hexval(cursrc[0]) << 12) | (hexval(cursrc[1]) << 8) | (hexval(cursrc[2]) << 4) | hexval(cursrc[3] << 0); break; } }
int pla_parse(const void *data, size_t length, jed_data *result) { const UINT8 *src = (const UINT8 *)data; const UINT8 *srcend = src + length; parse_info pinfo; memset(&pinfo, 0, sizeof(pinfo)); result->numfuses = 0; memset(result->fusemap, 0, sizeof(result->fusemap)); while (src < srcend) { switch (*src) { // comment line case '#': while (src < srcend && !iscrlf(*src)) src++; break; // keyword case '.': src++; if (!process_field(result, &src, srcend, &pinfo)) return JEDERR_INVALID_DATA; break; // terms case '0': case '1': case '-': case '~': if (!process_terms(result, &src, srcend, &pinfo)) return JEDERR_INVALID_DATA; break; default: src++; break; } } // 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; }
static void process_field(jed_data *data, const UINT8 *cursrc, const UINT8 *srcend, parse_info *pinfo) { cursrc++; // 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; cursrc++; while (cursrc < srcend && *cursrc != '.') { switch (*cursrc) { case '-': if (!outputs) { jed_set_fuse(data, curfuse++, 1); jed_set_fuse(data, curfuse++, 1); if (LOG_PARSE) printf("11"); } break; 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++; } data->numfuses = curfuse; break; } // end of file case 'e': printf("End of file\n"); break; } cursrc++; }
static bool process_terms(jed_data *data, const UINT8 **src, const UINT8 *srcend, parse_info *pinfo) { UINT32 curinput = 0; UINT32 curoutput = 0; bool outputs = false; // symbols for 0, 1, dont_care, no_meaning // PLA format documentation also describes them as simply 0, 1, 2, 3 static const char symbols[] = { "01-~" }; while (*src < srcend && **src != '.' && **src != '#') { if (!outputs) { // and-matrix if (strrchr(symbols, **src)) curinput++; switch (**src) { case '0': jed_set_fuse(data, data->numfuses++, 0); jed_set_fuse(data, data->numfuses++, 1); if (LOG_PARSE) printf("01"); break; case '1': jed_set_fuse(data, data->numfuses++, 1); jed_set_fuse(data, data->numfuses++, 0); if (LOG_PARSE) printf("10"); break; // anything goes case '-': jed_set_fuse(data, data->numfuses++, 1); jed_set_fuse(data, data->numfuses++, 1); if (LOG_PARSE) printf("11"); break; // this product term is inhibited case '~': jed_set_fuse(data, data->numfuses++, 0); jed_set_fuse(data, data->numfuses++, 0); if (LOG_PARSE) printf("00"); break; case ' ': case '\t': if (curinput > 0) { outputs = true; if (LOG_PARSE) printf(" "); } break; default: break; } } else { // or-matrix if (strrchr(symbols, **src)) { curoutput++; if (**src == '1') { jed_set_fuse(data, data->numfuses++, 0); if (LOG_PARSE) printf("0"); } else { // write 1 for anything else jed_set_fuse(data, data->numfuses++, 1); if (LOG_PARSE) printf("1"); } } } if (iscrlf(**src) && outputs) { outputs = false; if (LOG_PARSE) printf("\n"); if (curinput != pinfo->inputs || curoutput != pinfo->outputs) return false; curinput = 0; curoutput = 0; } (*src)++; } return true; }