aboutsummaryrefslogtreecommitdiffstats
path: root/icepack
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2015-07-18 13:05:02 +0200
committerClifford Wolf <clifford@clifford.at>2015-07-18 13:05:02 +0200
commitdfeb92a46b2228b4f3886a9c06502ccd0dde5562 (patch)
tree20cebe482ae2954f4597489658b27828f5316921 /icepack
downloadicestorm-dfeb92a46b2228b4f3886a9c06502ccd0dde5562.tar.gz
icestorm-dfeb92a46b2228b4f3886a9c06502ccd0dde5562.tar.bz2
icestorm-dfeb92a46b2228b4f3886a9c06502ccd0dde5562.zip
Import of icestorm-snapshot-150322.zip
Diffstat (limited to 'icepack')
-rw-r--r--icepack/Makefile25
-rw-r--r--icepack/iceunpack.c368
2 files changed, 393 insertions, 0 deletions
diff --git a/icepack/Makefile b/icepack/Makefile
new file mode 100644
index 0000000..06aeaeb
--- /dev/null
+++ b/icepack/Makefile
@@ -0,0 +1,25 @@
+
+CC = clang
+CXX = clang
+LDFLAGS = -lm -lstdc++
+CFLAGS = -MD -Os -Wall -std=c99
+CXXFLAGS = -MD -Os -Wall -std=c99
+
+all: iceunpack
+
+iceunpack: iceunpack.o
+
+install: all
+ cp iceunpack /usr/local/bin/iceunpack
+
+uninstall:
+ rm -f /usr/local/bin/iceunpack
+
+clean:
+ rm -f iceunpack
+ rm -f *.o *.d
+
+-include *.d
+
+.PHONY: install uninstall clean
+
diff --git a/icepack/iceunpack.c b/icepack/iceunpack.c
new file mode 100644
index 0000000..ce8a2fa
--- /dev/null
+++ b/icepack/iceunpack.c
@@ -0,0 +1,368 @@
+// Written by Mathias Lasser
+// License terms are unclear at the moment
+
+#include<stdio.h>
+#include<stdbool.h>
+#include<stdlib.h>
+#include<stdint.h>
+#include<string.h>
+
+int enable_debug=0;
+#define debugf(...) do{if(enable_debug)fprintf(stderr,__VA_ARGS__);}while(0)
+
+#pragma pack(2)
+
+typedef struct
+{
+ uint16_t bfType;
+ uint32_t bfSize;
+ uint16_t bfReserved1;
+ uint16_t bfReserved2;
+ uint32_t bfOffBits;
+}BITMAPFILEHEADER;
+
+typedef struct
+{
+ uint32_t biSize;
+ uint32_t biWidth;
+ uint32_t biHeight;
+ uint16_t biPlanes;
+ uint16_t biBitCount;
+ uint32_t biCompression;
+ uint32_t biSizeImage;
+ uint32_t biXPelsPerMeter;
+ uint32_t biYPelsPerMeter;
+ uint32_t biClrUsed;
+ uint32_t biClrImportant;
+}BITMAPINFOHEADER;
+
+typedef struct{
+ uint16_t boot_mode;
+ uint16_t crc;
+ uint8_t freq;
+ uint8_t bank;
+ uint32_t write_pointer;
+
+ uint32_t CRAM_rowsize;
+ uint32_t CRAM_colsize;
+ uint8_t* CRAM[4];
+ uint32_t BRAM_rowsize;
+ uint32_t BRAM_colsize;
+ uint8_t* BRAM[4];
+}FPGA_t;
+
+typedef struct{
+ uint32_t len;
+ uint32_t pointer;
+ uint16_t crc;
+ uint8_t payload[0];
+}bitstream_t;
+
+typedef union{
+ struct{
+ uint8_t lo:4;
+ uint8_t hi:4;
+ };
+ uint8_t full;
+}nibble_t;
+
+const char* freq_settings[]={"low","medium","high"};
+const char* boot_settings[]={"Disable","Enable"};
+
+uint16_t crc16(uint32_t crc,uint8_t in){
+ for(int i=7;i>=0;i--){
+ crc<<=1;
+ if((crc^(in<<(16-i)))&0x10000)
+ crc^=0x1021;
+ }
+ return crc;
+}
+
+uint32_t get_byte(bitstream_t* bitstream){
+ if(bitstream->pointer>=bitstream->len)return 0xFFFFFF;
+ uint8_t data=bitstream->payload[bitstream->pointer++];
+ bitstream->crc=crc16(bitstream->crc,data);
+ return data;
+}
+
+uint32_t get_payload(bitstream_t* bitstream,int len){
+ uint32_t ret=get_byte(bitstream);
+ for(int i=1;i<len&&ret!=0xFFFFFFFF;i++){
+ ret<<=8;
+ ret|=get_byte(bitstream);
+ }
+ return ret;
+}
+
+void FPGA_write(FPGA_t* FPGA,bitstream_t* bitstream){
+ int n=FPGA->CRAM_colsize*FPGA->CRAM_rowsize/8;
+ uint8_t* temp=(uint8_t*)malloc(n);
+ for(int i=0;i<n;i++)
+ temp[i]=get_byte(bitstream);
+ FPGA->CRAM[FPGA->bank]=temp;
+}
+
+void FPGA_EBR_write(FPGA_t* FPGA,bitstream_t* bitstream){
+ int n=FPGA->BRAM_colsize*FPGA->BRAM_rowsize/8;
+ uint8_t* temp=(uint8_t*)malloc(FPGA->write_pointer+n);
+ if(FPGA->write_pointer!=0){
+ uint8_t* old_data=FPGA->BRAM[FPGA->bank];
+ memcpy(temp,old_data,FPGA->write_pointer);
+ free(old_data);
+ }
+ for(int i=0;i<n;i++)temp[FPGA->write_pointer++]=get_byte(bitstream);
+ FPGA->BRAM[FPGA->bank]=temp;
+}
+
+int parse(bitstream_t* bitstream, FPGA_t* FPGA) {
+ uint32_t preamble=0;
+ while(1){
+ preamble<<=8;
+ preamble|=get_byte(bitstream);
+ if(preamble==0x7EAA997E){
+ debugf("Got preamble\n");
+ break;
+ }
+ if(preamble==0xFFFFFFFF){
+ fprintf(stderr,"Error: could not find preamble...\n");
+ return -1;
+ }
+ }
+ nibble_t command;
+ uint32_t payload;
+ uint16_t crc;
+ while(1){
+ crc=bitstream->crc;
+ command.full=get_byte(bitstream);
+ if(command.full==0xFF){
+ payload=get_byte(bitstream);
+ if(payload!=0x00)goto err;
+ char*comment=(char*)&bitstream->payload[bitstream->pointer];
+ debugf("Got comment section start\n");
+ while(1){
+ payload<<=8;
+ payload|=get_byte(bitstream);
+ if((payload&0xFFFF)==0x00FF)break;
+ if(payload==0xFFFFFFFF){
+ fprintf(stderr,"Error: could not find comment section end\n");
+ return -1;
+ }
+ }
+ debugf("\n%s\n\n",comment);
+ debugf("Got comment section end\n");
+ continue;
+ }
+ payload=get_payload(bitstream,command.lo);
+ switch(command.hi){
+ case 0x0:
+ if(command.lo!=0x01)goto err;
+ switch(payload){
+ case 0x01:
+ debugf("Write to CRAM!!!\n");
+ FPGA_write(FPGA,bitstream);
+ get_payload(bitstream,2);
+ break;
+ case 0x03:
+ debugf("Write to BRAM!!!\n");
+ FPGA_EBR_write(FPGA,bitstream);
+ get_payload(bitstream,2);
+ break;
+ case 0x05:
+ debugf("Resetting CRC\n");
+ bitstream->crc=0;
+ break;
+ case 0x06:
+ debugf("Wake up\n");
+ return 0;
+ default:
+ goto err;
+ }
+ break;
+ case 0x1:
+ if(command.lo!=0x01)goto err;
+ if(payload>3){
+ fprintf(stderr,"Error: bank %u does not exist...\n",payload);
+ }
+ debugf("Set bank to %u\n",payload);
+ FPGA->bank=payload;
+ break;
+ case 0x2:
+ if(command.lo!=0x02)goto err;
+ debugf("CRC check: %04X %04X\n",payload,crc);
+ break;
+ case 0x5:
+ if(command.lo!=0x01)goto err;
+ if(payload>2){
+ fprintf(stderr,"Error: unknown frequency setting...\n");
+ return -1;
+ }
+ debugf("Boot frequency set to %s\n",freq_settings[payload]);
+ FPGA->freq=payload;
+ break;
+ case 0x6:
+ if(command.lo!=0x02)goto err;
+ payload++;
+ debugf("Row size: %i\n",payload);
+ if(FPGA->CRAM_rowsize)FPGA->BRAM_rowsize=payload;
+ else FPGA->CRAM_rowsize=payload;
+ break;
+ case 0x7:
+ if(command.lo!=0x02)goto err;
+ debugf("Column size: %i\n",payload);
+ if(FPGA->CRAM_colsize)FPGA->BRAM_colsize=payload;
+ else FPGA->CRAM_colsize=payload;
+ break;
+ case 0x8:
+ if(command.lo!=0x02)goto err;
+ if(payload==0x0000){
+ debugf("Reset write pointer\n");
+ FPGA->write_pointer=0;
+ }
+ else if(payload==0x0080){
+ debugf("Don't reset write pointer\n");
+ }
+ else goto err;
+ break;
+ case 0x9:
+ if(command.lo!=0x02)goto err;
+ if(payload&0xFFDF){
+ fprintf(stderr,"Error: Unknown warmboot setting... %04X\n",payload);
+ return -1;
+ }
+ debugf("%s warmboot\n",boot_settings[payload?1:0]);
+ FPGA->boot_mode=payload;
+ break;
+ default:
+ goto err;
+ }
+ }
+err:
+ fprintf(stderr,"Error: unkown command... %08X\n",bitstream->pointer);
+ return -1;
+}
+
+uint8_t get_CRAM_bit_from_sector(FPGA_t* FPGA,int bank,int x,int y){
+ if(x<0||x>=FPGA->CRAM_rowsize)return 0xFF;
+ if(y<0||y>=FPGA->CRAM_colsize)return 0xFF;
+ if(bank<0||bank>=4)return 0xFF;
+
+
+ int bit=y*FPGA->CRAM_rowsize+x;
+ int pointer=bit>>3;
+ int shifts=7-(bit&7);
+ return (FPGA->CRAM[bank][pointer]>>shifts)&1;
+}
+
+int tiles[2][20]={
+ {18,54,54,42,54,54,54},
+ {18,2,54,54,54,54,54,54,54,42,54,54,54,54,54,54,54,54}
+};
+
+int permx[2][18]={
+ {23,25,26,27,16,17,18,19,20,14,32,33,34,35,36,37,4,5},
+ {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17}};
+int permy[4][16]={
+ {0,1,3,2,4,5,7,6,8,9,11,10,12,13,15,14},
+ {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},
+};
+
+int tile_row_size[2]={7,17};
+int tile_col_size[2]={9,17};
+
+void print_tile(FPGA_t* FPGA,int x,int y){
+ int type=FPGA->CRAM_rowsize==872;
+ int dirx=0;
+ int diry=0;
+ int tx=x;
+ int ty=y;
+
+ int corner_flags=0;
+ if(x==0)corner_flags|=1;
+ if(y==0)corner_flags|=2;
+ if(x==tile_row_size[type]*2-1)corner_flags|=4;
+ if(y==tile_col_size[type]*2-1)corner_flags|=8;
+ if(corner_flags&(corner_flags-1))
+ return;
+
+ if(x>=tile_row_size[type]){
+ dirx=1;
+ tx=tile_row_size[type]*2-1-x;
+ }
+ if(y>=tile_col_size[type]){
+ diry=1;
+ ty=tile_col_size[type]*2-1-y;
+ }
+ int sector=(diry|dirx<<1);
+ int offx=0;for(int i=0;i<tx;i++)offx+=tiles[type][i];
+ if(corner_flags){
+ printf(".io_tile %i %i\n",x,y);
+ for(int cy=0;cy<16;cy++){
+ for(int cx=0;cx<18;cx++){
+ int val;
+ if(corner_flags&5){
+ if(diry){
+ val=get_CRAM_bit_from_sector(FPGA,sector,offx+tiles[type][tx]-1-permx[1][cx],ty*16+15-permy[1][cy]);
+ }else{
+ val=get_CRAM_bit_from_sector(FPGA,sector,offx+tiles[type][tx]-1-permx[1][cx],ty*16+permy[1][cy]);
+ }
+ }else{
+ if(dirx){
+ val=get_CRAM_bit_from_sector(FPGA,sector,offx+tiles[type][tx]-1-permx[0][cx],ty*16+15-permy[0][cy]);
+ }else{
+ val=get_CRAM_bit_from_sector(FPGA,sector,offx+permx[0][cx],ty*16+15-permy[0][cy]);
+ }
+ }
+ printf("%i",val);
+ }
+ printf("\n");
+ }
+ }
+ else{
+ if(tiles[type][tx]==20)printf(".io_tile %i %i\n",x,y);
+ if(tiles[type][tx]==42)printf(".ram_tile %i %i\n",x,y);
+ if(tiles[type][tx]==54)printf(".logic_tile %i %i\n",x,y);
+ for(int cy=0;cy<16;cy++){
+ for(int cx=0;cx<tiles[type][tx];cx++){
+ printf("%i",get_CRAM_bit_from_sector(FPGA,sector,(dirx?(offx+tiles[type][tx]-1-cx):(offx+cx)),(diry?(ty*16+(15-cy)):(ty*16+cy))));
+ }
+ printf("\n");
+ }
+ }
+}
+
+int main(int argc,char**argv) {
+ if(argc>=2&&!strcmp(argv[1], "-v")) {
+ enable_debug=1;
+ argc--;
+ argv++;
+ }
+ if(argc!=2) {
+ fprintf(stderr,"iceunpack [-v] input\n");
+ return 1;
+ }
+
+ FILE*r_file=fopen(argv[1],"rb");
+ if(r_file==NULL) {
+ fprintf(stderr,"could not open %s\n",argv[1]);
+ return 1;
+ }
+ fseek(r_file,0,SEEK_END);
+ size_t r_size=ftell(r_file);
+ fseek(r_file,0,SEEK_SET);
+
+ bitstream_t* bitstream=(bitstream_t*)malloc(sizeof(bitstream_t)+r_size);
+ bitstream->len=r_size;
+ bitstream->pointer=0;
+ fread(bitstream->payload,1,r_size,r_file);
+ fclose(r_file);
+
+ FPGA_t FPGA;
+ memset(&FPGA,0,sizeof(FPGA));
+
+ parse(bitstream,&FPGA);
+ free(bitstream);
+
+ printf(".device 1k\n");
+ for(int y=0;y<18;y++)for(int x=0;x<14;x++)print_tile(&FPGA,x,y);
+ return 0;
+}