diff --git a/LINKS b/LINKS index db5e8de..3657df9 100644 --- a/LINKS +++ b/LINKS @@ -13,8 +13,54 @@ Andrew's redtin logic analyzer gtkwave wave viewer http://gtkwave.sourceforge.net +cores + https://github.com/openrisc/mor1kx + https://github.com/milkymist + Fedora Electronic Lab tool overview http://spins.fedoraproject.org/fel/#portfolio http://chitlesh.fedorapeople.org/FEL/list.html with links to magic, toped, qucs, iverilog, alliance, etc. + +chip makers + www.xilinx.com FPGA + www.altera.com FPGA + Murata + Peregrine + TriQuint + Maxim + Avago + Skyworks + Analog Devices + +standards + IEEE 1149.1 Boundary Scan/JTAG + IEEE 1532 Configuration and Programming + + http://www.xilinx.com/products/design_resources/config_sol/isp_standards_specs.htm + +materials + www.injectorall.com photoresist + www.dudadiesel.com NaOH, KOH + www.mtixtl.com individual 6'' wafers + www.unitednuclear.com + www.tedpella.com/gold_html/Nanotubes.htm + Carbon Nanotubes + www.tubedevices.com/alek/pwl/pwl_e.htm + Private Tube Manufacture-PWL vacuum tubes + +wafer makers + www.oci.co.kr/eng/ OCI (South Korea) + www.gcl-poly.com GCL-Poly (China) + www.hscpoly.com Hemlock (USA) + www.wacker.com/cms/de/wacker_group/divisions/polysilicon/polysilicon.jsp + Wacker (EU) + +semiconductor supplies + www.asml.com lithography systems + www.kns.com assembly equipment + +foundries + http://cmp.imag.fr/products/ic/?p=prices CMP + www.lfoundry.com analog and mixed signal diff --git a/Makefile b/Makefile index 2502d5f..1aed6d1 100644 --- a/Makefile +++ b/Makefile @@ -82,7 +82,7 @@ libs/%.so: FAKE test_dirs := $(shell mkdir -p test.gold test.out) DESIGN_TESTS := hello_world blinking_led -AUTO_TESTS := logic_cfg routing_sw io_sw iob_cfg +AUTO_TESTS := logic_cfg routing_sw io_sw iob_cfg lut_encoding COMPARE_TESTS := xc6slx9_tiles xc6slx9_devs xc6slx9_ports xc6slx9_conns xc6slx9_sw xc6slx9_swbits DESIGN_GOLD := $(foreach target, $(DESIGN_TESTS), test.gold/design_$(target).fp) diff --git a/autotest.c b/autotest.c index ff0e0db..e5adffd 100644 --- a/autotest.c +++ b/autotest.c @@ -1093,12 +1093,12 @@ fail: static int test_lut_encoding(struct test_state* tstate) { int idx_enum[] = { DEV_LOG_M_OR_L, DEV_LOG_X }; - int x_enum[] = { /*xm*/ 13, /* center-xl*/ 22, /*xl*/ 39 }; - int y, x_i, i, j, k, lut_str_len, rc; + // The center column (x==22 on a xc6slx9) is a regular XL column + // for the lut encoding, so it doesn't need separate testing. + int x_enum[] = { /*xm*/ 13, /*xl*/ 39 }; + int y, x_i, i, j, lut_str_len, rc; int type_i, lut; char lut_str[128]; - const char* lut5_parents[] = {"(A6+~A6)*1", "(A6+~A6)*0", - "(A6+~A6)*A1", "(A6+~A6)*A3", 0}; tstate->diff_to_null = 1; @@ -1135,36 +1135,35 @@ static int test_lut_encoding(struct test_state* tstate) if (rc) FAIL(rc); } // lut6 and lut5 pairs - i = 0; - while (lut5_parents[i]) { + rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i], + lut, /*lut6*/ "(A6+~A6)*1", /*lut5*/ "0"); + if (rc) FAIL(rc); + rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i], + lut, /*lut6*/ "(A6+~A6)*0", /*lut5*/ "1"); + if (rc) FAIL(rc); + for (i = '1'; i <= '5'; i++) { + snprintf(lut_str, sizeof(lut_str), "A%c", i); rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i], - lut, /*lut6*/ lut5_parents[i], /*lut5*/ "0"); + lut, + /*lut6*/ pf("(A6+~A6)*%s", lut_str), + /*lut5*/ lut_str); if (rc) FAIL(rc); + } + for (i = 0; i < 32; i++) { + lut_str_len = 0; + for (j = 0; j < 5; j++) { + if (lut_str_len) + lut_str[lut_str_len++] = '*'; + if (!(i & (1<&1 | tee autotest.log setvbuf(stdout, /*buf*/ 0, _IOLBF, /*size*/ 0); +#if 0 +int lut_map1[64] = {63,62,61,60,59,58,57,56,55,54,53,52,51,50, + 49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31, + 30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10, + 9,8,7,6,5,4,3,2,1,0}; +//int bool_str2bits(const char* str, uint64_t* u64, int num_bits); +//const char* bool_bits2str(uint64_t u64, int num_bits); +{ + uint64_t u64, u64_2; + + rc = bool_str2bits("~A6*~A5*~A4*~A3*~A2*~A1", &u64, 64); + printf("rc %i u64 %llX 2str %s\n", rc, u64, bool_bits2str(u64, 64)); + rc = bool_str2bits("~A6*~A5*~A4*~A3*~A2*A1", &u64, 64); + printf("rc %i u64 %llX 2str %s\n", rc, u64, bool_bits2str(u64, 64)); + rc = bool_str2bits("A6*A5*A4*A3*A2*A1", &u64, 64); + printf("rc %i u64 %llX 2str %s\n", rc, u64, bool_bits2str(u64, 64)); + rc = bool_str2bits("A5*A4*A3*A2*A1", &u64, 32); + printf("rc %i u32 %llX 2str %s\n", rc, u64, bool_bits2str(u64, 32)); + rc = bool_str2bits("A4*A3", &u64, 32); + printf("rc %i u32 %llX 2str %s\n", rc, u64, bool_bits2str(u64, 32)); + rc = bool_str2bits("A1", &u64, 64); + printf("rc %i u64 %llX 2str %s\n", rc, u64, bool_bits2str(u64, 64)); + rc = bool_str2bits("A1", &u64, 32); + printf("rc %i u32 %llX 2str %s\n", rc, u64, bool_bits2str(u64, 32)); + + u64 = 1; + u64_2 = map_bits(u64, 64, lut_map1); + printf("u %llX mapped %llX\n", u64, u64_2); + + return 0; +} +#endif + if (argc < 2) { printf_help(argv[0], available_tests); return 0; diff --git a/libs/bit_regs.c b/libs/bit_regs.c index 5c20470..6e90280 100644 --- a/libs/bit_regs.c +++ b/libs/bit_regs.c @@ -764,32 +764,31 @@ static void printf_v64_mi20(const uint8_t* bits, int row, int major) static void printf_lut(const uint8_t* bits, int row, int major, int minor, int v32_i) { - int i, byte_off_in_frame; - uint32_t u32; - uint64_t u64; char bit_str[64]; + uint64_t u64; + int i, num_on_bits; - byte_off_in_frame = v32_i*4; - if (byte_off_in_frame >= 64) - byte_off_in_frame += XC6_HCLK_BYTES; - u64 = read_lut64(&bits[minor*FRAME_SIZE], byte_off_in_frame*8); + u64 = frame_get_lut64(&bits[minor*FRAME_SIZE], v32_i); if (u64) { - for (i = 0; i < 64; i++) - bit_str[i] = (u64 & (1ULL << i)) ? '1' : '0'; - printf("r%i ma%i v32_%02i mip%i_lut %.64s\n", row, - major, v32_i, minor, bit_str); - - u32 = frame_get_u32(&bits[minor*FRAME_SIZE + byte_off_in_frame]); - for (i = 0; i < 32; i++) - bit_str[i] = (u32 & (1 << i)) ? '1' : '0'; - printf("r%i ma%i v32_%02i mi%i_f32 %.32s\n", row, major, - v32_i, minor, bit_str); - - u32 = frame_get_u32(&bits[(minor+1)*FRAME_SIZE + byte_off_in_frame]); - for (i = 0; i < 32; i++) - bit_str[i] = (u32 & (1 << i)) ? '1' : '0'; - printf("r%i ma%i v32_%02i mi%i_f32 %.32s\n", row, major, - v32_i, minor+1, bit_str); + num_on_bits = 0; + for (i = 0; i < 64; i++) { + if (u64 & (1ULL << i)) + num_on_bits++; + } + if (num_on_bits < 5) { + printf("r%i ma%02i v32_%02i mip%02i_lut", row, + major, v32_i, minor); + for (i = 0; i < 64; i++) { + if (u64 & (1ULL << i)) + printf(" b%i", i); + } + printf("\n"); + } else { + for (i = 0; i < 64; i++) + bit_str[i] = (u64 & (1ULL << i)) ? '1' : '0'; + printf("r%i ma%02i v32_%02i mip%02i_lut %.64s\n", row, + major, v32_i, minor, bit_str); + } } } @@ -833,6 +832,8 @@ static int dump_maj_center(const uint8_t* bits, int row, int major) { int minor, i; + if (get_major_minors(XC6SLX9, major) != 31) HERE(); + for (minor = 0; minor < get_major_minors(XC6SLX9, major); minor++) printf_clock(&bits[minor*FRAME_SIZE], row, major, minor); @@ -850,10 +851,17 @@ static int dump_maj_center(const uint8_t* bits, int row, int major) printf_lut(bits, row, major, 21, i*2+1); printf_lut(bits, row, major, 23, i*2+1); } - - for (minor = 25; minor < get_major_minors(XC6SLX9, major); minor++) - printf_frames(&bits[minor*FRAME_SIZE], /*max_frames*/ 1, - row, major, minor, /*print_empty*/ 0, /*no_clock*/ 1); + printf_frames(&bits[25*FRAME_SIZE], /*max_frames*/ 1, + row, major, 25, /*print_empty*/ 0, /*no_clock*/ 1); + // X devices + for (i = 0; i < 16; i++) { + printf_lut(bits, row, major, 26, i*2); + printf_lut(bits, row, major, 28, i*2); + printf_lut(bits, row, major, 26, i*2+1); + printf_lut(bits, row, major, 28, i*2+1); + } + printf_frames(&bits[30*FRAME_SIZE], /*max_frames*/ 1, + row, major, 30, /*print_empty*/ 0, /*no_clock*/ 1); return 0; } @@ -861,6 +869,8 @@ static int dump_maj_logic_xm(const uint8_t* bits, int row, int major) { int minor, i; + if (get_major_minors(XC6SLX9, major) != 31) HERE(); + for (minor = 0; minor < get_major_minors(XC6SLX9, major); minor++) printf_clock(&bits[minor*FRAME_SIZE], row, major, minor); @@ -902,6 +912,8 @@ static int dump_maj_logic_xl(const uint8_t* bits, int row, int major) { int minor, i; + if (get_major_minors(XC6SLX9, major) != 30) HERE(); + for (minor = 0; minor < get_major_minors(XC6SLX9, major); minor++) printf_clock(&bits[minor*FRAME_SIZE], row, major, minor); @@ -919,10 +931,15 @@ static int dump_maj_logic_xl(const uint8_t* bits, int row, int major) printf_lut(bits, row, major, 21, i*2+1); printf_lut(bits, row, major, 23, i*2+1); } - - for (minor = 25; minor < get_major_minors(XC6SLX9, major); minor++) - printf_frames(&bits[minor*FRAME_SIZE], /*max_frames*/ 1, - row, major, minor, /*print_empty*/ 0, /*no_clock*/ 1); + printf_frames(&bits[25*FRAME_SIZE], /*max_frames*/ 1, + row, major, 25, /*print_empty*/ 0, /*no_clock*/ 1); + // X devices + for (i = 0; i < 16; i++) { + printf_lut(bits, row, major, 26, i*2); + printf_lut(bits, row, major, 28, i*2); + printf_lut(bits, row, major, 26, i*2+1); + printf_lut(bits, row, major, 28, i*2+1); + } return 0; } diff --git a/libs/control.c b/libs/control.c index 9feba55..8443df0 100644 --- a/libs/control.c +++ b/libs/control.c @@ -478,7 +478,6 @@ int fdev_logic_a2d_lut(struct fpga_model* model, int y, int x, int type_idx, // todo: the logic by which we auto-enable the direct // output could have more cases, the O6 signal // could go into the carry chain/XOR/CY, F7/F8, others? - // O5 could go into carry chain/XOR/CY, others? // We need to find out over time what makes sense for // the caller. if (lut_5or6 == 6 @@ -486,6 +485,7 @@ int fdev_logic_a2d_lut(struct fpga_model* model, int y, int x, int type_idx, && dev->u.logic.a2d[lut_a2d].out_mux != MUX_O6) dev->u.logic.a2d[lut_a2d].out_used = 1; if (lut_5or6 == 5 + && dev->u.logic.a2d[lut_a2d].cy0 != CY0_O5 && dev->u.logic.a2d[lut_a2d].ff_mux != MUX_O5 && !dev->u.logic.a2d[lut_a2d].out_mux) dev->u.logic.a2d[lut_a2d].out_mux = MUX_O5; diff --git a/libs/helper.c b/libs/helper.c index 536b1bb..f27cb44 100644 --- a/libs/helper.c +++ b/libs/helper.c @@ -6,6 +6,7 @@ // #include +#include #include "helper.h" #include "parts.h" @@ -177,6 +178,157 @@ fail: return -1; } +uint64_t map_bits(uint64_t u64, int num_bits, int* dest_pos) +{ + uint64_t result; + int i; + + result = 0; + for (i = 0; i < num_bits; i++) { + if (u64 & (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 parse_boolexpr(const char* expr, uint64_t* lut) { int i, j, result, vars[6]; @@ -198,36 +350,6 @@ int parse_boolexpr(const char* expr, uint64_t* lut) return 0; } -void printf_lut6(const char* cfg) -{ - uint64_t lut; - uint32_t first_major, second_major; - int i; - - first_major = 0; - second_major = 0; - // todo: this is missing the different base_values, flip_b0 etc. - parse_boolexpr(cfg, &lut); - - for (i = 0; i < 16; i++) { - if (lut & (1LL<<(i*4))) - first_major |= 1<<(i*2); - if (lut & (1LL<<(i*4+1))) - first_major |= 1<<(i*2+1); - if (lut & (1LL<<(i*4+2))) - second_major |= 1<<(i*2); - if (lut & (1LL<<(i*4+3))) - second_major |= 1<<(i*2+1); - } - printf("first_major 0x%X second_major 0x%X\n", first_major, second_major); -} - -typedef struct _minterm_entry -{ - char a[6]; // 0=A1, 5=A6. value can be 0, 1 or 2 for 'removed' - int merged; -} minterm_entry; - // bits is tested only for 32 and 64 const char* lut2bool(const uint64_t lut, int bits, int (*logic_base)[6], int flip_b0) @@ -574,6 +696,48 @@ void frame_set_u64(uint8_t* frame_d, uint64_t v) frame_set_u32(frame_d+4, high_w); } +uint64_t frame_get_lut64(const uint8_t* two_minors, int v32) +{ + int off_in_frame, i; + uint32_t m0, m1; + uint64_t lut64; + + off_in_frame = v32*4; + if (off_in_frame >= 64) + off_in_frame += XC6_HCLK_BYTES; + + m0 = frame_get_u32(&two_minors[off_in_frame]); + m1 = frame_get_u32(&two_minors[FRAME_SIZE + off_in_frame]); + lut64 = 0; + for (i = 0; i < 32; i++) { + if (m0 & (1<= 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); +} + int printf_frames(const uint8_t* bits, int max_frames, int row, int major, int minor, int print_empty, int no_clock) { diff --git a/libs/helper.h b/libs/helper.h index 99a16fe..4505679 100644 --- a/libs/helper.h +++ b/libs/helper.h @@ -57,8 +57,11 @@ typedef struct _cfg_atom int atom_found(char* bits, const cfg_atom_t* atom); void atom_remove(char* bits, const cfg_atom_t* atom); +uint64_t map_bits(uint64_t u64, int num_bits, int* dest_pos); +int bool_str2bits(const char* str, uint64_t* u64, int num_bits); +const char* bool_bits2str(uint64_t u64, int num_bits); + int parse_boolexpr(const char* expr, uint64_t* lut); -void printf_lut6(const char* cfg); // bits is tested only for 32 and 64 const char* lut2bool(const uint64_t lut, int bits, int (*logic_base)[6], int flip_b0); @@ -83,6 +86,12 @@ void frame_set_u16(uint8_t* frame_d, uint16_t v); void frame_set_u32(uint8_t* frame_d, uint32_t v); void frame_set_u64(uint8_t* frame_d, uint64_t v); +uint64_t frame_get_lut64(const uint8_t* two_minors, int v32); +// In a lut pair, LOW32 is lut5, HIGH32 is lut6. +#define ULL_LOW32(v) ((uint32_t) (((uint64_t)v) & 0xFFFFFFFFULL)) +#define ULL_HIGH32(v) ((uint32_t) (((uint64_t)v) >> 32)) +void frame_set_lut64(uint8_t* two_minors, int v32, uint64_t v); + // if row is negative, it's an absolute frame number and major and // minor are ignored int printf_frames(const uint8_t* bits, int max_frames, int row, int major, diff --git a/libs/parts.c b/libs/parts.c index 6fffb12..5c330ed 100644 --- a/libs/parts.c +++ b/libs/parts.c @@ -809,3 +809,42 @@ void free_xc6_routing_bitpos(struct xc6_routing_bitpos* bitpos) { free(bitpos); } + +void xc6_lut_bitmap(int lut_pos, int* map, int num_bits) +{ + static const int xc6_lut_wiring[4][16] = { + // xm-m a; xm-m c; + { 17, 19, 16, 18, 23, 21, 22, 20, 31, 29, 30, 28, 25, 27, 24, 26 }, + // xm-m b; xm-m d; + { 47, 45, 46, 44, 41, 43, 40, 42, 33, 35, 32, 34, 39, 37, 38, 36 }, + // xm-x a; xm-x b; xl-l b; xl-l d; xl-x a; xl-x b; + { 31, 29, 30, 28, 27, 25, 26, 24, 19, 17, 18, 16, 23, 21, 22, 20 }, + // xm-x c; xm-x d; xl-l a; xl-l c; xl-x c; xl-x d; + { 33, 35, 32, 34, 37, 39, 36, 38, 45, 47, 44, 46, 41, 43, 40, 42 }}; + + int map32[32]; + int i; + + // expand from 16 to 32 bit positions + for (i = 0; i < 16; i++) { + map32[i] = xc6_lut_wiring[lut_pos][i]; + if (map32[i] < 32) { + if (map32[i] < 16) HERE(); + map32[16+i] = map32[i]-16; + } else { + if (map32[i] > 47) HERE(); + map32[16+i] = map32[i]+16; + } + } + // expand from 32 to 64 for either lut6 only or lut5/lut6 pair. + for (i = 0; i < 32; i++) { + if (num_bits == 32) { + map[i] = map32[i]%32; + map[32+i] = 32+map[i]; + } else { + if (num_bits != 64) HERE(); + map[i] = map32[i]; + map[32+i] = (map[i]+32)%64; + } + } +} diff --git a/libs/parts.h b/libs/parts.h index b0c70ce..ee20e5f 100644 --- a/libs/parts.h +++ b/libs/parts.h @@ -97,6 +97,8 @@ #define XC6_IOB_OUTPUT_LVCMOS12_DRIVE_8 0x0014000002000000 #define XC6_IOB_OUTPUT_LVCMOS12_DRIVE_12 0x00FC008802000000 +#define XC6_IOB_OUTPUT_SSTL2_I 0x0040001C00000000 + #define XC6_IOB_IMUX_I_B 0x0000000000000400 #define XC6_IOB_O_PINW 0x0000000000000100 #define XC6_IOB_SLEW_SLOW 0x0000000000000000 @@ -152,3 +154,26 @@ struct xc6_routing_bitpos int get_xc6_routing_bitpos(struct xc6_routing_bitpos** bitpos, int* num_bitpos); void free_xc6_routing_bitpos(struct xc6_routing_bitpos* bitpos); + +#define XC6_LMAP_XM_M_A 0 +#define XC6_LMAP_XM_M_B 1 +#define XC6_LMAP_XM_M_C 0 +#define XC6_LMAP_XM_M_D 1 +#define XC6_LMAP_XM_X_A 2 +#define XC6_LMAP_XM_X_B 2 +#define XC6_LMAP_XM_X_C 3 +#define XC6_LMAP_XM_X_D 3 +#define XC6_LMAP_XL_L_A 3 +#define XC6_LMAP_XL_L_B 2 +#define XC6_LMAP_XL_L_C 3 +#define XC6_LMAP_XL_L_D 2 +#define XC6_LMAP_XL_X_A 2 +#define XC6_LMAP_XL_X_B 2 +#define XC6_LMAP_XL_X_C 3 +#define XC6_LMAP_XL_X_D 3 + +// num_bits must be 32 or 64. If it is 32, the lower +// 32 entries of map contain the bit positions for lut5, +// the upper 32 entries of map the ones for lut6. +// In either case 64 entries are written to map. +void xc6_lut_bitmap(int lut_pos, int* map, int num_bits);