From df9180a30ba3570fa1c21b4013a761dea5238981 Mon Sep 17 00:00:00 2001 From: tevador Date: Wed, 14 Nov 2018 20:17:44 +0100 Subject: [PATCH] Performance benchmark for x86 --- tests/performance/benchmark.cpp | 306 ++++++++++++++++++++++++++++++++ tests/performance/test1.data | Bin 0 -> 16384 bytes tests/performance/test2.data | Bin 0 -> 16384 bytes tests/rx2c.py | 11 +- 4 files changed, 312 insertions(+), 5 deletions(-) create mode 100644 tests/performance/benchmark.cpp create mode 100644 tests/performance/test1.data create mode 100644 tests/performance/test2.data diff --git a/tests/performance/benchmark.cpp b/tests/performance/benchmark.cpp new file mode 100644 index 0000000..fa5fca1 --- /dev/null +++ b/tests/performance/benchmark.cpp @@ -0,0 +1,306 @@ +//RandomX performance test for x86 +//https://github.com/tevador/RandomX +//License: GPL v3 + +#include +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) || defined(__MINGW32__) || defined(__CYGWIN__) || defined(__CYGWIN32__) + #define WINDOWS + #include + #include +#endif + +#if defined(__GNUC__) && defined(__x86_64__) + #include + typedef unsigned __int128 uint128_t; + typedef __int128 int128_t; + static inline uint64_t umulhi64(uint64_t a, uint64_t b) { + return ((uint128_t)a * b) >> 64; + } + static inline uint64_t imulhi64(int64_t a, int64_t b) { + return ((int128_t)a * b) >> 64; + } + #define ror64 __rorq + #define rol64 __rolq + #define forceinline inline +#elif defined(_MSC_VER) && defined(_M_X64) + #include + #include + #define umulhi64 __umulh + static inline uint64_t imulhi64(int64_t a, int64_t b) { + int64_t hi; + _mul128(a, b, &hi); + return hi; + } + #define ror64 _rotr64 + #define rol64 _rotl64 + #define forceinline __forceinline +#else + #error "Unsupported platform" +#endif + +typedef union { + double f64; + int64_t i64; + uint64_t u64; + int32_t i32; + uint32_t u32; +} convertible_t; + +forceinline void NOOP(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u64; +} + +forceinline void FNOOP(convertible_t& a, convertible_t& b, convertible_t& c) { + c.f64 = (double)a.i64; +} + +forceinline void ADD_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u64 + b.u64; +} + +forceinline void ADD_32(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u32 + b.u32; +} + +forceinline void SUB_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u64 - b.u64; +} + +forceinline void SUB_32(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u32 - b.u32; +} + +forceinline void MUL_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u64 * b.u64; +} + +forceinline void MULH_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = umulhi64(a.u64, b.u64); +} + +forceinline void MUL_32(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = (uint64_t)a.u32 * b.u32; +} + +forceinline void IMUL_32(convertible_t& a, convertible_t& b, convertible_t& c) { + c.i64 = (int64_t)a.i32 * b.i32; +} + +forceinline void IMULH_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.i64 = imulhi64(a.i64, b.i64); +} + +forceinline void DIV_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u64 / (b.u32 != 0 ? b.u32 : 1U); +} + +forceinline void IDIV_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.i64 = a.i64 / (b.i32 != 0 ? b.i32 : 1); +} + +forceinline void AND_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u64 & b.u64; +} + +forceinline void AND_32(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u32 & b.u32; +} + +forceinline void OR_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u64 | b.u64; +} + +forceinline void OR_32(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u32 | b.u32; +} + +forceinline void XOR_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u64 ^ b.u64; +} + +forceinline void XOR_32(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u32 ^ b.u32; +} + +forceinline void SHL_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u64 << (b.u64 & 63); +} + +forceinline void SHR_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = a.u64 >> (b.u64 & 63); +} + +forceinline void SAR_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.i64 = a.i64 >> (b.u64 & 63); +} + +forceinline void ROL_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = rol64(a.u64, (b.u64 & 63)); +} + +forceinline void ROR_64(convertible_t& a, convertible_t& b, convertible_t& c) { + c.u64 = ror64(a.u64, (b.u64 & 63)); +} + +forceinline void FADD(convertible_t& a, convertible_t& b, convertible_t& c) { + c.f64 = (double)a.i64 + (double)b.i64; +} + +forceinline void FSUB(convertible_t& a, convertible_t& b, convertible_t& c) { + c.f64 = (double)a.i64 - (double)b.i64; +} + +forceinline void FMUL(convertible_t& a, convertible_t& b, convertible_t& c) { + c.f64 = (double)a.i64 * (double)b.i64; +} + +forceinline void FDIV(convertible_t& a, convertible_t& b, convertible_t& c) { + c.f64 = (double)a.i64 / (double)b.i64; +} + +forceinline void FSQRT(convertible_t& a, convertible_t& b, convertible_t& c) { + double d = fabs((double)a.i64); + c.f64 = _mm_cvtsd_f64(_mm_sqrt_sd(_mm_setzero_pd(), _mm_load_pd(&d))); +} + +static uint32_t mxcsr; + +forceinline void FROUND(convertible_t& a, convertible_t& b, convertible_t& c) { + c.f64 = (double)a.i64; + _mm_setcsr(mxcsr | ((uint32_t)(a.u64 << 13) & _MM_ROUND_MASK)); +} + +inline void init_FPU() { + mxcsr = (_mm_getcsr() | _MM_FLUSH_ZERO_ON) & ~_MM_ROUND_MASK; + _mm_setcsr(mxcsr); +} + +template +bool tryParse(char* buffer, T& out) { + std::istringstream ss(buffer); + if (!(ss >> out)) { + std::cout << "Invalid value '" << buffer << "'" << std::endl; + return false; + } + return true; +} + +//#define ITERATIONS 10000000 +#define SCRATCHPAD_SIZE (16 * 1024) +#define SCRATCHPAD_LENGTH (SCRATCHPAD_SIZE / sizeof(convertible_t)) +#define SCRATCHPAD_MASK (SCRATCHPAD_SIZE / sizeof(convertible_t) - 1) +#define SCRATCHPAD_16K(x) scratchpad[(x) & SCRATCHPAD_MASK] + +#define BENCHMARK(FUNC,TYPE) do { \ + memcpy((void*)scratchpad, input, SCRATCHPAD_SIZE); \ + tstart = std::chrono::high_resolution_clock::now(); \ + for (uint64_t i = 0; i < iterations; ++i) { \ + FUNC(SCRATCHPAD_16K(i + 8 + 0), r0, SCRATCHPAD_16K(i + 0)); \ + SCRATCHPAD_16K(i + 0).u64 ^= r7.u64;\ + FUNC(SCRATCHPAD_16K(i + 8 + 1), r1, SCRATCHPAD_16K(i + 1)); \ + SCRATCHPAD_16K(i + 1).u64 ^= r6.u64;\ + FUNC(SCRATCHPAD_16K(i + 8 + 2), r2, SCRATCHPAD_16K(i + 2)); \ + SCRATCHPAD_16K(i + 2).u64 ^= r5.u64;\ + FUNC(SCRATCHPAD_16K(i + 8 + 3), r3, SCRATCHPAD_16K(i + 3)); \ + SCRATCHPAD_16K(i + 3).u64 ^= r4.u64;\ + FUNC(SCRATCHPAD_16K(i + 8 + 4), r4, SCRATCHPAD_16K(i + 4)); \ + SCRATCHPAD_16K(i + 4).u64 ^= r3.u64;\ + FUNC(SCRATCHPAD_16K(i + 8 + 5), r5, SCRATCHPAD_16K(i + 5)); \ + SCRATCHPAD_16K(i + 5).u64 ^= r2.u64;\ + FUNC(SCRATCHPAD_16K(i + 8 + 6), r6, SCRATCHPAD_16K(i + 6)); \ + SCRATCHPAD_16K(i + 6).u64 ^= r1.u64;\ + FUNC(SCRATCHPAD_16K(i + 8 + 7), r7, SCRATCHPAD_16K(i + 7)); \ + SCRATCHPAD_16K(i + 7).u64 ^= r0.u64;\ + } \ + tend = std::chrono::high_resolution_clock::now(); \ + uint64_t acum = 0; \ + for (int i = 0; i < SCRATCHPAD_LENGTH; ++i) \ + acum += scratchpad[i].u64; \ + std::cout << "| " << #FUNC << " | " << std::chrono::duration(tend - tstart).count() << " | " << acum << " |" << std::endl; \ + } while(false) + + +int main(int argc, char** argv) { + uint64_t iterations; + if (argc > 1) { + if (!tryParse(argv[1], iterations)) + return 1; + } + else { + iterations = 100000000; + } +#ifdef WINDOWS + _setmode(_fileno(stdin), O_BINARY); +#endif + convertible_t input[SCRATCHPAD_LENGTH]; + + std::cout << "Reading " << sizeof(input) << " bytes from STDIN..." << std::endl; + std::cin.read((char*)input, sizeof(input)); + + if (!std::cin) { + std::cerr << "Insufficient input" << std::endl; + return 1; + } + + convertible_t scratchpad[SCRATCHPAD_LENGTH]; + convertible_t r0, r1, r2, r3, r4, r5, r6, r7; + + r0.u64 = input[0].u64; + r1.u64 = input[1].u64; + r2.u64 = input[2].u64; + r3.u64 = input[3].u64; + r4.u64 = input[4].u64; + r5.u64 = input[5].u64; + r6.u64 = input[6].u64; + r7.u64 = input[7].u64; + + std::chrono::high_resolution_clock::time_point tstart, tend; + + std::cout << iterations << " iterations:" << std::endl << std::endl; + + std::cout << "| operation | time [s] | (result) |" << std::endl; + std::cout << "|-----------|----------|----------|" << std::endl; + + BENCHMARK(NOOP, u64); + BENCHMARK(ADD_64, u64); + BENCHMARK(ADD_32, u64); + BENCHMARK(SUB_64, u64); + BENCHMARK(SUB_32, u64); + BENCHMARK(MUL_64, u64); + BENCHMARK(MULH_64, u64); + BENCHMARK(MUL_32, u64); + BENCHMARK(IMUL_32, u64); + BENCHMARK(IMULH_64, u64); + BENCHMARK(DIV_64, u64); + BENCHMARK(IDIV_64, u64); + BENCHMARK(AND_64, u64); + BENCHMARK(AND_32, u64); + BENCHMARK(OR_64, u64); + BENCHMARK(OR_32, u64); + BENCHMARK(XOR_64, u64); + BENCHMARK(XOR_32, u64); + BENCHMARK(SHL_64, u64); + BENCHMARK(SHR_64, u64); + BENCHMARK(SAR_64, u64); + BENCHMARK(ROR_64, u64); + BENCHMARK(ROL_64, u64); + + init_FPU(); + + BENCHMARK(FNOOP, f64); + BENCHMARK(FADD, f64); + BENCHMARK(FSUB, f64); + BENCHMARK(FMUL, f64); + BENCHMARK(FDIV, f64); + BENCHMARK(FSQRT, f64); + BENCHMARK(FROUND, f64); + + return 0; +} diff --git a/tests/performance/test1.data b/tests/performance/test1.data new file mode 100644 index 0000000000000000000000000000000000000000..2eb8fe539df5fac9bd66a381c174287bb841d127 GIT binary patch literal 16384 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 O^;Y$z5%TLqG+mv#TF>AB literal 0 HcmV?d00001 diff --git a/tests/performance/test2.data b/tests/performance/test2.data new file mode 100644 index 0000000000000000000000000000000000000000..11c8b487fd8a3d9bf9589421b27c5d03a0db3aaf GIT binary patch literal 16384 zcmV+bK>xooW?g)Q?n27;KmVjD7s%icWYJuub+YOKW1Con0sR$QecB*Gh6N4ly&C;d zWJn}VJ6oDSvH&59$reX;F`igd2==dD?k9g6Y;0KfF!@ve@B2OA#!fdOX|t?3VnKNkfMCBWHkMn06(2iVjT|8_Akp0m~PL)gBjs4F5@XamF7-lb%76@7#2N6|LR zLI(+2%=At4300RO7Xb2%v&1_<0t{?D>ceC(> zAEWy1^5DM*XQ)vHVSE%F&Z71mUXKZPJ>j23?qjY`_?Ry~H7Uc`J11DbT=Y~NMY$SK z5?HeE276;*)^N90TL{yD+8luxsL(ruDZHNmsUcS#jlX@i`?T1afV2EN!DAsn1n7(! z0haVjQaNzDcXW1u)nUt=_mI4$AFs}T2F>$T$|hSW$Mj$t?uyT|Z<-i_IJok}=BMOh zob2Kjuhv#PuobnC% z4I5<%*_GeM!-Aru>WR}B1}H~$Clb_wYnv{dcIx!qLP2MrRWcZxEB4EWs5+PI(iXij zC~vn07EeIggT*~;0?cnx&!vZiAwMD5>5HZs;>F=*z1kLi=k*vo^y6WN7oYhC>vbRLUB%H=L1 zu8g&~$p9)Mi~W71DacfdMH*@v0IR_Q^l8rSP{eU)ux|zJQhnLb!Est$F34f;lkxOX zB|{)n!2UqWH3PKFTu@&Yn4;z{ADvcxm#M7u2X5|_Yc<+LrU{m#iZK>)a=zZ#u3|oR?lg-V?yp`9*fD877Ea<<~duKy`CB89q||S=9|zEu`LoV!H3H ziHbv|i;_=~yX` zdQs-IO7o>tJgDkAk@>XVdocv=yF2w^bv5dzhi*H}X<$Y)38KfPplLNfi!?yaPce!hzm#$TYQayhD&^z4qQ3FJ~XtLIKUiAr=l?VH4oAyT?RVxVG4aZH0~diRZ;BZ~!jy|VX3dp4YX zkHL_mWco@8wRTpR*}(gDBipzqy?iM4cdlno}P80&5-qsndV=C4-v||OFMA>1@Dd^w~OwO zk8gRdts1`1YJwL4Tt4oL8E!M`o`e_-Kth{5Y*i2(w59@U= zkfV3B44-Q%AjGT#~-q?pRX3jw~s-3$ecp7x9HlwOt1hfZkopMQx)V;Ljg8YuA*_ zTe@D4`2TG&z6>x|c8uW>>h9H%*Duz2M2@!HT_e91byGfLsNQr(rSu>1Ckl6`YNjeE zR(<-ku2cPVwS02nHx*(|83W`Nd@HFn*1;$PG1I)e6T&zM5Sf`*-HLr{hU9tC&S zqH#S-vOuPPd^9xz;Ut*c2lI>O0@QN=v`b{AK!&f`mRd`O{dpkiP*@ti*~ueZwrvhP zMljWCOd)AKAkOHQtnlXc>9+ml<&kRwCeAYEB-_mXn(rfrt>QiwB)LfdA+WME@950d zvpRIS1-Wk3HNYc`JKRkB(PQbM*m^kkl4r&4N6toSoc!AZ5zxpeW6s(=PnPM zC3X4^9vb^1?9T57*lye1LkP9k|Bd}KqfiB*veXCA4e!!P=Ic&KQ*htOn-ABAq}v@} zDJ_VC%IR%SLDA=@c*osTO&^K@J(iWT7KPHo7)FV2JkJA(R79yQwB_Lm`yVZ-nngkr zz|D-UMVdmOPvv3t((A#a&FtR7;Q;UQQ~&hG?1S@(;<(^DkUhte(&Rj$9msakPh6lL zevX&v7QD#kny?_+CUv@dcY7+3kW8Bwt?MWx7n^SEVuFCM69jw%u-eU_{|ug|O{{GU z^1Ul=b3)Qt+4|Hs7vV<^sG{L8_98&Fv5~kn6t%_*@lIgR_HCb>Fh*q(Dk=nk^!7Gb z>o+g))ElS0i9U^#qdlAmF>ymzrAsayD{A3C7}Wn`2K|C4=@_GsB=R3U!gRjr>EdRt z&Rphn2{pW9Q}hj7>fKaCfgfsy2rBvxO*PYz_oKcF@-f|G(!JtSBBZt{g-lVj-+uT3 z%kCg}NeKPXh1tza8a@X^S3MQYtXN+m+jD;#@fg3W`S!B&Ntk6JtS?XHtVh5fmIjdW z2#&Xf;2$;;v85u5wbVYGUYdg;FcK$_MI8|VwZMeXWN(oBJ;av_s4g13Q7LXq7-xWF zX$I34kRsAC!1(uDRPuRqgD)2A?SBabyRoZ7ZBKW&yL!3F9boAO!g=z#)07|_GmU0J z9iEYpp6y0b2d!5qj8F8~O zbrlBVMQ36CZr-uC4xJ0bbw4s$zF?;;j&-?wl`^4yqv&ssWyGg7Vv}Da+zP~1UG6*) zoUhMj$`(Jxeq|#x1Zul$wxy}jh}HboAz-&uY{{Kp^kMIa-)zH>DX9->&2^YFH(t$1 zrjWZu<{kU*!^p`ySrE%t6nuyce(_xD1cJ(575*|^N4e~{V1l`qS!_sL`X5Cx=B_R$ zb@QA3F!{3k2-5XF8;qLiwrQsFrbekd~PA%c@~6zl!u)w&iVbwR(!KPr+2)j#;J% zlaZC24sf%u1!i#s0!uiWWkbqt&szvyM~VUf!sB~RJ#?TBZ4Kvd&$cYFbZt9Ca#t8E zR<*=w=@CqYjF@8@Gb(@4bcw5Umx(E};!A)8OziH=;WKJyATIH?N7VLY0|6*3@cg!T z;HyI19y*e$HXnOw_J$-ei07Ml<&J~%)+#%NgT-$E^~yI(96|2oy4K}~yxIBjh^G=Z z5v#UF(p0JRdc2$;eCX7r&c(juhY7ac<|9l#7hjFvWsUJYmJnyn;$B1T*wW%%;{bM4 zRnbA+#5i#p@7hu4%ghAk##5wiP-033RfeA9pKMflHzMRnS9ROrNY#QH37*pDPw(Q1 zE9AdduslZ!sBOve_UYSqXmN66&q#^TX81G_$;T6D7quW6Twc5!7%cWS?wiMj)HSgCG6t+&pJ9iM&e(*v_~oyLwZ?c2kFR$;<&5zzg@kn@1Y-H zvN`jx>!p``VN-A|C$+yRMgv`jGv8y7Q4lY&->N%#(mzarQK^F%HXenUvtB&wj2U>@ z{qFyoZ~k2fWT;A4I~t(ce94i)WH&@=7|g19p6%&F2z*BiyhyrF`b+n+-jjG-oYzn)Wv&AUybak96kEW*5DgyG&2;r}v=y$jX!je9529jAD)7j`-r(WI1K};adgVe> zU9^*-oCZ@$+Mfi>L$y+u4n{%YSph;Qr&Fu^;U?(-0@_D zK9#Y=Q_|2U?1LWb%jh_yqU1ZdNf3V+0&I z9dfCXBZeL;p^>v2ryW%s&MuU~oJitQav`SxVOc8W z$K`#b=tf`)wXXqaOsMVDFP%OV`k=Dp?5+}5j^8-;<*qcqA72$W?9A*4I3O?1@{Z_> zv+gm>C1Cb;w~<`BD(*u)8z>UEO4yp+zHNy>nnP|^QGpwxIyp!ogYl-JC-m*- zW*{nWWiEudm!<(4kJEo}By9`Q_MH*Qs7z!x{hQVyM+}FdTjug`$opMwXk?DhC-h2* z+<*=k(f8L27e9|A2-98%EGFH3N|LbSi1>gVH!5xZx9a*;h{8(g0{n<;=OsA2^^SFf zrNN~+C8pP`57x7`VZOhS3^ApQ?1H^bl?rZKL50yoo0P-})fmD~W)+t|+j8b?UC z)@1laH6*d-FN9y+xZh~(dkxfxS0`X1udo?|TD#^yoY#nUIZN`c@lD|lE0einp_c|NQf)X%G*) zc)0}*s2^du@1GNzuKko#tmjfiQu|LyWyTKnAuN;p%J_w!QV`ACUEpxL9V}`0q`qj& zXAQY{pwPG^_MBEa3nB8|L)4l-VfgNxaZE-3c|6Cv*Y9e@P5y@F_t~_;I?h<>~@i zLmzG-0R5hBLeJjC!~2XJU29It`JOsNy@uJ)CUIfgfe@;l5kf{d%Hd#84lcPM#tb$c z4&!950{B$^wU_-srCqH2yAZz?VUAoBvvW5u))WD~4pMmUS#U{e`p51d@onG6)KECg zP;Q{qH1Ui!gA*sh^~#5NzjtS{S8==F2dXmh1yTG6(pDHC%H;e}sz54z;+t{%EPLtu zosVMyf-Up0yqAc{gV$m;agl`et`v!Ko_SLT`eM!cYR}OKWELL)PpiW7VlufDAIZ#^ zrJLz6Xm!hPmOZXLiJ!X(e@uSuZ!E4Sw_&|Glbx=Kf`1^PV24__O3?G*bFI@^U^Bw;>;@%nFOk@NGV)mF6)C2V^lYwS`__BIqU|e+ z+3lSzHBuGmO|Q1qL@1ZSN7~=JttoZV>1Bd2Czv#~|2=sHp|KWC6-ZneS|>?Fiia$Y zz81>pSm>i=SY#GaCFi@;jI357O>T`F7tS@p%!he-BkJqa9V4XGj`q{%X$B8DAKIt_ zn8$)rZ~H~Xruny#n2+6Z+OpvdiJ-MbCQ7;9f#QlC*@AU$B`PNssSkV zeX+tx-}p7n3sS&{wg=74TKDg&`nX43SepNSb1Lt-Lc9=3mWWWI52|-5Sbvq|;Savn zp+!UALhRZ$-6vKMkyNXj$JOV#6D*pg`p+jCM+5s&_T9~-6buF#9?juy7qeoD5ecc5 z%C154-Gq6>AszwGu@Bf@#iv$s2hobiVT`$8L!|09J1O{=rDi{f z2MC-W<&I0g&u#s#)EEyP5A*jPYZQTBv9`_C9jq}S0Lb*{Y>mWlSg<+ywW*t2G~eL> zoQl->haEf|HI2HvKN0NsQB|ReM91zKo(YGM9#d)Sk-xFtwcLv7BCAF%r{V&3k=iva zxeD#PSOKTS(E3H# zei`Qs(Fk7Vg*8xvlgdTjm&LYEr>C?Eh+!}Ocv?9g7yT?ARo79uSBOZFK)1M7z~n;) zoFtP1>{#w(wEJlpxu#Rz92pthx-KIXM^8>jVlG`O0rAFJuL#H45GY*%J~OfD{=L#A zZ1}T*=tKUBDYh+tUf)EesI4YJ#YMtBuVqr`A7@NX{)pYZ_x1Kv3>?jJEB-n{Va_}E zt;6lp+KHpfFA$`AoJpUp3~%jehM)Y{TVatw>5|bR>jI5a~1d= zDq4NuAd59?tt*YQq7C44bxr9D=ZHcofL-W%`RA(KkvYdep(tBoOz4pygUjPAEOQPh zs-csS7W&?cG=cJDkUsIods5#wj0V#Ri*9m>=`>-JnaUNRD2u99;M<>Y-1kHF9-}$@ z3T@1}NiM}s=Nv_euBaT47=y5LIQ&FzQYCp$7Jam8KvhibfZ#?+T4sYgc^eJ7tzCQ% zP+rqSJucvv)IR;x(AcMHG`1(z?-r{e@c$lD_6@U-@?-*J<ToMluDuwM41}{E;s`v-zYsZ+Ox^D%W?E3h=uXeCW`YYb zom1lHVGqwOWIFXWl3f^8#ALgJsH*FJ&2y{MYV<~`(C_=zNLFEQRrW7te!WZ9rL;d_ zCW!i+x*5_~R_rch+`Eh0tfLSY*>j`eiMrt2%Jt*dV2z_jmQ_kSow(1h$P478Jy!>lB`a`08KB7 z)Z0*i(MtYAKIQKVH(xKM^~`@(Pm^AZtvBePq%rRGH4ZxiMHI`~o)#4P!~)vpk#B(u zBD+okVLenl0xnVAqsauvH2{joMCqN9Hj>_mi_9wA=6EwD{`HvYl`4u6_=RL5PwLXO z;QZb(J`=~u+0hB2RGp&Bl8`1fQD0%mVTsN`Urk@8=~QCgSoJ>Ptl;blw3d0&7cZmS z?yEb~qP5TMh__#*Yb5JybayaaES$cvcy!SR59zPBA@>PruE9@sRzpl8)qhpYCI}3wUtFx z*r(1vf(4#i)~)+z&)WJ>Ee(*5;yvF&SS7)nis3;NYOpL4p9(li91PoES{O}S&*%ex zM>&W7=BJP3_o*5f!f+jdRJZY$!EXAL>wJw>YwK4&%h0!ykNB=u+dT+^7L#sUS8+T= z#v)XtPfJM#6=(Nbx^$s<*_Xyg-I+?L{mJKLv(N*bAz-BCDl$;;aGzVex@IY65IPPVmObhZkR@55kIyGDQWT%&*MkW@hP(3K(?m)S6y0+a`@hp ziE1v-1nP|AtGs~1SZSV48bZ1}TAqx|84&Ma_=|*U!mNZ0@~4sqZv11^D2{ z1){SXUN7u92gIKwi&%D;L6>B1NC$SZrkRp!&7uF!e-oqz5613@Q?|$%FfOCi65RN@ ztMO4__=sL#`j;~${`MHYn=5fO0d>af~-+K`?UD~J+IVfWe>dyMYZ;xytKLC?B$Rxq&P{L^N1DPhwK6&%Y=vjoj&8 zDv~4KU0(n_13uZA$_`U0_*iRl!$R8u?AueY^89J$ zVu-)&pw|r_N)BU%vr-FM`zxaN2_=JJtfYWyBB%6Rm`7l{%piz(YpV3q0>rUDl2-`v zF)kOUZ`GkR8>S=uM}^AmL?;PSgtliLF(i~=~e+WMc{51!ow_g-ao+xDt$ zTfZ6YF5f%@kHA6FefAYsI4a5!G~liS8Uqz#0c_j$FTXRlzg6;ha<|bEHE3>|8N$c1 z8(;{D`h6U&_22raXUM?Y%eU7IYDZ?B^>9Uy30N_XJw{*bRI1>-xY17t@RFwd((Um; zCqeTRP@-Iy6<1OG`Hbu)FQ9|%2k=96BK-tDlM}^&O-K4sDn4}t_Pe3W$aqg=zHK~` zn(tx+i*VPfY{(LVoNF`k2@H(Q^>mxQ4*_9NQ-VkxY8S0YCiIG;JAoaOc{qHB#7GnM zO~`~&Lc6-)g7Lg(3ZSIARkWpUAJnTd+sy6!9+1;0v*2cl(FlKXV1e;Uv{<4`N93u* zAQqW~p@kUEI>*nUMEay^pE8pXo{2PPB>F85x$b_fF9ZY*l_TGAa#{d>b5L@I(YJqG zb%qhl`X^i|*;D~p|99=_ch9{-7zpA&UAL+Onp~eZPb@xT!?ou3en0SNE$nm1g}KJv zVY3}IOyv)|Ru0=(BPbriF&&HY7c}OUW+HW$7ku_42R07p9+Is;ulq3Vf)5rM&3Wib zo79s%jU|3;XjZZGfrw6;twVy-w>r9srDdZs)l{K1e1G4L_Y^0q2r5<}aj-8-i_zJs zy2nHm%eP4C;`8OWI!qmN4ph=h^q(BXFZL;hIv!mckHp1CI>R_0yzS4~ggmG-4^ZAo zOVe7tm_pYix{8{B6#>)8%p|-21$znQtOsP68kVJhY0+ca5E~!Jafoy4KmATm4WF?G z8eE9#l!*qN0=d|EJf%35cqse5>{1}UD4W=)&>5VQE0sl4J0>%=v6{u!Z24YTsT@Zh zfnrpJk=fYm6}d*8;G*hxtQ3|tcg9L<_ce|gOJT1t$W&&ieGeE7;6m0M>Vn3d?neL= zp!bIQI*cUyfvy!2A^R6VHbxTN&Quf+gI7;DJWjAw=PIQd;3L6AoDtX?ih_h z2gh>a{E1S^{M4`Zf%_J4KB^VB%N%K6I-0SWO8XD9y|?{NG`pM{wQ3f$ACn@(40}$S zu_4H4{#eRZdh~oje6Pc55dV)U2BJ>~IZcOj*?e5Y1goAd`&xNGQybPjOs&wHpbp}S zKA2#hCQ~r^ga6mkm{gDWSfMZIp2N-_ZdAW6St8mnapW1=_JV19n|v54VSphrpi%llm@W_gk=|FHGeekC zOAXwvek92vFN+ahv)jqL$uq~mkR$OGx)>!2-URAo;~rdyJcbXS=}TW~K9khv#Fy2ky1zoQ9oHlVPN&v7=8z~{ zea){#&j<-m-ZKAe#5&%hu`*6>d$2wQ3|cv58}FbmV}9fWcJV$+DF5wWetFe7`%O@> zL;p6i>$A#KHC`xc5R=?$f{oq|Zy;0@0@`6SZv+?#TtR{YjwsHyAs*OI#cw0gn4gL3 zgjg}+*zQ#h>6@K(Z&}X<>m85^rpgJhH~S@hVR6=bxH>bLcaW<5HKic6RFz5&NwDL} z7(Ij(omw#C(H>v+Bw_374(eIU_zhOogBc69@e4XdIV9SSH^szyUrNyc+HwAJYGN8x zgXnk-w(aY5tpI>Pke`Vq^25#5Ruj$w$`h4CC)VA2AvrsCC{_@5fmcGJ?2#c_r4ZJKySUV+G#Gah&s4SkMAyb<5#l=U?Y--0m_q z{V8K|wV}{)2WHfSF}D2+rgCz+`B7sWX_M@SmO%XhFOlppBqcuQ zj2(-xB`{lwUk~Ji6*i2iEi*RrhQJMrQZCPx+4in^%vilKgV0^Cam!PPn;Ulq;;h}g z{$_$IJGFOITq$aUK-C2Y$@#R){6ZmU65YLGnS;`>MO)0cg)m8(6H1ZR!zfL{3X0DD z;$wVfQyoOFT_OBUwD$nHhV{ba`hg1C%(~ep5hQN+M(7az@~&zld^4eiIF>(q!TgKG z*M;ClY1O%9_5agG3bSMSX=8`%EhBLZU-RpO~tSvs8u93e?ul_F@8J zXe-Wh`Y?yWRCF|YPj{N&yO-o*a-|U#py)+-*-rX`y-IdAR8k|tnHDX`Lz4NTX^!Oq zuNB>>8uJ;*Q3^#wf=Y*=uCDGhgiv;O*Nm%JoT-Opt}`tzylRCOJpV_-J`&x8Eo}fe zI8!OE*D&;LTmgIbo1|1RsnJdhd`ioNxEA`cwzoH7mUXZJ%pL{T0~Iq;5(9(-wGGRy zul44N86mM~!K;~EM$Yts*%vr$9h`2o=7lU6CI45<9;lw`;LOC=IqM9rQP6OBS z6&*0h2QH`*0Ud^qo>(08fdm^*9 z)X~MjQXl{=OGSQ2#X{J=bYUiqM>FHZJoopFao}{{cVWmca30(U(T=~JrII^Jlj-{b z@j}f!_q1+$S~(J4df0Hz+RRT@oPC5d)M`&DYWj>Vq;1G(P{q}&Q3W8eCkJ@Y&q|&G zfEd20OQ}x962-0I3Ru5bA&?bv@g4^<|=kClk_*2dYmR!1pPg9>JK?T zBr>#uc(TG~@%sLaI)Q+1fy!w)KX=MMAJ-XfjI%E(H|;8d)|QSm+sS0CVVAjpUUq%- z0vq6Xbi`vR`a`ExX@fEu*;eQB-V;kx(a7y@=G@P3=zV*QmXYP%tsh6$PUGM{vP+}g zk+?bFGm7kL%?~WlkIpW?e^IQ+)@>vp&a0r*r1^1ua3bPxCH27FRUb0zZ|0dLK6@5&@9(f{&wRD?SFDsrvqAT;_W~rW?M;PhgCtM& zMJRH`11rBC;W^_`$5!tGEbXk+Ug6Z~k>U9sliU!7uD!IpIXs)~1E@F)CxpqR5-DTk7 z<5-td8UzyZvyDTY;6{r$^Cg;%OORegCG(noR(e@l>o-OArTA~jywgmZ@({52_;CrcU623pg%P+yVH+Fu`>c;hOW#@u4dQ|DXw>-B)P1j<5 z$}eo=ZFrWfL#zccdtLc1ZJ_e~ED`aw&$nNLt7M5mt(>Lt{SKvHV&Ev*_fRJob0xm~ zg+Ufr|JoG9t!dumwi%@Em4DS&5??4fExj#IMd8^kZ{PPFn<1>u6UZ#2fT;e0U1evL zepkx;u*n%vKL;5+8tyt&uT-z*nz-OzTW}6jf`saK&&3xArro>k=3dR?@h1Xj_xB`p zj~BqkMnKtiMkRha#x#tR5Y*N^(*___Xl2gr(OwJAMXFIPaMOTgY}p4iso3sXqRO(l zPz>{K%&q}ZGtPEL>ZDiUfy%K=iw1p%ex3=T4<7PRh}pC%ZN;CjuG}K0bD+n~BX)ZyCmEgJbUd3}*ZZE;6h5311PI(_QjO(B41>J)?>RQlQFYlC#dp_Z9 zYN8fST}tSr-uascYH`Z}DrdmF z#gDdF%@N3}*UWrPw^eJcMNwbmUwdtm4MsY?9={g=>;W*7aMm zAqdfnZ*0Jk2Ih#W*~q(5s;vM%U8Tk9INrRQ%Eb|3OxgV>t8-&j5`C@YKk}Ze$pXUC zL1Nz)_Je3ndB+~+*v*rbECE0L9$o7uci+up(#SWg6QIbsy_COC zA<*!}|8CkAWQK+}dPwpen*+E*)JFS}+g;2L*}c#PDFW{VEVQDpMpUrbWZhsQK?bhb z%~{$hCE_YkAL2Srhh<$&G5|e$|JKtC208!NKr{zAV%5?x;~r(g*TQp<6+fT3QA|L$ z8+dX(wE1hh^;)szhv^E2?Kz|sG3J&A>RSBxMUn+&h$0v3dzXUb&sHgOb9;7y62e)@WD#t92l$?^FkR>WCm5G;ks z6`QnXk5MGXju1tX9hi}SdD5MID50suW$~+FNQUz0*D{V-tOM>p1{i>t_C_9Ci%9_e zW)x?qCcc;nn@NkPN{<6p6E^OTMMVaVzyj-AcvSOKp>`6TmjSDB1*c6Nha|PV$UliF zO#*bGYFZ5q?1hXam0s;);o;aW4zjaq*H4?v!CR*U`B+m(1SSfDfze54Twi!YKiq-G` z@J)%mrJmuEs27Hf=puJf38@N^o05h8p@9$Z@;(}&2e_;678npvsYA8|;}pS1g$c>X z9n=SDIQ1G>W>Pru0_z2a!ZkX&QeHS^M%Supd1B`Q2cRg=oyD94|g6S1W}Vcprdsd zp?Ttk8lk-dO*l9K;ttGx(+(;9a=Irumc<-@N!OtqK2=|}F7sS(7~IEd>_f-W=GCk- z`n5shVo0njI9mB?Dn#XSOiq>yp(T``&ddZps0F8gYnZv(K7%hhK6T^VZo(?d zaH-$50uB{W8rZ)b*&ilo$$-nnjy43c(qj04bv&cacTtkHZE9I;s*tVHjd+ecR?-Zp zd2}pUHcST=cE6Qk*^tcydpXtAsLMUnl8Z1^_Vkdp>!aZ&?PNxR&HT#^+=3Qk1@ zPGDCkIt148k>huAgdk7+;ayte@gtS*W)Hr{M>dMf<*k&H)NjK*0?jkbBjytRra=?Z zOTGzj3_|frrY91kwpy}T#Cm6c;8W2m9OoATnM7gBsL^7(>zXeOtIXT_iM z%D~@CdO&8b5p5ocz-EV)UK&cp%$9(S@&?{YU1DSE{v)T8xgcC`%!8B6q)65s zPN(~tuEz_WUmRNX1TFfp$0&~tfLi@02~AVTbd+vK#Yrwi&1<@Vm#xOBj9b4GV>nLn z0@WWuWH6+ZxG|{>?QPLS8&b19!ufETClEP7m1dO+mIHHuXW^F-^IR{(CIoBOlAbQm zZipXMCK|&vmuWRylpb^(Qrn9R75m6rAOY4Txkl8TIEg}T*y&!z^!YE^0OP)RKDRek z*q-w^$RV(T7vZ>CUzTfI!M-WGqk*4wu+pWwcEE*L%z9(m8&kvzS(m{}$yJ~I(dLca z!rgBw9dr+E)>)5yZoUag3X9PT3-Xbe7Hp;4tv>Crty2<3Z;OJMN=@?Jp!Kp*4;wR+ zEb~t}Y3GpW#1InYY7TYhE8v-~kAV3wvB#)Y$BU^6#-_@#aiG z=cerz1EYKyRH26*n6wvHie#%O&4d193J|$M*t@D`UyqwQjd4#Nhk!?~AhFCu1x(%L zIPwfi&k0{O!Ec641r6PLH-w|&I_N1^SrNrNq6CVJf|BT_qRIduROst55~jXM`u7u= zbW(3p&QX{K%p0wx%}Q{zasAwnhk;$YYu-GDMTL2bf89##r=WfWt)%and1WcnuFL&X zx+eB!FCpv=FPKn@q_NaMxmyB1!4GutaV8s7&SQSe=rkD149!*^uEhCXkM7->Xac|3 zq0P#1Yo91!h0eLup-tBJi)+}1z)SUZ;1l5ttX=B+#Gl&Jm*2M=42McF@#aL-$F>K(0Q3AupV&v~oijz=mbn2lo0%GG1; zs7Q{|V(bbJ^bps1hiudEUf`X~jb}Dl2JV{p5G1NoeJVL2r~6NDJil(NAWF!tQqTY0 zud@Xhq|9wL@&d(!p+lIqK~huq7vHS<6*$m5{MQWC6S#C9_=w?O%EJ-SxRw$N<({ z?+06Hm{>6q7cYo7TZ%FC{wQ9xen1SdFbp*;3R!c5hRyuLc^2bu)X~(=8ImI*pK=6D%$2>?L}z4}x5a=&#{BjUeY+Nzkn_)9(5BX%)#JX@dXC{T>>2zTAolS1~s5r&4 z2&zghJM}xxgvgy=uXQG`agYv!yDo-~P;B4*Fw$B3y)LC4@AL6AH>Xcr3X=b9W`IN?x7vdb9@sPR zp(Ei@3=F(hJm9q2+|*?&L*FNGeKCpEN%kWXnSWbMt>U4$FkIiZHu}{V`A(TWK8lR- zB-_az?HZK@F|EgSZra3Ek_J#8on(|9>tIg?`zVweo>J-@YX#(|4QUIp?ay=C|8cFw zTW&qcnL>Flxz|uY>g9gpw2H5k^SioI6VQsM_KN493OAHiVAivzkdq5-K+qfwxy*6zCw zy5|reS`O2~uGh*b7%(?+Rg@g^0kX)vdH5>z-P>_1)CkV#JFgV+sTgvUU7Gzs6QOMvgJNm6e3_2?(MFCVR`FAx7H+W zU;0|KDwc#wPs@j;Rh1gF4m!`x2B$siLxWPRX3%)S~(}aQ6S4Ac=-AQ#<|7Xij**PvE~gI)ZRT zAh7ew83_@;46#nLWA0P%HTS-<`Oq^gI{$eIshha9!)BmTuL@3aoK|}saYc7rU+AF3 z*D3wi|2Vyd*RB}-K>rwI1N=&zwNkj^-Eh^s)ELjtJ@^<(mpmi3$`!mnch@ROK^6!GcV|P=>rhB{T z^(&&`-kFWi@d)gvc9cKi4csh+Zr4KC$RBc18ck}<5J%067F=T8uVn3cZ0^m;%Wm5~< z2JpOmjfwCb%Mc=R{7TYv{jEFrII^s+&ba&KB8*EE>kL5{VVmVMZNp`jpzG->jo zT#S<2l~=cRXt{rzbY07qgA$oAj$hZ<{1~VX3YN@m^4PM*qm2Us5^iX|GE;f>^L}Nu z&wNi%r)B6WBG63$Hw;dsI14S7zWTMdG$xT!3>$yoCMR6V* zLCC|`7X(9B1pTaEH`oeT7T}GX3gsO7{*bV5iS+MQ5XkNXpY4TjPfk2qD#n+df^B%) zntX>5%%bp2CL{I9rZ>0mTc$N1BUD!F%!`3Dy0fpS&{-Ypu`>%rnQ{R&3(|;aS6T%? zg8hphJhE=g_3-Nr zck&%Lyx^}}EW?UPTC#N=H!hOJSG%3Gt>|uzJRYm|nFy6Bx|?UulhP`~i&%mSaP^O< z^YR;q7UE#@91m?IIW{>K{RQ$&^lW{cWqaG`gVO=(CkI%0JpwKm2{|l#m!>kw@YsP& z|1nveKU36Q=kg_T9s|pNh_HsO<1I!%K;xtIH4|I_vJW#RfT5r6AOc2GlGN*NGole{ zchH=sF03x(zV}y0P-%@TH>r%)923VzQM5`amnJ%IeDX4auSwVPP$~>DL89+1-a!=i zqEpM1@{I8Fh)ueIG3PZ}Efu}Nc9WU30-byTMZeQO` zh|AN&1HtbRgKFt>CW!eY7J_Rt`t(gE%axdh76ATGJ6+W2u;)lnlHVKHYFHKS2=s2= zzE|DWuEe}%y%Ow7F{!eSMgBXEnt}?X1+285ft1$g@u_lv!3J>p?9MrM_<3sON$g@0 zvVi2=(^>I`d1xk*H@77-mv^Oeq79lh*yV`=s=xFKeJbGwR>$_*)_XPM471raqe>74 z=yxOaeJX=*!U>}*!(A$_EWDDv$k=^Z03&F~Cq`M^;Am8XA@5++#TK`iQ0>tXK;#nPpZBTQxO4*G$3qyU&Mo&E zxQ{{_%%_Kkdj+nPvq?wxrVanskW9N%S!`SA$1N$?q2aka4<6gGdcvbRu&ZW^&yq;N z%9qD>(R_dZ9dP``Pr=viJM-x7Vv?<}i}u9eAhuI=k?g|5Qpo~s=J&qh\n" "#include \n" "#include \n" + "#include \n" "typedef uint32_t addr_t;\n" "typedef unsigned __int128 uint128_t;\n" "typedef __int128 int128_t;\n" @@ -669,14 +670,14 @@ def writeProlog(file): " const char* buffer;\n" "#endif\n" "} mmu_t;\n" - "#define DRAM_SIZE (1UL << 32)\n" + "#define DRAM_SIZE (1ULL << 32)\n" "#define SCRATCHPAD_SIZE (256 * 1024)\n" "#define SCRATCHPAD_LENGTH (SCRATCHPAD_SIZE / sizeof(convertible_t))\n" "#define SCRATCHPAD_MASK14 (16 * 1024 / sizeof(convertible_t) - 1)\n" "#define SCRATCHPAD_MASK18 (SCRATCHPAD_LENGTH - 1)\n" "#define SCRATCHPAD_16K(x) scratchpad[(x) & SCRATCHPAD_MASK14]\n" "#define SCRATCHPAD_256K(x) scratchpad[(x) & SCRATCHPAD_MASK18]\n" - "#define STACK_LENGTH (32 * 1024)\n" + "#define STACK_LENGTH (128 * 1024)\n" "#ifdef RAM\n" "#define DRAM_READ(mmu) (convertible_t)*(uint64_t*)((mmu)->buffer + (mmu)->m0)\n" "#define PREFETCH(mmu) _mm_prefetch(((mmu)->buffer + (mmu)->m1), _MM_HINT_T0)\n"