33 int s3l_tap_reset(tap_t *tap)
35 unsigned char reset[] = {0xAA, 0x02};
36 tap->tapstate = TAP_RESET;
37 return nexys2_jtag_puttmstdi(tap->nexys, 5, reset, NULL);
40 int s3l_tap_idle(tap_t *tap)
42 switch (tap->tapstate)
45 printf("Resetting TAP from unknown state...\n");
49 unsigned char idle[] = {0x00};
50 printf("Placing TAP in idle state...\n");
51 tap->tapstate = TAP_IDLE;
52 return nexys2_jtag_puttmstdi(tap->nexys, 1, idle, NULL);
57 printf("cannot transition to idle from %d\n", tap->tapstate);
90 typedef struct token {
101 if (c >= '0' && c <= '9')
103 if (c >= 'a' && c <= 'f')
105 if (c >= 'A' && c <= 'F')
107 printf("Bad hex nybble %c\n", c);
111 token_t *tokenize(int fd)
113 /* First off, suck in ALL of the file */
114 char *f = NULL, *fst;
116 token_t *start = NULL, *cur = NULL;
121 f = realloc(f, sz + 16385);
122 if ((rsz = read(fd, &(f[sz]), 16384)) < 16384)
134 if (!strncmp(f, "//", 2))
136 // Comment, eat the rest of the line
138 if (f && f[1] == '\r')
142 } else if (*f == '\n' || *f == '\r' || *f == '\t' || *f == ' ')
147 start = cur = malloc(sizeof(*cur)); \
148 start->next = NULL; \
150 cur->next = malloc(sizeof(*cur)); \
154 #define MATCHSTRING(str, tok) \
155 if (!strncmp(f, str, strlen(str))) { \
160 else MATCHSTRING("TRST", TOK_TRST)
161 else MATCHSTRING("OFF", TOK_OFF)
162 else MATCHSTRING("ENDIR", TOK_ENDIR)
163 else MATCHSTRING("IDLE", TOK_IDLE)
164 else MATCHSTRING("ENDDR", TOK_ENDDR)
165 else MATCHSTRING("STATE", TOK_STATE)
166 else MATCHSTRING("RESET", TOK_RESET)
167 else MATCHSTRING("FREQUENCY", TOK_FREQUENCY)
168 else MATCHSTRING("1E6", TOK_1E6)
169 else MATCHSTRING("HZ", TOK_HZ)
170 else MATCHSTRING(";", TOK_SEMICOLON)
171 else MATCHSTRING("TIR", TOK_TIR)
172 else MATCHSTRING("HIR", TOK_HIR)
173 else MATCHSTRING("TDR", TOK_TDR)
174 else MATCHSTRING("HDR", TOK_HDR)
175 else MATCHSTRING("TDI", TOK_TDI)
176 else MATCHSTRING("SMASK", TOK_SMASK)
177 else MATCHSTRING("SIR", TOK_SIR)
178 else MATCHSTRING("MASK", TOK_MASK)
179 else MATCHSTRING("TDO", TOK_TDO)
180 else MATCHSTRING("SDR", TOK_SDR)
181 else MATCHSTRING("RUNTEST", TOK_RUNTEST)
182 else MATCHSTRING("TCK", TOK_TCK)
183 else if (isdigit(*f)) {
185 cur->token = TOK_NUMBER;
186 cur->data.i = *f - '0';
191 cur->data.i += *f - '0';
194 } else if (*f == '(') {
198 cur->token = TOK_BITSTRING;
201 while (*f && *f != ')')
204 while (isspace(*f) && *f && *f != ')')
206 if (!*f || *f == ')')
210 while (isspace(*f) && *f && *f != ')')
212 if (!*f || *f == ')')
214 printf("Unpaired hex digit in bitstring\n");
222 cur->data.s = realloc(cur->data.s, asz);
224 cur->data.s[l++] = hex2nyb(c1) << 4 | hex2nyb(c2);
228 printf("Tokenizing error, unhandled: %s\n", f);
238 typedef struct blitval {
240 char *tdi, *tdo, *mask, *smask;
243 /* Copies bits from an input in format:
244 * (msb first) 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 | ...
245 * To an output in format:
246 * 7 6 5 4 3 2 1 0 | 15 14 13 12 11 10 9 8 | ...
248 void bitcopy(int len, unsigned char *inbits, int inpos, int indir, unsigned char *outbits, int outpos, int outdir)
251 if (!inbits || !outbits)
253 for (i = 0; i < len; i++)
256 inbit = inbits[(inpos + i * indir) / 8] & (1 << (7 - ((inpos + i * indir) % 8)));
257 outbits[(outpos + i * outdir) / 8] |= inbit ? (1 << ((outpos + i * outdir) % 8)) : 0;
261 void printprog(int done, int total)
264 int progresscounter = done * 32 / total;
265 static int spinnerstate;
266 char *spinner = "_.oOo.";
269 for (i=0; i < progresscounter; i++)
271 if (progresscounter != 32)
273 for (i=0; i < (31 - progresscounter); i++)
275 printf("] %c %d/%d", spinner[(spinnerstate++) % 6], done, total);
278 void pokethrough(tap_t *tap, blitval_t *tbv, blitval_t *sbv, blitval_t *hbv)
280 int totlen = tbv->len + sbv->len + hbv->len;
281 int lenb = (totlen / 4) + ((totlen % 4) != 0) + 1; // Number of nexys2_* bytes
282 unsigned char *inb = calloc(lenb, 1); // Bitstream to be fed to nexys2_*
283 unsigned char *outb = calloc(lenb, 1);
284 unsigned char *expoutb = calloc(lenb, 1);
285 int bitp = 0; // Position in the "inb" bitstream
292 printf("t:%d, s:%d, h:%d\n", tbv->len, sbv->len, hbv->len);
295 #define ROUNDUP(x) (((x / 8) + ((x % 8) != 0)) * 8 - 1)
296 bitcopy(hbv->len, hbv->tdi, ROUNDUP(hbv->len), -1, inb, bitp*2, 2); bitp += hbv->len;
297 bitcopy(sbv->len, sbv->tdi, ROUNDUP(sbv->len), -1, inb, bitp*2, 2); bitp += sbv->len;
298 bitcopy(tbv->len, tbv->tdi, ROUNDUP(tbv->len), -1, inb, bitp*2, 2); bitp += tbv->len;
299 inb[(bitp*2-2)/8] |= 2 << ((bitp*2-2) % 8);
300 assert(bitp == totlen);
304 bitp = 0; /* Have to throw away one bit :( */
305 bitcopy(tbv->len, tbv->tdo, ROUNDUP(tbv->len), -1, expoutb, bitp, 1); bitp += tbv->len;
306 bitcopy(sbv->len, sbv->tdo, ROUNDUP(sbv->len), -1, expoutb, bitp, 1); bitp += sbv->len;
307 bitcopy(hbv->len, hbv->tdo, ROUNDUP(hbv->len), -1, expoutb, bitp, 1); bitp += hbv->len;
310 for (txp = 0; txp < totlen; txp += 0x8000)
312 int len = (((txp + 0x8000) > totlen) ? totlen : (txp + 0x8000)) - txp;
313 printf("Shifting: "); printprog(txp + len, totlen); printf("\r");
315 nexys2_jtag_puttmstdi(tap->nexys, len, inb + ((txp * 2) / 8), needout ? (outb + (txp / 8)) : NULL);
319 printf("I: %02x, %02x, %02x, %02x\n", (int)inb[0], (int)inb[1], (int) inb[2], (int)inb[3]);
320 printf("O: %02x, %02x, %02x, %02x\n", (int)outb[0], (int)outb[1], (int)outb[2], (int)outb[3]);
321 printf("X: %02x, %02x, %02x, %02x\n", (int)expoutb[0], (int)expoutb[1], (int)expoutb[2], (int)expoutb[3]);
328 void runsvf(tap_t *tap, token_t *tlist)
331 int endir = TOK_IDLE, enddr = TOK_IDLE;
332 blitval_t tir, tdr, hir, hdr;
339 #define NEXT tlist = tlist->next
340 #define REQUIRENEXT do { NEXT; if (!tlist) { printf("Unexpected end of stream\n"); abort(); } } while(0)
341 #define EXPECT(tok) \
342 if (tlist->token != tok) \
344 printf("Expected " #tok ", got %d\n", tok); \
350 switch (tlist->token)
353 REQUIRENEXT; EXPECT(TOK_OFF);
355 REQUIRENEXT; EXPECT(TOK_SEMICOLON);
359 REQUIRENEXT; EXPECT(TOK_IDLE);
361 REQUIRENEXT; EXPECT(TOK_SEMICOLON);
365 REQUIRENEXT; EXPECT(TOK_IDLE);
367 REQUIRENEXT; EXPECT(TOK_SEMICOLON);
372 printf("Changing state...\n");
373 if (tlist->token == TOK_RESET)
375 else if (tlist->token == TOK_IDLE)
378 printf("Unknown token after TOK_STATE\n");
381 REQUIRENEXT; EXPECT(TOK_SEMICOLON);
385 REQUIRENEXT; EXPECT(TOK_1E6);
386 REQUIRENEXT; EXPECT(TOK_HZ);
387 REQUIRENEXT; EXPECT(TOK_SEMICOLON);
397 int oldtok = tlist->token;
401 if (oldtok == TOK_TIR)
403 else if (oldtok == TOK_HIR)
405 else if (oldtok == TOK_TDR)
407 else if (oldtok == TOK_HDR)
412 REQUIRENEXT; EXPECT(TOK_NUMBER);
413 bv->len = tlist->data.i;
420 while (tlist->token != TOK_SEMICOLON)
422 switch (tlist->token)
425 REQUIRENEXT; EXPECT(TOK_BITSTRING);
426 bv->tdi = tlist->data.s;
430 REQUIRENEXT; EXPECT(TOK_BITSTRING);
431 bv->tdo = tlist->data.s;
435 REQUIRENEXT; EXPECT(TOK_BITSTRING);
436 bv->mask = tlist->data.s;
440 REQUIRENEXT; EXPECT(TOK_BITSTRING);
441 bv->smask = tlist->data.s;
448 EXPECT(TOK_SEMICOLON);
451 if (oldtok == TOK_SIR || oldtok == TOK_SDR)
453 char *capturedr = "\x02";
454 char *captureir = "\x0A";
455 char *returnidle = "\x02";
457 /* Enter capture DR is TMS 1 0 */
458 /* Enter capture IR is TMS 1 1 0 */
459 /* Return to RTI is TMS 1 0 */
461 if (oldtok == TOK_SIR)
463 printf("Shifting IR (%d bits)...\n", tir.len + s.len + hdr.len);
464 nexys2_jtag_puttmstdi(tap->nexys, 4, captureir, NULL);
465 pokethrough(tap, &tir, &s, &hir);
467 printf("Shifting DR (%d bits)...\n", tdr.len + s.len + hdr.len);
468 nexys2_jtag_puttmstdi(tap->nexys, 3, capturedr, NULL);
469 pokethrough(tap, &tdr, &s, &hdr);
471 nexys2_jtag_puttmstdi(tap->nexys, 2, returnidle, NULL);
480 REQUIRENEXT; EXPECT(TOK_NUMBER);
482 REQUIRENEXT; EXPECT(TOK_TCK);
483 REQUIRENEXT; EXPECT(TOK_SEMICOLON);
490 printf("Going RTI for %d clocks...\n", n);
494 int b = (n < 512) ? n : 512;
495 nexys2_jtag_puttdi(tap->nexys, 0, n, loss, NULL);
503 printf("Unknown top level token %d\n", tlist->token);
509 int main(int argc, char **argv)
517 printf("usage: s3load <file.svf>\n");
520 if ((fd = open(argv[1], O_RDONLY)) < 0)
525 tlist = tokenize(fd);
529 tap.tapstate = TAP_UNKNOWN;
530 tap.nexys = nexys2_init();
533 fprintf(stderr, "Board init failed :(\n");
537 if (nexys2_jtag_enable(tap.nexys) < 0)
542 nexys2_jtag_disable(tap.nexys);