lut cleanup and support for more cases - unfinished
This commit is contained in:
parent
0a0dfaca31
commit
6200ea710c
46
LINKS
46
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
|
||||
|
|
2
Makefile
2
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)
|
||||
|
|
92
autotest.c
92
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<<j)))
|
||||
lut_str[lut_str_len++] = '~';
|
||||
lut_str[lut_str_len++] = 'A';
|
||||
lut_str[lut_str_len++] = '1' + j;
|
||||
}
|
||||
lut_str[lut_str_len] = 0;
|
||||
rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i],
|
||||
lut, /*lut6*/ lut5_parents[i], /*lut5*/ "1");
|
||||
lut, /*lut6*/ pf("(A6+~A6)*%s", lut_str),
|
||||
/*lut5*/ lut_str);
|
||||
if (rc) FAIL(rc);
|
||||
for (j = '1'; j <= '5'; j++) {
|
||||
snprintf(lut_str, sizeof(lut_str), "A%c", j);
|
||||
rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i],
|
||||
lut, /*lut6*/ lut5_parents[i], /*lut5*/ lut_str);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
for (j = 0; j < 32; j++) {
|
||||
lut_str_len = 0;
|
||||
for (k = 0; k < 5; k++) {
|
||||
if (lut_str_len)
|
||||
lut_str[lut_str_len++] = '*';
|
||||
if (!(j & (1<<k)))
|
||||
lut_str[lut_str_len++] = '~';
|
||||
lut_str[lut_str_len++] = 'A';
|
||||
lut_str[lut_str_len++] = '1' + k;
|
||||
}
|
||||
lut_str[lut_str_len] = 0;
|
||||
rc = test_lut(tstate, y, x_enum[x_i], idx_enum[type_i],
|
||||
lut, /*lut6*/ lut5_parents[i], /*lut5*/ lut_str);
|
||||
if (rc) FAIL(rc);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1211,6 +1210,39 @@ int main(int argc, char** argv)
|
|||
// for example: ./autotest 2>&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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
224
libs/helper.c
224
libs/helper.c
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#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<<i))
|
||||
result |= 1ULL<<(dest_pos[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int bool_str2bits(const char* str, uint64_t* u64, int num_bits)
|
||||
{
|
||||
int i, j, bool_res, rc, vars[6];
|
||||
|
||||
if (num_bits != 32 && num_bits != 64) HERE();
|
||||
*u64 = 0;
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
for (j = 0; j < sizeof(vars)/sizeof(*vars); j++)
|
||||
vars[j] = (i & (1<<j)) != 0;
|
||||
bool_res = bool_eval(str, strlen(str), vars);
|
||||
if (bool_res == -1) FAIL(EINVAL);
|
||||
if (bool_res) *u64 |= 1ULL<<i;
|
||||
}
|
||||
return 0;
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
||||
typedef struct _minterm_entry
|
||||
{
|
||||
char a[6]; // 0=A1, 5=A6. value can be 0, 1 or 2 for 'removed'
|
||||
int merged;
|
||||
} minterm_entry;
|
||||
|
||||
const char* bool_bits2str(uint64_t u64, int num_bits)
|
||||
{
|
||||
// round 0 needs 64 entries
|
||||
// round 1 (size2): 192
|
||||
// round 2 (size4): 240
|
||||
// round 3 (size8): 160
|
||||
// round 4 (size16): 60
|
||||
// round 5 (size32): 12
|
||||
// round 6 (size64): 1
|
||||
minterm_entry mt[7][256];
|
||||
int mt_size[7];
|
||||
int i, j, k, round, only_diff_bit;
|
||||
int str_end, first_op, bit_width;
|
||||
static char str[2048];
|
||||
|
||||
if (num_bits == 64)
|
||||
bit_width = 6;
|
||||
else if (num_bits == 32)
|
||||
bit_width = 5;
|
||||
else {
|
||||
HERE();
|
||||
return "0";
|
||||
}
|
||||
if (!u64) return "0";
|
||||
if (u64 == 0xFFFFFFFFFFFFFFFFULL) return "1";
|
||||
|
||||
memset(mt, 0, sizeof(mt));
|
||||
memset(mt_size, 0, sizeof(mt_size));
|
||||
|
||||
// set starting minterms
|
||||
for (i = 0; i < num_bits; i++) {
|
||||
if (u64 & (1ULL<<i)) {
|
||||
for (j = 0; j < bit_width; j++) {
|
||||
if (i&(1<<j))
|
||||
mt[0][mt_size[0]].a[j] = 1;
|
||||
}
|
||||
mt_size[0]++;
|
||||
}
|
||||
}
|
||||
|
||||
// go through five rounds of merging
|
||||
for (round = 1; round < 7; round++) {
|
||||
for (i = 0; i < mt_size[round-1]; i++) {
|
||||
for (j = i+1; j < mt_size[round-1]; j++) {
|
||||
only_diff_bit = -1;
|
||||
for (k = 0; k < bit_width; k++) {
|
||||
if (mt[round-1][i].a[k] != mt[round-1][j].a[k]) {
|
||||
if (only_diff_bit != -1) {
|
||||
only_diff_bit = -1;
|
||||
break;
|
||||
}
|
||||
only_diff_bit = k;
|
||||
}
|
||||
}
|
||||
if (only_diff_bit != -1) {
|
||||
char new_term[6];
|
||||
|
||||
for (k = 0; k < bit_width; k++)
|
||||
new_term[k] =
|
||||
(k == only_diff_bit) ? 2
|
||||
: mt[round-1][i].a[k];
|
||||
for (k = 0; k < mt_size[round]; k++) {
|
||||
if (new_term[0] == mt[round][k].a[0]
|
||||
&& new_term[1] == mt[round][k].a[1]
|
||||
&& new_term[2] == mt[round][k].a[2]
|
||||
&& new_term[3] == mt[round][k].a[3]
|
||||
&& new_term[4] == mt[round][k].a[4]
|
||||
&& new_term[5] == mt[round][k].a[5])
|
||||
break;
|
||||
}
|
||||
if (k >= 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<<i)) lut64 |= 1ULL << (2*i);
|
||||
if (m1 & (1<<i)) lut64 |= 1ULL << (2*i+1);
|
||||
}
|
||||
return lut64;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
int printf_frames(const uint8_t* bits, int max_frames,
|
||||
int row, int major, int minor, int print_empty, int no_clock)
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
39
libs/parts.c
39
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
25
libs/parts.h
25
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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user