#include #include #include #include #include #include #include #define MAX(x, y) (x) > (y) ? (x) : (y) typedef struct irw_file { FILE *f; uint16_t crc; uint32_t offset; } IRW_FILE; int print_hex_offset(const void *block, int count, int offset, uint32_t start); int print_hex(const void *block, int count, uint32_t start); static void update_crc16(uint16_t *crc, uint8_t byte) { // CRC-16-CCITT, Initialize to 0xFFFF, No zero padding for (int i = 7; i >= 0; i--) { uint16_t xor_value = ((*crc >> 15) ^ ((byte >> i) & 1)) ? 0x1021 : 0; *crc = (*crc << 1) ^ xor_value; } } static uint8_t reverse_u8(uint8_t b) { b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; b = (b & 0xCC) >> 2 | (b & 0x33) << 2; b = (b & 0xAA) >> 1 | (b & 0x55) << 1; return b; } struct irw_file *irw_open(const char *filename, const char *mode) { struct irw_file *f = malloc(sizeof(*f)); memset(f, 0, sizeof(*f)); f->f = fopen(filename, mode); return f; } int irw_readb(struct irw_file *f) { int val = fgetc(f->f); if (val == EOF) return EOF; update_crc16(&f->crc, val); return val; } struct Ice40Bitstream { uint32_t offset; uint32_t current_bank; uint32_t current_width; uint32_t current_height; uint32_t current_offset; uint32_t cram_width; uint32_t cram_height; uint32_t bram_width; uint32_t bram_height; uint16_t crc_value; uint8_t warmboot; uint8_t nosleep; uint8_t frequency_range; uint8_t bram_banks[4][2560 * 2]; }; struct Ice40Bitstream bs; int ice40_find_header(struct irw_file *f) { uint32_t preamble = 0; uint8_t wakeup = 0; memset(&bs, 0, sizeof(bs)); while (1) { int b = irw_readb(f); if (b == EOF) break; preamble = (preamble << 8) | b; if (preamble == 0x7eaa997e) { // printf("found preamble at %d\n", bs.offset); break; } } while (!wakeup) { int b = irw_readb(f); if (b == EOF) { // printf("reached end of file\n"); break; } uint8_t cmd = b >> 4; uint8_t payload_len = b & 0xf; uint32_t payload = 0; uint8_t last0, last1; int i; for (i = 0; i < payload_len; i++) { payload = (payload << 8) | (irw_readb(f) & 0xff); } // printf("cmd: %02x payload: %02x payload_len: %d\n", cmd, payload, payload_len); switch (cmd) { case 0: switch (payload) { case 1: printf("CRAM data (bank %d): %d x %d @ 0x%08x; %d bits = %d bytes\n", bs.current_bank, bs.current_width, bs.current_height, bs.current_offset, bs.current_width * bs.current_height, (bs.current_width * bs.current_height) / 8); bs.cram_width = MAX(bs.cram_width, bs.current_width); bs.cram_height = MAX(bs.cram_height, bs.current_height); for (i = 0; i < ((bs.current_width * bs.current_height) / 8); i++) { (void)irw_readb(f); } last0 = irw_readb(f); last1 = irw_readb(f); if (last0 || last1) { printf("expected 0x0000 after CRAM data, got %02x %02x\n", last0, last1); } break; case 3: { printf("BRAM data (bank %d): %d x %d @ 0x%08x; %d bits = %d bytes\n", bs.current_bank, bs.current_width, bs.current_height, bs.current_offset, bs.current_width * bs.current_height, (bs.current_width * bs.current_height) / 8); bs.bram_width = MAX(bs.bram_width, bs.current_width); bs.bram_height = MAX(bs.bram_height, bs.current_height); uint8_t try_1[(bs.current_height * bs.current_width) / 8]; uint8_t try_2[(bs.current_height * bs.current_width) / 8]; uint8_t try_3[(bs.current_height * bs.current_width) / 8]; uint8_t try_4[(bs.current_height * bs.current_width) / 8]; memset(try_1, 0, sizeof(try_1)); memset(try_2, 0, sizeof(try_2)); memset(try_3, 0, sizeof(try_3)); memset(try_4, 0, sizeof(try_4)); for (i = 0; i < ((bs.current_width * bs.current_height) / 8); i++) { uint8_t byte = irw_readb(f); // int j; // for (j = 0; j < 8; j++) // { // int x = (i * 8 + j) % bs.current_width; // int y = (i * 8 + j) / bs.current_width;// + bs.current_offset; // printf("x: %d y: %d\n", x, y); // try_2[(x * bs.current_width + y) / 8] |= (1 << j); // } try_1[i] = byte; // try_3[i] = reverse_u8(byte); // try_4[i] = byte; } // for (i = 0; i < sizeof(try_4); i += 2) // { // uint8_t t = try_4[i]; // try_4[i] = try_4[i + 1]; // try_4[i + 1] = t; // } printf("try 1:\n"); print_hex(try_1, sizeof(try_1), 0); // printf("try 2:\n"); // print_hex(try_2, sizeof(try_2), 0); // printf("try 3:\n"); // print_hex(try_3, sizeof(try_3), 0); // printf("try 4:\n"); // print_hex(try_4, sizeof(try_4), 0); last0 = irw_readb(f); last1 = irw_readb(f); if (last0 || last1) { printf("expected 0x0000 after BRAM data, got %02x %02x\n", last0, last1); } break; } case 5: // printf("resetting crc\n"); f->crc = 0xffff; break; case 6: // printf("wakeup\n"); wakeup = 1; break; default: printf("unrecognized command 0x%02x 0x%02x\n", cmd, payload); break; } break; case 1: bs.current_bank = payload; // printf("setting bank number to %d\n", bs.current_bank); break; case 2: printf("crc check (%04x == %04x)\n", f->crc, 0); break; case 5: switch (payload) { case 0: bs.frequency_range = 0; break; case 1: bs.frequency_range = 1; break; case 2: bs.frequency_range = 2; break; default: printf("unknown frequency range payload: %02x\n", payload); break; } break; case 6: bs.current_width = payload + 1; // printf("setting bank width to %d\n", bs.current_width); break; case 7: bs.current_height = payload; // printf("setting bank height to %d\n", bs.current_height); break; case 8: bs.current_offset = payload; // printf("setting bank offset to %d\n", bs.current_offset); break; case 9: switch (payload) { case 0: bs.warmboot = 0; bs.nosleep = 0; break; case 1: bs.warmboot = 0; bs.nosleep = 1; break; case 32: bs.warmboot = 1; bs.nosleep = 0; break; case 33: bs.warmboot = 1; bs.nosleep = 1; break; default: printf("unrecognized feature flags: %02x\n", payload); break; } break; default: printf("unrecognized command: %02x\n", cmd); break; } } // printf("read %d bytes\n", bs.offset); return 0; } int main(int argc, char **argv) { struct irw_file *f = irw_open("memtest/memtest.bin", "r"); if (!f) { perror("couldn't open top.bin"); return 1; } ice40_find_header(f); return 0; }