table SIN_WAVE 16 1024 { 0, 201, 402, 603, 804, 1005, 1206, 1406, 1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011, 3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608, 4807, 5006, 5205, 5403, 5601, 5799, 5997, 6195, 6392, 6589, 6786, 6982, 7179, 7375, 7571, 7766, 7961, 8156, 8351, 8545, 8739, 8932, 9126, 9319, 9511, 9703, 9895, 10087, 10278, 10469, 10659, 10849, 11038, 11227, 11416, 11604, 11792, 11980, 12166, 12353, 12539, 12724, 12909, 13094, 13278, 13462, 13645, 13827, 14009, 14191, 14372, 14552, 14732, 14911, 15090, 15268, 15446, 15623, 15799, 15975, 16150, 16325, 16499, 16672, 16845, 17017, 17189, 17360, 17530, 17699, 17868, 18036, 18204, 18371, 18537, 18702, 18867, 19031, 19194, 19357, 19519, 19680, 19840, 20000, 20159, 20317, 20474, 20631, 20787, 20942, 21096, 21249, 21402, 21554, 21705, 21855, 22004, 22153, 22301, 22448, 22594, 22739, 22883, 23027, 23169, 23311, 23452, 23592, 23731, 23869, 24006, 24143, 24278, 24413, 24546, 24679, 24811, 24942, 25072, 25201, 25329, 25456, 25582, 25707, 25831, 25954, 26077, 26198, 26318, 26437, 26556, 26673, 26789, 26905, 27019, 27132, 27244, 27355, 27466, 27575, 27683, 27790, 27896, 28001, 28105, 28208, 28309, 28410, 28510, 28608, 28706, 28802, 28897, 28992, 29085, 29177, 29268, 29358, 29446, 29534, 29621, 29706, 29790, 29873, 29955, 30036, 30116, 30195, 30272, 30349, 30424, 30498, 30571, 30643, 30713, 30783, 30851, 30918, 30984, 31049, 31113, 31175, 31236, 31297, 31356, 31413, 31470, 31525, 31580, 31633, 31684, 31735, 31785, 31833, 31880, 31926, 31970, 32014, 32056, 32097, 32137, 32176, 32213, 32249, 32284, 32318, 32350, 32382, 32412, 32441, 32468, 32495, 32520, 32544, 32567, 32588, 32609, 32628, 32646, 32662, 32678, 32692, 32705, 32717, 32727, 32736, 32744, 32751, 32757, 32761, 32764, 32766, 32767, 32766, 32764, 32761, 32757, 32751, 32744, 32736, 32727, 32717, 32705, 32692, 32678, 32662, 32646, 32628, 32609, 32588, 32567, 32544, 32520, 32495, 32468, 32441, 32412, 32382, 32350, 32318, 32284, 32249, 32213, 32176, 32137, 32097, 32056, 32014, 31970, 31926, 31880, 31833, 31785, 31735, 31684, 31633, 31580, 31525, 31470, 31413, 31356, 31297, 31236, 31175, 31113, 31049, 30984, 30918, 30851, 30783, 30713, 30643, 30571, 30498, 30424, 30349, 30272, 30195, 30116, 30036, 29955, 29873, 29790, 29706, 29621, 29534, 29446, 29358, 29268, 29177, 29085, 28992, 28897, 28802, 28706, 28608, 28510, 28410, 28309, 28208, 28105, 28001, 27896, 27790, 27683, 27575, 27466, 27355, 27244, 27132, 27019, 26905, 26789, 26673, 26556, 26437, 26318, 26198, 26077, 25954, 25831, 25707, 25582, 25456, 25329, 25201, 25072, 24942, 24811, 24679, 24546, 24413, 24278, 24143, 24006, 23869, 23731, 23592, 23452, 23311, 23169, 23027, 22883, 22739, 22594, 22448, 22301, 22153, 22004, 21855, 21705, 21554, 21402, 21249, 21096, 20942, 20787, 20631, 20474, 20317, 20159, 20000, 19840, 19680, 19519, 19357, 19194, 19031, 18867, 18702, 18537, 18371, 18204, 18036, 17868, 17699, 17530, 17360, 17189, 17017, 16845, 16672, 16499, 16325, 16150, 15975, 15799, 15623, 15446, 15268, 15090, 14911, 14732, 14552, 14372, 14191, 14009, 13827, 13645, 13462, 13278, 13094, 12909, 12724, 12539, 12353, 12166, 11980, 11792, 11604, 11416, 11227, 11038, 10849, 10659, 10469, 10278, 10087, 9895, 9703, 9511, 9319, 9126, 8932, 8739, 8545, 8351, 8156, 7961, 7766, 7571, 7375, 7179, 6982, 6786, 6589, 6392, 6195, 5997, 5799, 5601, 5403, 5205, 5006, 4807, 4608, 4409, 4210, 4011, 3811, 3611, 3411, 3211, 3011, 2811, 2610, 2410, 2209, 2009, 1808, 1607, 1406, 1206, 1005, 804, 603, 402, 201, 0, 65335, 65134, 64933, 64732, 64531, 64330, 64130, 63929, 63728, 63527, 63327, 63126, 62926, 62725, 62525, 62325, 62125, 61925, 61725, 61525, 61326, 61127, 60928, 60729, 60530, 60331, 60133, 59935, 59737, 59539, 59341, 59144, 58947, 58750, 58554, 58357, 58161, 57965, 57770, 57575, 57380, 57185, 56991, 56797, 56604, 56410, 56217, 56025, 55833, 55641, 55449, 55258, 55067, 54877, 54687, 54498, 54309, 54120, 53932, 53744, 53556, 53370, 53183, 52997, 52812, 52627, 52442, 52258, 52074, 51891, 51709, 51527, 51345, 51164, 50984, 50804, 50625, 50446, 50268, 50090, 49913, 49737, 49561, 49386, 49211, 49037, 48864, 48691, 48519, 48347, 48176, 48006, 47837, 47668, 47500, 47332, 47165, 46999, 46834, 46669, 46505, 46342, 46179, 46017, 45856, 45696, 45536, 45377, 45219, 45062, 44905, 44749, 44594, 44440, 44287, 44134, 43982, 43831, 43681, 43532, 43383, 43235, 43088, 42942, 42797, 42653, 42509, 42367, 42225, 42084, 41944, 41805, 41667, 41530, 41393, 41258, 41123, 40990, 40857, 40725, 40594, 40464, 40335, 40207, 40080, 39954, 39829, 39705, 39582, 39459, 39338, 39218, 39099, 38980, 38863, 38747, 38631, 38517, 38404, 38292, 38181, 38070, 37961, 37853, 37746, 37640, 37535, 37431, 37328, 37227, 37126, 37026, 36928, 36830, 36734, 36639, 36544, 36451, 36359, 36268, 36178, 36090, 36002, 35915, 35830, 35746, 35663, 35581, 35500, 35420, 35341, 35264, 35187, 35112, 35038, 34965, 34893, 34823, 34753, 34685, 34618, 34552, 34487, 34423, 34361, 34300, 34239, 34180, 34123, 34066, 34011, 33956, 33903, 33852, 33801, 33751, 33703, 33656, 33610, 33566, 33522, 33480, 33439, 33399, 33360, 33323, 33287, 33252, 33218, 33186, 33154, 33124, 33095, 33068, 33041, 33016, 32992, 32969, 32948, 32927, 32908, 32890, 32874, 32858, 32844, 32831, 32819, 32809, 32800, 32792, 32785, 32779, 32775, 32772, 32770, 32769, 32770, 32772, 32775, 32779, 32785, 32792, 32800, 32809, 32819, 32831, 32844, 32858, 32874, 32890, 32908, 32927, 32948, 32969, 32992, 33016, 33041, 33068, 33095, 33124, 33154, 33186, 33218, 33252, 33287, 33323, 33360, 33399, 33439, 33480, 33522, 33566, 33610, 33656, 33703, 33751, 33801, 33852, 33903, 33956, 34011, 34066, 34123, 34180, 34239, 34300, 34361, 34423, 34487, 34552, 34618, 34685, 34753, 34823, 34893, 34965, 35038, 35112, 35187, 35264, 35341, 35420, 35500, 35581, 35663, 35746, 35830, 35915, 36002, 36090, 36178, 36268, 36359, 36451, 36544, 36639, 36734, 36830, 36928, 37026, 37126, 37227, 37328, 37431, 37535, 37640, 37746, 37853, 37961, 38070, 38181, 38292, 38404, 38517, 38631, 38747, 38863, 38980, 39099, 39218, 39338, 39459, 39582, 39705, 39829, 39954, 40080, 40207, 40335, 40464, 40594, 40725, 40857, 40990, 41123, 41258, 41393, 41530, 41667, 41805, 41944, 42084, 42225, 42367, 42509, 42653, 42797, 42942, 43088, 43235, 43383, 43532, 43681, 43831, 43982, 44134, 44287, 44440, 44594, 44749, 44905, 45062, 45219, 45377, 45536, 45696, 45856, 46017, 46179, 46342, 46505, 46669, 46834, 46999, 47165, 47332, 47500, 47668, 47837, 48006, 48176, 48347, 48519, 48691, 48864, 49037, 49211, 49386, 49561, 49737, 49913, 50090, 50268, 50446, 50625, 50804, 50984, 51164, 51345, 51527, 51709, 51891, 52074, 52258, 52442, 52627, 52812, 52997, 53183, 53370, 53556, 53744, 53932, 54120, 54309, 54498, 54687, 54877, 55067, 55258, 55449, 55641, 55833, 56025, 56217, 56410, 56604, 56797, 56991, 57185, 57380, 57575, 57770, 57965, 58161, 58357, 58554, 58750, 58947, 59144, 59341, 59539, 59737, 59935, 60133, 60331, 60530, 60729, 60928, 61127, 61326, 61525, 61725, 61925, 62125, 62325, 62525, 62725, 62926, 63126, 63327, 63527, 63728, 63929, 64130, 64330, 64531, 64732, 64933, 65134, 65335 } regfile FFT_REG 64 2 fftv regfile FFT_REG_SIMD 128 2 fftsv function [31:0] FFT_VAR_SHIFT([31:0] data, [3:0] sh) { assign FFT_VAR_SHIFT = TIEmux(sh, data[31:0], {data[30:0], 1'b0}, {data[29:0], 2'b0}, {data[28:0], 3'b0}, {data[27:0], 4'b0}, {data[26:0], 5'b0}, {data[25:0], 6'b0}, {data[24:0], 7'b0}, {data[23:0], 8'b0}, {data[22:0], 9'b0}, {data[21:0], 10'b0}, {data[20:0], 11'b0}, {data[19:0], 12'b0}, {data[18:0], 13'b0}, {data[17:0], 14'b0}, {data[16:0], 15'b0} ); } operation FFT_SIMD_LOAD {in AR *base, in AR offset, out FFT_REG_SIMD data} {out VAddr, in MemDataIn128} { assign VAddr = TIEadd(base, {offset[30:0], 1'b0}, 1'b0); wire [15:0] o1 = MemDataIn128[15:0]; wire [15:0] o2 = MemDataIn128[31:16]; wire [15:0] o3 = MemDataIn128[47:32]; wire [15:0] o4 = MemDataIn128[63:48]; wire [15:0] o5 = MemDataIn128[79:64]; wire [15:0] o6 = MemDataIn128[95:80]; wire [15:0] o7 = MemDataIn128[111:96]; wire [15:0] o8 = MemDataIn128[127:112]; assign data = {o1, o2, o3, o4, o5, o6, o7, o8 }; } operation FFT_SIMD_STORE {in AR *base, in AR offset, in FFT_REG_SIMD data} {out VAddr, out MemDataOut128} { assign VAddr = TIEadd(base, {offset[30:0], 1'b0}, 1'b0); wire [15:0] o1 = data[15:0]; wire [15:0] o2 = data[31:16]; wire [15:0] o3 = data[47:32]; wire [15:0] o4 = data[63:48]; wire [15:0] o5 = data[79:64]; wire [15:0] o6 = data[95:80]; wire [15:0] o7 = data[111:96]; wire [15:0] o8 = data[127:112]; assign MemDataOut128 = {o1, o2, o3, o4, o5, o6, o7, o8 }; } operation FFT_SHIFT_CHECK {in AR *base, in AR offset, out AR needs_shift} {out VAddr, in MemDataIn128} { assign VAddr = TIEadd(base, offset[31:1], 1'b0); wire [15:0] o1 = MemDataIn128[15:0]; wire [15:0] o2 = MemDataIn128[31:16]; wire [15:0] o3 = MemDataIn128[47:32]; wire [15:0] o4 = MemDataIn128[63:48]; wire [15:0] o5 = MemDataIn128[79:64]; wire [15:0] o6 = MemDataIn128[95:80]; wire [15:0] o7 = MemDataIn128[111:96]; wire [15:0] o8 = MemDataIn128[127:112]; wire s1 = (!o1[15] && o1[14]) || (o1[15] && (!o1[14] || o1[13:0] == 14'b0)); wire s2 = (!o2[15] && o2[14]) || (o2[15] && (!o2[14] || o2[13:0] == 14'b0)); wire s3 = (!o3[15] && o3[14]) || (o3[15] && (!o3[14] || o3[13:0] == 14'b0)); wire s4 = (!o4[15] && o4[14]) || (o4[15] && (!o4[14] || o4[13:0] == 14'b0)); wire s5 = (!o5[15] && o5[14]) || (o5[15] && (!o5[14] || o5[13:0] == 14'b0)); wire s6 = (!o6[15] && o6[14]) || (o6[15] && (!o6[14] || o6[13:0] == 14'b0)); wire s7 = (!o7[15] && o7[14]) || (o7[15] && (!o7[14] || o7[13:0] == 14'b0)); wire s8 = (!o8[15] && o8[14]) || (o8[15] && (!o8[14] || o8[13:0] == 14'b0)); assign needs_shift = {31'b0, s1 || s2 || s3 || s4 || s5 || s6 || s7 || s8 }; } operation FFT_BIT_REVERSE {inout AR m, out AR mr, in AR mm} {} { wire [15:0] x = TIEadd(m, 1'b0, 1'b1); assign mr = { TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, x[0]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, x[0], x[1]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, x[0], x[1], x[2]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, x[0], x[1], x[2], x[3]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, x[0], x[1], x[2], x[3], x[4]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, x[0], x[1], x[2], x[3], x[4], x[5]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, x[0], x[1], x[2], x[3], x[4], x[5], x[6]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, 1'b0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10],x[11]), TIEmux(mm[3:0], 1'b0, 1'b0, 1'b0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10],x[11],x[12]), TIEmux(mm[3:0], 1'b0, 1'b0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10],x[11],x[12],x[13]), TIEmux(mm[3:0], 1'b0, x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7], x[8], x[9], x[10],x[11],x[12],x[13],x[14]) }; assign m = x; } function [31:0] FFT_TWIDDLE ([31:0] j, [0:0] shift, [0:0] inverse) { // 256 = N_WAVE / 4 wire [9:0] idx = TIEadd(j, 256, 1'b0); wire [15:0] sin = SIN_WAVE[j]; wire [15:0] wr1 = SIN_WAVE[idx]; wire [15:0] wi1 = TIEadd(~sin, 16'b0, 1'b1); wire [15:0] wi2 = TIEmux(inverse, wi1, sin); assign FFT_TWIDDLE = { TIEmux(shift, wr1, {wr1[15], wr1[15:1]}), TIEmux(shift, wi2, {wi2[15], wi2[15:1]}) }; } function [63:0] FFT_BUTTERFLY ([63:0] data, [15:0] wr, [15:0] wi, [0:0] shift) { // operands real parts wire [15:0] r1 = data[63:48]; wire [15:0] r2 = data[47:32]; // operands imaginary parts wire [15:0] i1 = data[31:16]; wire [15:0] i2 = data[15:0]; // odd real part wire [31:0] oddr1 = TIEmul(wr, r2, 1'b1); wire [15:0] oddr1s = oddr1[30:15]; wire [31:0] oddr2 = TIEmul(wi, i2, 1'b1); wire [15:0] oddr2s = oddr2[30:15]; wire [15:0] oddr = TIEadd(oddr1s, ~oddr2s, 1'b1); // odd imaginary part wire [31:0] oddi1 = TIEmul(wr, i2, 1'b1); wire [15:0] oddi1s = oddi1[30:15]; wire [31:0] oddi2 = TIEmul(wi, r2, 1'b1); wire [15:0] oddi2s = oddi2[30:15]; wire [15:0] oddi = TIEadd(oddi1s, oddi2s, 1'b0); // even parts wire [15:0] evenr = TIEmux(shift[0], r1, {r1[15], r1[15:1]}); wire [15:0] eveni = TIEmux(shift[0], i1, {i1[15], i1[15:1]}); // final result wire [15:0] resr1 = TIEadd(evenr, oddr, 1'b0); wire [15:0] resr2 = TIEadd(evenr, ~oddr, 1'b1); wire [15:0] resi1 = TIEadd(eveni, oddi, 1'b0); wire [15:0] resi2 = TIEadd(eveni, ~oddi, 1'b1); assign FFT_BUTTERFLY = { resr1, resr2, resi1, resi2 }; } operation FFT_CALC {inout FFT_REG data, in AR i, in BR shift, in BR inverse} {} { wire [31:0] twiddle = FFT_TWIDDLE(i, shift, inverse); wire [15:0] wr = twiddle[31:16]; wire [15:0] wi = twiddle[15:0]; assign data = FFT_BUTTERFLY(data, wr, wi, shift); } // 4 butterflies at once operation FFT_SIMD_FIRST {inout FFT_REG_SIMD fr, inout FFT_REG_SIMD fi, in BR shift} {} { wire [15:0] wr = TIEmux(shift, 16'h7fff, 16'h3fff); wire [15:0] wi = 16'b0; wire [63:0] res1 = FFT_butterfly({fr[127:96], fi[127:96]}, wr, wi, shift); wire [63:0] res2 = FFT_butterfly({fr[95:64], fi[95:64]}, wr, wi, shift); wire [63:0] res3 = FFT_butterfly({fr[63:32], fi[63:32]}, wr, wi, shift); wire [63:0] res4 = FFT_butterfly({fr[31:0], fi[31:0]}, wr, wi, shift); assign fr = { res1[63:32], res2[63:32], res3[63:32], res4[63:32] }; assign fi = { res1[31:0], res2[31:0], res3[31:0], res4[31:0] }; } //-------------------------------------------------------------------------- // // Immediate Ranges // //-------------------------------------------------------------------------- immediate_range ST.FFT_REG_immed2 -32 24 8 immediate_range LD.FFT_REG_immed2 -32 24 8 //-------------------------------------------------------------------------- // // FLIX Formats and Slots // // flix64_0, format width 64 bits, 2 slots format flix64_0 64 { flix64_0_slot0, flix64_0_slot1, flix64_0_slot2 } slot_opcodes flix64_0_slot0 { MOVI, J, ADDX2, L16SI, S16I, FFT_BIT_REVERSE, S32I, L32I, FFT_SHIFT_CHECK, OR, NOP, ADD, FFT_CALC, FFT_SIMD_LOAD, FFT_SIMD_STORE } slot_opcodes flix64_0_slot1 { SSL, SLL, MOVI, ADDX2, NOP, ADDI.N, ANDBC, ADD, MOV.N, J } slot_opcodes flix64_0_slot2 { S32I, ADDI.N, L32I, L16SI, ADDX2, NOP, FFT_SHIFT_CHECK, J, MOVI, SSL, MOV.N, S16I, FFT_SIMD_LOAD, FFT_SIMD_STORE } //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- // // Ctypes // //-------------------------------------------------------------------------- ctype FFT_REG 64 64 FFT_REG default ctype FFT_REG_SIMD 128 128 FFT_REG_SIMD default