bits_t * bits_xor_d(bits_t *x1, bits_t *x2) { bits_t *ret; ret = bits_xor(x1, x2); bits_free(x1); bits_free(x2); return ret; }
void bits_assign(bits_t **lhs, bits_t *rhs) { bits_free(*lhs); *lhs = rhs; }
string_t * bits_encode_d(bits_t *in) { string_t *ret; ret = bits_encode(in); bits_free(in); return ret; }
bits_t * bits_fget(FILE *f, size_t len) { bits_t *bits; int ret; bits = emalloc(sizeof(*bits)); bits->length = len; bits->text = emalloc(BITS2BYTES(bits->length)); ret = fread(bits->text, BITS2BYTES(bits->length), 1, f); if (ret != 1) { bits_free(bits); return NULL; } return bits; }
int main(int argc, char **argv) { struct ftdi_context ftdi; uint8_t buf[4]; uint8_t conf_buf[] = {SET_BITS_LOW, 0x08, 0x0b, SET_BITS_HIGH, 0x00, 0x00, TCK_DIVISOR, 0x00, 0x00, LOOPBACK_END}; if (argc < 2) { usage(argv[0]); return 1; } if (strcmp (argv[1], "idcode") && strcmp (argv[1], "reset") && strcmp (argv[1], "load") && strcmp (argv[1], "readreg") && strcmp (argv[1], "read") && strcmp (argv[1], "write") ) { usage(argv[0]); return 1; } /* Init */ ftdi_init(&ftdi); if (ftdi_usb_open_desc(&ftdi, VENDOR, PRODUCT, 0, 0) < 0) { fprintf(stderr, "Can't open device %04x:%04x\n", VENDOR, PRODUCT); return 1; } ftdi_usb_reset(&ftdi); ftdi_set_interface(&ftdi, INTERFACE_A); ftdi_set_latency_timer(&ftdi, 1); ftdi_set_bitmode(&ftdi, 0xfb, BITMODE_MPSSE); if (ftdi_write_data(&ftdi, conf_buf, 10) != 10) { fprintf(stderr, "Can't configure device %04x:%04x\n", VENDOR, PRODUCT); return 1; } buf[0] = GET_BITS_LOW; buf[1] = SEND_IMMEDIATE; if (ftdi_write_data(&ftdi, buf, 2) != 2) { fprintf(stderr, "Can't send command to device\n"); return 1; } ftdi_read_data(&ftdi, &buf[2], 1); if (!(buf[2] & 0x10)) { fprintf(stderr, "Vref not detected. Please power on target board\n"); return 1; } if (!strcmp(argv[1], "idcode")) { uint8_t out[4]; tap_reset_rti(&ftdi); tap_shift_dr_bits(&ftdi, NULL, 32, out); rev_dump(out, 4); printf("\n"); } if (!strcmp (argv[1], "reset")) brd_reset(&ftdi); if (!strcmp (argv[1], "load")) { int i; struct load_bits *bs; FILE *fp; uint8_t *dr_data; uint32_t u; if(argc < 3) { usage(argv[0]); goto exit; } if (!strcmp(argv[2], "-")) fp = stdin; else { fp = fopen(argv[2], "r"); if (!fp) { perror("Unable to open file"); goto exit; } } bs = calloc(1, sizeof(*bs)); if (!bs) { perror("memory allocation failed"); goto exit; } if (load_bits(fp, bs) != 0) { fprintf(stderr, "%s not supported\n", argv[2]); goto free_bs; } printf("Bitstream information:\n"); printf("\tDesign: %s\n", bs->design); printf("\tPart name: %s\n", bs->part_name); printf("\tDate: %s\n", bs->date); printf("\tTime: %s\n", bs->time); printf("\tBitstream length: %d\n", bs->length); /* copy data into shift register */ dr_data = calloc(1, bs->length); if (!dr_data) { perror("memory allocation failed"); goto free_bs; } for (u = 0; u < bs->length; u++) dr_data[u] = rev8(bs->data[u]); brd_reset(&ftdi); tap_shift_ir(&ftdi, CFG_IN); tap_shift_dr_bits(&ftdi, dr_data, bs->length * 8, NULL); /* ug380.pdf * P161: a minimum of 16 clock cycles to the TCK */ tap_shift_ir(&ftdi, JSTART); for (i = 0; i < 32; i++) tap_tms(&ftdi, 0, 0); tap_reset_rti(&ftdi); free(dr_data); free_bs: bits_free(bs); fclose(fp); } if (!strcmp(argv[1], "readreg") && argc == 3) { int i; char *err; uint8_t reg; uint8_t out[2]; uint8_t dr_in[14]; uint8_t in[14] = { 0xaa, 0x99, 0x55, 0x66, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00 }; uint16_t cmd = 0x2801; /* type 1 packet (word count = 1) */ reg = strtol(argv[2], &err, 0); if((*err != 0x00) || (reg < 0) || (reg > 0x22)) { fprintf(stderr, "Invalid register, use a decimal or hexadecimal(0x...) number between 0x0 and 0x22\n"); goto exit; } cmd |= ((reg & 0x3f) << 5); in[4] = (cmd & 0xff00) >> 8; in[5] = cmd & 0xff; tap_reset_rti(&ftdi); tap_tms(&ftdi, 1, 0); tap_tms(&ftdi, 1, 0); tap_tms(&ftdi, 0, 0); tap_tms(&ftdi, 0, 0); /* Goto shift IR */ tap_shift_ir_only(&ftdi, CFG_IN); tap_tms(&ftdi, 1, 0); tap_tms(&ftdi, 1, 0); tap_tms(&ftdi, 0, 0); tap_tms(&ftdi, 0, 0); /* Goto SHIFT-DR */ for (i = 0; i < 14; i++) dr_in[i] = rev8(in[i]); tap_shift_dr_bits_only(&ftdi, dr_in, 14 * 8, NULL); tap_tms(&ftdi, 1, 0); tap_tms(&ftdi, 1, 0); tap_tms(&ftdi, 1, 0); /* Goto SELECT-IR */ tap_tms(&ftdi, 0, 0); tap_tms(&ftdi, 0, 0); /* Goto SHIFT-IR */ tap_shift_ir_only(&ftdi, CFG_OUT); tap_tms(&ftdi, 1, 0); tap_tms(&ftdi, 1, 0); tap_tms(&ftdi, 0, 0); tap_tms(&ftdi, 0, 0); /* Goto SHIFT-IR */ tap_shift_dr_bits_only(&ftdi, NULL, 2 * 8, out); tap_tms(&ftdi, 1, 0); tap_tms(&ftdi, 1, 0); tap_tms(&ftdi, 1, 0); /* Goto SELECT-IR */ tap_tms(&ftdi, 0, 0); tap_tms(&ftdi, 0, 0); /* Goto SHIFT-IR */ tap_reset_rti(&ftdi); out[0] = rev8(out[0]); out[1] = rev8(out[1]); printf("REG[%d]: 0x%02x%02x\n", reg, out[0], out[1]); }
bool solve(queue_t* q, uint16_t maxblk) { srand(time(NULL)); printf(" _ _ \n"); printf(" __ ____ _| || | wg4 v%d.%d\n", 0, 1); printf(" \\ \\ /\\ / / _` | || |_ \n"); printf(" \\ V V / (_| |__ _| This program is distributed under the\n"); printf(" \\_/\\_/ \\__, | |_| MIT License; read the README file for\n"); printf(" |___/ more information.\n"); printf(" \n"); printf(" This is wg4 solving a scheduling problem with %d events.\n", q->size); printf(" wg4 is designed to be very verbose. Expect lots of output.\n"); printf(" \n"); // Check phase: check if the problem makes sense if (q->size < 1) { printf("- EMPTY_PROBLEM\n The problem is empty (i.e. doesn't have events).\n"); exit(EXIT_FAILURE); } // Preflight phase: optimize the problem to make solving quicker. // Pf: Sort the events by number of options, ascending. printf(" Pf: Sorting events.\n"); if (q->size) { qsort(q->evs, q->size, sizeof(event_t), cmp_ev_optcount); } // Pf: Check that there aren't any events that don't have options printf(" Pf: Checking for optionless events.\n"); for (uint16_t i = 0; i < q->size; i++) { if (q->evs[i].opts[0] < 1) { printf("- ZERO_OPTS %s\n Event %d (%s) has zero options. Bailing.\n\n", q->evs[i].name, i, q->evs[i].name); exit(EXIT_FAILURE); } else { break; // Events are sorted. If this one has an option, so do the next ones. } } // Pf: Check that there aren't any zero-length events printf(" Pf: Checking for zero-length events.\n"); for (uint16_t i = 0; i < q->size; i++) { if (q->evs[i].len < 1) { printf("- ZERO_LEN %s\n Event %d (%s) has zero length. Bailing.\n\n", q->evs[i].name, i, q->evs[i].name); exit(EXIT_FAILURE); } } // End of preflight. printf(" Pf: Done.\n\n"); // Recon phase: Find out certain things about the problem set. uint16_t tight = 0; for (int i = 0; i < q->size; i++) { if (q->evs[i].opts[0] == 1) { tight += 1; } } uint64_t maxsteps = 1; for (int i = 0; i < q->size; i++) { maxsteps *= q->evs[i].opts[0]; } uint64_t estdsteps = 1; for (int i = 0; i < q->size; i++) { estdsteps *= (uint64_t) ceil(q->evs[i].opts[0] / 2.0); } printf(" Re: Done. %d tight, %lld steps max, %lld estd.\n\n", tight, maxsteps, estdsteps); // End of recon. // Set up solver. bits use = bits_alloc(maxblk); // Solving time! if (subsolve(q, use)) { qsort(q->evs, q->size, sizeof(event_t), cmp_ev_start); for (int i = 0; i < q->size; i++) { printf("e %s %d\n", q->evs[i].name, q->evs[i].opts[q->evs[i].opt]); } } else { printf("- SOLVER_FAIL\n For some reason, solving didn't work. Investigating.\n"); } // Done solving. Clean up the mess. bits_free(use); printf(" \n"); // End of output. clock_t end = clock(); printf(" Done scheduling %d events after %ld ticks (%ld avg).\n\n", q->size, end, end/q->size); return false; }