ice40: convert from dos to unix line endings

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2019-02-25 18:38:53 +08:00
parent 7fb6e4bb7b
commit d2b4ff089d
2 changed files with 466 additions and 466 deletions

876
ice40.c
View File

@ -1,438 +1,438 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include "ice40.h" #include "ice40.h"
#define MAX(x, y) (x) > (y) ? (x) : (y) #define MAX(x, y) (x) > (y) ? (x) : (y)
#define DEBUG_PRINT(...) #define DEBUG_PRINT(...)
struct Ice40Bitstream struct Ice40Bitstream
{ {
uint32_t offset; uint32_t offset;
uint32_t current_bank; uint32_t current_bank;
uint32_t current_width; uint32_t current_width;
uint32_t current_height; uint32_t current_height;
uint32_t current_offset; uint32_t current_offset;
uint32_t cram_width; uint32_t cram_width;
uint32_t cram_height; uint32_t cram_height;
uint32_t bram_width; uint32_t bram_width;
uint32_t bram_height; uint32_t bram_height;
uint16_t crc_value; uint16_t crc_value;
uint8_t warmboot; uint8_t warmboot;
uint8_t nosleep; uint8_t nosleep;
uint8_t frequency_range; uint8_t frequency_range;
}; };
static void update_crc16(uint16_t *crc, uint8_t byte) static void update_crc16(uint16_t *crc, uint8_t byte)
{ {
// CRC-16-CCITT, Initialize to 0xFFFF, No zero padding // CRC-16-CCITT, Initialize to 0xFFFF, No zero padding
for (int i = 7; i >= 0; i--) for (int i = 7; i >= 0; i--)
{ {
uint16_t xor_value = ((*crc >> 15) ^ ((byte >> i) & 1)) ? 0x1021 : 0; uint16_t xor_value = ((*crc >> 15) ^ ((byte >> i) & 1)) ? 0x1021 : 0;
*crc = (*crc << 1) ^ xor_value; *crc = (*crc << 1) ^ xor_value;
} }
} }
static uint32_t get_bit_offset(int x, int total_bits) { static uint32_t get_bit_offset(int x, int total_bits) {
// return (8192 * (x & 7)) + (x >> 3); // return (8192 * (x & 7)) + (x >> 3);
int bitshift = ffs(total_bits)-1; int bitshift = ffs(total_bits)-1;
return ((x * 8192) % total_bits) + ((x*8192) >> bitshift); return ((x * 8192) % total_bits) + ((x*8192) >> bitshift);
} }
uint32_t xorshift32(uint32_t x) uint32_t xorshift32(uint32_t x)
{ {
/* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */ /* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
x = x ^ (x << 13); x = x ^ (x << 13);
x = x ^ (x >> 17); x = x ^ (x >> 17);
x = x ^ (x << 5); x = x ^ (x << 5);
return x; return x;
} }
uint32_t get_rand(uint32_t x) { uint32_t get_rand(uint32_t x) {
uint32_t out = 0; uint32_t out = 0;
int i; int i;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
x = xorshift32(x); x = xorshift32(x);
if ((x & 1) == 1) if ((x & 1) == 1)
out = out | (1 << i); out = out | (1 << i);
} }
return out; return out;
} }
static uint32_t fill_rand(uint32_t *bfr, int count) { static uint32_t fill_rand(uint32_t *bfr, int count) {
int i; int i;
uint32_t last = 1; uint32_t last = 1;
for (i = 0; i < count / 4; i++) { for (i = 0; i < count / 4; i++) {
last = get_rand(last); last = get_rand(last);
bfr[i] = last; bfr[i] = last;
} }
return i; return i;
} }
uint32_t swap_u32(uint32_t word) { uint32_t swap_u32(uint32_t word) {
return (((word >> 24) & 0x000000ff) return (((word >> 24) & 0x000000ff)
| ((word >> 8) & 0x0000ff00) | ((word >> 8) & 0x0000ff00)
| ((word << 8) & 0x00ff0000) | ((word << 8) & 0x00ff0000)
| ((word << 24) & 0xff000000)); | ((word << 24) & 0xff000000));
} }
struct irw_file *irw_open(const char *filename, const char *mode) struct irw_file *irw_open(const char *filename, const char *mode)
{ {
struct irw_file *f = malloc(sizeof(*f)); struct irw_file *f = malloc(sizeof(*f));
memset(f, 0, sizeof(*f)); memset(f, 0, sizeof(*f));
f->f = fopen(filename, mode); f->f = fopen(filename, mode);
return f; return f;
} }
struct irw_file *irw_open_fake(void *hook_data, struct irw_file *irw_open_fake(void *hook_data,
int (*read_hook)(void *data), int (*read_hook)(void *data),
int (*write_hook)(void *data, uint8_t b)) { int (*write_hook)(void *data, uint8_t b)) {
struct irw_file *f = malloc(sizeof(*f)); struct irw_file *f = malloc(sizeof(*f));
memset(f, 0, sizeof(*f)); memset(f, 0, sizeof(*f));
f->read_hook = read_hook; f->read_hook = read_hook;
f->write_hook = write_hook; f->write_hook = write_hook;
f->hook_data = hook_data; f->hook_data = hook_data;
return f; return f;
} }
int irw_readb(struct irw_file *f) int irw_readb(struct irw_file *f)
{ {
int val; int val;
if (f->read_hook) if (f->read_hook)
val = f->read_hook(f->hook_data); val = f->read_hook(f->hook_data);
else else
val = fgetc(f->f); val = fgetc(f->f);
if (val == EOF) if (val == EOF)
return EOF; return EOF;
update_crc16(&f->crc, val); update_crc16(&f->crc, val);
return val; return val;
} }
int irw_writeb(struct irw_file *f, int c) { int irw_writeb(struct irw_file *f, int c) {
update_crc16(&f->crc, c); update_crc16(&f->crc, c);
if (f->write_hook) if (f->write_hook)
return f->write_hook(f->hook_data, c); return f->write_hook(f->hook_data, c);
else else
return fputc(c, f->f); return fputc(c, f->f);
} }
void irw_close(struct irw_file **f) { void irw_close(struct irw_file **f) {
if (!f) if (!f)
return; return;
if (!*f) if (!*f)
return; return;
if (!(*f)->f) if (!(*f)->f)
return; return;
fclose((*f)->f); fclose((*f)->f);
*f = NULL; *f = NULL;
} }
uint8_t get_bit(uint32_t *field, uint32_t offset) uint8_t get_bit(uint32_t *field, uint32_t offset)
{ {
// printf("offset&31: %d\n", offset & 31); // printf("offset&31: %d\n", offset & 31);
// printf("offset/sizeof(*field): %d\n", offset >> 5); // printf("offset/sizeof(*field): %d\n", offset >> 5);
assert(offset < 65536); assert(offset < 65536);
return !!(field[offset >> 5] & (1 << (offset & 31))); return !!(field[offset >> 5] & (1 << (offset & 31)));
} }
void set_bit(uint32_t *field, uint32_t offset) void set_bit(uint32_t *field, uint32_t offset)
{ {
assert(offset < 65536); assert(offset < 65536);
field[offset >> 5] |= (1 << (offset & 31)); field[offset >> 5] |= (1 << (offset & 31));
} }
void clear_bit(uint32_t *field, uint32_t offset) void clear_bit(uint32_t *field, uint32_t offset)
{ {
assert(offset < 65536); assert(offset < 65536);
field[offset >> 5] &= ~(1 << (offset & 31)); field[offset >> 5] &= ~(1 << (offset & 31));
} }
int ice40_patch(struct irw_file *f, struct irw_file *rom, int ice40_patch(struct irw_file *f, struct irw_file *rom,
struct irw_file *o, uint32_t byte_count) struct irw_file *o, uint32_t byte_count)
{ {
uint32_t preamble = 0; uint32_t preamble = 0;
uint8_t wakeup = 0; uint8_t wakeup = 0;
struct Ice40Bitstream bs; struct Ice40Bitstream bs;
uint32_t input_rom[byte_count / sizeof(uint32_t)]; uint32_t input_rom[byte_count / sizeof(uint32_t)];
uint32_t input_rand[byte_count / sizeof(uint32_t)]; uint32_t input_rand[byte_count / sizeof(uint32_t)];
uint32_t output_rand[byte_count / sizeof(uint32_t)]; uint32_t output_rand[byte_count / sizeof(uint32_t)];
uint32_t output_rom[byte_count / sizeof(uint32_t)]; uint32_t output_rom[byte_count / sizeof(uint32_t)];
uint8_t *i8 = (uint8_t *)input_rom; uint8_t *i8 = (uint8_t *)input_rom;
uint16_t *ora16 = (uint16_t *)output_rand; uint16_t *ora16 = (uint16_t *)output_rand;
uint16_t *oro16 = (uint16_t *)output_rom; uint16_t *oro16 = (uint16_t *)output_rom;
unsigned int ora_ptr = 0; unsigned int ora_ptr = 0;
unsigned int ora_matches = 0; unsigned int ora_matches = 0;
unsigned int input_ptr; unsigned int input_ptr;
int b; int b;
int errors = 0; int errors = 0;
memset(&bs, 0, sizeof(bs)); memset(&bs, 0, sizeof(bs));
// Read the ROM into a source buffer // Read the ROM into a source buffer
memset(input_rom, 0, sizeof(input_rom)); memset(input_rom, 0, sizeof(input_rom));
input_ptr = 0; input_ptr = 0;
while ((b = irw_readb(rom)) != EOF) while ((b = irw_readb(rom)) != EOF)
i8[input_ptr++] = b; i8[input_ptr++] = b;
DEBUG_PRINT("read %d bytes from rom\n", input_ptr); DEBUG_PRINT("read %d bytes from rom\n", input_ptr);
// Generate our reference pattern // Generate our reference pattern
memset(input_rand, 0, sizeof(input_rand)); memset(input_rand, 0, sizeof(input_rand));
fill_rand(input_rand, sizeof(input_rand)); fill_rand(input_rand, sizeof(input_rand));
// Swap either the input or output data, as necessary // Swap either the input or output data, as necessary
for (input_ptr = 0; input_ptr < sizeof(input_rom)/4; input_ptr++) { for (input_ptr = 0; input_ptr < sizeof(input_rom)/4; input_ptr++) {
// input_rand[input_ptr] = swap_u32(input_rand[input_ptr]); // input_rand[input_ptr] = swap_u32(input_rand[input_ptr]);
// input_rom[input_ptr] = swap_u32(input_rom[input_ptr]); // input_rom[input_ptr] = swap_u32(input_rom[input_ptr]);
} }
// Spray the reference pattern and ROM like they would exist in the FPGA // Spray the reference pattern and ROM like they would exist in the FPGA
for (input_ptr = 0; input_ptr < sizeof(input_rom) * 8; input_ptr++) { for (input_ptr = 0; input_ptr < sizeof(input_rom) * 8; input_ptr++) {
int bit; int bit;
bit = get_bit(input_rand, get_bit_offset(input_ptr, sizeof(input_rand)*8)); bit = get_bit(input_rand, get_bit_offset(input_ptr, sizeof(input_rand)*8));
if (bit) if (bit)
set_bit(output_rand, input_ptr); set_bit(output_rand, input_ptr);
else else
clear_bit(output_rand, input_ptr); clear_bit(output_rand, input_ptr);
bit = get_bit(input_rom, get_bit_offset(input_ptr, sizeof(input_rom)*8)); bit = get_bit(input_rom, get_bit_offset(input_ptr, sizeof(input_rom)*8));
if (bit) if (bit)
set_bit(output_rom, input_ptr); set_bit(output_rom, input_ptr);
else else
clear_bit(output_rom, input_ptr); clear_bit(output_rom, input_ptr);
} }
while (1) while (1)
{ {
b = irw_readb(f); b = irw_readb(f);
if (b == EOF) if (b == EOF)
break; break;
irw_writeb(o, b); irw_writeb(o, b);
preamble = (preamble << 8) | b; preamble = (preamble << 8) | b;
if (preamble == 0x7eaa997e) if (preamble == 0x7eaa997e)
{ {
// DEBUG_PRINT("found preamble at %d\n", bs.offset); // DEBUG_PRINT("found preamble at %d\n", bs.offset);
break; break;
} }
} }
while (!wakeup) while (!wakeup)
{ {
int b = irw_readb(f); int b = irw_readb(f);
if (b == EOF) if (b == EOF)
{ {
// DEBUG_PRINT("reached end of file\n"); // DEBUG_PRINT("reached end of file\n");
break; break;
} }
irw_writeb(o, b); irw_writeb(o, b);
uint8_t cmd = b >> 4; uint8_t cmd = b >> 4;
uint8_t payload_len = b & 0xf; uint8_t payload_len = b & 0xf;
uint32_t payload = 0; uint32_t payload = 0;
uint8_t last0, last1; uint8_t last0, last1;
unsigned int i; unsigned int i;
for (i = 0; i < payload_len; i++) for (i = 0; i < payload_len; i++)
{ {
b = irw_readb(f); b = irw_readb(f);
payload = (payload << 8) | (b & 0xff); payload = (payload << 8) | (b & 0xff);
// Don't write the CRC16 out, since we'll do that later on. // Don't write the CRC16 out, since we'll do that later on.
if (cmd != 2) if (cmd != 2)
irw_writeb(o, b); irw_writeb(o, b);
} }
switch (cmd) switch (cmd)
{ {
case 0: case 0:
switch (payload) switch (payload)
{ {
case 1: case 1:
DEBUG_PRINT("CRAM data (bank %d): %d x %d @ 0x%08x; %d bits = %d bytes\n", DEBUG_PRINT("CRAM data (bank %d): %d x %d @ 0x%08x; %d bits = %d bytes\n",
bs.current_bank, bs.current_bank,
bs.current_width, bs.current_width,
bs.current_height, bs.current_height,
bs.current_offset, bs.current_offset,
bs.current_width * bs.current_height, bs.current_width * bs.current_height,
(bs.current_width * bs.current_height) / 8); (bs.current_width * bs.current_height) / 8);
bs.cram_width = MAX(bs.cram_width, bs.current_width); bs.cram_width = MAX(bs.cram_width, bs.current_width);
bs.cram_height = MAX(bs.cram_height, bs.current_height); bs.cram_height = MAX(bs.cram_height, bs.current_height);
for (i = 0; i < ((bs.current_width * bs.current_height) / 8); i++) for (i = 0; i < ((bs.current_width * bs.current_height) / 8); i++)
{ {
irw_writeb(o, irw_readb(f)); irw_writeb(o, irw_readb(f));
} }
last0 = irw_readb(f); last0 = irw_readb(f);
last1 = irw_readb(f); last1 = irw_readb(f);
if (last0 || last1) if (last0 || last1)
{ {
printf("expected 0x0000 after CRAM data, got %02x %02x\n", last0, last1); printf("expected 0x0000 after CRAM data, got %02x %02x\n", last0, last1);
} }
irw_writeb(o, last0); irw_writeb(o, last0);
irw_writeb(o, last1); irw_writeb(o, last1);
break; break;
case 3: case 3:
DEBUG_PRINT("BRAM data (bank %d): %d x %d @ 0x%08x; %d bits = %d bytes\n", DEBUG_PRINT("BRAM data (bank %d): %d x %d @ 0x%08x; %d bits = %d bytes\n",
bs.current_bank, bs.current_bank,
bs.current_width, bs.current_width,
bs.current_height, bs.current_height,
bs.current_offset, bs.current_offset,
bs.current_width * bs.current_height, bs.current_width * bs.current_height,
(bs.current_width * bs.current_height) / 8); (bs.current_width * bs.current_height) / 8);
bs.bram_width = MAX(bs.bram_width, bs.current_width); bs.bram_width = MAX(bs.bram_width, bs.current_width);
bs.bram_height = MAX(bs.bram_height, bs.current_height); bs.bram_height = MAX(bs.bram_height, bs.current_height);
for (i = 0; i < ((bs.current_width * bs.current_height) / 8); i += 2) for (i = 0; i < ((bs.current_width * bs.current_height) / 8); i += 2)
{ {
uint16_t word = uint16_t word =
((irw_readb(f) << 8) & 0x0000ff00) ((irw_readb(f) << 8) & 0x0000ff00)
| |
((irw_readb(f) << 0) & 0x000000ff) ((irw_readb(f) << 0) & 0x000000ff)
; ;
int i; int i;
if (word) { if (word) {
int found = 0; int found = 0;
int start = ora_ptr - 64; int start = ora_ptr - 64;
int end = ora_ptr + 64; int end = ora_ptr + 64;
if (start < 0) if (start < 0)
start = 0; start = 0;
if (end > 8192) if (end > 8192)
end = 8192; end = 8192;
for (i = start; i < end; i++) { for (i = start; i < end; i++) {
if (ora16[i] == word) { if (ora16[i] == word) {
found = 1; found = 1;
word = oro16[i]; word = oro16[i];
ora_matches++; ora_matches++;
ora_ptr = i; ora_ptr = i;
break; break;
} }
} }
if (!found) { if (!found) {
printf("couldn't find word %04x (ora_ptr: %d matches: %d)\n", word, ora_ptr, ora_matches); printf("couldn't find word %04x (ora_ptr: %d matches: %d)\n", word, ora_ptr, ora_matches);
errors++; errors++;
} }
} }
else { else {
ora_ptr++; ora_ptr++;
// DEBUG_PRINT("word is 0, ptr is %d\n", ora_ptr); // DEBUG_PRINT("word is 0, ptr is %d\n", ora_ptr);
} }
irw_writeb(o, word >> 8); irw_writeb(o, word >> 8);
irw_writeb(o, word); irw_writeb(o, word);
} }
last0 = irw_readb(f); last0 = irw_readb(f);
last1 = irw_readb(f); last1 = irw_readb(f);
if (last0 || last1) if (last0 || last1)
{ {
printf("expected 0x0000 after BRAM data, got %02x %02x\n", last0, last1); printf("expected 0x0000 after BRAM data, got %02x %02x\n", last0, last1);
} }
irw_writeb(o, last0); irw_writeb(o, last0);
irw_writeb(o, last1); irw_writeb(o, last1);
break; break;
// Reset CRC // Reset CRC
case 5: case 5:
f->crc = 0xffff; f->crc = 0xffff;
o->crc = 0xffff; o->crc = 0xffff;
break; break;
// Wakeup // Wakeup
case 6: case 6:
wakeup = 1; wakeup = 1;
break; break;
default: default:
printf("unrecognized command 0x%02x 0x%02x\n", cmd, payload); printf("unrecognized command 0x%02x 0x%02x\n", cmd, payload);
break; break;
} }
break; break;
// Set current bank // Set current bank
case 1: case 1:
bs.current_bank = payload; bs.current_bank = payload;
ora_ptr = 0; ora_ptr = 0;
ora_matches = 0; ora_matches = 0;
// printf("setting bank number to %d\n", bs.current_bank); // printf("setting bank number to %d\n", bs.current_bank);
break; break;
// Validate CRC16 // Validate CRC16
case 2: case 2:
DEBUG_PRINT("crc check (%04x == %04x)\n", f->crc, 0); DEBUG_PRINT("crc check (%04x == %04x)\n", f->crc, 0);
uint16_t crc16 = o->crc; uint16_t crc16 = o->crc;
irw_writeb(o, crc16 >> 8); irw_writeb(o, crc16 >> 8);
irw_writeb(o, crc16); irw_writeb(o, crc16);
break; break;
// Set frequency range // Set frequency range
case 5: case 5:
switch (payload) switch (payload)
{ {
case 0: case 0:
bs.frequency_range = 0; bs.frequency_range = 0;
break; break;
case 1: case 1:
bs.frequency_range = 1; bs.frequency_range = 1;
break; break;
case 2: case 2:
bs.frequency_range = 2; bs.frequency_range = 2;
break; break;
default: default:
printf("unknown frequency range payload: %02x\n", payload); printf("unknown frequency range payload: %02x\n", payload);
break; break;
} }
break; break;
// Set current width // Set current width
case 6: case 6:
bs.current_width = payload + 1; bs.current_width = payload + 1;
break; break;
// Set current height // Set current height
case 7: case 7:
bs.current_height = payload; bs.current_height = payload;
break; break;
// Set current ofset // Set current ofset
case 8: case 8:
bs.current_offset = payload; bs.current_offset = payload;
break; break;
// Set flags // Set flags
case 9: case 9:
switch (payload) switch (payload)
{ {
case 0: case 0:
bs.warmboot = 0; bs.warmboot = 0;
bs.nosleep = 0; bs.nosleep = 0;
break; break;
case 1: case 1:
bs.warmboot = 0; bs.warmboot = 0;
bs.nosleep = 1; bs.nosleep = 1;
break; break;
case 32: case 32:
bs.warmboot = 1; bs.warmboot = 1;
bs.nosleep = 0; bs.nosleep = 0;
break; break;
case 33: case 33:
bs.warmboot = 1; bs.warmboot = 1;
bs.nosleep = 1; bs.nosleep = 1;
break; break;
default: default:
printf("unrecognized feature flags: %02x\n", payload); printf("unrecognized feature flags: %02x\n", payload);
break; break;
} }
break; break;
default: default:
printf("unrecognized command: %02x\n", cmd); printf("unrecognized command: %02x\n", cmd);
break; break;
} }
} }
// Padding // Padding
irw_writeb(o, 0); irw_writeb(o, 0);
return errors; return errors;
} }

56
ice40.h
View File

@ -1,28 +1,28 @@
#ifndef _ICE40_H #ifndef _ICE40_H
#define _ICE40_H #define _ICE40_H
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
typedef struct irw_file typedef struct irw_file
{ {
FILE *f; FILE *f;
uint16_t crc; uint16_t crc;
uint32_t offset; uint32_t offset;
void *hook_data; void *hook_data;
int (*read_hook)(void *data); int (*read_hook)(void *data);
int (*write_hook)(void *data, uint8_t b); int (*write_hook)(void *data, uint8_t b);
} IRW_FILE; } IRW_FILE;
struct irw_file *irw_open(const char *filename, const char *mode); struct irw_file *irw_open(const char *filename, const char *mode);
struct irw_file *irw_open_fake(void *hook_data, struct irw_file *irw_open_fake(void *hook_data,
int (*read_hook)(void *data), int (*read_hook)(void *data),
int (*write_hook)(void *data, uint8_t b)); int (*write_hook)(void *data, uint8_t b));
int irw_readb(struct irw_file *f); int irw_readb(struct irw_file *f);
int irw_writeb(struct irw_file *f, int c); int irw_writeb(struct irw_file *f, int c);
void irw_close(struct irw_file **f); void irw_close(struct irw_file **f);
int ice40_patch(struct irw_file *f, struct irw_file *rom, int ice40_patch(struct irw_file *f, struct irw_file *rom,
struct irw_file *o, uint32_t byte_count); struct irw_file *o, uint32_t byte_count);
#endif /* _ICE40_H */ #endif /* _ICE40_H */