// // Author: Wolfgang Spraul // // This is free and unencumbered software released into the public domain. // For details see the UNLICENSE file at the root of the source tree. // #include #include #include "model.h" void printf_stdout(const char* fmt, ...) { va_list arg_list; va_start(arg_list, fmt); vfprintf(stdout, fmt, arg_list); va_end(arg_list); } void printf_stderr(const char* fmt, ...) { va_list arg_list; va_start(arg_list, fmt); vfprintf(stderr, fmt, arg_list); va_end(arg_list); } const char *bitstr(uint32_t value, int digits) { static char str[2 /* "0b" */ + 32 + 1 /* '\0' */]; int i; str[0] = '0'; str[1] = 'b'; for (i = 0; i < digits; i++) str[digits-i+1] = (value & (1< 15) indent = 15; for (i = 0; i < indent; i++) indent_str[i] = ' '; indent_str[i] = 0; i = 0; if (len <= 0x100) fmt_str[5] = '2'; else if (len <= 0x10000) fmt_str[5] = '4'; else fmt_str[5] = '6'; while (i < len) { printf(fmt_str, indent_str, i); for (j = 0; (j < 8) && (i + j < len); j++) { if (i + j >= len) break; if (base == 16) printf(" %02x", data[i+j]); else if (base == 2) { printf(" "); for (k = 0; k < 8; k++) printf(data[i+j] & (1<<(7-k)) ? "1" : "0"); } else { printf(" #E"); break; } } printf("\n"); i += 8; } } // returns a 16-bit word (0:15) plus 2 bits parity in bits 16 & 17 static int get_ramb_word_with_parity(const void *d, int word_idx, int clear_bits) { int w, i, bit_pos, bit_mask; w = 0; for (i = 0; i < 16; i++) { bit_pos = word_idx * 18 + 2 + 15-i; bit_mask = 1<<((7-(bit_pos%8))); if (((uint8_t *)d)[bit_pos/8] & bit_mask) w |= 1<> 8)); \ } uint32_t __swab32(uint32_t x) { return (((x & 0x000000ffUL) << 24) | \ ((x & 0x0000ff00UL) << 8) | \ ((x & 0x00ff0000UL) >> 8) | \ ((x & 0xff000000UL) >> 24)); \ } static int bool_nextlen(const char *expr, int len) { int i, depth; if (!len) return -1; i = 0; if (expr[i] == '~') { i++; if (i >= len) return -1; } if (expr[i] == '(') { if (i+2 >= len) return -1; i++; for (depth = 1; depth && i < len; i++) { if (expr[i] == '(') depth++; else if (expr[i] == ')') depth--; } if (depth) return -1; return i; } if (expr[i] == 'A') { i++; if (i >= len) return -1; if (expr[i] < '1' || expr[i] > '6') return -1; return i+1; } if (expr[i] == '0' || expr[i] == '1') return i+1; return -1; } // + or, * and, @ xor, ~ not // var must point to array of A1..A6 variables static int bool_eval(const char *expr, int len, const int *var) { int i, negate, result, oplen; if (len == 1) { if (*expr == '1') return 1; if (*expr == '0') return 0; } oplen = bool_nextlen(expr, len); if (oplen < 1) goto fail; i = 0; negate = 0; if (expr[i] == '~') { negate = 1; if (++i >= oplen) goto fail; } if (expr[i] == '(') { if (i+2 >= oplen) goto fail; result = bool_eval(&expr[i+1], oplen-i-2, var); if (result == -1) goto fail; } else if (expr[i] == 'A') { if (i+1 >= oplen) goto fail; if (expr[i+1] < '1' || expr[i+1] > '6') goto fail; result = var[expr[i+1]-'1']; if (oplen != i+2) goto fail; } else goto fail; if (negate) result = !result; i = oplen; while (i < len) { if (expr[i] == '+') { if (result) return 1; return bool_eval(&expr[i+1], len-i-1, var); } if (expr[i] == '@') { int right_side = bool_eval(&expr[i+1], len-i-1, var); if (right_side == -1) goto fail; return (result && !right_side) || (!result && right_side); } if (expr[i] != '*') goto fail; if (!result) break; if (++i >= len) goto fail; oplen = bool_nextlen(&expr[i], len-i); if (oplen < 1) goto fail; result = bool_eval(&expr[i], oplen, var); if (result == -1) goto fail; i += oplen; } return result; fail: return -1; } uint64_t map_bits(uint64_t u64, int num_bits, int *src_pos) { uint64_t result; int i; result = 0; for (i = 0; i < num_bits; i++) { if (u64 & (1ULL<<(src_pos[i]))) result |= 1ULL<= mt_size[round]) { mt[round][mt_size[round]].a[0] = new_term[0]; mt[round][mt_size[round]].a[1] = new_term[1]; mt[round][mt_size[round]].a[2] = new_term[2]; mt[round][mt_size[round]].a[3] = new_term[3]; mt[round][mt_size[round]].a[4] = new_term[4]; mt[round][mt_size[round]].a[5] = new_term[5]; mt_size[round]++; } mt[round-1][i].merged = 1; mt[round-1][j].merged = 1; } } } } str_end = 0; for (round = 0; round < 7; round++) { for (i = 0; i < mt_size[round]; i++) { if (!mt[round][i].merged) { if (str_end) str[str_end++] = '+'; first_op = 1; for (j = 0; j < bit_width; j++) { if (mt[round][i].a[j] != 2) { if (!first_op) str[str_end++] = '*'; if (!mt[round][i].a[j]) str[str_end++] = '~'; str[str_end++] = 'A'; str[str_end++] = '1' + j; first_op = 0; } } } } } str[str_end] = 0; // TODO: This could be further simplified, see Petrick's method. // XOR don't simplify well, try A2@A3 return str; } int bool_req_pins(uint64_t u64, int num_bits) { static const uint64_t pin_mask[6] = { 0xAAAAAAAAAAAAAAAA, /*A1*/ 0xCCCCCCCCCCCCCCCC, /*A2*/ 0xF0F0F0F0F0F0F0F0, /*A3*/ 0xFF00FF00FF00FF00, /*A4*/ 0xFFFF0000FFFF0000, /*A5*/ 0xFFFFFFFF00000000 /*A6*/ }; uint64_t bit_mask; int req_pins, num_pins, i; if (num_bits == 32) { num_pins = 5; bit_mask = 0x00000000FFFFFFFF; } else { if (num_bits != 64) HERE(); num_pins = 6; bit_mask = 0xFFFFFFFFFFFFFFFF; } // Special cases of all bits 0 and all bits 1 will // correctly lead to req_pins == 0 because all bits // are the same. req_pins = 0; for (i = 0; i < num_pins; i++) { if ((u64 & pin_mask[i] & bit_mask) >> (1<data, &init->parity); } int is_empty(const uint8_t *d, int l) { while (--l >= 0) if (d[l]) return 0; return 1; } int count_set_bits(const uint8_t *d, int l) { int bits = 0; while (--l >= 0) { if (d[l] & 0x01) bits++; if (d[l] & 0x02) bits++; if (d[l] & 0x04) bits++; if (d[l] & 0x08) bits++; if (d[l] & 0x10) bits++; if (d[l] & 0x20) bits++; if (d[l] & 0x40) bits++; if (d[l] & 0x80) bits++; } return bits; } int frame_get_bit(const uint8_t *frame_d, int bit) { uint8_t v = 1<<(7-(bit%8)); return (frame_d[(bit/16)*2 + !((bit/8)%2)] & v) != 0; } void frame_clear_bit(uint8_t *frame_d, int bit) { uint8_t v = 1<<(7-(bit%8)); frame_d[(bit/16)*2 + !((bit/8)%2)] &= ~v; } void frame_set_bit(uint8_t *frame_d, int bit) { uint8_t v = 1<<(7-(bit%8)); frame_d[(bit/16)*2 + !((bit/8)%2)] |= v; } int frame_get_cpuword(const void *bits) { return mirror_2bytes(frame_get_pinword(bits)); } void frame_set_cpuword(void *bits, int v) { frame_set_pinword(bits, mirror_2bytes(v)); } // see ug380, table 2-5, bit ordering int frame_get_pinword(const void *bits) { int byte0, byte1; byte0 = ((uint8_t*)bits)[0]; byte1 = ((uint8_t*)bits)[1]; return byte0 << 8 | byte1; } void frame_set_pinword(void *bits, int v) { ((uint8_t*)bits)[0] = v >> 8; ((uint8_t*)bits)[1] = v & 0xFF; } uint8_t mirror_bits(uint8_t v) { uint8_t mv = 0; int i; for (i = 0; i < 8; i++) if (v & (1<> 8)) << 8 | mirror_bits(v & 0xFF); } // see ug380, table 2-5, bit ordering uint16_t frame_get_u16(const uint8_t *frame_d) { uint16_t high_b, low_b; high_b = mirror_bits(frame_d[0]); low_b = mirror_bits(frame_d[1]); return (high_b << 8) | low_b; } static uint32_t frame_get_u32(const uint8_t *frame_d) { uint32_t high_w, low_w; low_w = frame_get_u16(frame_d); high_w = frame_get_u16(frame_d+2); return (high_w << 16) | low_w; } uint64_t frame_get_u64(const uint8_t *frame_d) { uint64_t high_w, low_w; low_w = frame_get_u32(frame_d); high_w = frame_get_u32(frame_d+4); return (high_w << 32) | low_w; } void frame_set_u16(uint8_t *frame_d, uint16_t v) { uint16_t high_b, low_b; high_b = v >> 8; low_b = v & 0xFF; frame_d[0] = mirror_bits(high_b); frame_d[1] = mirror_bits(low_b); } static void frame_set_u32(uint8_t* frame_d, uint32_t v) { uint32_t high_w, low_w; high_w = v >> 16; low_w = v & 0xFFFF; frame_set_u16(frame_d, low_w); frame_set_u16(frame_d+2, high_w); } void frame_set_u64(uint8_t* frame_d, uint64_t v) { uint32_t high_w, low_w; low_w = v & 0xFFFFFFFF; high_w = v >> 32; frame_set_u32(frame_d, low_w); frame_set_u32(frame_d+4, high_w); } uint64_t frame_get_lut64(int lut_pos, const uint8_t *two_minors, int v16) { int off_in_frame, lutw_tl, lutw_tr, lutw_bl, lutw_br; off_in_frame = v16*XC6_WORD_BYTES; if (off_in_frame >= XC6_HCLK_POS) off_in_frame += XC6_HCLK_BYTES; lutw_tl = frame_get_pinword(two_minors + off_in_frame); lutw_tr = frame_get_pinword(two_minors + FRAME_SIZE + off_in_frame); lutw_bl = frame_get_pinword(two_minors + off_in_frame + XC6_WORD_BYTES); lutw_br = frame_get_pinword(two_minors + FRAME_SIZE + off_in_frame + XC6_WORD_BYTES); return xc6_lut_value(lut_pos, lutw_tl, lutw_tr, lutw_bl, lutw_br); } void frame_set_lut64(uint8_t* two_minors, int v32, uint64_t v) { int off_in_frame, i; uint32_t m0, m1; m0 = 0; m1 = 0; for (i = 0; i < 64; i++) { if (v & (1ULL << i)) { if (i%2) m1 |= 1<<(i/2); else m0 |= 1<<(i/2); } } off_in_frame = v32*4; if (off_in_frame >= 64) off_in_frame += XC6_HCLK_BYTES; frame_set_u32(&two_minors[off_in_frame], m0); frame_set_u32(&two_minors[FRAME_SIZE + off_in_frame], m1); } // see ug380, table 2-5, bit ordering static int xc6_bit2pin(int bit) { int pin = bit % XC6_WORD_BITS; if (pin >= 8) return 15-(pin-8); return 7-pin; } int printf_frames(const uint8_t* bits, int max_frames, int row, int major, int minor, int print_empty, int no_clock) { int i, i_without_clk; char prefix[128], suffix[128]; if (row < 0) sprintf(prefix, "f%i ", abs(row)); else sprintf(prefix, "r%i ma%i mi%i ", row, major, minor); if (is_empty(bits, 130)) { for (i = 1; i < max_frames; i++) { if (!is_empty(&bits[i*130], 130)) break; } if (print_empty) { if (i > 1) printf("%s- *%i\n", prefix, i); else printf("%s-\n", prefix); } return i; } // value 128 chosen randomly for readability to decide // between printing individual bits or a hex block. if (count_set_bits(bits, 130) <= 128) { for (i = 0; i < FRAME_SIZE*8; i++) { if (!frame_get_bit(bits, i)) continue; if (i >= 512 && i < 528) { // hclk if (!no_clock) printf("%sbit %i\n", prefix, i); continue; } i_without_clk = i; if (i_without_clk >= 528) i_without_clk -= 16; snprintf(suffix, sizeof(suffix), "64*%i+%i 256*%i+%i pin %i", i_without_clk/64, i_without_clk%64, i_without_clk/256, i_without_clk%256, xc6_bit2pin(i_without_clk)); printf("%sbit %i %s\n", prefix, i, suffix); } return 1; } printf("%shex\n", prefix); printf("{\n"); dump_data(1, bits, /*len*/ FRAME_SIZE, /*base*/ 16); printf("}\n"); return 1; } void printf_clock(const uint8_t* frame, int row, int major, int minor) { int i; for (i = 0; i < 16; i++) { if (frame_get_bit(frame, 512 + i)) printf("r%i ma%i mi%i clock %i pin %i\n", row, major, minor, i, xc6_bit2pin(i)); } } int clb_empty(uint8_t* maj_bits, int idx) { int byte_off, i, minor; byte_off = idx * 8; if (idx >= 8) byte_off += 2; for (i = 0; i < 16; i++) { for (minor = 20; minor < 31; minor++) { if (!is_empty(&maj_bits[minor*130 + byte_off], 8)) return 0; } } return 1; } void printf_extrabits(const uint8_t* maj_bits, int start_minor, int num_minors, int start_bit, int num_bits, int row, int major) { int minor, bit, bit_no_clk; for (minor = start_minor; minor < start_minor + num_minors; minor++) { for (bit = start_bit; bit < start_bit + num_bits; bit++) { if (frame_get_bit(&maj_bits[minor*FRAME_SIZE], bit)) { bit_no_clk = bit; if (bit_no_clk >= 528) bit_no_clk -= XC6_HCLK_BITS; printf("r%i ma%i mi%i bit %i 64*%i+%i 256*%i+%i\n", row, major, minor, bit, bit_no_clk/64, bit_no_clk%64, bit_no_clk/256, bit_no_clk%256); } } } } void write_lut64(uint8_t* two_minors, int off_in_frame, uint64_t u64) { int i; for (i = 0; i < 16; i++) { if (u64 & (1LL << (i*4))) frame_set_bit(two_minors, off_in_frame+i*2); if (u64 & (1LL << (i*4+1))) frame_set_bit(two_minors, off_in_frame+(i*2)+1); if (u64 & (1LL << (i*4+2))) frame_set_bit(two_minors + FRAME_SIZE, off_in_frame+i*2); if (u64 & (1LL << (i*4+3))) frame_set_bit(two_minors + FRAME_SIZE, off_in_frame+(i*2)+1); } } void printf_routing_2minors(const uint8_t* bits, int row, int major, int even_minor) { int y, i, hclk; uint64_t u64_0, u64_1; char bit_str[129]; bit_str[128] = 0; for (y = 0; y < 16; y++) { hclk = (y < 8) ? 0 : 2; u64_0 = frame_get_u64(bits + y*8 + hclk); u64_1 = frame_get_u64(bits + y*8 + hclk + FRAME_SIZE); if (u64_0 || u64_1) { for (i = 0; i < 128; i++) bit_str[i] = '0'; for (i = 0; i < 64; i++) { if (u64_0 & (1ULL << i)) bit_str[i*2] = '1'; if (u64_1 & (1ULL << i)) bit_str[i*2+1] = '1'; } // todo: might be nice to add the tile y and x here printf("r%i ma%i v64_%i mip%i %s\n", row, major, y, even_minor, bit_str); } } } void printf_v64_mi20(const uint8_t* bits, int row, int major) { int y, i, num_bits_on, hclk; uint64_t u64; char bit_str[65]; bit_str[64] = 0; for (y = 0; y < 16; y++) { hclk = (y < 8) ? 0 : 2; u64 = frame_get_u64(bits + y*8 + hclk); if (u64) { for (i = 0; i < 64; i++) bit_str[i] = (u64 & (1ULL << i)) ? '1' : '0'; printf("r%i ma%i v64_%i mi20 %s\n", row, major, y, bit_str); num_bits_on = 0; for (i = 0; i < 64; i++) { if (u64 & (1ULL << i)) num_bits_on++; } // this is most helpful for bits 24:39 which are // part of logic device configuration if (num_bits_on < 5) { for (i = 0; i < 64; i++) { if (!(u64 & (1ULL << i))) continue; printf("r%i ma%i v64_%i mi20 b%i\n", row, major, y, i); } } } } } const char *fmt_word(int word) { enum { NUM_BUFS = 16, BUF_SIZE = 64 }; static char buf[NUM_BUFS][BUF_SIZE]; static int last_buf = 0; char bit_str[XC6_WORD_BITS]; int i; last_buf = (last_buf+1)%NUM_BUFS; for (i = 0; i < XC6_WORD_BITS; i++) bit_str[i] = (word & (1ULL << (XC6_WORD_BITS-i-1))) ? '1' : '0'; snprintf(buf[last_buf], sizeof(*buf), "0b%.*s 0x%.*X", XC6_WORD_BITS, bit_str, XC6_WORD_BITS/4, word); for (i = 0; i < XC6_WORD_BITS; i++) { if (word & (1 << i)) sprintf(&buf[last_buf][strlen(buf[last_buf])], " %i", i); else sprintf(&buf[last_buf][strlen(buf[last_buf])], i < 10 ? " " : " "); } strcat(buf[last_buf], "\n"); return buf[last_buf]; } void printf_lut_words(const uint8_t *major_bits, int row, int major, int minor, int v16_i) { int off_in_frame, w; off_in_frame = v16_i*XC6_WORD_BYTES; if (off_in_frame >= XC6_HCLK_POS) off_in_frame += XC6_HCLK_BYTES; w = frame_get_pinword(&major_bits[minor*FRAME_SIZE + off_in_frame]); if (w) printf("r%i ma%i v%i_%i mi%i pin %s", row, major, XC6_WORD_BITS, v16_i, minor, fmt_word(w)); w = frame_get_pinword(&major_bits[minor*FRAME_SIZE + off_in_frame + XC6_WORD_BYTES]); if (w) printf("r%i ma%i v%i_%i mi%i pin %s", row, major, XC6_WORD_BITS, v16_i+1, minor, fmt_word(w)); w = frame_get_pinword(&major_bits[(minor+1)*FRAME_SIZE + off_in_frame]); if (w) printf("r%i ma%i v%i_%i mi%i pin %s", row, major, XC6_WORD_BITS, v16_i, minor+1, fmt_word(w)); w = frame_get_pinword(&major_bits[(minor+1)*FRAME_SIZE + off_in_frame + XC6_WORD_BYTES]); if (w) printf("r%i ma%i v%i_%i mi%i pin %s", row, major, XC6_WORD_BITS, v16_i+1, minor+1, fmt_word(w)); } int get_vm_mb(void) { FILE* statusf = fopen("/proc/self/status", "r"); char line[1024]; int vm_size = 0; while (fgets(line, sizeof(line), statusf)) { if (sscanf(line, "VmSize: %i kB", &vm_size) == 1) break; } fclose(statusf); if (!vm_size) return 0; return (vm_size+1023)/1024; } int get_random(void) { int random_f, random_num; random_f = open("/dev/urandom", O_RDONLY); read(random_f, &random_num, sizeof(random_num)); close(random_f); return random_num; } int compare_with_number(const char* a, const char* b) { int i, a_i, b_i, non_numeric_result, a_num, b_num; for (i = 0; a[i] && (a[i] == b[i]); i++); if (a[i] == b[i]) { if (a[i]) fprintf(stderr, "Internal error in line %i\n", __LINE__); return 0; } non_numeric_result = a[i] - b[i]; // go back to beginning of numeric section while (i && a[i-1] >= '0' && a[i-1] <= '9') i--; // go forward to first non-digit for (a_i = i; a[a_i] >= '0' && a[a_i] <= '9'; a_i++ ); for (b_i = i; b[b_i] >= '0' && b[b_i] <= '9'; b_i++ ); // There must be at least one digit in both a and b // and the suffix must match. if (a_i <= i || b_i <= i || strcmp(&a[a_i], &b[b_i])) return non_numeric_result; a_num = strtol(&a[i], 0 /* endptr */, 10); b_num = strtol(&b[i], 0 /* endptr */, 10); return a_num - b_num; } void next_word(const char*s, int start, int* beg, int* end) { int i = start; while (s[i] == ' ' || s[i] == '\t' || s[i] == '\n') i++; *beg = i; while (s[i] != ' ' && s[i] != '\t' && s[i] != '\n' && s[i]) i++; *end = i; } int str_cmp(const char* a, int a_len, const char* b, int b_len) { int i = 0; if (a_len == -1) { a_len = 0; while (a[a_len]) a_len++; } if (b_len == -1) { b_len = 0; while (b[b_len]) b_len++; } while (1) { if (i >= a_len) { if (i >= b_len) return 0; return -1; } if (i >= b_len) { if (i >= a_len) return 0; return 1; } if (a[i] != b[i]) return a[i] - b[i]; i++; } } int all_digits(const char* a, int len) { int i; if (!len) return 0; for (i = 0; i < len; i++) { if (a[i] < '0' || a[i] > '9') return 0; } return 1; } int to_i(const char* s, int len) { int num, base; for (base = 1, num = 0; len; num += base*(s[--len]-'0'), base *= 10); return num; } int mod4_calc(int a, int b) { return (unsigned int) (a+b)%4; } int all_zero(const void* d, int num_bytes) { int i; for (i = 0; i < num_bytes; i++) if (((uint8_t*)d)[i]) return 0; return 1; } void printf_wrap(FILE* f, char* line, int prefix_len, const char* fmt, ...) { va_list list; int i; va_start(list, fmt); i = strlen(line); if (i >= 80) { line[i] = '\n'; line[i+1] = 0; fprintf(f, "%s", line); line[prefix_len] = 0; i = prefix_len; } line[i] = ' '; vsnprintf(&line[i+1], 256, fmt, list); va_end(list); } // Dan Bernstein's hash function uint32_t hash_djb2(const unsigned char* str) { uint32_t hash = 5381; int c; while ((c = *str++) != 0) hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ return hash; } // // The format of each entry in a bin is. // uint32_t idx // uint16_t entry len including 4-byte header // char[] zero-terminated string // // Offsets point to the zero-terminated string, so the len // is at off-2, the index at off-6. offset0 can thus be // used as a special value to signal 'no entry'. // #define BIN_STR_HEADER (4+2) #define BIN_MIN_OFFSET BIN_STR_HEADER #define BIN_INCREMENT 32768 const char* strarray_lookup(struct hashed_strarray* array, int idx) { int bin, offset; if (!array->index_to_bin || !array->bin_offsets || idx==STRIDX_NO_ENTRY) return 0; bin = array->index_to_bin[idx-1]; offset = array->bin_offsets[idx-1]; // bin 0 offset 0 is a special value that signals 'no // entry'. Normal offsets cannot be less than BIN_MIN_OFFSET. if (!bin && !offset) return 0; if (!array->bin_strings[bin] || offset >= array->bin_len[bin] || offset < BIN_MIN_OFFSET) { // This really should never happen and is an internal error. fprintf(stderr, "Internal error.\n"); return 0; } return &array->bin_strings[bin][offset]; } int strarray_find(struct hashed_strarray* array, const char* str) { int bin, search_off, i; uint32_t hash; hash = hash_djb2((const unsigned char*) str); bin = hash % array->num_bins; // iterate over strings in bin to find match if (array->bin_strings[bin]) { search_off = BIN_MIN_OFFSET; while (search_off < array->bin_len[bin]) { if (!strcmp(&array->bin_strings[bin][search_off], str)) { i = *(uint32_t*)&array->bin_strings[bin][search_off-6]; if (!i) { fprintf(stderr, "Internal error - index 0.\n"); return STRIDX_NO_ENTRY; } return i+1; } search_off += *(uint16_t*)&array->bin_strings[bin][search_off-2]; } } return STRIDX_NO_ENTRY; } int s_stash_at_bin(struct hashed_strarray* array, const char* str, int idx, int bin); int strarray_add(struct hashed_strarray* array, const char* str, int* idx) { int bin, i, free_index, rc, start_index; unsigned long hash; *idx = strarray_find(array, str); if (*idx != STRIDX_NO_ENTRY) return 0; hash = hash_djb2((const unsigned char*) str); // search free index start_index = hash % array->highest_index; for (i = 0; i < array->highest_index; i++) { int cur_i = (start_index+i)%array->highest_index; if (!cur_i) // never issue index 0 continue; if (!array->bin_offsets[cur_i]) break; } if (i >= array->highest_index) { fprintf(stderr, "All array indices full.\n"); return -1; } free_index = (start_index+i)%array->highest_index; bin = hash % array->num_bins; rc = s_stash_at_bin(array, str, free_index, bin); if (rc) return rc; *idx = free_index + 1; return 0; } int s_stash_at_bin(struct hashed_strarray* array, const char* str, int idx, int bin) { int str_len = strlen(str); // check whether bin needs expansion if (!(array->bin_len[bin]%BIN_INCREMENT) || array->bin_len[bin]%BIN_INCREMENT + BIN_STR_HEADER+str_len+1 > BIN_INCREMENT) { int new_alloclen; void* new_ptr; new_alloclen = ((array->bin_len[bin] + BIN_STR_HEADER+str_len+1)/BIN_INCREMENT + 1) * BIN_INCREMENT; new_ptr = realloc(array->bin_strings[bin], new_alloclen); if (!new_ptr) { fprintf(stderr, "Out of memory.\n"); return -1; } if (new_alloclen > array->bin_len[bin]) memset(new_ptr+array->bin_len[bin], 0, new_alloclen-array->bin_len[bin]); array->bin_strings[bin] = new_ptr; } // append new string at end of bin *(uint32_t*)&array->bin_strings[bin][array->bin_len[bin]] = idx; *(uint16_t*)&array->bin_strings[bin][array->bin_len[bin]+4] = BIN_STR_HEADER+str_len+1; strcpy(&array->bin_strings[bin][array->bin_len[bin]+BIN_STR_HEADER], str); array->index_to_bin[idx] = bin; array->bin_offsets[idx] = array->bin_len[bin]+BIN_STR_HEADER; array->bin_len[bin] += BIN_STR_HEADER+str_len+1; return 0; } int strarray_stash(struct hashed_strarray* array, const char* str, int idx) { // The bin is just a random number here, because find // cannot be used after stash anyway, only lookup can. return s_stash_at_bin(array, str, idx-1, idx % array->num_bins); } int strarray_used_slots(struct hashed_strarray* array) { int i, num_used_slots; num_used_slots = 0; if (!array->bin_offsets) return 0; for (i = 0; i < array->highest_index; i++) { if (array->bin_offsets[i]) num_used_slots++; } return num_used_slots; } int strarray_init(struct hashed_strarray* array, int highest_index) { memset(array, 0, sizeof(*array)); array->highest_index = highest_index; array->num_bins = highest_index / 64; array->bin_strings = calloc(array->num_bins,sizeof(*array->bin_strings)); array->bin_len = calloc(array->num_bins,sizeof(*array->bin_len)); array->bin_offsets = calloc(array->highest_index,sizeof(*array->bin_offsets)); array->index_to_bin = calloc(array->highest_index,sizeof(*array->index_to_bin)); if (!array->bin_strings || !array->bin_len || !array->bin_offsets || !array->index_to_bin) { fprintf(stderr, "Out of memory in %s:%i\n", __FILE__, __LINE__); free(array->bin_strings); free(array->bin_len); free(array->bin_offsets); free(array->index_to_bin); return -1; } return 0; } void strarray_free(struct hashed_strarray* array) { int i; for (i = 0; i < sizeof(array->bin_strings)/ sizeof(array->bin_strings[0]); i++) { free(array->bin_strings[i]); array->bin_strings[i] = 0; } free(array->bin_strings); array->bin_strings = 0; free(array->bin_len); array->bin_len = 0; free(array->bin_offsets); array->bin_offsets = 0; free(array->index_to_bin); array->index_to_bin = 0; } int row_pos_to_y(int num_rows, int row, int pos) { int y; if (row >= num_rows) { HERE(); return -1; } y = TOP_IO_TILES; if (row < num_rows/2) y++; // below center y += num_rows - row - 1; // hclk in full rows from top if (pos >= HALF_ROW) y++; // hclk in row return y; } int cmdline_help(int argc, char **argv) { int i; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "--help")) { printf( "\n" "%s floorplan\n" "\n" "Usage: %s [--part=xc6slx9]\n" " %*s [--package=tqg144|ftg256]\n" " %*s [--help]\n", *argv, *argv, (int) strlen(*argv), "", (int) strlen(*argv), ""); return 1; } } return 0; } int cmdline_part(int argc, char **argv) { int i; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "--part=xc6slx9")) return XC6SLX9; } return XC6SLX9; } int cmdline_package(int argc, char **argv) { int i; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "--package=tqg144")) return TQG144; if (!strcmp(argv[i], "--package=ftg256")) return FTG256; } return FTG256; } const char *cmdline_strvar(int argc, char **argv, const char *var) { enum { NUM_BUFS = 32, BUF_SIZE = 256 }; static char buf[NUM_BUFS][BUF_SIZE]; static int last_buf = 0; char scan_str[128]; int i, next_buf; next_buf = (last_buf+1)%NUM_BUFS; snprintf(scan_str, sizeof(scan_str), "-D%s=%%s", var); for (i = 1; i < argc; i++) { if (sscanf(argv[i], scan_str, buf[next_buf]) == 1) { last_buf = next_buf; return buf[last_buf]; } } return 0; } int cmdline_intvar(int argc, char **argv, const char *var) { char buf[128]; int i, out_int; snprintf(buf, sizeof(buf), "-D%s=%%i", var); for (i = 1; i < argc; i++) { if (sscanf(argv[i], buf, &out_int) == 1) return out_int; } return 0; }