diff --git a/.trinity/seals/ternary_GftExp2.json b/.trinity/seals/ternary_GftExp2.json new file mode 100644 index 0000000000..c69a0ca6bc --- /dev/null +++ b/.trinity/seals/ternary_GftExp2.json @@ -0,0 +1,11 @@ +{ + "gen_hash_c": "sha256:4622b231fae99d22258e7f918ffba79d6536a3f9cfc84be4893be06683ed046f", + "gen_hash_rust": "sha256:3ad0d2798dd31b1f2237ccf4d8e9bb58f98568f6aca15d8a70154eda53e089c9", + "gen_hash_verilog": "sha256:01824789d4eb57b9bea30b6e740dd785429487973e21aea9bd7d8f974d4ae908", + "gen_hash_zig": "sha256:86ba88aa4c6d45064d01d183a682f5a75bf59c7e1c6831fc09a0fe6f9ce4582d", + "module": "GftExp2", + "ring": 12, + "sealed_at": "2026-08-06T16:24:43Z", + "spec_hash": "sha256:52849a662623d3213c2b5f2c397c84a8f75045b867bb210ca9f322a4527d30f4", + "spec_path": "specs/ternary/gft_exp2.t27" +} \ No newline at end of file diff --git a/.trinity/seals/ternary_GftLayer4.json b/.trinity/seals/ternary_GftLayer4.json new file mode 100644 index 0000000000..fd617e4fc5 --- /dev/null +++ b/.trinity/seals/ternary_GftLayer4.json @@ -0,0 +1,11 @@ +{ + "gen_hash_c": "sha256:9bf0c0acfa30c4015949c67d9941253db0bd67b7f02be99c62b8ff0d8e11d159", + "gen_hash_rust": "sha256:a6a71ad96385715538578c4bf47745459718194dc3201cc96dcb0aa0ceedd09d", + "gen_hash_verilog": "sha256:4329ebd770dae1cb20139e795371e43b07b6a7494fa0626f954a4927c7cfb661", + "gen_hash_zig": "sha256:0faf6c887362433f449fbb8ece58c1ab881fe120664641ccf844e753e0e12bcf", + "module": "GftLayer4", + "ring": 12, + "sealed_at": "2026-08-06T16:24:43Z", + "spec_hash": "sha256:b47247ab396672cad9a48e3429ab1ebb09a9b729e0ea8a7a761505b56914d456", + "spec_path": "specs/ternary/gft_layer4.t27" +} \ No newline at end of file diff --git a/.trinity/seals/ternary_GftRecip.json b/.trinity/seals/ternary_GftRecip.json new file mode 100644 index 0000000000..687251a7f0 --- /dev/null +++ b/.trinity/seals/ternary_GftRecip.json @@ -0,0 +1,11 @@ +{ + "gen_hash_c": "sha256:0d3f730a503ad68b663b25c169f5ac98021918c50148556af410eba34ae15080", + "gen_hash_rust": "sha256:5d4388dfab08026b34849e8367916d69571cf0dfe989d0d21cf71c64d0ffe62f", + "gen_hash_verilog": "sha256:61ae0eefef219c08ae8f1eef692e6d0fef2a37117cd303b819d84b378557ec92", + "gen_hash_zig": "sha256:e0ec5bac7a5f1f6569509b5869fdc8ce47be0e885d971d70f25a2d5444749fa7", + "module": "GftRecip", + "ring": 12, + "sealed_at": "2026-08-06T16:37:21Z", + "spec_hash": "sha256:29996bb0f8c54f920745ae5b4990af7c35d7d88513b9682b4f59a30bb342ba31", + "spec_path": "specs/ternary/gft_recip.t27" +} \ No newline at end of file diff --git a/.trinity/seals/ternary_GftSoftmax4.json b/.trinity/seals/ternary_GftSoftmax4.json new file mode 100644 index 0000000000..6603b8b4d6 --- /dev/null +++ b/.trinity/seals/ternary_GftSoftmax4.json @@ -0,0 +1,11 @@ +{ + "gen_hash_c": "sha256:f7a75ffa403fe0cad383dc525ad321e8bc0eba1a4c1644afe4f0e16a2e2277af", + "gen_hash_rust": "sha256:9123d46a1037c9c4a731d18fb893a318d40874e533073e5423a1dba037ca19ff", + "gen_hash_verilog": "sha256:f3a3f96ebc601543d7357e8d8ddf719c170fb5022ed95dec174aa1324a372af8", + "gen_hash_zig": "sha256:50bd63072a2bf4d6ca27d413afbc08298be4b9bdf7cab039c90d275f795a2693", + "module": "GftSoftmax4", + "ring": 12, + "sealed_at": "2026-08-06T16:37:21Z", + "spec_hash": "sha256:8f1855265b9a598a2d50973226ebf78aa05d96c0a03d5873bf1391e54a2137d2", + "spec_path": "specs/ternary/gft_softmax4.t27" +} \ No newline at end of file diff --git a/bootstrap/tests/gft_exp2.rs b/bootstrap/tests/gft_exp2.rs new file mode 100644 index 0000000000..088250afbe --- /dev/null +++ b/bootstrap/tests/gft_exp2.rs @@ -0,0 +1,78 @@ +// ============================================================================ +// Check for the spec-first GF-T exp2 primitive (specs/ternary/gft_exp2.t27): +// 2^x for a signed GF-T16 input, result a positive GF-T16. The missing building +// block for a GF-T softmax. Bit-exact to the committed integer oracle over 606 +// vectors (tests/gft_exp2_vectors.txt); the oracle is itself <=1 ULP vs the true +// round_to_GFT(2^x) (measured in the prototype). +// ============================================================================ + +use std::env; +use std::fs; +use std::path::PathBuf; +use std::process::Command; + +fn t27c() -> &'static str { env!("CARGO_BIN_EXE_t27c") } +fn spec_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..").join("specs").join("ternary").join("gft_exp2.t27") +} +fn vectors_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests").join("gft_exp2_vectors.txt") +} +fn tool_available(t: &str) -> bool { + Command::new(t).arg("-V").output().map(|o| o.status.success()).unwrap_or(false) +} + +#[test] +fn spec_first_gft_exp2_matches_oracle() { + let gen = Command::new(t27c()).arg("gen-verilog").arg(spec_path()).output().expect("gen-verilog"); + assert!(gen.status.success(), "gen-verilog failed:\n{}", String::from_utf8_lossy(&gen.stderr)); + let v = String::from_utf8_lossy(&gen.stdout).into_owned(); + assert!( + v.contains("input wire [31:0] x") && v.contains("output wire [31:0] result"), + "exp2 missing x -> result interface:\n{}", v + ); + + if !tool_available("iverilog") || !tool_available("vvp") { + eprintln!("SKIP: iverilog/vvp not on PATH; skipping exp2 check"); + return; + } + + let vectors = fs::read_to_string(vectors_path()).expect("read vectors"); + let n = vectors.lines().filter(|l| !l.trim().is_empty()).count(); + let dir = env::temp_dir().join(format!("t27_exp2_{}", std::process::id())); + let _ = fs::remove_dir_all(&dir); + fs::create_dir_all(&dir).unwrap(); + fs::write(dir.join("spec.v"), &gen.stdout).unwrap(); + fs::write(dir.join("vec.txt"), &vectors).unwrap(); + + let tb = format!( + r#"`timescale 1ns/1ps +module tb; + reg [31:0] x; wire [31:0] y; integer fails,nn,fd,code; reg [31:0] exp; + GftExp2 dut(.clk(1'b0),.rst_n(1'b1),.en(1'b1),.x(x),.ready(),.result(y)); + initial begin + fails=0; nn=0; fd=$fopen("{}","r"); + while(!$feof(fd)) begin code=$fscanf(fd,"%h %h\n",x,exp); + if(code==2) begin #1; nn=nn+1; + if(y!==exp) begin fails=fails+1; if(fails<=6)$display("FAIL x=%h y=%h exp=%h",x,y,exp); end + end end + $fclose(fd); + if(fails==0)$display("ALL_PASS %0d",nn); else $display("FAILED %0d/%0d",fails,nn); + $finish; + end +endmodule +"#, + dir.join("vec.txt").to_str().unwrap() + ); + fs::write(dir.join("tb.v"), tb).unwrap(); + + let vvp = dir.join("sim.vvp"); + let compile = Command::new("iverilog").args(["-g2012", "-o", vvp.to_str().unwrap()]) + .arg(dir.join("spec.v")).arg(dir.join("tb.v")).output().unwrap(); + assert!(compile.status.success(), "iverilog compile failed:\n{}", String::from_utf8_lossy(&compile.stderr)); + let run = Command::new("vvp").arg(&vvp).output().unwrap(); + let stdout = String::from_utf8_lossy(&run.stdout).into_owned(); + let _ = fs::remove_dir_all(&dir); + assert!(stdout.contains(&format!("ALL_PASS {}", n)), "exp2 differs from the oracle:\n{}", stdout); + assert!(!stdout.contains("FAIL"), "exp2 mismatch:\n{}", stdout); +} diff --git a/bootstrap/tests/gft_exp2_vectors.txt b/bootstrap/tests/gft_exp2_vectors.txt new file mode 100644 index 0000000000..47308a5ce7 --- /dev/null +++ b/bootstrap/tests/gft_exp2_vectors.txt @@ -0,0 +1,606 @@ +14498 04ff2 +15343 04956 +153f9 0480a +051d6 053c7 +14a57 04f9d +04ca7 05084 +05420 05861 +14a7d 04f97 +05348 0566e +0570e 06854 +1489f 04fc7 +05813 07105 +15686 03bc0 +157b9 03228 +053cc 0577a +14423 04ff4 +04b05 05047 +14841 04fd0 +14fbb 04e18 +05002 05201 +14d11 04f11 +15a1f 00c17 +05b33 0a1ff +0564e 06254 +058de 07dd5 +044c2 05008 +145e6 04feb +14301 04ff8 +04978 05028 +04761 05013 +157f4 03047 +059c4 08c2e +145fa 04fea +054d7 05b34 +04ac1 05041 +148c4 04fc4 +14643 04fe7 +1477b 04fdb +04b1f 0504a +0532a 0563e +05178 05353 +04579 0500a +04fb8 051d0 +15899 02654 +14aa1 04f91 +154c9 044b1 +057a9 06d1e +14df4 04ed6 +049ab 0502a +05127 052fb +1420f 04ffb +04780 05014 +15a8a 00200 +0444d 05006 +04e80 05116 +147b6 04fd8 +1594a 01b38 +15712 0374b +14881 04fca +0478e 05014 +04c62 05075 +1485d 04fcd +04fde 051e9 +04d36 050a4 +0476a 05013 +14c49 04f48 +04ae5 05044 +049b3 0502b +157b9 03228 +15568 04247 +1476d 04fdb +1547f 04603 +14b69 04f73 +14b75 04f72 +14bdd 04f62 +1448c 04ff2 +15b66 00200 +051a7 0538c +14e31 04ebc +04e13 050dd +15314 049ca +04c2c 0506a +04ceb 05093 +15795 0332f +050fe 052d2 +04944 05025 +148a4 04fc7 +152ac 04a83 +15107 04ccd +044c7 05008 +14ce4 04f1d +05b19 0a1ff +04eeb 05150 +04cfe 05097 +051fd 053fc +04d53 050ab +14239 04ffb +04d6d 050b1 +05073 05256 +057a1 06cdc +04f7b 051a8 +15161 04c7b +05a4a 09916 +05ae8 0a1ff +143ba 04ff6 +04c0f 05064 +156e2 038c4 +15002 04dfd +15064 04d7e +050cb 052a2 +049e1 0502d +14a63 04f9b +0561b 060ae +051ec 053e5 +04b5a 05050 +0519b 0537c +14bf7 04f5f +04517 05009 +04fd7 051e5 +14b22 04f7e +057d7 06e90 +05549 05cf8 +045ef 0500b +149df 04fad +04ead 0512e +14e56 04eab +14a93 04f94 +144f4 04fef +155ba 040ec +0550f 05c2b +14f88 04e2b +042f9 05004 +14b84 04f70 +04c50 05071 +148aa 04fc7 +0454f 05009 +047bb 05015 +15018 04ddf +14d28 04f0b +045f5 0500b +15b00 00200 +14933 04fbc +0531d 0562a +04906 05023 +1486d 04fcb +15734 03647 +14e56 04eab +1465c 04fe6 +15631 03e5a +056a2 064e3 +04aa8 0503e +05286 054e0 +14f0e 04e5b +14ed7 04e72 +155c4 040c4 +14301 04ff8 +0597c 087ab +04b44 0504e +15713 03741 +048a7 0501e +045d7 0500b +0473d 05012 +0520c 05411 +14fd0 04e11 +15b04 00200 +14556 04fee +1476d 04fdb +05b29 0a1ff +1489a 04fc8 +04f1e 0516e +04e81 05116 +056c1 06606 +05b4f 0a1ff +05150 05327 +142f0 04ff8 +05466 0597a +0583e 073d5 +1508b 04d50 +148a4 04fc7 +15af3 00200 +1456e 04fed +15453 0468d +15701 037f5 +14473 04ff2 +04918 05023 +04765 05013 +14c90 04f34 +04411 05006 +15b11 00200 +1592f 01ce3 +04959 05026 +053e9 057c2 +05020 05217 +1586d 02905 +04230 05003 +05387 056e2 +055a2 05e67 +05464 05970 +05254 05483 +14aa2 04f91 +04579 0500a +14406 04ff5 +04ea8 0512b +1472c 04fdd +14753 04fdc +1439a 04ff7 +15287 04ac6 +04391 05005 +05bfa 0a1ff +14d8a 04ef1 +04507 05008 +148f3 04fc0 +049e4 0502d +04233 05003 +14b22 04f7e +04fdf 051ea +15a50 00600 +05678 063ab +04afe 05047 +057f2 06f70 +05385 056de +154b7 044f8 +14ba0 04f6b +04f38 0517e +14a3f 04fa1 +15818 02e61 +1496e 04fb6 +14bda 04f63 +14382 04ff7 +04e09 050d8 +14b08 04f82 +152a3 04a92 +05481 05a03 +14f16 04e58 +04ef6 05157 +155dc 0406e +04edc 05148 +052c0 0555e +14c26 04f52 +146fb 04fe0 +04285 05003 +1455c 04fee +148fc 04fc0 +14895 04fc8 +158e3 021c0 +14f88 04e2b +0541a 0584d +1574d 0357a +056f7 067a1 +1506d 04d74 +05356 05686 +144b5 04ff1 +145ca 04feb +047a3 05015 +0559e 05e5a +15360 04916 +14265 04ffa +04827 05018 +14b53 04f77 +057a3 06cec +14d46 04f03 +15027 04dcb +0558d 05e25 +05a4a 09916 +1482b 04fd1 +14a00 04fab +04c52 05072 +15b43 00200 +148e9 04fc1 +0522a 0543e +14bb4 04f68 +04420 05006 +059df 08dea +05967 08654 +0477c 05014 +05a93 0a1ff +04692 0500e +04b3a 0504d +050f1 052c5 +05066 0524c +15283 04ace +04918 05023 +043b0 05005 +1540c 047c0 +043e7 05005 +05560 05d5e +148f3 04fc0 +14317 04ff8 +14729 04fdd +042a1 05004 +15519 0437e +15341 0495a +05adb 0a1ff +0559c 05e54 +05931 082e3 +04f70 051a1 +14b53 04f77 +14337 04ff8 +04eac 0512d +1543f 046d8 +1501d 04dd9 +14702 04fdf +147b3 04fd8 +04d8a 050b8 +04e23 050e5 +157ce 03170 +145ec 04fea +052df 055a8 +143f4 04ff5 +04ffa 051fc +056fd 067df +156a6 03aa6 +1448e 04ff2 +04e83 05117 +14801 04fd5 +04cca 0508c +05243 05466 +14a84 04f96 +04411 05006 +145ed 04fea +05410 0582e +147a2 04fd9 +0557c 05dea +05364 0569f +15764 034b5 +04b7f 05053 +0586b 0768a +155e5 04050 +14df6 04ed6 +042c0 05004 +149d8 04fae +04fce 051dd +1482b 04fd1 +14c5a 04f43 +05ace 0a1ff +1471f 04fde +1557b 0420e +14f37 04e4a +058c2 07c17 +04ca1 05083 +14bed 04f60 +14c40 04f4b +04b15 05049 +0534e 05678 +15745 035ca +043d7 05005 +14be3 04f62 +04338 05004 +15af5 00200 +046e3 05010 +145e1 04feb +05312 0561a +14313 04ff8 +047d5 05016 +04db9 050c3 +149b0 04fb1 +05854 07516 +150ae 04d29 +1590b 01f27 +1514b 04c8e +15023 04dd1 +0563a 061c0 +15037 04db6 +15a27 00af4 +04eed 05152 +05016 0520f +14dc0 04ee3 +1486f 04fcb +04a04 0502f +05992 088f4 +054f1 05bb0 +04f55 05190 +051b9 053a2 +159cd 01305 +04bb7 05059 +047f6 05016 +05ae0 0a1ff +152cf 04a49 +15bd0 00200 +149e3 04fad +142fa 04ff8 +055e1 05f62 +04f1f 05170 +04b54 0504f +04fb6 051ce +0566f 06353 +1422e 04ffb +05682 0640b +148f6 04fc0 +045b8 0500a +0555d 05d4f +1454f 04fee +05a6a 09d16 +04da1 050bd +14565 04fee +04e35 050ee +14736 04fdd +14b91 04f6d +14c9b 04f31 +05459 0593d +14d17 04f0f +042fa 05004 +14ed3 04e74 +14beb 04f61 +04e69 05109 +15090 04d4b +152a1 04a96 +0422a 05003 +14848 04fcf +044a6 05007 +058b3 07b05 +04c50 05071 +152f1 04a15 +0545e 05953 +05185 05363 +1441a 04ff4 +05ba2 0a1ff +1442d 04ff3 +054cc 05b05 +0468f 0500e +04c2d 0506a +15bc1 00200 +0422a 05003 +05951 084e3 +14654 04fe7 +05315 0561e +053ee 057d0 +04354 05005 +15bbc 00200 +0575d 06abd +14c8c 04f35 +14a4b 04f9f +05463 0596b +055ae 05e90 +058c3 07c22 +047d0 05016 +05383 056d9 +14bd0 04f64 +04791 05014 +15bf4 00200 +04a48 05035 +143a0 04ff7 +0433c 05004 +146cd 04fe1 +15028 04dca +045e9 0500b +04d0b 0509a +1516e 04c70 +15a3d 00847 +14788 04fd9 +042e8 05004 +04d75 050b2 +14b88 04f6e +15ada 00200 +05205 05407 +0581a 07184 +1530f 049d8 +0455a 05009 +14c7d 04f39 +0499b 05029 +147cb 04fd7 +059ea 08e7c +14f4d 04e42 +056b8 065ab +1482d 04fd1 +0513c 05311 +04805 05017 +047a6 05015 +04dae 050c0 +04c24 05068 +142f8 04ff8 +04426 05006 +04aaa 0503e +0503b 0522b +149ae 04fb1 +159dd 01222 +04cff 05098 +157ae 0326e +04f7b 051a8 +04279 05003 +14b6c 04f73 +154e3 04457 +0456f 0500a +05a10 09200 +14e8e 04e91 +14b86 04f6f +058d6 07d38 +056e2 066e3 +04499 05007 +04795 05014 +151c5 04c2b +057fb 06fca +1535f 04918 +158fd 02022 +04aa7 0503e +05a19 092f4 +144b3 04ff1 +14a95 04f93 +05496 05a41 +15576 0421c +14d39 04f06 +052f1 055d8 +04397 05005 +143f6 04ff5 +14efb 04e63 +14ee5 04e6c +04357 05005 +05a5c 09b5e +15b00 00200 +1538a 048c1 +14697 04fe5 +14c62 04f41 +05475 059c4 +1461e 04fe9 +05802 07017 +05073 05256 +1466d 04fe6 +154d8 0447c +159a7 01570 +15403 047ef +143f3 04ff5 +04f92 051b6 +04388 05005 +045ea 0500b +147c3 04fd8 +148b2 04fc5 +05446 058ec +14674 04fe6 +1569c 03af4 +15458 0467c +048cd 05020 +0512a 052fe +05066 0524c +14c64 04f40 +05522 05c67 +14e7b 04e9a +053ad 05731 +148b0 04fc5 +143fc 04ff5 +0481a 05018 +14c43 04f49 +1451a 04fef +05070 05254 +0426b 05003 +04aa7 0503e +0493a 05025 +055a7 05e78 +15745 035ca +0560f 0605a +04b75 05053 +055ba 05ebd +1478b 04fd9 +15460 04661 +05abf 0a1ff +1570c 03784 +15463 04657 +058b3 07b05 +159a0 01600 +14968 04fb7 +1574a 03597 +0524c 05475 +145c5 04feb +043e1 05005 +1423e 04ffb +143b7 04ff6 +14e93 04e8f +04917 05023 +145b7 04feb +04b08 05048 +14b1e 04f7e +152b9 04a6c +14c66 04f3f +144cc 04ff1 +1548d 045ba +15667 03c9f +04ddc 050cb +04dbc 050c3 +045c3 0500b +14994 04fb3 +055e6 05f7a +14f6a 04e37 +14b9e 04f6b +05023 05219 +159f6 0107c +155ec 0403a +1490a 04fbe +05875 07727 +14c82 04f38 +0553b 05cc1 +04673 0500e +0552c 05c8a +14b59 04f76 +04e28 050e7 +045e3 0500b +151bf 04c2f +15566 0424d +15036 04db7 +155b7 040f8 +15969 0194b +04fcd 051dd +00000 05000 +05000 05200 +15000 04e00 +05200 05400 +05400 05800 +15400 04800 diff --git a/bootstrap/tests/gft_layer4.rs b/bootstrap/tests/gft_layer4.rs new file mode 100644 index 0000000000..9ef52ac504 --- /dev/null +++ b/bootstrap/tests/gft_layer4.rs @@ -0,0 +1,88 @@ +// ============================================================================ +// Check for the spec-first BitNet x GF-T LAYER of 3 neurons (specs/ternary/ +// gft_layer4.t27): four shared GF-T16 activations feed four neurons, each with +// its own ternary weight vector; every neuron is sign(sum_i w_i * a_i) in signed +// GF-T (RNE) -> trit {N=0,Z=1,P=2}, and the three trits are packed low->high two +// bits each (result = n0 | n1<<2 | n2<<4). Bit-exact to the ideal oracle over 400 +// vectors (tests/gft_layer4_vectors.txt). +// ============================================================================ + +use std::env; +use std::fs; +use std::path::PathBuf; +use std::process::Command; + +fn t27c() -> &'static str { env!("CARGO_BIN_EXE_t27c") } +fn spec_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..").join("specs").join("ternary").join("gft_layer4.t27") +} +fn vectors_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests").join("gft_layer4_vectors.txt") +} +fn tool_available(t: &str) -> bool { + Command::new(t).arg("-V").output().map(|o| o.status.success()).unwrap_or(false) +} + +#[test] +fn spec_first_gft_layer4_matches_oracle() { + let gen = Command::new(t27c()).arg("gen-verilog").arg(spec_path()).output().expect("gen-verilog"); + assert!(gen.status.success(), "gen-verilog failed:\n{}", String::from_utf8_lossy(&gen.stderr)); + let v = String::from_utf8_lossy(&gen.stdout).into_owned(); + assert!( + v.contains("input wire [7:0] w00") && v.contains("input wire [31:0] a3") + && v.contains("output wire [31:0] result"), + "layer4 missing weight/activation -> packed-trit interface:\n{}", v + ); + + if !tool_available("iverilog") || !tool_available("vvp") { + eprintln!("SKIP: iverilog/vvp not on PATH; skipping layer4 check"); + return; + } + + let vectors = fs::read_to_string(vectors_path()).expect("read vectors"); + let n = vectors.lines().filter(|l| !l.trim().is_empty()).count(); + let dir = env::temp_dir().join(format!("t27_l4_{}", std::process::id())); + let _ = fs::remove_dir_all(&dir); + fs::create_dir_all(&dir).unwrap(); + fs::write(dir.join("spec.v"), &gen.stdout).unwrap(); + fs::write(dir.join("vec.txt"), &vectors).unwrap(); + + let tb = format!( + r#"`timescale 1ns/1ps +module tb; + reg [7:0] w00,w01,w02,w03,w10,w11,w12,w13,w20,w21,w22,w23,w30,w31,w32,w33; + reg [31:0] a0,a1,a2,a3; wire [31:0] y; integer fails,nn,fd,code; reg [31:0] exp; + GftLayer4 dut(.clk(1'b0),.rst_n(1'b1),.en(1'b1), + .w00(w00),.w01(w01),.w02(w02),.w03(w03), + .w10(w10),.w11(w11),.w12(w12),.w13(w13), + .w20(w20),.w21(w21),.w22(w22),.w23(w23), + .w30(w30),.w31(w31),.w32(w32),.w33(w33), + .a0(a0),.a1(a1),.a2(a2),.a3(a3),.ready(),.result(y)); + initial begin + fails=0; nn=0; fd=$fopen("{}","r"); + while(!$feof(fd)) begin + code=$fscanf(fd,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %h %h %h %h %d\n", + w00,w01,w02,w03,w10,w11,w12,w13,w20,w21,w22,w23,w30,w31,w32,w33,a0,a1,a2,a3,exp); + if(code==21) begin #1; nn=nn+1; + if(y!==exp) begin fails=fails+1; if(fails<=6)$display("FAIL y=%0d exp=%0d",y,exp); end + end end + $fclose(fd); + if(fails==0)$display("ALL_PASS %0d",nn); else $display("FAILED %0d/%0d",fails,nn); + $finish; + end +endmodule +"#, + dir.join("vec.txt").to_str().unwrap() + ); + fs::write(dir.join("tb.v"), tb).unwrap(); + + let vvp = dir.join("sim.vvp"); + let compile = Command::new("iverilog").args(["-g2012", "-o", vvp.to_str().unwrap()]) + .arg(dir.join("spec.v")).arg(dir.join("tb.v")).output().unwrap(); + assert!(compile.status.success(), "iverilog compile failed:\n{}", String::from_utf8_lossy(&compile.stderr)); + let run = Command::new("vvp").arg(&vvp).output().unwrap(); + let stdout = String::from_utf8_lossy(&run.stdout).into_owned(); + let _ = fs::remove_dir_all(&dir); + assert!(stdout.contains(&format!("ALL_PASS {}", n)), "layer4 differs from the oracle:\n{}", stdout); + assert!(!stdout.contains("FAIL"), "layer4 mismatch:\n{}", stdout); +} diff --git a/bootstrap/tests/gft_layer4_vectors.txt b/bootstrap/tests/gft_layer4_vectors.txt new file mode 100644 index 0000000000..19c64d3796 --- /dev/null +++ b/bootstrap/tests/gft_layer4_vectors.txt @@ -0,0 +1,500 @@ +0 1 2 2 1 1 1 1 1 0 0 1 2 1 2 1 04edc 155f5 15090 14a90 36 +1 1 0 2 1 2 2 1 0 0 1 0 0 0 0 0 15502 148f0 14d71 14fa9 160 +1 1 1 2 0 2 2 2 2 0 2 0 1 2 2 1 15686 1485a 053ce 15209 136 +1 0 2 1 1 1 1 2 1 0 0 1 0 1 2 1 15554 05053 15550 14fe9 160 +1 1 0 0 1 0 1 1 1 1 2 0 1 0 2 1 14a7b 0493a 14d86 159d6 34 +2 0 2 1 2 1 1 1 0 1 0 2 1 1 0 1 15358 057b9 04e42 05751 32 +1 0 1 1 1 2 1 2 2 1 2 2 0 0 0 2 14c40 04f17 15023 155f6 0 +2 0 0 0 1 2 0 0 2 1 2 0 0 0 0 1 04815 04e60 049d3 14fdd 42 +0 0 0 1 0 0 2 0 1 2 2 0 2 1 0 0 04b65 152cf 0521c 04a82 10 +2 2 1 1 1 2 0 0 2 0 1 1 1 1 2 2 14938 0561c 0570c 05414 130 +0 0 0 0 0 0 2 1 0 0 2 1 0 0 2 2 05635 0570e 15969 05606 0 +1 0 2 0 1 2 0 1 2 0 0 0 1 1 0 1 04d76 05173 0498b 0590b 8 +0 1 2 1 0 1 0 2 1 0 1 2 2 0 2 2 04b2a 14b1d 04bba 050f5 170 +0 1 2 2 0 1 0 2 0 2 0 2 1 0 0 1 148ef 15909 15782 049eb 136 +1 2 0 2 2 2 0 2 1 2 1 1 0 0 1 1 05644 059dd 14822 04fcb 42 +0 1 2 0 2 0 2 0 1 0 0 0 2 2 1 2 152da 15726 04c76 15411 42 +1 0 1 2 1 0 2 2 0 1 0 1 0 0 0 1 057a7 15177 04b8b 048f0 10 +1 1 0 0 2 0 2 0 2 2 2 0 0 1 0 0 14ddf 15773 05122 14e3e 8 +1 0 0 1 0 1 1 0 0 0 2 0 2 2 2 1 15618 1597c 15448 14d95 42 +0 2 1 0 2 1 0 2 1 2 2 0 1 0 2 0 04ddc 04d43 04a9f 149ff 42 +2 1 0 2 1 2 1 1 2 0 2 0 1 0 2 2 04cb2 049db 051fa 14925 168 +0 0 2 2 2 0 1 2 1 1 0 1 0 2 0 2 04f51 14caa 055a8 04a74 10 +1 2 1 2 0 1 2 1 1 2 2 2 0 1 1 0 159da 04cc7 04876 0571d 170 +1 0 2 0 2 1 2 0 1 1 2 0 2 1 2 2 14c24 0597e 15763 048b6 0 +1 1 1 0 2 2 2 1 1 0 1 2 0 0 0 1 05808 159b9 159f3 1523a 162 +1 0 1 1 1 1 2 1 2 1 0 0 1 0 2 2 15468 149a7 04f76 15483 10 +1 0 2 0 0 2 0 0 2 1 0 2 1 2 0 2 15909 1518f 14bdc 152ff 10 +1 0 0 1 1 2 1 1 2 2 1 0 0 2 2 2 1497e 053e4 14e1d 15705 40 +1 1 0 0 1 0 2 0 1 1 1 2 1 0 0 0 14fb2 1534d 054ca 04942 40 +0 0 0 0 2 0 2 2 0 1 1 1 0 1 0 1 14bff 156c4 1571b 0597d 168 +2 2 1 2 2 1 0 1 0 1 1 0 2 1 1 1 15759 150f7 05601 1570d 32 +0 1 1 0 1 0 0 1 2 1 2 1 2 0 0 0 05754 14e80 14f41 053dc 168 +0 0 2 1 1 1 1 1 2 0 2 1 0 0 0 0 14b27 14b68 04fb7 1480f 38 +0 2 2 0 0 0 1 2 0 1 0 0 1 1 2 1 05528 14c2a 15700 1593f 34 +0 2 1 2 2 1 0 1 2 1 1 1 0 0 2 2 04d54 156f5 04d02 057b1 170 +2 2 0 0 2 0 1 0 0 0 1 1 0 1 0 0 05242 04ae9 048e8 14cff 10 +1 2 2 2 1 1 0 1 0 1 1 2 2 0 2 1 15661 14cfb 14df6 05774 42 +0 0 1 1 1 2 1 2 2 1 2 0 1 2 1 2 1526a 056a0 04ee6 157a7 32 +1 2 0 0 1 1 2 0 1 0 0 1 1 2 0 2 15753 156b9 050ea 14c75 40 +2 2 1 1 1 1 1 1 1 2 0 2 1 0 0 1 155c3 14e55 05299 15205 4 +0 0 0 0 2 2 1 1 2 2 0 1 2 2 2 1 1531e 05304 04ae6 048a9 128 +2 0 0 0 1 0 1 2 0 2 1 2 1 2 1 0 04937 056c5 158db 04b90 162 +1 1 2 1 1 0 2 0 2 2 0 1 1 0 0 1 15978 0484e 157cf 04d38 128 +2 2 2 2 0 2 2 1 1 2 2 2 1 1 2 0 04e9e 058da 0569b 056cf 42 +0 1 1 0 2 1 0 0 2 1 0 1 2 0 0 1 149bd 156a5 1514f 1541b 170 +0 2 1 1 1 2 0 0 0 1 1 1 0 1 1 0 148f2 04c78 15364 14a25 170 +2 1 0 1 0 1 2 0 1 0 0 0 0 2 0 0 154c7 14821 04ba6 1505c 168 +1 2 2 0 0 2 2 0 2 2 2 1 0 2 2 1 15356 04be4 14eca 04a2e 136 +1 2 1 0 1 1 0 1 2 0 2 1 1 0 0 2 14cc0 155ee 14a00 05586 168 +1 0 2 0 1 2 2 1 1 2 1 0 1 2 1 0 154f2 14bfb 15908 059df 0 +1 0 2 2 1 2 1 1 0 1 2 2 1 1 0 2 15261 052f3 055ec 05835 170 +1 1 1 2 0 2 0 0 2 0 2 2 1 1 2 1 05743 053e5 048ba 04d95 162 +1 0 1 0 1 2 2 1 0 1 0 0 0 2 0 0 0534c 14984 04aaf 14843 10 +1 2 2 0 0 1 2 0 1 1 1 1 1 2 1 0 156db 15670 04c4e 14964 24 +2 2 0 0 0 0 2 0 2 2 1 2 2 0 1 1 1559f 157d1 14a08 14eea 136 +1 1 2 1 1 2 2 1 1 2 1 2 2 0 2 0 054a8 058e7 14993 04b13 40 +0 2 2 1 0 1 2 0 0 1 1 1 1 2 1 2 15796 14b31 1561f 0524f 170 +2 0 1 2 2 1 2 1 2 0 1 2 1 1 1 1 154d8 053c7 15298 05572 64 +0 2 0 1 0 0 0 1 2 0 0 2 0 0 0 0 15145 048eb 051df 159b3 128 +1 1 2 1 1 1 1 2 1 2 1 2 1 2 1 0 04a36 05176 05337 04ec9 170 +2 0 2 1 2 2 2 0 0 0 0 2 1 2 1 2 150fd 04e88 04d35 0543c 160 +2 2 0 0 0 1 2 2 2 1 0 1 1 1 2 1 1511a 04f27 152ec 1481b 34 +1 0 1 0 0 1 2 1 1 1 1 1 1 0 0 1 04b4b 1545f 15036 0494a 146 +2 2 2 2 0 2 0 0 0 0 2 1 0 2 2 1 158c1 15883 04942 151dd 168 +0 0 2 2 0 0 2 1 2 2 0 2 1 1 1 2 05405 157c9 1523f 04889 138 +0 0 1 0 2 1 0 2 1 1 1 2 2 0 2 1 14f1a 0550e 155ab 1589e 2 +0 0 0 0 2 2 2 1 0 0 2 2 2 1 2 1 1572d 04b32 0481c 14b5d 34 +0 0 2 2 0 1 2 1 1 1 0 1 2 0 2 0 0572f 04f45 15199 14cf8 160 +0 1 0 2 0 1 1 2 2 0 2 0 2 1 1 2 04bd6 14bc3 055b6 14a92 160 +0 2 0 2 1 2 0 1 1 1 2 2 1 0 1 2 152d9 04a05 15325 05362 170 +1 2 2 0 1 1 2 1 2 0 2 1 2 0 0 1 05542 04f18 04c2e 04dc3 170 +1 2 2 0 1 2 1 2 2 0 0 1 2 1 0 0 04c31 05510 0581f 14cfb 10 +0 2 1 1 2 0 2 2 0 0 1 0 2 0 1 0 0546f 15977 15267 05814 168 +1 0 1 1 1 1 1 2 2 1 0 2 2 2 0 2 153a1 14caa 055b7 14c81 2 +2 1 1 1 1 0 1 2 2 1 0 0 1 2 1 1 05143 050d5 1537a 14b78 162 +1 0 1 0 0 2 2 1 1 2 0 1 0 1 1 0 154ef 04a52 15080 156b2 170 +1 0 2 0 0 2 0 1 0 2 2 0 2 1 1 2 05531 055f8 14e1c 15682 42 +0 1 0 0 2 2 1 0 1 2 0 2 0 0 0 1 0536b 04c1d 05569 05321 8 +1 1 0 0 0 2 1 2 2 1 2 2 0 2 1 2 04b65 05606 05414 14d7d 168 +2 1 0 2 1 2 2 0 2 2 2 1 1 2 2 0 14ec7 05138 056c8 14d09 168 +0 0 0 2 2 2 1 0 0 1 0 1 1 2 1 2 0598e 154f0 1527c 156ea 8 +0 2 2 2 0 2 0 2 2 1 0 2 1 1 0 1 157b6 14a19 0564e 05405 10 +0 2 1 1 0 0 0 0 1 0 2 1 2 2 1 1 05253 14d37 14dac 0497e 128 +2 2 2 1 0 0 1 2 0 2 0 1 1 0 2 0 155be 14a69 14ee0 14f62 168 +2 2 2 2 2 0 1 2 0 2 2 1 2 0 0 2 152b8 14911 0597b 0584f 42 +0 0 0 2 2 1 0 1 0 0 0 2 2 1 2 2 14f34 1568b 15183 14b3e 42 +1 1 0 1 2 1 0 2 0 2 0 1 0 2 2 1 05244 05928 0576e 14837 160 +2 1 1 2 2 2 0 1 2 2 2 0 2 2 1 0 04977 15587 14bc4 1579f 160 +2 0 2 1 0 2 2 2 1 1 0 2 1 0 2 1 04aa8 05369 1551f 05797 40 +1 0 2 1 2 1 1 2 2 2 2 1 0 1 1 0 04b3b 14e89 059d6 153fc 162 +1 0 1 0 2 0 0 2 0 0 1 2 0 1 2 0 14fe6 0553e 059d0 04a25 128 +1 0 1 0 1 1 2 1 2 0 1 0 0 1 2 2 14e25 14ac6 15296 15340 34 +2 1 1 2 2 2 1 2 0 0 2 1 2 0 0 0 152e4 054d0 1576d 1538d 128 +0 0 0 0 2 1 1 1 1 0 2 0 0 1 1 1 053cf 15437 05530 0490c 40 +0 0 0 0 1 2 1 2 1 2 1 0 2 2 2 0 04b6b 0530d 04ee3 04d95 168 +2 0 2 2 1 2 0 2 2 1 1 0 2 1 2 2 04d23 04f4c 04b82 14a37 168 +0 1 2 1 1 1 1 2 0 0 2 2 1 2 2 1 14cd0 04d84 14d49 14c11 128 +2 0 0 1 0 2 2 2 0 0 2 1 1 1 2 2 056c4 14bf0 048f7 157b1 2 +2 2 1 1 2 0 1 0 1 1 0 1 1 1 0 0 15696 14eda 14dbd 1564f 160 +1 2 2 2 2 0 0 0 1 2 1 0 0 2 1 2 054bb 05682 14922 04d62 162 +0 0 0 0 1 0 0 1 2 0 2 2 0 2 1 1 04d87 14e28 04f29 053df 32 +2 1 0 1 0 1 1 1 2 0 1 1 0 0 2 1 0534a 14e89 04b55 04ccb 34 +1 0 2 0 2 1 2 2 2 1 0 2 1 0 1 2 14853 15103 158a4 14ea2 160 +0 0 0 0 1 0 2 0 2 1 0 2 2 2 2 2 04b26 1569e 04c1f 0497f 42 +2 0 2 0 1 1 0 2 0 2 1 2 0 1 1 0 15834 0579a 053e4 14ebc 160 +2 1 0 0 0 0 0 1 1 1 2 0 0 0 0 2 04cd2 1529c 14843 05040 136 +0 2 0 1 0 2 1 0 0 2 2 1 1 0 2 0 04b58 1531a 04d47 052a5 128 +0 0 1 0 0 2 1 1 0 2 2 1 0 0 1 1 14ae1 05679 050ca 157a9 42 +0 1 0 0 0 2 0 2 0 1 0 0 0 2 0 1 04c7a 04ca2 04862 14989 0 +0 0 1 0 1 2 1 1 1 1 1 1 1 0 1 0 1540d 158c0 157d4 15196 146 +1 2 1 2 1 0 2 2 0 1 1 2 0 2 0 1 04c95 04b48 05311 14f1a 8 +1 0 0 0 2 2 1 2 2 1 2 0 2 1 0 1 153f6 14e4a 04f88 0578e 8 +2 1 0 1 0 0 0 0 0 2 2 0 0 1 1 1 157f2 048ea 04cff 14a5e 168 +0 1 2 1 1 0 1 1 2 0 2 0 2 2 1 2 04fdd 152c8 14d6d 156d2 40 +1 1 2 1 2 0 1 1 1 1 2 2 1 0 0 1 05543 0548f 14c21 157cb 8 +0 2 1 1 1 0 2 0 1 2 2 1 1 1 1 0 1535d 048e4 04a97 15097 170 +2 2 0 2 1 1 2 0 1 1 0 0 1 2 1 2 14a5c 04c6b 15784 15970 40 +2 1 2 2 2 1 1 1 1 1 0 1 2 0 1 1 15398 1493e 14ae0 0538e 32 +2 1 1 1 0 1 1 0 2 1 0 0 0 1 1 1 04cf9 04b32 04eb3 04e89 2 +0 0 0 2 2 2 1 0 1 1 1 0 1 2 0 0 1512e 15362 04fcb 04a1b 2 +1 2 2 2 0 2 1 2 2 2 1 0 2 0 1 0 04a4a 157c8 1570d 04ae3 128 +1 2 2 0 1 0 0 0 2 2 0 1 1 2 0 2 14db4 14e74 1574c 04b50 168 +2 0 2 1 2 0 0 2 1 0 1 1 0 1 2 2 14cfe 05234 054bd 054ba 130 +0 0 0 0 0 0 1 0 0 0 0 0 1 1 2 2 04be3 1544f 15357 14ce7 42 +1 1 2 1 1 2 2 1 0 1 0 1 2 0 1 1 14bd6 059f6 04f1d 04fe2 10 +2 0 0 1 2 2 1 1 0 1 2 2 1 1 2 2 0549d 0506e 14e2f 14a8d 10 +1 1 0 1 2 2 1 1 1 1 0 2 1 0 0 2 14fc4 04d0b 14cfd 05704 162 +1 1 1 2 2 2 0 2 1 0 1 0 1 2 2 0 15698 04be8 14db4 04f6f 2 +1 1 1 2 0 2 0 1 2 1 0 1 0 0 2 2 156cd 15598 14c83 05917 138 +2 0 0 1 2 1 0 1 1 2 1 0 2 1 0 0 15270 14fd9 04fed 15647 160 +1 0 2 0 0 1 0 0 2 1 2 2 1 0 2 0 04a05 0555f 14fea 05316 32 +1 0 2 2 1 2 1 2 2 1 1 1 1 0 2 2 05019 0585b 04fd2 04f93 40 +2 1 1 1 0 2 1 2 1 1 2 1 0 0 1 1 04e91 151e3 14dfa 15132 130 +1 2 0 0 0 2 1 1 1 0 1 1 0 0 1 0 04801 05630 052f6 1507e 10 +1 2 0 1 0 1 0 1 1 0 0 0 1 0 2 1 050e7 1514a 05669 157d9 160 +0 1 0 0 2 0 0 1 0 2 2 2 0 1 0 0 1580b 15778 15423 04c52 138 +2 2 2 2 2 1 2 1 1 2 2 1 0 1 2 1 14ce9 15803 14b32 05216 128 +2 0 2 0 2 1 2 0 0 2 0 0 2 2 2 1 052af 15560 04eda 1509c 10 +2 1 1 2 0 2 2 2 0 2 0 0 1 2 1 2 04d7e 05909 05217 0576f 170 +0 2 2 0 0 0 0 0 0 1 0 2 2 2 1 2 053b0 05477 14a9e 048e4 130 +2 0 2 2 1 1 1 2 1 0 1 0 2 1 1 1 15383 0545c 05786 057ef 10 +0 2 2 2 2 0 1 2 1 0 1 1 1 2 0 1 15825 152f8 051a1 05583 34 +0 0 2 2 0 1 0 2 0 0 1 0 1 2 0 0 056a6 159f9 049aa 14ada 34 +2 1 0 2 1 1 0 0 0 2 1 1 0 1 1 1 14827 04a74 0502f 15473 168 +2 1 1 0 1 0 0 2 0 1 2 2 1 0 2 1 158f2 04d6d 05669 05595 160 +0 2 2 0 2 1 1 1 2 1 1 2 1 0 1 1 14ebc 0515e 15254 14cc6 2 +2 0 1 0 0 0 2 0 1 1 0 2 0 2 0 2 14b67 159f1 05302 14c4d 10 +1 2 2 1 2 0 0 0 2 2 1 1 0 0 1 0 05109 15038 053f8 14bfa 34 +0 1 1 0 1 1 1 1 0 1 2 1 0 0 2 2 14830 04e7b 14c3f 1517c 6 +0 0 2 2 2 2 0 2 0 1 0 1 0 1 1 2 057b6 14b8c 057e8 14b60 2 +0 1 2 0 2 0 1 2 0 0 2 1 1 2 1 0 1489c 15970 04958 051bc 40 +2 0 0 1 0 2 1 1 2 2 1 0 2 1 1 1 14e41 152d3 1548c 05554 2 +1 2 0 0 2 0 1 1 0 0 0 1 1 1 2 1 05086 148b8 0480c 0541e 136 +0 2 2 0 1 1 2 2 0 2 2 0 1 2 1 0 04a9b 04ab4 05517 14fed 170 +1 2 1 1 1 2 1 1 2 2 0 1 0 1 2 2 14c5a 04dce 1566c 15470 42 +2 0 0 1 2 2 2 1 0 2 0 2 0 0 1 1 05588 14c3f 04870 14a75 10 +1 2 2 0 0 1 2 0 1 0 1 2 2 2 1 0 04c7b 05279 04b84 159f5 138 +1 1 2 1 1 0 1 0 0 1 0 1 1 0 2 0 04870 15270 05469 057b9 2 +1 1 2 2 1 1 2 1 1 0 1 0 1 0 1 0 14aea 05777 15155 04ec8 0 +0 0 0 2 0 1 2 0 2 2 0 1 2 0 0 0 154d3 14a01 15635 05491 34 +0 2 0 2 2 1 2 0 0 1 1 0 0 2 0 1 15264 14e4f 0575e 0500b 40 +2 0 2 1 1 2 2 1 1 0 2 0 1 0 1 2 1574a 04912 155b7 05659 128 +1 1 2 2 2 2 0 1 1 2 2 1 1 2 1 1 055eb 04b03 0489e 04c1c 170 +0 1 1 1 0 1 0 2 1 0 0 2 1 2 2 1 14b66 05608 1515a 04bf1 138 +2 2 0 2 1 1 1 1 2 1 2 2 2 2 0 0 054f1 04b3b 14cfb 14e6f 166 +1 1 0 2 1 0 2 0 0 1 2 0 0 2 2 2 14a4b 14e4d 156db 14da1 2 +2 2 1 2 2 2 2 0 0 2 1 2 0 1 1 1 0584c 15051 1494a 15558 10 +1 2 0 0 2 2 0 0 0 0 1 2 0 2 0 1 15958 14f16 04b6d 14969 160 +1 0 1 2 1 2 1 1 0 0 0 2 2 0 1 1 0509d 14b5d 04af7 054a2 162 +1 1 1 0 1 2 1 0 1 2 2 0 2 2 1 1 04b8e 0501e 05882 1548b 170 +0 0 1 1 0 1 0 0 0 1 1 0 1 0 0 2 0534b 1578b 14948 1547c 170 +1 2 2 2 0 1 2 0 0 0 2 0 1 1 1 0 04975 05070 15246 15034 128 +0 2 2 1 2 2 2 1 2 2 1 2 0 2 0 0 14fa2 052e0 14e74 052fc 170 +0 0 2 0 1 2 0 0 0 1 0 2 2 1 1 1 15548 05967 151b6 053d8 40 +2 1 2 1 1 0 2 0 2 2 0 2 0 1 0 1 05951 04bbb 056ab 153e1 42 +0 0 2 2 1 0 1 1 1 1 2 0 2 1 2 2 15389 05441 15062 04ad1 0 +2 2 1 0 2 1 0 1 0 1 2 1 2 2 0 2 1528c 0559b 14f44 15175 162 +1 0 1 2 2 2 0 1 2 2 0 1 1 0 0 1 05994 156dd 056d6 155de 170 +2 0 0 2 2 2 0 1 1 1 2 0 2 2 2 0 04bbf 149f2 0514a 15918 160 +2 1 0 0 2 0 2 1 1 1 1 0 2 2 0 2 05767 04c74 1547a 1489a 170 +1 1 0 0 1 1 2 2 2 0 2 2 1 1 1 2 0532f 14fcc 057d9 054ab 168 +0 0 2 1 0 2 0 2 0 1 1 1 2 0 0 0 05545 058b7 05007 04e3a 8 +1 1 2 1 2 1 2 2 1 2 2 1 2 2 0 2 15221 04d2a 1596e 05855 128 +1 0 1 0 0 0 2 1 2 2 2 2 1 2 0 0 04f43 059b9 0590a 15592 160 +0 2 1 0 1 0 1 1 2 2 0 1 1 2 2 2 14ec9 04c37 04f3b 14bf4 130 +2 0 0 0 1 2 0 1 0 1 0 1 1 0 0 2 04807 14f28 15234 05283 170 +0 2 2 0 2 0 2 2 1 1 2 0 2 1 1 0 04f32 052ed 157bf 14ac4 128 +2 1 2 1 1 2 1 1 1 0 0 2 2 1 2 2 04963 1563a 156f0 14be5 32 +0 1 1 0 2 1 2 0 1 0 2 0 1 1 1 1 15564 1480c 05041 05435 66 +0 0 1 2 1 1 2 0 1 0 1 0 0 2 0 1 14c1b 0593e 15352 05722 128 +2 0 2 1 0 0 1 1 1 1 1 1 0 2 1 2 04d92 04f0f 159e3 14bc6 144 +2 1 1 2 1 1 0 1 0 0 1 2 0 1 2 0 0500a 04e03 0499a 152d1 128 +2 0 0 1 0 2 0 0 2 1 0 2 1 0 0 1 14f9c 058c2 1554d 14e14 40 +2 1 2 0 1 2 0 1 0 1 1 2 1 1 0 2 14fd7 14fa5 04f2a 1561e 2 +2 1 1 0 0 0 0 0 0 0 0 1 2 2 1 2 04c4d 157b5 05967 14f4a 2 +1 0 2 1 2 2 0 1 2 0 0 1 2 0 0 2 1529f 04b31 04cf9 15198 2 +0 1 2 1 1 1 2 2 1 1 0 0 2 1 0 0 04dc3 14c15 148f2 14e5f 160 +0 2 1 2 0 2 2 1 2 1 2 1 0 1 0 0 150f3 14c79 14d42 05682 10 +2 1 2 0 2 1 1 1 0 2 2 0 0 0 0 2 04fa5 150ff 14907 155d4 42 +1 1 1 1 1 0 1 0 2 2 1 0 1 1 2 0 14b1c 0498a 154df 15015 41 +2 1 2 0 1 2 2 2 1 0 1 1 1 0 2 2 153d7 049dc 1505c 1495f 0 +0 0 2 0 0 2 0 1 2 0 2 0 2 0 0 1 158f5 04e7b 14c96 05671 10 +1 1 1 2 1 0 0 0 2 1 1 2 1 1 2 0 0567e 15117 05585 0593b 34 +1 1 1 2 0 2 0 1 1 2 1 1 2 0 2 1 055f0 15927 051ff 04e1a 130 +2 2 2 1 1 0 2 2 1 0 1 1 0 2 0 2 04981 04f13 05320 14998 10 +1 0 2 1 0 2 2 1 0 1 0 2 0 0 1 2 0567c 1584d 051cb 151a7 130 +2 0 1 1 0 2 1 0 1 2 0 2 0 0 2 2 04de1 14d1a 055dc 04995 130 +1 2 1 2 2 1 2 0 2 0 0 2 0 1 1 1 149aa 0488c 15458 1550d 136 +0 2 0 1 2 2 0 1 0 1 0 1 0 1 1 0 14a88 159aa 04911 14d64 160 +2 0 2 2 1 0 0 1 0 1 0 0 0 1 0 1 04d72 05263 0580a 14dea 2 +1 2 0 1 2 0 2 1 1 0 1 2 0 1 1 0 05365 04f07 05032 05903 40 +1 0 1 0 0 1 0 1 1 2 0 0 2 0 2 0 14b9d 059f5 0559e 14fd6 32 +1 2 1 1 0 2 1 0 1 1 0 2 0 0 0 2 0505d 155d7 04f42 05872 160 +1 0 0 0 1 0 0 1 1 0 1 2 0 0 0 1 05144 148a2 051bc 0524a 32 +0 0 2 1 0 0 0 1 2 2 1 1 2 0 0 0 05875 057a8 04c2c 1486e 160 +0 1 2 1 1 0 0 0 2 2 1 2 0 2 0 1 04d6e 053df 04836 05634 160 +1 2 0 2 1 0 0 2 0 1 0 1 2 1 2 2 14c94 14af5 148aa 1558d 32 +1 0 0 0 1 0 2 2 0 1 0 2 1 0 0 2 054e0 0531e 14d9b 14ce4 0 +0 1 0 2 2 2 0 1 1 2 2 1 1 0 1 0 057c0 054ff 04ac7 04f87 40 +1 1 1 0 0 2 2 1 2 2 0 0 1 0 2 1 1522d 153c6 14baf 1492a 130 +0 0 2 1 1 0 2 1 2 2 1 0 0 0 0 0 04d28 048bd 14dc6 054e1 0 +2 0 1 0 0 2 2 2 0 2 2 0 2 0 0 0 050f4 058b9 156c3 149a1 40 +2 2 0 2 0 0 2 1 2 0 0 2 0 2 1 0 14ce1 15712 0570a 04b47 8 +2 1 2 1 0 0 1 0 2 2 0 0 0 0 2 0 04a45 15362 04b41 155ee 170 +0 1 0 0 1 0 1 2 0 2 2 0 2 1 0 1 0559f 14960 159a6 150fa 130 +0 1 0 0 1 1 2 2 0 0 2 1 2 0 1 0 15551 053e4 0510b 058d1 40 +0 1 1 0 0 2 0 0 1 2 2 0 2 1 0 2 0572f 15599 149c4 1557c 128 +0 1 0 0 1 2 2 0 2 2 2 2 2 1 2 1 1545d 14954 14b9e 156e0 10 +2 2 0 1 2 0 0 2 0 1 0 2 0 0 0 0 04e07 05676 1579d 0540a 170 +0 1 0 2 1 0 1 2 1 2 2 1 2 1 0 1 14a3e 04fa7 15314 04bb7 130 +0 0 0 2 1 2 2 2 1 0 2 0 1 2 0 2 04a94 1509b 14fac 15884 32 +0 1 1 1 1 0 1 0 0 0 0 0 1 1 0 0 055fa 149de 14bb5 04e35 0 +0 1 0 2 2 1 0 0 2 0 0 1 2 1 1 2 05867 156fb 14ec5 04f14 168 +1 0 0 1 0 2 0 2 0 1 2 0 0 1 0 0 05446 055b4 15454 149d2 136 +2 0 0 0 2 2 1 1 1 2 1 2 2 0 2 2 154a3 04e2b 05671 054f4 160 +1 0 2 0 0 2 0 0 0 2 1 0 2 0 0 0 15682 14b7a 156ff 14ac1 168 +2 1 1 2 1 1 2 2 2 2 2 0 2 0 2 1 1519c 148a5 050f8 15161 32 +2 0 1 0 2 0 1 0 1 0 1 0 2 1 1 1 04db2 0530f 158ba 14af2 128 +2 0 0 0 2 2 0 0 1 2 2 1 0 1 2 2 055c2 04dcf 05815 04891 160 +0 2 2 1 1 1 0 1 0 0 2 2 2 1 0 0 053eb 057b8 05896 04e2a 34 +1 1 1 1 1 1 1 2 0 2 0 2 1 0 1 1 150ba 15810 151c3 14ed0 129 +2 2 1 0 2 0 2 0 1 2 1 1 2 1 0 0 04dfa 04db0 14df9 055d5 32 +2 1 2 1 1 1 0 1 2 2 0 2 1 1 1 2 1599f 05740 151c2 059b5 168 +0 2 0 0 2 0 0 0 0 0 2 1 0 2 2 2 05766 049c3 149a2 153a0 8 +2 0 2 0 2 2 2 0 2 2 0 0 0 2 0 0 158e4 05273 05628 1497a 128 +0 0 2 1 0 0 2 1 1 2 2 2 1 2 2 1 151b2 05459 0563b 058e3 170 +1 1 0 1 1 2 0 1 1 0 0 0 1 1 0 2 14d00 1552f 15849 050e1 170 +0 2 2 0 2 0 0 2 0 2 2 2 2 2 0 0 14b5a 14d21 0524d 155b6 130 +2 2 0 1 2 1 2 1 1 0 1 1 2 1 0 1 153a8 1559b 051e8 14eda 32 +0 2 0 0 2 2 1 0 2 1 0 0 2 1 2 0 14aa6 04e8d 05555 148f1 136 +0 2 0 0 0 1 2 0 1 1 0 0 0 0 2 1 04aaf 0531f 15538 15945 42 +0 2 0 0 1 0 1 0 1 1 0 2 2 1 1 0 15452 04b93 14c15 156f2 138 +0 2 0 1 0 1 2 2 2 1 0 0 0 2 2 2 149c0 14baa 14c82 05979 138 +0 1 1 1 2 0 2 2 1 0 0 1 0 1 1 2 048e0 04acd 051e4 056f8 136 +0 1 0 2 0 1 2 0 2 0 1 2 2 2 1 0 14fa8 0594d 04a8d 05795 130 +1 2 2 0 2 0 2 2 2 2 2 1 1 0 1 0 058dc 14947 05680 04dc7 42 +1 1 0 1 0 0 0 1 2 0 1 0 1 0 1 1 0489c 14b71 15625 14ab5 170 +2 0 2 2 2 0 2 0 1 0 1 1 0 1 1 1 0509f 158ef 14b50 14e1e 42 +0 2 1 1 2 0 0 0 2 1 0 0 2 0 0 0 04ea8 053bd 15870 14d1d 170 +0 1 1 1 2 0 0 2 2 2 2 1 0 1 2 2 048dc 15779 14d56 15335 8 +0 1 2 0 2 2 2 1 2 0 1 1 0 2 1 0 0536f 15193 15523 04830 32 +1 2 2 1 0 2 1 0 0 1 1 2 2 1 2 1 14b6e 04e18 15028 0528c 32 +2 1 2 2 0 2 2 1 2 2 2 0 1 2 2 1 054d9 1544e 14edb 1526c 34 +0 1 2 1 2 1 2 1 1 1 2 2 0 0 2 1 15434 14aa2 04adf 156a9 130 +2 2 1 1 1 1 2 1 0 0 0 2 0 1 0 0 048dd 04d67 04d49 157d2 138 +2 0 0 1 0 2 0 0 0 1 1 0 1 0 0 0 04d55 15751 14918 14d75 162 +1 1 2 1 1 0 1 0 1 2 1 0 2 1 1 0 051fd 04a66 05975 0496a 162 +1 0 0 1 1 1 2 2 0 2 1 0 1 2 1 1 149c8 049bd 1551c 156ce 162 +2 1 2 2 2 1 1 0 1 0 0 2 1 0 1 2 059a6 148c4 04ed5 14e94 10 +2 1 0 0 1 2 2 0 2 1 2 0 2 1 2 1 05935 14f23 1529e 0503d 162 +2 1 1 2 2 2 1 2 0 1 2 2 1 1 1 0 1585b 15004 04d9b 1513e 160 +1 2 0 2 0 0 0 2 2 0 0 1 2 2 0 2 053ff 04f69 05360 1487b 128 +1 0 0 2 0 0 1 1 1 1 1 0 2 0 1 1 14b0d 14a77 05973 056d5 8 +1 1 2 2 1 2 0 1 2 0 1 0 1 1 1 0 153d3 14833 14a2a 04e0b 10 +0 0 0 0 1 2 1 2 1 1 2 2 0 1 2 0 1517f 151e9 14c17 04d24 162 +1 2 2 1 1 0 2 0 1 2 2 1 2 2 1 2 04e80 157ea 0513f 15756 8 +0 2 2 1 0 2 0 2 0 2 2 1 2 2 2 2 05176 04f43 04fc1 15722 34 +2 2 1 1 0 0 0 2 1 0 2 1 2 0 1 2 050fa 05229 152ee 14e4c 2 +0 2 1 2 2 2 0 1 2 1 1 2 1 2 1 1 05221 14afc 14c72 04a38 40 +0 0 0 0 0 2 2 0 2 1 0 2 0 1 0 1 0534b 058d8 15780 149fa 168 +1 2 0 0 1 1 1 1 1 2 1 0 1 0 2 1 04f80 15679 0512e 049f9 132 +0 1 2 0 2 1 1 2 2 0 2 0 2 1 0 0 14d4e 04977 0488a 1543d 162 +0 2 0 2 0 1 2 0 2 1 1 1 0 1 0 2 15969 14ebe 05947 05731 138 +2 2 2 1 0 2 0 2 0 0 1 1 1 0 0 2 05237 14def 05523 14a90 2 +1 2 2 1 1 2 2 1 1 1 0 2 1 0 1 0 0532d 05931 14da5 14ff9 10 +2 0 0 2 0 0 2 0 0 0 1 0 2 0 0 0 04c4f 15414 05837 04e78 40 +2 2 0 1 1 1 0 1 1 0 1 1 2 1 0 1 14b92 04f8e 15601 15869 138 +2 2 2 2 1 1 1 1 2 0 0 1 1 0 2 2 159e8 0574d 053ac 14918 4 +0 2 2 0 0 1 2 2 2 0 0 0 0 2 0 0 04811 04eb8 15090 15679 162 +0 0 2 1 1 0 1 2 1 2 2 1 0 2 1 0 04e1e 04c02 058b2 150b5 162 +0 1 0 0 2 1 0 1 0 2 1 1 2 2 2 0 0579e 14e3e 0586c 148f5 128 +2 1 1 0 2 2 2 2 1 2 2 2 0 0 0 0 0506f 14dd1 14c1b 15165 130 +0 1 2 0 1 0 0 1 0 0 0 2 2 1 2 2 14d89 1496f 04ace 15131 2 +0 0 1 1 1 1 1 2 0 0 2 2 0 0 0 0 052a3 04c4e 058f2 050eb 40 +1 1 2 2 0 0 1 0 2 2 1 0 1 0 0 2 051b4 156a0 05850 15136 10 +2 0 2 0 1 0 0 0 2 2 2 1 2 2 1 1 05664 1579d 0498f 14899 10 +0 2 2 0 1 1 0 2 1 2 0 1 2 0 0 2 14c49 051c4 14be6 14dd7 34 +1 2 2 1 2 2 0 0 0 1 2 2 0 1 1 2 148da 048bb 14afe 04d97 160 +0 2 0 0 1 0 0 1 0 1 2 2 1 0 1 1 050ed 05892 158e9 156e0 10 +0 2 1 1 1 2 2 1 2 2 0 1 1 1 1 2 04cd5 0582a 04cb0 14aed 42 +0 1 1 2 0 1 1 1 2 2 1 2 1 2 1 1 15684 04e1b 149a7 04c0a 138 +0 2 0 2 0 1 2 1 1 2 0 1 0 1 2 2 14fac 0517c 14d92 152f5 42 +2 0 1 2 2 1 1 2 0 2 0 0 1 0 2 0 157bf 0530f 05857 05274 128 +0 0 1 0 2 2 1 1 2 1 2 2 2 0 0 2 14f36 1576c 15511 05542 130 +1 0 0 0 2 1 1 1 1 1 1 1 0 1 2 0 04a24 1536a 04c49 153b3 154 +1 0 0 0 0 1 2 0 1 0 0 2 0 2 1 1 15584 14969 05703 14b39 136 +0 0 1 2 2 2 2 0 0 0 1 2 1 2 1 0 05665 14c24 14dc5 14d94 136 +0 1 0 0 2 1 1 1 1 1 1 0 1 2 0 2 055db 15614 156bf 14807 170 +1 0 1 2 0 2 0 0 0 2 0 2 1 2 0 1 04b03 151d8 05940 15180 2 +0 1 0 2 1 2 0 1 1 2 1 1 0 2 2 0 159d4 04f0c 14da1 15376 170 +0 2 1 0 2 1 1 1 2 2 1 1 1 2 0 2 14a74 054d7 14857 0584a 160 +2 0 0 0 0 0 2 1 2 0 2 0 2 2 0 1 054a2 14ba1 04c2e 14fbb 162 +0 0 0 1 1 0 1 2 0 1 2 1 2 0 2 1 04d02 0515f 14e9d 04df6 0 +1 0 1 2 2 2 0 1 0 2 2 2 1 1 2 1 056ed 053ac 1490f 14f9b 8 +1 2 2 1 0 2 2 0 0 1 2 0 1 0 1 1 049a3 15541 1555f 052bb 128 +1 1 2 1 0 1 2 1 2 1 2 2 2 2 0 1 15697 05754 15562 04a1b 136 +1 0 2 1 2 2 2 2 1 0 1 2 0 2 1 0 1518e 15016 159d2 05798 32 +1 1 2 2 0 0 1 0 0 1 0 1 0 2 2 0 05846 04b89 05549 04e9c 2 +0 2 1 0 2 2 0 1 1 2 1 1 1 0 2 2 14a05 053ef 05651 059db 160 +0 2 0 2 2 2 2 0 2 1 0 2 0 1 0 0 1546c 04b38 04e40 04d65 130 +1 1 2 0 0 2 0 1 0 2 1 1 0 0 0 1 1562b 14896 14b5d 1591f 170 +2 2 0 0 0 1 2 0 2 1 2 2 1 0 2 0 04979 14c0f 14cfa 058c3 32 +1 1 1 2 1 0 2 1 1 1 1 2 0 1 2 1 05250 14920 1536f 14e40 0 +1 0 2 0 1 0 0 1 0 0 1 2 0 2 1 2 156ea 05204 15736 15919 10 +1 2 2 2 0 2 1 1 0 2 0 1 1 0 1 1 04ae0 04ff9 05037 1497f 10 +1 0 1 0 1 2 2 0 1 2 0 0 0 0 1 1 148fe 1591a 157c4 0564d 130 +1 0 0 2 0 1 2 0 1 0 0 2 2 2 1 1 154be 0582e 15655 148f6 128 +2 2 2 1 2 0 1 0 0 0 2 2 2 2 1 1 04cb5 04aad 1496e 048c2 138 +1 1 1 0 2 1 2 0 2 0 1 2 1 2 1 1 04b15 157ab 052f6 04996 40 +2 1 2 2 2 2 2 0 2 0 2 1 2 2 0 2 05164 054b1 14903 14908 138 +1 1 1 2 0 0 0 2 1 2 0 0 2 2 0 0 15712 156ef 04d54 14bcf 8 +1 2 0 0 1 2 1 0 1 1 2 1 2 1 2 0 150d2 15863 15373 1526c 0 +2 2 0 2 2 2 2 1 2 2 1 1 1 2 0 0 04a43 05786 049bc 15052 170 +2 1 0 0 0 1 0 1 0 1 0 2 2 1 2 0 151c6 04d24 14dee 04cdb 40 +1 2 0 0 1 1 2 0 0 0 0 2 1 1 2 0 059db 14daf 14af5 15880 138 +2 0 2 2 0 2 2 1 0 2 0 0 2 2 0 0 1547f 14dd0 15196 1574d 168 +2 2 2 0 1 1 0 0 1 1 0 2 0 2 0 2 04e69 14810 04e1c 15686 10 +0 0 2 2 2 1 2 1 1 0 1 2 1 1 0 2 053bb 04f3c 051d2 05429 170 +1 2 0 0 0 2 2 1 2 1 0 0 0 1 1 0 0563e 058f3 056f9 04b56 10 +0 1 0 1 2 1 1 1 0 2 2 2 0 0 0 0 159ba 04cd1 15582 1590a 130 +1 1 2 2 1 1 1 0 2 1 1 1 1 0 0 0 058d5 04839 14ac9 0503d 34 +2 1 2 0 2 0 0 0 1 1 0 0 1 1 0 1 0584c 1584d 14d08 15341 170 +1 0 0 0 2 2 2 2 1 0 2 1 1 1 0 1 15969 151f7 04e7c 15811 34 +2 0 1 2 2 0 0 1 0 2 0 0 1 1 1 1 14a4a 15056 14cb5 055f1 74 +0 1 2 2 2 2 1 0 2 2 0 1 1 1 2 1 059fd 056b1 15399 04ab1 40 +0 0 2 2 1 1 2 0 0 1 2 1 2 0 2 1 155b9 15458 04c44 148ab 42 +1 0 0 0 2 0 2 1 1 0 2 2 0 1 2 2 059e2 154c3 14cca 151f2 42 +1 1 0 0 2 2 1 2 0 0 0 1 1 0 1 0 05966 148cd 14c74 04baf 10 +2 1 2 1 2 1 1 1 0 0 1 1 0 1 0 0 1523a 05519 14e7c 14ee4 128 +0 1 0 0 0 1 2 0 0 0 0 1 2 1 2 2 154f7 0523a 05996 1592b 10 +1 0 1 1 0 0 1 0 1 0 2 1 2 2 0 2 0525f 15428 04828 15734 42 +2 1 2 0 1 2 1 1 2 1 1 2 2 0 0 1 056c9 04aeb 05426 04fc0 170 +1 1 0 2 2 1 1 2 1 2 0 2 2 2 0 0 04d14 14d1e 14de9 05769 42 +2 1 2 2 0 1 1 2 0 2 1 2 0 1 1 1 15584 04eb2 05268 15977 128 +1 1 0 2 1 2 1 1 0 2 1 2 1 1 2 0 14ede 15170 14f9b 0596f 34 +2 2 2 2 0 2 0 0 1 1 1 1 1 0 0 1 15450 1521b 04ece 04deb 152 +0 0 1 1 2 1 0 1 1 2 2 1 1 1 1 0 04a35 14e34 1576b 048e9 10 +1 2 1 0 0 2 1 2 0 1 2 0 0 1 0 2 14fed 049a3 149e0 0485e 170 +0 1 0 0 1 1 1 2 1 2 2 0 2 2 1 0 14805 14fd8 04869 15691 162 +0 0 2 2 1 1 1 1 1 2 2 2 2 1 2 2 04a59 15624 154ad 1550a 4 +2 0 0 2 0 2 2 1 2 2 1 1 0 1 1 0 04c68 05543 148fe 050dc 40 +0 0 1 0 1 1 1 1 2 1 0 1 2 0 2 2 14cf6 157b3 15516 14dcb 166 +2 1 2 2 2 0 1 2 2 2 2 2 1 2 1 0 056a8 0502f 15332 04925 170 +0 1 2 2 1 0 0 2 2 1 2 2 0 1 2 0 1580b 051ce 049a8 14fcc 130 +1 0 0 2 1 2 2 0 2 1 1 1 0 0 0 1 1580c 05290 14c88 0527d 130 +1 1 1 0 1 0 0 1 1 2 2 0 1 0 2 0 04d22 04d93 148e4 04ff8 0 +0 0 2 2 0 1 0 1 0 1 0 0 2 2 2 1 05542 150fb 1555e 05510 8 +2 1 0 0 2 0 1 1 0 0 2 1 0 1 0 2 14b07 049bf 14f0a 1570d 2 +1 0 1 1 1 0 2 0 0 1 0 0 1 0 1 2 04ae6 04b62 156a8 058d8 128 +0 2 1 1 2 2 1 2 0 0 1 1 0 0 2 0 04955 04e0f 0561f 05529 138 +2 2 2 2 0 2 0 2 1 2 1 2 2 2 0 2 15460 04bf1 15397 148c4 40 +0 2 0 2 0 0 2 1 0 2 1 0 1 2 0 1 157c6 0590c 1571b 04edc 162 +1 0 2 2 1 2 2 0 2 2 2 1 0 0 1 2 05678 0558b 14893 14a75 40 +2 1 1 2 2 2 1 1 2 1 0 2 0 2 2 1 04f6f 150b6 15437 05627 34 +2 2 0 2 0 1 0 0 1 2 0 0 0 2 2 0 15709 14fb5 158ee 0488e 42 +1 1 2 2 2 0 1 1 0 1 0 1 2 1 1 2 15589 0531d 057f3 04cee 2 +0 2 1 2 2 1 2 2 1 2 0 2 2 0 2 2 05840 14bf7 150cd 0555a 168 +2 1 1 0 1 0 1 1 1 2 2 2 1 0 1 1 04ef6 14ad4 149e4 152c5 138 +2 2 1 2 2 1 2 0 2 2 1 2 2 2 0 1 05525 15939 159f8 14d08 128 +0 2 2 0 1 2 1 1 0 0 1 2 2 2 0 0 04de9 1590c 1534c 15233 32 +1 0 0 1 1 2 1 2 0 2 2 0 1 1 1 1 1508f 15060 05414 15467 96 +1 2 1 2 0 0 2 0 2 0 0 1 1 0 1 1 057e7 0488b 04e16 14972 32 +2 1 0 1 1 0 2 2 1 1 0 0 1 1 1 2 15989 1568e 04809 14fa1 40 +1 0 2 0 1 1 2 0 2 0 0 0 2 1 1 1 15574 1525b 059d3 05615 10 +2 1 2 2 1 0 0 0 0 2 1 2 2 1 0 2 04f0f 15926 152c1 14c6f 136 +0 1 2 1 1 1 2 2 0 0 0 1 1 0 2 1 04f7c 05515 0584d 051dd 138 +0 2 1 2 1 2 0 0 2 1 0 2 2 2 2 2 1578a 15996 04dad 0568a 0 +2 0 2 0 1 0 1 2 2 2 2 1 2 2 1 2 152b8 149c3 054c3 05283 42 +1 2 1 2 2 1 1 1 0 2 0 1 1 1 2 2 04880 1497b 14bbf 14915 40 +0 1 2 0 2 1 2 0 1 2 0 1 2 0 1 0 14d68 058d8 15458 15596 42 +1 1 1 0 2 2 0 1 2 1 2 0 1 2 2 0 04a3d 14f08 04dfa 14e21 162 +2 1 1 1 2 2 2 1 1 1 0 2 2 2 1 1 15820 1483a 14def 053d1 32 +1 2 2 1 1 1 2 1 0 2 2 2 2 1 1 2 153a1 059d8 0569f 053e1 170 +1 2 1 2 0 1 2 0 0 1 2 1 0 1 1 2 04d87 152ab 052a8 157bc 40 +0 0 1 1 2 2 1 1 0 1 0 2 1 0 0 1 04832 1481d 154b5 04c8e 168 +0 0 0 1 1 2 0 2 0 1 2 0 2 1 1 1 15622 158ba 15465 15425 34 +2 2 2 1 1 0 1 0 2 2 1 1 1 0 1 1 0524d 1545a 14d57 05861 128 +1 0 1 1 0 0 0 0 1 2 0 2 1 2 2 1 14a61 053b0 0496e 155c5 136 +2 2 1 0 1 2 0 2 1 2 1 1 0 1 0 0 04a27 05822 15282 14b24 170 +2 1 1 2 0 2 0 0 1 0 2 0 0 0 0 2 1544f 148a8 154d7 14f24 136 +2 1 2 1 0 0 0 0 2 0 2 0 1 2 1 1 153bb 0520f 14abe 1593a 168 +2 1 0 1 2 2 2 2 2 2 0 1 2 1 2 1 15038 14d16 056da 0502f 136 +0 0 1 2 1 2 0 0 0 1 2 1 2 0 0 0 15769 05197 152b3 052c2 42 +2 1 1 2 0 2 0 0 1 1 1 2 2 2 2 0 0536a 05069 14f77 14e7d 130 +2 0 1 2 2 2 2 0 1 1 1 0 0 2 0 2 057d6 148a1 05881 04cc2 10 +2 1 2 1 2 2 1 1 1 1 0 2 0 1 0 1 1594c 159ae 050af 15420 128 +2 1 0 0 0 2 2 2 1 1 0 2 1 0 0 2 14c58 05021 0521b 04842 8 +2 1 2 0 2 2 0 1 1 2 1 1 1 0 2 0 14972 15859 156aa 14901 128 +2 0 2 0 1 2 0 2 0 1 0 1 2 2 0 0 0511f 157bb 1545c 14bd1 34 +0 0 1 0 2 2 0 1 0 0 1 1 0 1 1 2 050e2 048ce 15592 0496a 8 +1 1 2 2 0 2 2 1 2 2 2 0 0 1 2 2 04971 15583 14916 15564 0 +0 2 1 1 2 2 1 0 2 2 1 0 1 2 1 0 15637 04812 04e29 051d5 2 +2 1 1 0 0 1 2 1 2 2 1 1 1 1 2 0 04a5a 14856 052bd 057b1 40 +0 2 0 0 1 1 2 1 1 1 2 1 1 1 1 1 05275 14e32 14c36 15313 66 +2 1 1 0 2 1 2 1 2 0 0 1 0 0 1 0 14eaf 14943 14ed5 05672 32 +0 2 2 0 1 1 2 2 1 2 1 0 2 1 0 2 04eff 050c7 04eb4 14a13 42 +1 1 2 0 2 1 1 1 0 1 1 1 2 2 2 0 04c6c 153da 04c21 15159 10 +2 1 1 0 0 1 2 1 0 0 2 0 1 1 1 1 1504f 14ff7 053c5 0513b 104 +1 2 2 1 1 1 2 1 0 1 0 0 0 1 1 2 155f3 15769 14ac9 048bb 160 +1 0 2 2 0 1 1 0 0 0 2 0 2 1 1 1 04820 056cf 050b8 059e4 130 +1 1 0 1 0 2 1 2 1 1 1 2 1 2 0 0 15205 14f69 04abf 14fd3 8 +0 0 1 0 2 0 1 2 2 1 2 1 1 0 2 0 14acb 04ba8 14c10 14ad5 2 +2 1 0 1 0 0 0 2 2 0 2 0 2 2 1 2 157ce 14b54 154af 051f3 8 +0 1 1 1 0 1 2 0 1 2 0 0 0 0 0 2 057f2 156f4 1487b 157b0 32 +0 0 0 1 0 2 1 2 0 0 2 1 1 1 0 2 05530 04e93 05139 056f2 136 +0 2 1 0 0 1 1 1 0 0 2 2 0 1 2 2 15920 15668 056e0 04ee7 170 +0 1 1 2 0 0 2 1 1 2 1 1 2 2 0 0 1548b 15249 058d1 1498e 10 +1 1 1 1 0 0 1 0 1 1 0 1 1 1 2 0 04fef 14f72 150af 055e3 33 +1 1 1 1 2 0 2 0 1 1 0 2 2 0 1 0 058a6 04cdd 05334 14e73 137 +2 0 0 0 1 1 2 0 0 2 2 1 0 1 2 2 04d2a 05373 055ed 05671 160 +1 1 0 1 2 0 0 1 0 0 0 1 2 1 2 1 1492a 14a8d 15367 15730 42 +1 1 1 0 0 1 0 1 2 1 0 1 1 1 1 0 04b25 05094 15586 14dd3 170 +2 2 1 1 0 1 0 1 1 0 2 0 2 2 2 2 156d7 0569e 153fc 048a9 8 +0 0 1 2 0 2 0 2 0 1 0 0 2 1 0 2 15348 052f6 14d63 14bde 42 +0 2 0 1 1 0 0 2 0 1 1 0 1 1 2 1 0555e 1595d 15441 151da 8 +2 0 2 1 0 0 2 0 1 0 0 2 0 2 1 2 14b0e 04945 04e7d 14f87 10 +1 1 1 0 2 0 0 1 2 1 0 1 2 0 0 1 15068 04c16 054e1 14b04 2 +0 1 0 2 0 2 0 2 2 2 1 0 0 0 2 2 0527f 150d0 153dd 15843 32 +1 0 1 0 0 2 0 1 2 1 2 2 0 1 1 2 14f75 051e8 057df 05646 160 +0 1 2 0 0 1 1 1 2 1 2 1 0 1 0 2 14d66 14873 04b71 0574f 136 +2 2 0 2 0 2 0 1 0 1 1 1 0 2 1 2 1512f 15994 157b4 15798 32 +2 1 2 1 2 2 0 2 1 1 1 2 2 0 2 2 1594a 15591 1581a 0496b 32 +0 1 2 2 1 2 1 2 0 1 2 1 0 0 2 0 159e1 14e23 04fb0 04e0f 162 +2 2 0 1 2 1 2 1 2 2 2 1 2 1 0 2 158bf 14864 052ae 14aab 0 +1 0 0 1 0 1 1 2 2 2 2 1 2 2 1 1 14ca8 04cb2 15211 14acd 138 +1 1 0 1 2 0 1 2 2 0 0 1 0 1 1 2 04e7d 14a3e 1585f 052a1 170 +1 0 0 1 0 0 0 1 0 0 1 0 2 0 2 0 04ca1 058b0 14a08 14860 0 +0 1 1 1 2 2 2 2 0 1 0 2 0 1 0 2 150e1 05814 15686 051aa 170 +2 2 2 0 1 2 1 0 1 1 1 2 1 1 0 1 14ca5 14f05 055d4 05553 32 +0 1 0 1 1 2 2 1 0 1 0 2 1 1 0 1 04c7a 15732 14c42 1495e 128 +0 0 0 0 0 2 0 1 1 1 2 2 0 2 0 2 04c7b 0524e 05651 148b4 32 +1 2 2 1 1 0 1 0 1 1 2 1 0 1 1 0 157a5 04eda 15329 04a30 128 +0 2 2 2 2 1 0 2 2 2 1 1 1 2 0 1 05973 14f56 05140 1590f 40 +0 0 1 2 0 1 2 1 1 0 1 2 1 1 1 2 152b9 051d9 053bd 15280 8 +1 1 2 2 1 2 0 2 0 1 1 0 1 1 2 0 056b6 04840 055c9 15626 128 +0 1 1 1 2 2 0 2 1 2 0 1 1 2 1 2 15839 14f20 055ad 14810 2 +0 0 2 0 2 0 2 1 2 2 2 0 0 0 2 2 055b4 15873 05134 051c1 138 +2 2 2 1 0 2 2 0 1 2 2 0 1 2 0 2 048b0 052f2 05311 15726 42 +1 2 0 1 2 2 0 2 2 0 1 0 2 1 2 2 04f45 159ff 1587b 0525f 32 +2 1 0 1 0 1 0 1 2 0 1 1 0 2 2 2 057f0 04d26 15309 053b6 34 +0 2 1 1 2 0 1 2 2 1 0 0 2 2 0 0 15899 04df2 15006 0518c 2 +0 2 2 1 2 0 1 2 1 2 1 2 0 2 2 0 0548c 14cdd 14c11 057b9 40 +0 2 1 1 1 2 0 1 1 2 0 0 2 2 1 1 054c9 049f6 15966 15466 168 +0 2 1 2 2 1 0 1 1 1 1 2 2 2 2 2 04bbf 14fca 14af5 0588f 170 +0 0 2 2 0 2 0 0 0 1 0 1 0 2 1 1 159f0 05611 04f3c 059af 170 +1 2 2 0 1 0 2 2 0 1 0 0 0 0 1 1 15904 05609 14c05 04d2e 162 +1 0 0 2 2 1 1 0 2 1 2 1 0 1 2 2 14a4f 14f31 052c4 05089 160 +1 0 1 1 1 0 1 0 1 1 1 2 0 1 1 2 04c5f 1530d 150dd 0558c 162 +2 0 1 0 2 2 1 1 0 0 2 2 1 2 1 1 150da 05642 14bb5 14be4 136 +0 2 0 2 2 2 0 2 1 1 0 0 1 0 2 1 1511f 15631 15497 14dd3 160 +2 2 2 1 2 2 0 1 2 1 2 1 1 1 0 2 14cbc 05303 1520d 1506d 138 +1 2 1 0 1 2 1 2 2 0 0 0 0 0 1 2 14995 04cc6 148ff 1548d 34 +2 0 1 0 0 2 1 2 0 2 0 1 2 0 0 1 05956 159d2 14f02 0570b 130 +1 1 1 0 2 0 2 2 1 1 1 2 1 2 0 0 150ba 04f95 048db 1524a 130 +2 1 0 0 0 1 2 2 1 2 2 1 0 2 1 2 155ca 153e7 14a94 04b9a 136 +0 2 2 1 1 1 0 1 1 2 1 1 2 2 0 1 1484e 05121 0581f 052d6 34 +1 1 2 1 1 0 0 1 1 0 2 2 2 0 2 0 05168 051f6 05837 04ed6 162 +1 0 2 1 2 1 2 1 0 0 1 0 1 2 2 0 14feb 056a7 159d0 15977 160 +0 2 2 1 0 0 2 0 1 2 1 0 1 0 2 0 158c7 14c8f 05377 05326 138 +1 1 0 1 1 1 0 1 1 2 0 0 0 1 0 0 0577a 04c6d 157b8 053ea 42 +2 1 2 2 1 0 0 1 2 0 0 2 1 0 0 2 14aea 14e88 04aaf 14e2f 8 +2 0 2 1 1 1 2 1 0 1 1 1 1 2 1 2 05995 1505c 14ceb 052be 130 +0 0 2 1 2 0 2 1 0 1 2 2 2 0 2 1 05407 14d4d 15745 14d02 0 +2 0 0 2 0 2 2 0 0 1 1 1 1 1 0 1 04d52 14e98 14fd0 04fbb 130 +1 0 2 0 1 0 0 0 1 2 1 2 1 0 0 0 155ea 04832 1580f 052fd 168 +2 2 0 1 1 2 1 1 1 0 0 1 0 0 1 0 156c5 04867 04afc 14a81 136 +0 1 2 1 0 2 2 1 1 1 0 0 1 1 1 2 04ce1 155df 05522 057e0 130 +2 0 0 0 2 0 0 1 0 0 1 1 1 0 2 2 04861 1564e 049f4 14bb7 170 +2 2 2 0 1 2 1 0 2 0 2 0 0 0 2 1 05066 157bf 058ac 054b2 162 +2 0 2 1 0 1 2 2 0 0 2 2 1 0 2 2 0514c 15136 15919 05629 0 +1 2 2 0 1 1 2 2 2 0 2 2 1 1 1 2 0509a 04b34 14862 15332 2 +2 0 0 1 0 0 2 1 0 2 0 2 1 2 2 0 04efb 04b5f 14b0e 14f3f 130 +1 1 2 2 0 0 0 2 1 2 2 0 1 2 2 1 05163 14a68 148a8 04fbc 2 +1 0 1 1 1 0 2 0 0 2 0 0 1 1 0 1 150e2 15469 0496a 04b37 10 +0 0 1 2 2 1 0 1 0 0 1 0 1 0 1 0 14d12 058fa 051f4 150e4 0 +2 1 2 2 0 1 0 1 2 1 2 1 1 0 2 1 04c97 150c0 14e60 05119 138 +0 2 2 1 0 2 2 2 2 0 2 1 1 1 2 2 1537a 0579f 14f89 1520f 10 +1 2 2 2 1 0 1 1 0 1 1 0 2 2 0 2 049d0 0558e 04911 148d7 130 +0 1 0 2 2 1 1 2 1 2 2 1 1 2 2 1 14e72 05557 057dd 0496c 160 +2 1 1 0 1 2 2 0 2 0 2 2 2 0 0 1 14a9c 1501b 14985 15118 138 diff --git a/bootstrap/tests/gft_recip.rs b/bootstrap/tests/gft_recip.rs new file mode 100644 index 0000000000..7670f89c41 --- /dev/null +++ b/bootstrap/tests/gft_recip.rs @@ -0,0 +1,78 @@ +// ============================================================================ +// Check for the spec-first GF-T recip primitive (specs/ternary/gft_recip.t27): +// 1/x for a signed GF-T16 input, result a signed GF-T16. The missing building +// block for a GF-T softmax. Bit-exact to the committed integer oracle over 606 +// vectors (tests/gft_recip_vectors.txt); the oracle is itself <=1 ULP vs the true +// true 1/x (exact, 0 ULP) (measured in the prototype). +// ============================================================================ + +use std::env; +use std::fs; +use std::path::PathBuf; +use std::process::Command; + +fn t27c() -> &'static str { env!("CARGO_BIN_EXE_t27c") } +fn spec_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..").join("specs").join("ternary").join("gft_recip.t27") +} +fn vectors_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests").join("gft_recip_vectors.txt") +} +fn tool_available(t: &str) -> bool { + Command::new(t).arg("-V").output().map(|o| o.status.success()).unwrap_or(false) +} + +#[test] +fn spec_first_gft_recip_matches_oracle() { + let gen = Command::new(t27c()).arg("gen-verilog").arg(spec_path()).output().expect("gen-verilog"); + assert!(gen.status.success(), "gen-verilog failed:\n{}", String::from_utf8_lossy(&gen.stderr)); + let v = String::from_utf8_lossy(&gen.stdout).into_owned(); + assert!( + v.contains("input wire [31:0] x") && v.contains("output wire [31:0] result"), + "recip missing x -> result interface:\n{}", v + ); + + if !tool_available("iverilog") || !tool_available("vvp") { + eprintln!("SKIP: iverilog/vvp not on PATH; skipping recip check"); + return; + } + + let vectors = fs::read_to_string(vectors_path()).expect("read vectors"); + let n = vectors.lines().filter(|l| !l.trim().is_empty()).count(); + let dir = env::temp_dir().join(format!("t27_recip_{}", std::process::id())); + let _ = fs::remove_dir_all(&dir); + fs::create_dir_all(&dir).unwrap(); + fs::write(dir.join("spec.v"), &gen.stdout).unwrap(); + fs::write(dir.join("vec.txt"), &vectors).unwrap(); + + let tb = format!( + r#"`timescale 1ns/1ps +module tb; + reg [31:0] x; wire [31:0] y; integer fails,nn,fd,code; reg [31:0] exp; + GftRecip dut(.clk(1'b0),.rst_n(1'b1),.en(1'b1),.x(x),.ready(),.result(y)); + initial begin + fails=0; nn=0; fd=$fopen("{}","r"); + while(!$feof(fd)) begin code=$fscanf(fd,"%h %h\n",x,exp); + if(code==2) begin #1; nn=nn+1; + if(y!==exp) begin fails=fails+1; if(fails<=6)$display("FAIL x=%h y=%h exp=%h",x,y,exp); end + end end + $fclose(fd); + if(fails==0)$display("ALL_PASS %0d",nn); else $display("FAILED %0d/%0d",fails,nn); + $finish; + end +endmodule +"#, + dir.join("vec.txt").to_str().unwrap() + ); + fs::write(dir.join("tb.v"), tb).unwrap(); + + let vvp = dir.join("sim.vvp"); + let compile = Command::new("iverilog").args(["-g2012", "-o", vvp.to_str().unwrap()]) + .arg(dir.join("spec.v")).arg(dir.join("tb.v")).output().unwrap(); + assert!(compile.status.success(), "iverilog compile failed:\n{}", String::from_utf8_lossy(&compile.stderr)); + let run = Command::new("vvp").arg(&vvp).output().unwrap(); + let stdout = String::from_utf8_lossy(&run.stdout).into_owned(); + let _ = fs::remove_dir_all(&dir); + assert!(stdout.contains(&format!("ALL_PASS {}", n)), "recip differs from the oracle:\n{}", stdout); + assert!(!stdout.contains("FAIL"), "recip mismatch:\n{}", stdout); +} diff --git a/bootstrap/tests/gft_recip_vectors.txt b/bootstrap/tests/gft_recip_vectors.txt new file mode 100644 index 0000000000..4b3595cfdf --- /dev/null +++ b/bootstrap/tests/gft_recip_vectors.txt @@ -0,0 +1,506 @@ +05541 04a75 +15390 14c3f +05536 04a7e +148bb 156ee +15271 14d47 +14bd1 15419 +0487f 05734 +14975 15650 +14a79 1553c +14f4d 1506c +05710 0489d +1492b 15686 +15431 14ba7 +15320 14c8f +152ce 14cda +15929 14688 +14f4b 1506e +04f30 05083 +14fe9 1500c +14ce4 152c4 +14b8b 15442 +05743 04874 +14908 156a4 +04de4 0520e +05428 04bb6 +04b3c 05479 +15413 14bdb +04f9a 05039 +054fe 04aac +15770 14854 +05934 0467f +0575c 04862 +05708 048a4 +1530c 14ca0 +15326 14c8a +050f9 04eb1 +05462 04b5b +1526d 14d4c +052b2 04cf8 +048b6 056f3 +14868 15753 +04e10 051e1 +059f9 04604 +153a7 14c31 +0540f 04be3 +14d15 15298 +04afe 054ac +04918 05696 +14f24 1508c +058d1 046d7 +05448 04b82 +0557b 04a4c +05120 04e8f +0514c 04e6d +14d2e 15284 +1494a 1566f +05450 04b76 +149e0 15611 +157e2 1480f +14a69 15552 +14a72 15546 +0480a 057ec +05844 04788 +04c87 0532a +04be8 0540c +04cac 052ff +151f9 14e04 +059db 04613 +155ab 14a2e +050d3 04ed5 +1529f 14d0d +14e16 151d6 +15842 1478b +152a8 14d03 +05989 04643 +0574d 0486c +1509e 14f0f +14b0d 1549f +04c6b 0534f +04eeb 050be +058d8 046d0 +152f4 14cb6 +04b6c 05457 +04a5a 05567 +14ffe 15001 +0547d 04b37 +15560 14a5f +0592d 04685 +054d8 04ad0 +055a5 04a32 +05602 049fc +14db3 1522a +1580a 147ec +0520e 04de5 +05139 04e7c +15059 14f68 +0540e 04be5 +14ed4 150d4 +150cc 14edc +04db2 0522a +04e6b 0514f +05577 04a4f +1530c 14ca0 +15637 1499d +155d0 14a19 +04f64 0505c +051e3 04e0f +04e84 0512e +1536a 14c58 +0563c 04995 +15422 14bc0 +058b1 046f9 +14edd 150cb +0592c 04686 +04fee 05009 +14aea 154bf +04acc 054dc +15357 14c65 +058ee 046bb +157bd 14824 +14f77 1504f +04a8f 05520 +04ce6 052c3 +14d2b 15286 +0554e 04a6c +04fce 0501a +04d61 0525e +053d6 04c16 +15326 14c8a +04a28 055b6 +15191 14e3e +14d19 15295 +04f32 05081 +14fc5 1501f +04982 05648 +15084 14f2e +14e59 15168 +14d93 1523d +1516b 14e57 +14ed0 150d8 +14c20 153c4 +04847 05783 +152e3 14cc5 +14fcc 1501b +059cf 0461a +0529a 04d13 +14fa6 15031 +153fe 14c01 +15543 14a74 +14cd8 152d0 +14e66 15156 +157ec 1480a +056c6 048e2 +04908 056a4 +151a2 14e34 +05110 04e9d +04f01 050aa +153c6 14c1f +14b3e 15478 +14a7c 15538 +14957 15665 +15053 14f71 +14e7e 15136 +05793 0483d +0568f 04920 +14df9 15204 +152ab 14d00 +15715 14898 +04fbb 05025 +0536e 04c55 +14dab 1522e +04b99 05439 +059f8 04604 +04c00 05400 +158c2 146e7 +05559 04a64 +152a7 14d04 +14edd 150cb +155cb 14a1c +151d7 14e15 +05269 04d52 +054ab 04b00 +05828 047b6 +04f6e 05055 +05775 04850 +04b47 05471 +04fb5 05028 +04d31 05282 +04f8c 05041 +055d5 04a16 +15007 14ff2 +0590d 0469f +148d9 156cf +148ed 156bc +0496a 05658 +05781 04848 +14a1f 155c6 +054b5 04af5 +15558 14a64 +14e96 15118 +158b2 146f8 +1495d 15661 +057e5 0480e +0599e 04636 +1505e 14f61 +059bb 04625 +1510f 14e9e +1529c 14d11 +1513b 14e7a +14e4a 1517f +04f62 0505d +04f85 05046 +04f7c 0504c +04b1e 05491 +04b89 05443 +150f5 14eb5 +05010 04fe1 +04b79 0544e +15425 14bbb +15453 14b71 +14d15 15298 +15769 14859 +14d8d 15241 +056ec 048bd +05973 04652 +04ce9 052c0 +1574d 1486c +1550a 14aa2 +149bb 15625 +0539b 04c38 +0535d 04c61 +04c03 053fa +05096 04f18 +0513e 04e78 +14c2a 153b2 +054a3 04b09 +05508 04aa4 +05902 046a9 +052ee 04cbb +04f82 05048 +05512 04a9b +1537b 14c4c +05021 04fc2 +0587c 04738 +050ad 04efd +158e4 146c4 +058db 046cd +14a89 15528 +055b8 04a27 +15736 1487e +153eb 14c0b +153eb 14c0b +14965 1565b +15478 14b3e +0488d 05723 +054f7 04ab3 +154f3 14ab6 +153b7 14c27 +1552e 14a84 +14c7c 15338 +04959 05664 +05666 04956 +0588e 04722 +1490e 1569e +1481b 157cd +155d4 14a17 +04c8e 05322 +15760 1485f +15992 1463e +053ed 04c0a +151f6 14e05 +053fe 04c01 +15843 1478a +054ac 04aff +0519f 04e36 +14fe3 1500f +149cc 1561b +14aea 154bf +15864 14759 +14f62 1505d +04c56 0536d +14ed9 150cf +05312 04c9b +04e49 05180 +148af 156fb +0491f 05690 +05841 0478d +059f6 04605 +05421 04bc2 +050cf 04ed9 +154fe 14aac +05148 04e70 +1517c 14e4c +04a4c 0557c +04aaf 054fb +15422 14bc0 +0590d 0469f +14ac1 154e8 +04bf7 05405 +15794 1483c +15839 14799 +14c7c 15338 +05835 047a0 +057b5 04828 +154ff 14aac +158d4 146d4 +15363 14c5d +04d2e 05284 +0520c 04de9 +15415 14bd8 +14c0d 153e7 +15790 1483f +0595a 04663 +04a98 05516 +14b23 1548d +14ed3 150d5 +055f9 04a04 +150ad 14efd +04bf8 05404 +14d3e 15278 +1485e 15761 +14f95 1503c +059f5 04606 +149b2 1562a +058c4 046e5 +15669 14952 +15328 14c89 +14ee9 150c0 +156c2 148e7 +14bbb 15425 +0482c 057af +04b7c 0544c +05677 0493f +05402 04bfc +04a49 05580 +151b9 14e26 +155ab 14a2e +04d9c 05237 +04a67 05555 +05050 04f76 +158b9 146f0 +04bb0 0542b +14c79 1533c +04a97 05517 +1598e 14640 +04e50 05176 +055d8 04a15 +057a9 04830 +04b39 0547c +1585c 14764 +1526e 14d4b +05709 048a3 +15830 147a8 +155f7 14a05 +051b3 04e2a +150ac 14eff +0495f 05660 +153ee 14c09 +1594e 1466c +15534 14a7f +14f49 1506f +058e4 046c4 +15740 14876 +14910 1569d +150b7 14ef2 +053e5 04c0e +14c50 15376 +15717 14897 +14a1f 155c6 +150b4 14ef6 +0568c 04924 +148a9 15702 +14b8b 15442 +04cb6 052f3 +05984 04647 +15754 14867 +14c70 15348 +15726 1488a +14985 15646 +15369 14c59 +153fc 14c02 +159b8 14627 +14ad4 154d4 +149d1 15619 +156b4 148f6 +154f4 14ab6 +14c02 153fc +15760 1485f +14812 157dd +151eb 14e0b +14cc9 152df +0507d 04f37 +1553e 14a78 +049e1 05610 +05008 04ff0 +0488b 05725 +04f8c 05041 +153c3 14c20 +15109 14ea3 +0496c 05657 +153c0 14c22 +1556b 14a57 +1547c 14b38 +156e9 148c0 +14c63 1535a +056fa 048b0 +148dd 156cb +05830 047a8 +14ffd 15002 +05973 04652 +14aeb 154be +05795 0483c +04c8e 05322 +14b5d 15461 +14c55 1536e +15627 149b8 +15953 14668 +055e7 04a0d +149d8 15615 +05980 04649 +14e1d 151c9 +04871 05747 +1571c 14893 +059e6 0460d +14811 157df +04e41 0518d +157e0 14811 +14e2e 151ac +159f5 14606 +14a34 155a2 +1517b 14e4c +148a1 1570b +1544d 14b7a +057e4 0480e +152fb 14caf +05973 04652 +14db9 15226 +0505d 04f63 +149f0 15608 +14cde 152ca +15001 14ffe +14e0d 151e7 +14830 157a8 +05232 04da5 +14a8f 15520 +14ee8 150c1 +14f6a 15058 +149d5 15616 +14b44 15473 +04cca 052de +14d16 15298 +05461 04b5d +15786 14845 +14eba 150ef +04f44 05073 +049d7 05615 +05231 04da7 +04999 05639 +05874 04743 +15689 14928 +0504e 04f79 +15468 14b53 +15091 14f1e +14f27 1508a +14e5a 15167 +058bb 046ee +04e94 0511a +059fe 04601 +1511e 14e91 +054b5 04af5 +154f2 14ab7 +04fa4 05033 +0579d 04837 +05725 0488b +14fb6 15028 +14f4e 1506c +04e7b 0513a +0553b 04a7a +14aad 154fd +05958 04664 +05128 04e89 +04d6a 05258 +04f00 050ab +04b63 0545d +0559f 04a36 +152d8 14cd0 +1554a 14a6f +1538c 14c41 +157ee 14809 +151b0 14e2b +14ebc 150ed +15951 1466a +14921 1568f +0533e 04c78 +0558e 04a40 +04dcb 0521c +14bed 1540a +05906 046a5 +0513d 04e78 +05885 0472d +05000 05000 +05200 04e00 +04e00 05200 +15000 15000 +05400 04c00 +04c00 05400 diff --git a/bootstrap/tests/gft_softmax4.rs b/bootstrap/tests/gft_softmax4.rs new file mode 100644 index 0000000000..1c70d224e5 --- /dev/null +++ b/bootstrap/tests/gft_softmax4.rs @@ -0,0 +1,81 @@ +// ============================================================================ +// Check for the spec-first GF-T softmax (specs/ternary/gft_softmax4.t27): softmax +// over four signed GF-T16 logits, base-2, max-stabilized -> p_sel as a positive +// GF-T16. Composes the verified GF-T primitives (max/sub/exp2/sum/reciprocal/mul). +// Bit-exact to the committed integer oracle over 2000 vectors +// (tests/gft_softmax4_vectors.txt); accuracy vs true float softmax <=0.0017 abs +// probability (measured in the oracle harness). +// ============================================================================ + +use std::env; +use std::fs; +use std::path::PathBuf; +use std::process::Command; + +fn t27c() -> &'static str { env!("CARGO_BIN_EXE_t27c") } +fn spec_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("..").join("specs").join("ternary").join("gft_softmax4.t27") +} +fn vectors_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests").join("gft_softmax4_vectors.txt") +} +fn tool_available(t: &str) -> bool { + Command::new(t).arg("-V").output().map(|o| o.status.success()).unwrap_or(false) +} + +#[test] +fn spec_first_gft_softmax4_matches_oracle() { + let gen = Command::new(t27c()).arg("gen-verilog").arg(spec_path()).output().expect("gen-verilog"); + assert!(gen.status.success(), "gen-verilog failed:\n{}", String::from_utf8_lossy(&gen.stderr)); + let v = String::from_utf8_lossy(&gen.stdout).into_owned(); + assert!( + v.contains("input wire [31:0] l0") && v.contains("input wire [7:0] sel") + && v.contains("output wire [31:0] result"), + "softmax4 missing logits/sel -> prob interface:\n{}", v + ); + + if !tool_available("iverilog") || !tool_available("vvp") { + eprintln!("SKIP: iverilog/vvp not on PATH; skipping softmax4 check"); + return; + } + + let vectors = fs::read_to_string(vectors_path()).expect("read vectors"); + let n = vectors.lines().filter(|l| !l.trim().is_empty()).count(); + let dir = env::temp_dir().join(format!("t27_sm4_{}", std::process::id())); + let _ = fs::remove_dir_all(&dir); + fs::create_dir_all(&dir).unwrap(); + fs::write(dir.join("spec.v"), &gen.stdout).unwrap(); + fs::write(dir.join("vec.txt"), &vectors).unwrap(); + + let tb = format!( + r#"`timescale 1ns/1ps +module tb; + reg [31:0] l0,l1,l2,l3; reg [7:0] sel; wire [31:0] y; + integer fails,nn,fd,code; reg [31:0] exp; + GftSoftmax4 dut(.clk(1'b0),.rst_n(1'b1),.en(1'b1),.l0(l0),.l1(l1),.l2(l2),.l3(l3),.sel(sel),.ready(),.result(y)); + initial begin + fails=0; nn=0; fd=$fopen("{}","r"); + while(!$feof(fd)) begin code=$fscanf(fd,"%h %h %h %h %d %h\n",l0,l1,l2,l3,sel,exp); + if(code==6) begin #1; nn=nn+1; + if(y!==exp) begin fails=fails+1; if(fails<=6)$display("FAIL sel=%0d y=%h exp=%h",sel,y,exp); end + end end + $fclose(fd); + if(fails==0)$display("ALL_PASS %0d",nn); else $display("FAILED %0d/%0d",fails,nn); + $finish; + end +endmodule +"#, + dir.join("vec.txt").to_str().unwrap() + ); + fs::write(dir.join("tb.v"), tb).unwrap(); + + let vvp = dir.join("sim.vvp"); + let compile = Command::new("iverilog").args(["-g2012", "-o", vvp.to_str().unwrap()]) + .arg(dir.join("spec.v")).arg(dir.join("tb.v")).output().unwrap(); + assert!(compile.status.success(), "iverilog compile failed:\n{}", String::from_utf8_lossy(&compile.stderr)); + let run = Command::new("vvp").arg(&vvp).output().unwrap(); + let stdout = String::from_utf8_lossy(&run.stdout).into_owned(); + let _ = fs::remove_dir_all(&dir); + assert!(stdout.contains(&format!("ALL_PASS {}", n)), "softmax4 differs from the oracle:\n{}", stdout); + assert!(!stdout.contains("FAIL"), "softmax4 mismatch:\n{}", stdout); +} diff --git a/bootstrap/tests/gft_softmax4_vectors.txt b/bootstrap/tests/gft_softmax4_vectors.txt new file mode 100644 index 0000000000..7f65a0f02d --- /dev/null +++ b/bootstrap/tests/gft_softmax4_vectors.txt @@ -0,0 +1,2000 @@ +149f7 04886 051a6 15476 0 04aa6 +149f7 04886 051a6 15476 1 04b0b +149f7 04886 051a6 15476 2 04e8e +149f7 04886 051a6 15476 3 0410a +14dc1 150c2 05792 1504e 0 03261 +14dc1 150c2 05792 1504e 1 0308a +14dc1 150c2 05792 1504e 2 05000 +14dc1 150c2 05792 1504e 3 030f4 +04c56 053bf 14d71 14c85 0 0486b +04c56 053bf 14d71 14c85 1 04f50 +04c56 053bf 14d71 14c85 2 046ed +04c56 053bf 14d71 14c85 3 0472c +05319 059fe 14bd9 04d43 0 0163a +05319 059fe 14bd9 04d43 1 05000 +05319 059fe 14bd9 04d43 2 00f84 +05319 059fe 14bd9 04d43 3 010c4 +0556e 14b0a 14d41 054e2 0 04eb3 +0556e 14b0a 14d41 054e2 1 0409d +0556e 14b0a 14d41 054e2 2 0403e +0556e 14b0a 14d41 054e2 3 04c88 +14847 153c0 1557b 04c37 0 04d64 +14847 153c0 1557b 04c37 1 0461f +14847 153c0 1557b 04c37 2 03faa +14847 153c0 1557b 04c37 3 04e28 +14c85 04dc6 14adc 04b84 0 04b08 +14c85 04dc6 14adc 04b84 1 04c9e +14c85 04dc6 14adc 04b84 2 04b55 +14c85 04dc6 14adc 04b84 3 04c33 +14eb7 154b6 14f5d 14d67 0 04c90 +14eb7 154b6 14f5d 14d67 1 0430f +14eb7 154b6 14f5d 14d67 2 04c4a +14eb7 154b6 14f5d 14d67 3 04d0f +04898 14f71 057f5 157dc 0 03061 +04898 14f71 057f5 157dc 1 02e7c +04898 14f71 057f5 157dc 2 05000 +04898 14f71 057f5 157dc 3 0115e +05235 050a2 05411 052e2 0 04a4e +05235 050a2 05411 052e2 1 0487b +05235 050a2 05411 052e2 2 04e30 +05235 050a2 05411 052e2 3 04baf +0597e 05494 15691 04cb3 0 05000 +0597e 05494 15691 04cb3 1 02254 +0597e 05494 15691 04cb3 2 00384 +0597e 05494 15691 04cb3 3 018a6 +05434 04e76 14cc9 15894 0 04f9b +05434 04e76 14cc9 15894 1 04816 +05434 04e76 14cc9 15894 2 04621 +05434 04e76 14cc9 15894 3 01d87 +14ba1 0497a 14d68 04984 0 04ba4 +14ba1 0497a 14d68 04984 1 04c4c +14ba1 0497a 14d68 04984 2 04b2c +14ba1 0497a 14d68 04984 3 04c4d +055ea 154bc 05720 0577f 0 0429e +055ea 154bc 05720 0577f 1 02827 +055ea 154bc 05720 0577f 2 04c16 +055ea 154bc 05720 0577f 3 04eeb +04c92 14e80 150f5 04bd8 0 04ce9 +04c92 14e80 150f5 04bd8 1 04b05 +04c92 14e80 150f5 04bd8 2 04958 +04c92 14e80 150f5 04bd8 3 04cc0 +15364 05998 059d1 15572 0 00b3d +15364 05998 059d1 15572 1 04b9b +15364 05998 059d1 15572 2 04f19 +15364 05998 059d1 15572 3 00449 +14e5f 049e5 14da5 158b9 0 04c23 +14e5f 049e5 14da5 158b9 1 04d82 +14e5f 049e5 14da5 158b9 2 04c5a +14e5f 049e5 14da5 158b9 3 021be +04e4d 14d79 048f7 059b9 0 01570 +04e4d 14d79 048f7 059b9 1 01370 +04e4d 14d79 048f7 059b9 2 0147c +04e4d 14d79 048f7 059b9 3 05000 +14c79 05009 14db8 14b1c 0 04aeb +14c79 05009 14db8 14b1c 1 04da8 +14c79 05009 14db8 14b1c 2 04a9d +14c79 05009 14db8 14b1c 3 04b28 +15617 15548 052d8 158f7 0 03978 +15617 15548 052d8 158f7 1 03d03 +15617 15548 052d8 158f7 2 04ffe +15617 15548 052d8 158f7 3 01ab4 +15240 0562e 0578b 14e08 0 02ee3 +15240 0562e 0578b 14e08 1 044db +15240 0562e 0578b 14e08 2 04fe9 +15240 0562e 0578b 14e08 3 0326e +0518f 14cf2 053b0 14d42 0 04b14 +0518f 14cf2 053b0 14d42 1 046c8 +0518f 14cf2 053b0 14d42 2 04ee3 +0518f 14cf2 053b0 14d42 3 046b5 +04fca 14c8e 14e49 14963 0 04d90 +04fca 14c8e 14e49 14963 1 04af6 +04fca 14c8e 14e49 14963 2 04a7c +04fca 14c8e 14e49 14963 3 04b70 +04f0d 14fda 05548 0484c 0 04439 +04f0d 14fda 05548 0484c 1 040b0 +04f0d 14fda 05548 0484c 2 04fdd +04f0d 14fda 05548 0484c 3 042bf +1526c 058c4 15245 157e3 0 01eb5 +1526c 058c4 15245 157e3 1 05000 +1526c 058c4 15245 157e3 2 01f05 +1526c 058c4 15245 157e3 3 0047c +04d5f 150af 15254 14a1a 0 04dc4 +04d5f 150af 15254 14a1a 1 04a38 +04d5f 150af 15254 14a1a 2 0483d +04d5f 150af 15254 14a1a 3 04c91 +04991 050d6 1510c 14960 0 04b6f +04991 050d6 1510c 14960 1 04e20 +04991 050d6 1510c 14960 2 04836 +04991 050d6 1510c 14960 3 04af4 +0550e 14ae5 04e8d 14a19 0 04fd0 +0550e 14ae5 04e8d 14a19 1 0431f +0550e 14ae5 04e8d 14a19 2 044c0 +0550e 14ae5 04e8d 14a19 3 04339 +0584d 058b0 04b1a 0480d 0 0495c +0584d 058b0 04b1a 0480d 1 04f95 +0584d 058b0 04b1a 0480d 2 024e2 +0584d 058b0 04b1a 0480d 3 024a5 +0536c 1562f 04998 0545f 0 04c39 +0536c 1562f 04998 0545f 1 03400 +0536c 1562f 04998 0545f 2 04593 +0536c 1562f 04998 0545f 3 04ec6 +14cfb 0593d 153ad 14958 0 01b4b +14cfb 0593d 153ad 14958 1 05000 +14cfb 0593d 153ad 14958 2 014a6 +14cfb 0593d 153ad 14958 3 01c00 +15692 15772 05856 153ff 0 0160b +15692 15772 05856 153ff 1 00ed4 +15692 15772 05856 153ff 2 05000 +15692 15772 05856 153ff 3 0227c +14e75 15125 04d9c 04ec2 0 04aa2 +14e75 15125 04d9c 04ec2 1 048b6 +14e75 15125 04d9c 04ec2 2 04cc1 +14e75 15125 04d9c 04ec2 3 04d40 +053a6 054d3 04996 14e41 0 04b1d +053a6 054d3 04996 14e41 1 04f1d +053a6 054d3 04996 14e41 2 04425 +053a6 054d3 04996 14e41 3 042b0 +054d2 050f0 15172 04bfc 0 04fb1 +054d2 050f0 15172 04bfc 1 04747 +054d2 050f0 15172 04bfc 2 040e0 +054d2 050f0 15172 04bfc 3 044d1 +05879 14dea 14d27 153a3 0 05000 +05879 14dea 14d27 153a3 1 0274b +05879 14dea 14d27 153a3 2 02784 +05879 14dea 14d27 153a3 3 02105 +055a7 15900 14880 04ded 0 04ff0 +055a7 15900 14880 04ded 1 0112b +055a7 15900 14880 04ded 2 04105 +055a7 15900 14880 04ded 3 0423e +04bb7 15622 15758 14bc8 0 04e52 +04bb7 15622 15758 14bc8 1 03cba +04bb7 15622 15758 14bc8 2 0330a +04bb7 15622 15758 14bc8 3 04d59 +05498 15108 04bfd 1585c 0 04fd6 +05498 15108 04bfd 1585c 1 0425b +05498 15108 04bfd 1585c 2 04601 +05498 15108 04bfd 1585c 3 01fad +1531f 04dea 14fb6 1521f 0 0473c +1531f 04dea 14fb6 1521f 1 04e78 +1531f 04dea 14fb6 1521f 2 04bb2 +1531f 04dea 14fb6 1521f 3 0493c +15210 059a1 04ad3 14d3e 0 011c0 +15210 059a1 04ad3 14d3e 1 05000 +15210 059a1 04ad3 14d3e 2 0163a +15210 059a1 04ad3 14d3e 3 014f4 +15681 0555b 14fa6 14e48 0 02e67 +15681 0555b 14fa6 14e48 1 04ff4 +15681 0555b 14fa6 14e48 2 04090 +15681 0555b 14fa6 14e48 3 04141 +05791 1545c 059d3 052a3 0 02f38 +05791 1545c 059d3 052a3 1 00938 +05791 1545c 059d3 052a3 2 05000 +05791 1545c 059d3 052a3 3 0180b +158c1 158f2 04a4a 050ce 0 02015 +158c1 158f2 04a4a 050ce 1 01ce2 +158c1 158f2 04a4a 050ce 2 04c5b +158c1 158f2 04a4a 050ce 3 04ed2 +05025 0576a 1566b 05496 0 036ad +05025 0576a 1566b 05496 1 04ffe +05025 0576a 1566b 05496 2 02136 +05025 0576a 1566b 05496 3 03edb +05289 0564b 155c3 15732 0 0428a +05289 0564b 155c3 15732 1 04ff6 +05289 0564b 155c3 15732 2 02e76 +05289 0564b 155c3 15732 3 02412 +054fc 057a2 04c08 04afa 0 03eb4 +054fc 057a2 04c08 04afa 1 04ffe +054fc 057a2 04c08 04afa 2 03349 +054fc 057a2 04c08 04afa 3 03325 +04bc3 0576f 14846 04bf8 0 034d4 +04bc3 0576f 14846 04bf8 1 05000 +04bc3 0576f 14846 04bf8 2 03447 +04bc3 0576f 14846 04bf8 3 034dc +15019 0503b 0551f 1482f 0 04120 +15019 0503b 0551f 1482f 1 04581 +15019 0503b 0551f 1482f 2 04fd2 +15019 0503b 0551f 1482f 3 04313 +14e33 14f39 15388 0500a 0 04b3d +14e33 14f39 15388 0500a 1 04ab7 +14e33 14f39 15388 0500a 2 0454b +14e33 14f39 15388 0500a 3 04e68 +05638 148bb 05364 04ba6 0 04fe5 +05638 148bb 05364 04ba6 1 03e03 +05638 148bb 05364 04ba6 2 044c9 +05638 148bb 05364 04ba6 3 03e7f +14f93 15151 14966 14b94 0 04b42 +14f93 15151 14966 14b94 1 049d6 +14f93 15151 14966 14b94 2 04cd0 +14f93 15151 14966 14b94 3 04c98 +15397 0499a 05933 150a1 0 01584 +15397 0499a 05933 150a1 1 01ce3 +15397 0499a 05933 150a1 2 05000 +15397 0499a 05933 150a1 3 01a22 +1529c 14a69 04a6d 15673 0 04868 +1529c 14a69 04a6d 15673 1 04d4e +1529c 14a69 04a6d 15673 2 04e0a +1529c 14a69 04a6d 15673 3 03a1b +14e64 149e9 14878 155cb 0 04c16 +14e64 149e9 14878 155cb 1 04ce7 +14e64 149e9 14878 155cb 2 04cff +14e64 149e9 14878 155cb 3 03e1b +1534e 153e8 158bb 0525c 0 04471 +1534e 153e8 158bb 0525c 1 04338 +1534e 153e8 158bb 0525c 2 01f67 +1534e 153e8 158bb 0525c 3 04fdf +04ac2 151a0 14d48 14846 0 04ce5 +04ac2 151a0 14d48 14846 1 048ee +04ac2 151a0 14d48 14846 2 04bde +04ac2 151a0 14d48 14846 3 04c72 +0553b 14e2f 1549e 04988 0 04fec +0553b 14e2f 1549e 04988 1 041e7 +0553b 14e2f 1549e 04988 2 03870 +0553b 14e2f 1549e 04988 3 04312 +1593d 152ba 055b4 1583a 0 00d38 +1593d 152ba 055b4 1583a 1 03bab +1593d 152ba 055b4 1583a 2 05000 +1593d 152ba 055b4 1583a 3 01d70 +159d3 04c63 15174 04f6f 0 00f33 +159d3 04c63 15174 04f6f 1 04cf0 +159d3 04c63 15174 04f6f 2 048e3 +159d3 04c63 15174 04f6f 3 04e2b +157ec 15783 15550 158b5 0 03dcd +157ec 15783 15550 158b5 1 040f6 +157ec 15783 15550 158b5 2 04ff8 +157ec 15783 15550 158b5 3 031e2 +04c9d 059bb 05356 04a3c 0 014c4 +04c9d 059bb 05356 04a3c 1 05000 +04c9d 059bb 05356 04a3c 2 01ad4 +04c9d 059bb 05356 04a3c 3 0146e +05621 058c0 1570b 1545f 0 034dc +05621 058c0 1570b 1545f 1 05000 +05621 058c0 1570b 1545f 2 00b84 +05621 058c0 1570b 1545f 3 01a61 +14aa2 14cc8 057e1 04b8b 0 0307c +14aa2 14cc8 057e1 04b8b 1 03034 +14aa2 14cc8 057e1 04b8b 2 05000 +14aa2 14cc8 057e1 04b8b 3 03141 +15881 057b9 14aa3 05055 0 00a17 +15881 057b9 14aa3 05055 1 05000 +15881 057b9 14aa3 05055 2 031d5 +15881 057b9 14aa3 05055 3 0346e +048cd 0492c 14dcd 14e9a 0 04c70 +048cd 0492c 14dcd 14e9a 1 04c75 +048cd 0492c 14dcd 14e9a 2 04b4c +048cd 0492c 14dcd 14e9a 3 04aec +14ca0 151ea 04a7f 05053 0 04ae4 +14ca0 151ea 04a7f 05053 1 047bf +14ca0 151ea 04a7f 05053 2 04c06 +14ca0 151ea 04a7f 05053 3 04e08 +048ac 1578a 04f4f 055c0 0 040f4 +048ac 1578a 04f4f 055c0 1 02480 +048ac 1578a 04f4f 055c0 2 04279 +048ac 1578a 04f4f 055c0 3 04ff0 +14f24 1534b 15046 04e77 0 04b79 +14f24 1534b 15046 04e77 1 04672 +14f24 1534b 15046 04e77 2 04ab9 +14f24 1534b 15046 04e77 3 04e4c +15025 05423 156aa 15623 0 04513 +15025 05423 156aa 15623 1 04fe7 +15025 05423 156aa 15623 2 0320a +15025 05423 156aa 15623 3 03639 +04fbe 14eb6 04e7d 15798 0 04dc0 +04fbe 14eb6 04e7d 15798 1 04a73 +04fbe 14eb6 04e7d 15798 2 04d04 +04fbe 14eb6 04e7d 15798 3 02f04 +14f43 0565c 153ed 15908 0 03b5e +14f43 0565c 153ed 15908 1 05000 +14f43 0565c 153ed 15908 2 0351e +14f43 0565c 153ed 15908 3 00c7c +15300 14a81 148b9 0593b 0 0163a +15300 14a81 148b9 0593b 1 01c00 +15300 14a81 148b9 0593b 2 01c17 +15300 14a81 148b9 0593b 3 05000 +0517c 15472 04ae6 05313 0 04c12 +0517c 15472 04ae6 05313 1 03ea9 +0517c 15472 04ae6 05313 2 048ce +0517c 15472 04ae6 05313 3 04e9b +0492c 053de 151ed 04a0c 0 04803 +0492c 053de 151ed 04a0c 1 04f6e +0492c 053de 151ed 04a0c 2 043dd +0492c 053de 151ed 04a0c 3 0480e +0575d 04c9d 15212 15186 0 05000 +0575d 04c9d 15212 15186 1 035ab +0575d 04c9d 15212 15186 2 030c4 +0575d 04c9d 15212 15186 3 03170 +04fd3 15565 0509a 04ce8 0 04cb9 +04fd3 15565 0509a 04ce8 1 03d3f +04fd3 15565 0509a 04ce8 2 04d76 +04fd3 15565 0509a 04ce8 3 04b9e +05133 05820 05530 04cec 0 03105 +05133 05820 05530 04cec 1 05000 +05133 05820 05530 04cec 2 03a98 +05133 05820 05530 04cec 3 02e98 +04e02 04b0e 155eb 04b7d 0 04d0b +04e02 04b0e 155eb 04b7d 1 04c74 +04e02 04b0e 155eb 04b7d 2 03c66 +04e02 04b0e 155eb 04b7d 3 04c80 +059a9 051a9 1501e 158ec 0 05000 +059a9 051a9 1501e 158ec 1 018f4 +059a9 051a9 1501e 158ec 2 01327 +059a9 051a9 1501e 158ec 3 00200 +15619 0596e 152d6 0529e 0 00847 +15619 0596e 152d6 0529e 1 05000 +15619 0596e 152d6 0529e 2 0134b +15619 0596e 152d6 0529e 3 01e47 +15708 159da 14a11 056b0 0 0222e +15708 159da 14a11 056b0 1 00200 +15708 159da 14a11 056b0 2 03a2e +15708 159da 14a11 056b0 3 05000 +14aef 056cb 051fc 04fc4 0 0391c +14aef 056cb 051fc 04fc4 1 04ffe +14aef 056cb 051fc 04fc4 2 03d82 +14aef 056cb 051fc 04fc4 3 03b64 +14da2 05950 04caf 057e8 0 01a0b +14da2 05950 04caf 057e8 1 05000 +14da2 05950 04caf 057e8 2 01b97 +14da2 05950 04caf 057e8 3 03a2e +14e05 14bb3 0493d 14d1b 0 04b52 +14e05 14bb3 0493d 14d1b 1 04c02 +14e05 14bb3 0493d 14d1b 2 04c88 +14e05 14bb3 0493d 14d1b 3 04b9b +05832 05868 154d3 14f02 0 04bca +05832 05868 154d3 14f02 1 04f0d +05832 05868 154d3 14f02 2 01d41 +05832 05868 154d3 14f02 3 0270d +159b8 05157 056fe 05658 0 0016e +159b8 05157 056fe 05658 1 03aca +159b8 05157 056fe 05658 2 04f6e +159b8 05157 056fe 05658 3 04a45 +058a8 0534a 15639 059d8 0 03cd3 +058a8 0534a 15639 059d8 1 018e2 +058a8 0534a 15639 059d8 2 001fe +058a8 0534a 15639 059d8 3 04ffe +14a18 0514f 15062 14b48 0 04ab9 +14a18 0514f 15062 14b48 1 04e59 +14a18 0514f 15062 14b48 2 0489d +14a18 0514f 15062 14b48 3 04a96 +14b29 04ac8 159cb 1536c 0 04d56 +14b29 04ac8 159cb 1536c 1 04e28 +14b29 04ac8 159cb 1536c 2 010fb +14b29 04ac8 159cb 1536c 3 046db +04931 05134 1522e 0531a 0 048a9 +04931 05134 1522e 0531a 1 04bc3 +04931 05134 1522e 0531a 2 04431 +04931 05134 1522e 0531a 3 04ea9 +055af 159e1 05108 156ee 0 04fee +055af 159e1 05108 156ee 1 00308 +055af 159e1 05108 156ee 2 0442d +055af 159e1 05108 156ee 3 029af +14bb0 14ef3 148d1 0566d 0 03c15 +14bb0 14ef3 148d1 0566d 1 03af1 +14bb0 14ef3 148d1 0566d 2 03c4b +14bb0 14ef3 148d1 0566d 3 04ffc +04b19 153a0 05629 04937 0 03ee8 +04b19 153a0 05629 04937 1 0374e +04b19 153a0 05629 04937 2 04ffa +04b19 153a0 05629 04937 3 03eb9 +15209 151d3 0569c 15949 0 036e3 +15209 151d3 0569c 15949 1 03727 +15209 151d3 0569c 15949 2 05000 +15209 151d3 0569c 15949 3 00661 +15188 052a5 049dd 14edf 0 0464b +15188 052a5 049dd 14edf 1 04f09 +15188 052a5 049dd 14edf 2 04a1c +15188 052a5 049dd 14edf 3 0485c +14991 052a5 0482e 04fe2 0 048e7 +14991 052a5 0482e 04fe2 1 04e75 +14991 052a5 0482e 04fe2 2 0494b +14991 052a5 0482e 04fe2 3 04b13 +14c9f 150e2 14e80 04cf0 0 04c0d +14c9f 150e2 14e80 04cf0 1 049cc +14c9f 150e2 14e80 04cf0 2 04b58 +14c9f 150e2 14e80 04cf0 3 04d53 +15755 0502b 04a09 156fd 0 031fd +15755 0502b 04a09 156fd 1 04ea4 +15755 0502b 04a09 156fd 2 04cb8 +15755 0502b 04a09 156fd 3 03495 +0576d 14a5d 15631 155fb 0 05000 +0576d 14a5d 15631 155fb 1 0343a +0576d 14a5d 15631 155fb 2 022e3 +0576d 14a5d 15631 155fb 3 0248a +158df 14e2e 14a50 14b99 0 01f5f +158df 14e2e 14a50 14b99 1 04c3e +158df 14e2e 14a50 14b99 2 04cf6 +158df 14e2e 14a50 14b99 3 04ccd +14d82 05221 14d4d 15293 0 049eb +14d82 05221 14d4d 15293 1 04ee7 +14d82 05221 14d4d 15293 2 049fc +14d82 05221 14d4d 15293 3 04591 +059e0 04e89 15229 14ddb 0 05000 +059e0 04e89 15229 14ddb 1 01316 +059e0 04e89 15229 14ddb 2 00d84 +059e0 04e89 15229 14ddb 3 010e3 +04c06 0539c 148e2 054bf 0 04491 +04c06 0539c 148e2 054bf 1 04b4a +04c06 0539c 148e2 054bf 2 04405 +04c06 0539c 148e2 054bf 3 04f09 +157bf 15578 054f9 14c89 0 02610 +157bf 15578 054f9 14c89 1 03626 +157bf 15578 054f9 14c89 2 04ff2 +157bf 15578 054f9 14c89 3 04347 +051dc 04834 14eda 0597d 0 01c0b +051dc 04834 14eda 0597d 1 0183a +051dc 04834 14eda 0597d 2 01698 +051dc 04834 14eda 0597d 3 05000 +152d0 052ae 1544b 0560c 0 039e9 +152d0 052ae 1544b 0560c 1 044c0 +152d0 052ae 1544b 0560c 2 03647 +152d0 052ae 1544b 0560c 3 04fe9 +0493e 04e4d 05366 059a1 0 01617 +0493e 04e4d 05366 059a1 1 016e3 +0493e 04e4d 05366 059a1 2 01c98 +0493e 04e4d 05366 059a1 3 05000 +05746 151aa 04825 0544a 0 04ffe +05746 151aa 04825 0544a 1 0321b +05746 151aa 04825 0544a 2 035e8 +05746 151aa 04825 0544a 3 03ecb +053f9 052e7 0567a 056a5 0 04130 +053f9 052e7 0567a 056a5 1 03f0e +053f9 052e7 0567a 056a5 2 04d0e +053f9 052e7 0567a 056a5 3 04e6f +149dc 14fdb 14d63 1576d 0 04d61 +149dc 14fdb 14d63 1576d 1 04bc3 +149dc 14fdb 14d63 1576d 2 04cbd +149dc 14fdb 14d63 1576d 3 03243 +05190 15817 049cf 054b3 0 0485b +05190 15817 049cf 054b3 1 02350 +05190 15817 049cf 054b3 2 044f9 +05190 15817 049cf 054b3 3 04f9d +04e2b 04e92 04986 057b7 0 03338 +04e2b 04e92 04986 057b7 1 03370 +04e2b 04e92 04986 057b7 2 03261 +04e2b 04e92 04986 057b7 3 05000 +15120 0550c 14d88 05546 0 03e20 +15120 0550c 14d88 05546 1 04d5b +15120 0550c 14d88 05546 2 04053 +15120 0550c 14d88 05546 3 04e4c +0518c 0529f 0541a 15756 0 049e8 +0518c 0529f 0541a 15756 1 04b84 +0518c 0529f 0541a 15756 2 04ea2 +0518c 0529f 0541a 15756 3 02b90 +14bf2 04915 148c5 04a17 0 04b6a +14bf2 04915 148c5 04a17 1 04c2a +14bf2 04915 148c5 04a17 2 04bd0 +14bf2 04915 148c5 04a17 3 04c37 +14abf 050a3 14f9b 15335 0 04b88 +14abf 050a3 14f9b 15335 1 04e7b +14abf 050a3 14f9b 15335 2 04a22 +14abf 050a3 14f9b 15335 3 04573 +048ad 04f70 14f5e 04e92 0 04b66 +048ad 04f70 14f5e 04e92 1 04ce9 +048ad 04f70 14f5e 04e92 2 04993 +048ad 04f70 14f5e 04e92 3 04c81 +04964 04938 149ca 058d4 0 022c4 +04964 04938 149ca 058d4 1 022c4 +04964 04938 149ca 058d4 2 02261 +04964 04938 149ca 058d4 3 05000 +14e07 0481e 04e7c 15077 0 04b07 +14e07 0481e 04e7c 15077 1 04c41 +14e07 0481e 04e7c 15077 2 04d50 +14e07 0481e 04e7c 15077 3 049ab +15323 14a6b 14f7d 05757 0 02ed4 +15323 14a6b 14f7d 05757 1 034cc +15323 14a6b 14f7d 05757 2 03366 +15323 14a6b 14f7d 05757 3 05000 +14fc4 14d4a 156d4 05234 0 048d5 +14fc4 14d4a 156d4 05234 1 04a0c +14fc4 14d4a 156d4 05234 2 03431 +14fc4 14d4a 156d4 05234 3 04f22 +04d86 049e0 14b1b 0499e 0 04c78 +04d86 049e0 14b1b 0499e 1 04bf4 +04d86 049e0 14b1b 0499e 2 04b2d +04d86 049e0 14b1b 0499e 3 04bef +150ea 049c9 14894 04da5 0 04919 +150ea 049c9 14894 04da5 1 04c4e +150ea 049c9 14894 04da5 2 04c02 +150ea 049c9 14894 04da5 3 04cea +1575d 0512c 050d9 14e60 0 02fb4 +1575d 0512c 050d9 14e60 1 04dc9 +1575d 0512c 050d9 14e60 2 04d62 +1575d 0512c 050d9 14e60 3 04957 +14fd8 04d03 150b1 153b2 0 04b9a +14fd8 04d03 150b1 153b2 1 04e47 +14fd8 04d03 150b1 153b2 2 04ac2 +14fd8 04d03 150b1 153b2 3 0462c +04841 054ed 159fb 0537e 0 043d6 +04841 054ed 159fb 0537e 1 04f4c +04841 054ed 159fb 0537e 2 0040c +04841 054ed 159fb 0537e 3 04a92 +054e9 04a19 15315 048a5 0 04fd8 +054e9 04a19 15315 048a5 1 04463 +054e9 04a19 15315 048a5 2 03e0d +054e9 04a19 15315 048a5 3 0444f +05315 15054 051d6 1587a 0 04eac +05315 15054 051d6 1587a 1 04640 +05315 15054 051d6 1587a 2 04c62 +05315 15054 051d6 1587a 3 020d9 +14d50 058fc 049f3 053a5 0 01f4b +14d50 058fc 049f3 053a5 1 05000 +14d50 058fc 049f3 053a5 2 02061 +14d50 058fc 049f3 053a5 3 02770 +14d99 055a6 14b47 151c4 0 0405a +14d99 055a6 14b47 151c4 1 04ff4 +14d99 055a6 14b47 151c4 2 040cc +14d99 055a6 14b47 151c4 3 03d79 +04e61 053dd 04b16 15472 0 048cd +04e61 053dd 04b16 15472 1 04f61 +04e61 053dd 04b16 15472 2 0481f +04e61 053dd 04b16 15472 3 03e02 +05989 055e1 058ed 155a1 0 04fdf +05989 055e1 058ed 155a1 1 026ad +05989 055e1 058ed 155a1 2 0461c +05989 055e1 058ed 155a1 3 0089f +04d6f 0593b 048c2 059fa 0 0110a +04d6f 0593b 048c2 059fa 1 04403 +04d6f 0593b 048c2 059fa 2 01064 +04d6f 0593b 048c2 059fa 3 04ff0 +15057 14f49 14fd0 1557a 0 04c51 +15057 14f49 14fd0 1557a 1 04cf3 +15057 14f49 14fd0 1557a 2 04cb1 +15057 14f49 14fd0 1557a 3 040b0 +04e8c 05082 153f1 04864 0 04c75 +04e8c 05082 153f1 04864 1 04dc6 +04e8c 05082 153f1 04864 2 0434b +04e8c 05082 153f1 04864 3 04b55 +14de0 148f1 148a4 04d68 0 04ae7 +14de0 148f1 148a4 04d68 1 04bcf +14de0 148f1 148a4 04d68 2 04bd6 +14de0 148f1 148a4 04d68 3 04cba +04e27 14c5c 151fc 151cd 0 04e15 +04e27 14c5c 151fc 151cd 1 04c57 +04e27 14c5c 151fc 151cd 2 048e1 +04e27 14c5c 151fc 151cd 3 04913 +15476 04c03 15425 04c5c 0 0435f +15476 04c03 15425 04c5c 1 04dce +15476 04c03 15425 04c5c 2 0449d +15476 04c03 15425 04c5c 3 04dec +14d3d 04c28 04d3f 04e5b 0 04a86 +14d3d 04c28 04d3f 04e5b 1 04c03 +14d3d 04c28 04d3f 04e5b 2 04c36 +14d3d 04c28 04d3f 04e5b 3 04c83 +04935 049c1 14c1f 14fee 0 04c74 +04935 049c1 14c1f 14fee 1 04c7c +04935 049c1 14c1f 14fee 2 04bcf +04935 049c1 14c1f 14fee 3 04a52 +148f8 050ce 05531 15214 0 042c0 +148f8 050ce 05531 15214 1 045df +148f8 050ce 05531 15214 2 04fd4 +148f8 050ce 05531 15214 3 03ec3 +15520 05450 05365 1580a 0 0390f +15520 05450 05365 1580a 1 04ece +15520 05450 05365 1580a 2 04c64 +15520 05450 05365 1580a 3 024ee +14eb8 04f6c 0516d 0564b 0 03c34 +14eb8 04f6c 0516d 0564b 1 03f30 +14eb8 04f6c 0516d 0564b 2 040e0 +14eb8 04f6c 0516d 0564b 3 04ff6 +14d2b 0491e 153f4 05597 0 040a6 +14d2b 0491e 153f4 05597 1 041b9 +14d2b 0491e 153f4 05597 2 039a0 +14d2b 0491e 153f4 05597 3 04ff4 +14996 14e3c 05526 15065 0 042f2 +14996 14e3c 05526 15065 1 04226 +14996 14e3c 05526 15065 2 04fe7 +14996 14e3c 05526 15065 3 040c6 +051db 14f0b 1497f 14873 0 04e6d +051db 14f0b 1497f 14873 1 04903 +051db 14f0b 1497f 14873 2 04a5e +051db 14f0b 1497f 14873 3 04a6b +15235 04bb8 15350 152b4 0 04a1c +15235 04bb8 15350 152b4 1 04edb +15235 04bb8 15350 152b4 2 047e9 +15235 04bb8 15350 152b4 3 048fc +054e1 05556 155f2 150f7 0 04cc3 +054e1 05556 155f2 150f7 1 04e9b +054e1 05556 155f2 150f7 2 03187 +054e1 05556 155f2 150f7 3 03e57 +04899 14ce8 051b2 1573d 0 04b1d +04899 14ce8 051b2 1573d 1 04a49 +04899 14ce8 051b2 1573d 2 04ea6 +04899 14ce8 051b2 1573d 3 0310c +05242 04d02 05835 157b7 0 03105 +05242 04d02 05835 157b7 1 02d4b +05242 04d02 05835 157b7 2 05000 +05242 04d02 05835 157b7 3 00ed4 +156cf 1501a 15259 14a13 0 03820 +156cf 1501a 15259 14a13 1 04c6d +156cf 1501a 15259 14a13 2 049f3 +156cf 1501a 15259 14a13 3 04e4c +14d5d 04cd4 14d3f 04d94 0 04ae3 +14d5d 04cd4 14d3f 04d94 1 04c78 +14d5d 04cd4 14d3f 04d94 2 04aea +14d5d 04cd4 14d3f 04d94 3 04ca2 +15981 14a69 049d2 159f2 0 015ed +15981 14a69 049d2 159f2 1 04da1 +15981 14a69 049d2 159f2 2 04e30 +15981 14a69 049d2 159f2 3 00eb8 +057b9 14f53 0551a 15279 0 04ffe +057b9 14f53 0551a 15279 1 0306d +057b9 14f53 0551a 15279 2 03e7b +057b9 14f53 0551a 15279 3 02d14 +04ee0 1485b 04d99 053d7 0 048e1 +04ee0 1485b 04d99 053d7 1 04753 +04ee0 1485b 04d99 053d7 2 04864 +04ee0 1485b 04d99 053d7 3 04f22 +155d1 14b79 0509a 04ce7 0 03c3b +155d1 14b79 0509a 04ce7 1 04afa +155d1 14b79 0509a 04ce7 2 04e22 +155d1 14b79 0509a 04ce7 3 04c3b +05569 15719 152e9 052cb 0 04fc4 +05569 15719 152e9 052cb 1 0293c +05569 15719 152e9 052cb 2 03c43 +05569 15719 152e9 052cb 3 047af +04ccd 14e38 14adc 05280 0 04a67 +04ccd 14e38 14adc 05280 1 04891 +04ccd 14e38 14adc 05280 2 04953 +04ccd 14e38 14adc 05280 3 04eaa +14a89 15619 14ab6 04fc2 0 04bdf +14a89 15619 14ab6 04fc2 1 03b4c +14a89 15619 14ab6 04fc2 2 04bd5 +14a89 15619 14ab6 04fc2 3 04e12 +04d2d 054dc 14aaa 053ce 0 04473 +04d2d 054dc 14aaa 053ce 1 04f0f +04d2d 054dc 14aaa 053ce 2 04351 +04d2d 054dc 14aaa 053ce 3 04b3e +15998 058ad 14b0c 04bdb 0 00200 +15998 058ad 14b0c 04bdb 1 05000 +15998 058ad 14b0c 04bdb 2 024a6 +15998 058ad 14b0c 04bdb 3 02597 +153e7 049e8 14825 048e0 0 044b3 +153e7 049e8 14825 048e0 1 04cbf +153e7 049e8 14825 048e0 2 04c68 +153e7 049e8 14825 048e0 3 04cb0 +15386 14897 04bd8 155e1 0 04682 +15386 14897 04bd8 155e1 1 04d69 +15386 14897 04bd8 155e1 2 04e22 +15386 14897 04bd8 155e1 3 03e22 +1538b 05108 14e7d 058ee 0 01a0b +1538b 05108 14e7d 058ee 1 02417 +1538b 05108 14e7d 058ee 2 01fd5 +1538b 05108 14e7d 058ee 3 05000 +055a7 05175 154e7 051db 0 04fd4 +055a7 05175 154e7 051db 1 04491 +055a7 05175 154e7 051db 2 0358b +055a7 05175 154e7 051db 3 044f4 +056d8 14a0e 05395 048b1 0 04ffa +056d8 14a0e 05395 048b1 1 038d0 +056d8 14a0e 05395 048b1 2 0404a +056d8 14a0e 05395 048b1 3 0393c +056fe 148e1 055bc 05302 0 04fd2 +056fe 148e1 055bc 05302 1 037a9 +056fe 148e1 055bc 05302 2 046b3 +056fe 148e1 055bc 05302 3 03de7 +14a0f 04c07 0511e 158d2 0 04ae6 +14a0f 04c07 0511e 158d2 1 04bc7 +14a0f 04c07 0511e 158d2 2 04e55 +14a0f 04c07 0511e 158d2 3 01e23 +1534a 14bc0 05273 15973 0 0440c +1534a 14bc0 05273 15973 1 04a1e +1534a 14bc0 05273 15973 2 04f68 +1534a 14bc0 05273 15973 3 01355 +05960 04be5 148b1 14f30 0 05000 +05960 04be5 148b1 14f30 1 01a61 +05960 04be5 148b1 14f30 2 019c0 +05960 04be5 148b1 14f30 3 01847 +15893 057ee 150e9 159ef 0 00738 +15893 057ee 150e9 159ef 1 05000 +15893 057ee 150e9 159ef 2 02d84 +15893 057ee 150e9 159ef 3 00200 +05109 05244 04e71 05029 0 04c07 +05109 05244 04e71 05029 1 04d67 +05109 05244 04e71 05029 2 04a29 +05109 05244 04e71 05029 3 04afe +15650 04f96 158be 04c77 0 03a2e +15650 04f96 158be 04c77 1 04e67 +15650 04f96 158be 04c77 2 020ad +15650 04f96 158be 04c77 3 04d32 +05559 053d7 1512d 14c8f 0 04f7a +05559 053d7 1512d 14c8f 1 049d8 +05559 053d7 1512d 14c8f 2 03edd +05559 053d7 1512d 14c8f 3 04170 +059d1 15970 052f4 05429 0 05000 +059d1 15970 052f4 05429 1 00200 +059d1 15970 052f4 05429 2 018b5 +059d1 15970 052f4 05429 3 01b70 +04fdf 14c41 054a1 05358 0 04672 +04fdf 14c41 054a1 05358 1 0440f +04fdf 14c41 054a1 05358 2 04efd +04fdf 14c41 054a1 05358 3 04b2b +1550a 158b1 158da 1548a 0 04cab +1550a 158b1 158da 1548a 1 02df0 +1550a 158b1 158da 1548a 2 02b2c +1550a 158b1 158da 1548a 3 04eab +151ff 14e30 15779 050a3 0 04856 +151ff 14e30 15779 050a3 1 04b32 +151ff 14e30 15779 050a3 2 03088 +151ff 14e30 15779 050a3 3 04ee9 +0594e 0569b 04a07 151ff 0 05000 +0594e 0569b 04a07 151ff 1 03000 +0594e 0569b 04a07 151ff 2 01b38 +0594e 0569b 04a07 151ff 3 016f4 +15915 052a9 053bf 04d85 0 015d7 +15915 052a9 053bf 04d85 1 04c65 +15915 052a9 053bf 04d85 2 04e8b +15915 052a9 053bf 04d85 3 0480f +14a5d 14cc6 04d7d 049fa 0 04b7e +14a5d 14cc6 04d7d 049fa 1 04b0b +14a5d 14cc6 04d7d 049fa 2 04c9e +14a5d 14cc6 04d7d 049fa 3 04c1c +049b9 15564 1494b 0533a 0 0490c +049b9 15564 1494b 0533a 1 03b4a +049b9 15564 1494b 0533a 2 0489e +049b9 15564 1494b 0533a 3 04f4a +052d3 1583e 15874 1587f 0 05000 +052d3 1583e 15874 1587f 1 02661 +052d3 1583e 15874 1587f 2 022f4 +052d3 1583e 15874 1587f 3 02254 +05229 14bce 05588 14f9a 0 0460c +05229 14bce 05588 14f9a 1 0411f +05229 14bce 05588 14f9a 2 04fd6 +05229 14bce 05588 14f9a 3 03ff1 +152d6 1592f 05554 0578c 0 02de4 +152d6 1592f 05554 0578c 1 001fa +152d6 1592f 05554 0578c 2 040c0 +152d6 1592f 05554 0578c 3 04ffa +04f8b 0518c 058ab 04f43 0 026e3 +04f8b 0518c 058ab 04f43 1 028b5 +04f8b 0518c 058ab 04f43 2 05000 +04f8b 0518c 058ab 04f43 3 026c4 +055f5 0547e 0599c 14f9c 0 0260b +055f5 0547e 0599c 14f9c 1 0202e +055f5 0547e 0599c 14f9c 2 05000 +055f5 0547e 0599c 14f9c 3 01454 +048e2 053f0 04cfa 14ebb 0 047b8 +048e2 053f0 04cfa 14ebb 1 04f59 +048e2 053f0 04cfa 14ebb 2 04842 +048e2 053f0 04cfa 14ebb 3 0462e +14f65 15680 14d5d 159e1 0 04d68 +14f65 15680 14d5d 159e1 1 03b12 +14f65 15680 14d5d 159e1 2 04e4b +14f65 15680 14d5d 159e1 3 010f9 +154db 054e5 0502d 04efd 0 038a5 +154db 054e5 0502d 04efd 1 04fbe +154db 054e5 0502d 04efd 2 0464c +154db 054e5 0502d 04efd 3 045a5 +1575d 05518 0506f 150af 0 02880 +1575d 05518 0506f 150af 1 04fdb +1575d 05518 0506f 150af 2 045f0 +1575d 05518 0506f 150af 3 040aa +0535c 14d09 050d0 0579a 0 039df +0535c 14d09 050d0 0579a 1 03254 +0535c 14d09 050d0 0579a 2 03600 +0535c 14d09 050d0 0579a 3 05000 +0591a 14b14 04de1 05130 0 05000 +0591a 14b14 04de1 05130 1 01e00 +0591a 14b14 04de1 05130 2 01f38 +0591a 14b14 04de1 05130 3 02170 +14c9e 1506a 04953 15168 0 04c71 +14c9e 1506a 04953 15168 1 04aa8 +14c9e 1506a 04953 15168 2 04d4b +14c9e 1506a 04953 15168 3 049c3 +14c10 0556d 150c3 05749 0 034fa +14c10 0556d 150c3 05749 1 0433b +14c10 0556d 150c3 05749 2 032c2 +14c10 0556d 150c3 05749 3 04ff2 +1567e 04d61 15114 14cb5 0 0394d +1567e 04d61 15114 14cb5 1 04e2a +1567e 04d61 15114 14cb5 2 04a39 +1567e 04d61 15114 14cb5 3 04c8e +04cbf 057dd 0579e 049de 0 03076 +04cbf 057dd 0579e 049de 1 04ea8 +04cbf 057dd 0579e 049de 2 04cb0 +04cbf 057dd 0579e 049de 3 0301d +05174 15399 04a64 1509a 0 04eb3 +05174 15399 04a64 1509a 1 04426 +05174 15399 04a64 1509a 2 04b9e +05174 15399 04a64 1509a 3 048a6 +04b67 04a29 1586a 05365 0 048e6 +04b67 04a29 1586a 05365 1 048c1 +04b67 04a29 1586a 05365 2 02200 +04b67 04a29 1586a 05365 3 04f4b +157d3 150db 14f57 15248 0 030d7 +157d3 150db 14f57 15248 1 04c9c +157d3 150db 14f57 15248 2 04df0 +157d3 150db 14f57 15248 3 04ae4 +14b30 058b3 05402 14cda 0 02454 +14b30 058b3 05402 14cda 1 05000 +14b30 058b3 05402 14cda 2 02cb5 +14b30 058b3 05402 14cda 3 02417 +059c2 14c9a 14971 0529d 0 05000 +059c2 14c9a 14971 0529d 1 01316 +059c2 14c9a 14971 0529d 2 01397 +059c2 14c9a 14971 0529d 3 018f4 +04d18 05753 0588a 04b87 0 02813 +04d18 05753 0588a 04b87 1 041ed +04d18 05753 0588a 04b87 2 04ff8 +04d18 05753 0588a 04b87 3 027b8 +04930 04d11 15313 1491e 0 04c80 +04930 04d11 15313 1491e 1 04d0b +04930 04d11 15313 1491e 2 04637 +04930 04d11 15313 1491e 3 04c2e +14a85 153ac 153f5 05494 0 04521 +14a85 153ac 153f5 05494 1 03e31 +14a85 153ac 153f5 05494 2 03d99 +14a85 153ac 153f5 05494 3 04fe3 +15483 04951 04d50 15587 0 04338 +15483 04951 04d50 15587 1 04d84 +15483 04951 04d50 15587 2 04e2e +15483 04951 04d50 15587 3 03f25 +0480a 151d4 14e1b 04843 0 04cbe +0480a 151d4 14e1b 04843 1 048c9 +0480a 151d4 14e1b 04843 2 04ba4 +0480a 151d4 14e1b 04843 3 04cc1 +048e3 15827 157df 04851 0 04e03 +048e3 15827 157df 04851 1 02b3d +048e3 15827 157df 04851 2 02eb2 +048e3 15827 157df 04851 3 04df9 +157f8 14db0 1497f 04a54 0 02d24 +157f8 14db0 1497f 04a54 1 04c1b +157f8 14db0 1497f 04a54 2 04cb1 +157f8 14db0 1497f 04a54 3 04d36 +14c76 14e3e 15284 04b57 0 04c4b +14c76 14e3e 15284 04b57 1 04bda +14c76 14e3e 15284 04b57 2 047f9 +14c76 14e3e 15284 04b57 3 04d48 +14ae9 14e48 156dd 14f26 0 04d4e +14ae9 14e48 156dd 14f26 1 04c86 +14ae9 14e48 156dd 14f26 2 036bf +14ae9 14e48 156dd 14f26 3 04c2c +058e9 153ea 14bbf 056a9 0 05000 +058e9 153ea 14bbf 056a9 1 01984 +058e9 153ea 14bbf 056a9 2 020d4 +058e9 153ea 14bbf 056a9 3 03690 +04c25 049d3 05880 0560d 0 0286e +04c25 049d3 05880 0560d 1 0282e +04c25 049d3 05880 0560d 2 05000 +04c25 049d3 05880 0560d 3 0384d +14d8e 1594a 15691 149f9 0 04d8f +14d8e 1594a 15691 149f9 1 019e8 +14d8e 1594a 15691 149f9 2 03a04 +14d8e 1594a 15691 149f9 3 04e39 +14e10 04cf8 152fe 04b55 0 04b6b +14e10 04cf8 152fe 04b55 1 04d29 +14e10 04cf8 152fe 04b55 2 04675 +14e10 04cf8 152fe 04b55 3 04cd2 +14823 14bdb 048ca 14ac5 0 04c0a +14823 14bdb 048ca 14ac5 1 04b9b +14823 14bdb 048ca 14ac5 2 04c44 +14823 14bdb 048ca 14ac5 3 04bc9 +154b6 15992 05086 1518b 0 04231 +154b6 15992 05086 1518b 1 01403 +154b6 15992 05086 1518b 2 04f88 +154b6 15992 05086 1518b 3 04975 +1594a 058e2 152b1 050e0 0 00200 +1594a 058e2 152b1 050e0 1 05000 +1594a 058e2 152b1 050e0 2 01c61 +1594a 058e2 152b1 050e0 3 02498 +04829 152f3 14d5b 04bad 0 04cb5 +04829 152f3 14d5b 04bad 1 046ad +04829 152f3 14d5b 04bad 2 04bde +04829 152f3 14d5b 04bad 3 04d08 +1543b 1560e 04fc4 14aff 0 0440a +1543b 1560e 04fc4 14aff 1 03c6c +1543b 1560e 04fc4 14aff 2 04eb3 +1543b 1560e 04fc4 14aff 3 04c78 +14cce 14d98 159a2 0570d 0 036bd +14cce 14d98 159a2 0570d 1 0368a +14cce 14d98 159a2 0570d 2 00200 +14cce 14d98 159a2 0570d 3 05000 +157b3 04bb1 14825 1556a 0 03027 +157b3 04bb1 14825 1556a 1 04e33 +157b3 04bb1 14825 1556a 2 04d94 +157b3 04bb1 14825 1556a 3 0401b +05767 0520f 159fc 057b0 0 04c80 +05767 0520f 159fc 057b0 1 0356c +05767 0520f 159fc 057b0 2 000c1 +05767 0520f 159fc 057b0 3 04ec1 +14e6f 151c5 04eaf 14c1c 0 04b22 +14e6f 151c5 04eaf 14c1c 1 04896 +14e6f 151c5 04eaf 14c1c 2 04dcd +14e6f 151c5 04eaf 14c1c 3 04bfb +14ec4 05244 05566 05555 0 03eec +14ec4 05244 05566 05555 1 044d3 +14ec4 05244 05566 05555 2 04e0b +14ec4 05244 05566 05555 3 04db9 +05832 04b05 15871 04cf4 0 05000 +05832 04b05 15871 04cf4 1 02d16 +05832 04b05 15871 04cf4 2 005ab +05832 04b05 15871 04cf4 3 02d84 +14ffd 0538c 154e1 05137 0 04619 +14ffd 0538c 154e1 05137 1 04f11 +14ffd 0538c 154e1 05137 2 03c78 +14ffd 0538c 154e1 05137 3 04b33 +050a1 14ccf 04ec3 0573d 0 03890 +050a1 14ccf 04ec3 0573d 1 03541 +050a1 14ccf 04ec3 0573d 2 03753 +050a1 14ccf 04ec3 0573d 3 05000 +1583d 14f13 05653 0538d 0 01972 +1583d 14f13 05653 0538d 1 03bc2 +1583d 14f13 05653 0538d 2 04fec +1583d 14f13 05653 0538d 3 04455 +048db 14d01 04d18 0536c 0 04875 +048db 14d01 04d18 0536c 1 0478f +048db 14d01 04d18 0536c 2 04905 +048db 14d01 04d18 0536c 3 04f18 +150dc 156d8 0571c 15832 0 0342e +150dc 156d8 0571c 15832 1 02047 +150dc 156d8 0571c 15832 2 05000 +150dc 156d8 0571c 15832 3 01400 +159ab 1520b 049d6 159b5 0 0145d +159ab 1520b 049d6 159b5 1 04aeb +159ab 1520b 049d6 159b5 2 04f46 +159ab 1520b 049d6 159b5 3 013cf +058e1 05764 04ffd 153d8 0 04ffe +058e1 05764 04ffd 153d8 1 03ce2 +058e1 05764 04ffd 153d8 2 023e8 +058e1 05764 04ffd 153d8 3 01a2d +157c0 050d0 05552 149cc 0 02480 +157c0 050d0 05552 149cc 1 04547 +157c0 050d0 05552 149cc 2 04fdb +157c0 050d0 05552 149cc 3 04247 +14fe3 14e1f 150ac 1541c 0 04c78 +14fe3 14e1f 150ac 1541c 1 04d5a +14fe3 14e1f 150ac 1541c 2 04bd6 +14fe3 14e1f 150ac 1541c 3 04615 +04b1c 1488d 05326 14ab7 0 04918 +04b1c 1488d 05326 14ab7 1 0488f +04b1c 1488d 05326 14ab7 2 04eff +04b1c 1488d 05326 14ab7 3 04868 +14bf1 05231 1554f 14f0a 0 04a3f +14bf1 05231 1554f 14f0a 1 04f0b +14bf1 05231 1554f 14f0a 2 03d77 +14bf1 05231 1554f 14f0a 3 04925 +14f4d 050d1 04dc3 15242 0 049be +14f4d 050d1 04dc3 15242 1 04e34 +14f4d 050d1 04dc3 15242 2 04c4d +14f4d 050d1 04dc3 15242 3 046c8 +154b9 15637 14eec 14d7d 0 04427 +154b9 15637 14eec 14d7d 1 03d3b +154b9 15637 14eec 14d7d 2 04d86 +154b9 15637 14eec 14d7d 3 04e2a +1539b 04c76 057e5 05450 0 02984 +1539b 04c76 057e5 05450 1 03153 +1539b 04c76 057e5 05450 2 05000 +1539b 04c76 057e5 05450 3 03a11 +05796 056c7 14b23 14b7e 0 04f9e +05796 056c7 14b23 14b7e 1 04913 +05796 056c7 14b23 14b7e 2 0327a +05796 056c7 14b23 14b7e 3 03273 +15161 14af7 0589a 15217 0 022d4 +15161 14af7 0589a 15217 1 02600 +15161 14af7 0589a 15217 2 05000 +15161 14af7 0589a 15217 3 02222 +04aea 04dc9 1535a 05506 0 0441b +04aea 04dc9 1535a 05506 1 04496 +04aea 04dc9 1535a 05506 2 03ce7 +04aea 04dc9 1535a 05506 3 04fd8 +157a6 05984 1592d 05385 0 00200 +157a6 05984 1592d 05385 1 05000 +157a6 05984 1592d 05385 2 00200 +157a6 05984 1592d 05385 3 01ea6 +05616 1582d 14c6e 14b3b 0 04ffa +05616 1582d 14c6e 14b3b 1 01c5d +05616 1582d 14c6e 14b3b 2 03e8c +05616 1582d 14c6e 14b3b 3 03eb9 +057d7 1494f 149a2 04b41 0 05000 +057d7 1494f 149a2 04b41 1 030e3 +057d7 1494f 149a2 04b41 2 030e3 +057d7 1494f 149a2 04b41 3 03197 +14c4b 054d1 05195 04b5b 0 043cd +14c4b 054d1 05195 04b5b 1 04f9b +14c4b 054d1 05195 04b5b 2 04802 +14c4b 054d1 05195 04b5b 3 044b1 +14a1f 051a3 05778 055b4 0 033f4 +14a1f 051a3 05778 055b4 1 037ca +14a1f 051a3 05778 055b4 2 04ff4 +14a1f 051a3 05778 055b4 3 042da +0495f 155b8 15695 1586f 0 04ffa +0495f 155b8 15695 1586f 1 040bd +0495f 155b8 15695 1586f 2 03af0 +0495f 155b8 15695 1586f 3 028b1 +153af 14e41 05419 15653 0 04018 +153af 14e41 05419 15653 1 04645 +153af 14e41 05419 15653 2 04fd8 +153af 14e41 05419 15653 3 034b8 +056db 0548b 152eb 156ee 0 04ff4 +056db 0548b 152eb 156ee 1 04321 +056db 0548b 152eb 156ee 2 0331e +056db 0548b 152eb 156ee 3 021a0 +054be 053cb 0568a 14f66 0 04664 +054be 053cb 0568a 14f66 1 042f8 +054be 053cb 0568a 14f66 2 04fcf +054be 053cb 0568a 14f66 3 039cf +1569f 05908 154d2 0563c 0 00a61 +1569f 05908 154d2 0563c 1 05000 +1569f 05908 154d2 0563c 2 0142e +1569f 05908 154d2 0563c 3 03138 +04c25 14920 15520 05041 0 04c38 +04c25 14920 15520 05041 1 04b73 +04c25 14920 15520 05041 2 03f1c +04c25 14920 15520 05041 3 04e04 +150ac 14f84 15785 14aa6 0 04b76 +150ac 14f84 15785 14aa6 1 04c61 +150ac 14f84 15785 14aa6 2 03214 +150ac 14f84 15785 14aa6 3 04de5 +05795 05120 14b5f 14fa9 0 05000 +05795 05120 14b5f 14fa9 1 0365a +05795 05120 14b5f 14fa9 2 032c4 +05795 05120 14b5f 14fa9 3 0315e +04f17 15051 14abc 155e5 0 04e3e +04f17 15051 14abc 155e5 1 04a5b +04f17 15051 14abc 155e5 2 04c54 +04f17 15051 14abc 155e5 3 03d09 +154ee 151cf 15050 04d95 0 0421b +154ee 151cf 15050 04d95 1 04a0a +154ee 151cf 15050 04d95 2 04b6d +154ee 151cf 15050 04d95 3 04e9a +1572c 04bed 151d6 05757 0 01bd5 +1572c 04bed 151d6 05757 1 035b4 +1572c 04bed 151d6 05757 2 0314b +1572c 04bed 151d6 05757 3 05000 +14e7c 058bc 150cb 04eb4 0 022d4 +14e7c 058bc 150cb 04eb4 1 05000 +14e7c 058bc 150cb 04eb4 2 0214b +14e7c 058bc 150cb 04eb4 3 02584 +05020 04db6 1547d 15612 0 04e62 +05020 04db6 1547d 15612 1 04d25 +05020 04db6 1547d 15612 2 04252 +05020 04db6 1547d 15612 3 03bc1 +050ca 05870 04b14 14ac9 0 02bc0 +050ca 05870 04b14 14ac9 1 05000 +050ca 05870 04b14 14ac9 2 02938 +050ca 05870 04b14 14ac9 3 0287c +05150 05765 14bf4 152f0 0 0381c +05150 05765 14bf4 152f0 1 05000 +05150 05765 14bf4 152f0 2 03441 +05150 05765 14bf4 152f0 3 02ed4 +14ecb 159c3 15776 14ab0 0 04d46 +14ecb 159c3 15776 14ab0 1 01278 +14ecb 159c3 15776 14ab0 2 032f8 +14ecb 159c3 15776 14ab0 3 04e5d +157ab 14bce 14b5e 050cb 0 02e52 +157ab 14bce 14b5e 050cb 1 04b1e +157ab 14bce 14b5e 050cb 2 04b2e +157ab 14bce 14b5e 050cb 3 04e6c +15500 15499 04af8 04e7d 0 040f0 +15500 15499 04af8 04e7d 1 04291 +15500 15499 04af8 04e7d 2 04d58 +15500 15499 04af8 04e7d 3 04e44 +04e14 04fa6 0488a 14972 0 04c2a +04e14 04fa6 0488a 14972 1 04cd7 +04e14 04fa6 0488a 14972 2 04b30 +04e14 04fa6 0488a 14972 3 04acd +04af9 14db6 04dd5 15274 0 04ca5 +04af9 14db6 04dd5 15274 1 04b5e +04af9 14db6 04dd5 15274 2 04d3e +04af9 14db6 04dd5 15274 3 04765 +049de 05914 14eba 150d2 0 01ed4 +049de 05914 14eba 150d2 1 05000 +049de 05914 14eba 150d2 2 01d38 +049de 05914 14eba 150d2 3 01bea +1520c 150e7 049c2 04c6c 0 048a5 +1520c 150e7 049c2 04c6c 1 04a00 +1520c 150e7 049c2 04c6c 2 04cf8 +1520c 150e7 049c2 04c6c 3 04d60 +05498 14ba9 051c4 152f9 0 04f8b +05498 14ba9 051c4 152f9 1 044a8 +05498 14ba9 051c4 152f9 2 048de +05498 14ba9 051c4 152f9 3 03f2e +14f52 14ee5 149c3 04e44 0 04a86 +14f52 14ee5 149c3 04e44 1 04ab8 +14f52 14ee5 149c3 04e44 2 04c11 +14f52 14ee5 149c3 04e44 3 04d52 +14b57 155fc 04f25 14ed8 0 04c29 +14b57 155fc 04f25 14ed8 1 03c8f +14b57 155fc 04f25 14ed8 2 04e27 +14b57 155fc 04f25 14ed8 3 04b0d +04b70 04c20 1588f 04d83 0 04c80 +04b70 04c20 1588f 04d83 1 04c96 +04b70 04c20 1588f 04d83 2 0231d +04b70 04c20 1588f 04d83 3 04ceb +04f2b 05475 15932 0519c 0 04721 +04f2b 05475 15932 0519c 1 04f6a +04f2b 05475 15932 0519c 2 01277 +04f2b 05475 15932 0519c 3 04929 +04ed5 14abb 04fa0 051f6 0 04b22 +04ed5 14abb 04fa0 051f6 1 04968 +04ed5 14abb 04fa0 051f6 2 04b98 +04ed5 14abb 04fa0 051f6 3 04dc9 +14ff1 152c9 15769 04b68 0 04c3b +14ff1 152c9 15769 04b68 1 04890 +14ff1 152c9 15769 04b68 2 032d3 +14ff1 152c9 15769 04b68 3 04e90 +056a0 14932 1489e 049bf 0 04ffe +056a0 14932 1489e 049bf 1 03aa5 +056a0 14932 1489e 049bf 2 03aad +056a0 14932 1489e 049bf 3 03b0b +05575 157e6 0503a 04fab 0 04fdf +05575 157e6 0503a 04fab 1 022bd +05575 157e6 0503a 04fab 2 0443a +05575 157e6 0503a 04fab 3 043df +14e22 155c7 14dee 04964 0 04c3a +14e22 155c7 14dee 04964 1 03e31 +14e22 155c7 14dee 04964 2 04c4b +14e22 155c7 14dee 04964 3 04d79 +05506 04f2e 15576 05308 0 04f7c +05506 04f2e 15576 05308 1 044ef +05506 04f2e 15576 05308 2 0358f +05506 04f2e 15576 05308 3 04972 +04eef 14d32 1597e 04a2d 0 04dc7 +04eef 14d32 1597e 04a2d 1 04b71 +04eef 14d32 1597e 04a2d 2 01466 +04eef 14d32 1597e 04a2d 3 04c7e +150ff 0561c 14d2f 15630 0 03c15 +150ff 0561c 14d2f 15630 1 04ffc +150ff 0561c 14d2f 15630 2 03e3f +150ff 0561c 14d2f 15630 3 02d80 +05866 04fda 05843 04e9c 0 04eb9 +05866 04fda 05843 04e9c 1 02a57 +05866 04fda 05843 04e9c 2 04c8d +05866 04fda 05843 04e9c 3 029c4 +158c5 1528f 04fe6 051c9 0 01e6f +158c5 1528f 04fe6 051c9 1 045b6 +158c5 1528f 04fe6 051c9 2 04cb0 +158c5 1528f 04fe6 051c9 3 04e8a +0487f 05809 14b71 14e42 0 02f70 +0487f 05809 14b71 14e42 1 05000 +0487f 05809 14b71 14e42 2 02ed4 +0487f 05809 14b71 14e42 3 02e3a +04e31 059cf 149bc 04861 0 01422 +04e31 059cf 149bc 04861 1 05000 +04e31 059cf 149bc 04861 2 012a6 +04e31 059cf 149bc 04861 3 01305 +05934 0530e 157e5 151fd 0 05000 +05934 0530e 157e5 151fd 1 022b5 +05934 0530e 157e5 151fd 2 00200 +05934 0530e 157e5 151fd 3 01898 +04fcb 14b82 14b3a 05933 0 01e8a +04fcb 14b82 14b3a 05933 1 01c47 +04fcb 14b82 14b3a 05933 2 01c54 +04fcb 14b82 14b3a 05933 3 05000 +14ef8 14d2f 14a52 14bb6 0 04b12 +14ef8 14d2f 14a52 14bb6 1 04be6 +14ef8 14d2f 14a52 14bb6 2 04c53 +14ef8 14d2f 14a52 14bb6 3 04c30 +04a59 154bf 0534d 154e5 0 04939 +04a59 154bf 0534d 154e5 1 03e0f +04a59 154bf 0534d 154e5 2 04f95 +04a59 154bf 0534d 154e5 3 03d5c +0539c 04ec3 0599a 159a3 0 01d84 +0539c 04ec3 0599a 159a3 1 017ab +0539c 04ec3 0599a 159a3 2 05000 +0539c 04ec3 0599a 159a3 3 00200 +1492d 14a49 14cc8 153d6 0 04cc5 +1492d 14a49 14cc8 153d6 1 04cb0 +1492d 14a49 14cc8 153d6 2 04c55 +1492d 14a49 14cc8 153d6 3 04552 +052e0 14ec7 1480c 14b7a 0 04f01 +052e0 14ec7 1480c 14b7a 1 04805 +052e0 14ec7 1480c 14b7a 2 04924 +052e0 14ec7 1480c 14b7a 3 048d1 +1506c 04bc7 04d71 05498 0 042ce +1506c 04bc7 04d71 05498 1 045d1 +1506c 04bc7 04d71 05498 2 0462f +1506c 04bc7 04d71 05498 3 04fb2 +149e2 0587b 14ca4 04bf4 0 0280b +149e2 0587b 14ca4 04bf4 1 05000 +149e2 0587b 14ca4 04bf4 2 02784 +149e2 0587b 14ca4 04bf4 3 028a6 +1544f 056a6 051c4 14f31 0 0316e +1544f 056a6 051c4 14f31 1 04ffe +1544f 056a6 051c4 14f31 2 03e6d +1544f 056a6 051c4 14f31 3 0390b +04dd9 04d20 15072 149c3 0 04cc1 +04dd9 04d20 15072 149c3 1 04c96 +04dd9 04d20 15072 149c3 2 04962 +04dd9 04d20 15072 149c3 3 04ba3 +14f10 15742 1559e 04d0f 0 04c7a +14f10 15742 1559e 04d0f 1 03413 +14f10 15742 1559e 04d0f 2 03f94 +14f10 15742 1559e 04d0f 3 04ebf +04caa 14bc2 04d68 05849 0 02c17 +04caa 14bc2 04d68 05849 1 02ac4 +04caa 14bc2 04d68 05849 2 02c3a +04caa 14bc2 04d68 05849 3 05000 +14a0e 052e4 055c9 0573b 0 035c5 +14a0e 052e4 055c9 0573b 1 03bd0 +14a0e 052e4 055c9 0573b 2 0450d +14a0e 052e4 055c9 0573b 3 04fe5 +155c0 0529c 14ee2 05127 0 03a55 +155c0 0529c 14ee2 05127 1 04e85 +155c0 0529c 14ee2 05127 2 04801 +155c0 0529c 14ee2 05127 3 04c77 +1555d 056e0 05330 14802 0 02b6d +1555d 056e0 05330 14802 1 04ffc +1555d 056e0 05330 14802 2 03f35 +1555d 056e0 05330 14802 3 038b2 +156f0 15587 05423 057c9 0 01a2e +156f0 15587 05423 057c9 1 02384 +156f0 15587 05423 057c9 2 03a2e +156f0 15587 05423 057c9 3 05000 +05412 15881 0526e 15547 0 04f11 +05412 15881 0526e 15547 1 01eb2 +05412 15881 0526e 15547 2 04bbe +05412 15881 0526e 15547 3 039cf +04b13 1531d 15853 15692 0 04fa2 +04b13 1531d 15853 15692 1 048f1 +04b13 1531d 15853 15692 2 02a1d +04b13 1531d 15853 15692 3 03a9f +14d68 04ae0 14eab 15696 0 04c61 +14d68 04ae0 14eab 15696 1 04d9e +14d68 04ae0 14eab 15696 2 04c03 +14d68 04ae0 14eab 15696 3 03880 +05359 154a9 14d02 05867 0 0302e +05359 154a9 14d02 05867 1 01ec4 +05359 154a9 14d02 05867 2 028a6 +05359 154a9 14d02 05867 3 05000 +04d9c 15918 057bc 15585 0 032dc +04d9c 15918 057bc 15585 1 00200 +04d9c 15918 057bc 15585 2 05000 +04d9c 15918 057bc 15585 3 0240b +04c8c 048e8 1593b 053cb 0 04877 +04c8c 048e8 1593b 053cb 1 0481b +04c8c 048e8 1593b 053cb 2 01439 +04c8c 048e8 1593b 053cb 3 04f6e +04819 04f5f 04b19 04cd0 0 04b2f +04819 04f5f 04b19 04cd0 1 04cbb +04819 04f5f 04b19 04cd0 2 04b7b +04819 04f5f 04b19 04cd0 3 04be2 +158c2 14c36 0526c 0536a 0 01ba6 +158c2 14c36 0526c 0536a 1 04721 +158c2 14c36 0526c 0536a 2 04c8b +158c2 14c36 0526c 0536a 3 04e87 +157ee 049af 14828 1539d 0 02e4d +157ee 049af 14828 1539d 1 04e0b +157ee 049af 14828 1539d 2 04d99 +157ee 049af 14828 1539d 3 04678 +151f0 058e5 049d2 05969 0 01530 +151f0 058e5 049d2 05969 1 04779 +151f0 058e5 049d2 05969 2 01966 +151f0 058e5 049d2 05969 3 04fc9 +1596b 149e8 0590b 05412 0 00200 +1596b 149e8 0590b 05412 1 01ee3 +1596b 149e8 0590b 05412 2 05000 +1596b 149e8 0590b 05412 3 02784 +154ea 154ab 1589d 04afd 0 043d0 +154ea 154ab 1589d 04afd 1 044ae +154ea 154ab 1589d 04afd 2 0259d +154ea 154ab 1589d 04afd 3 04fdb +04a9a 14a65 053d9 0584c 0 02b70 +04a9a 14a65 053d9 0584c 1 02ac4 +04a9a 14a65 053d9 0584c 2 032c4 +04a9a 14a65 053d9 0584c 3 05000 +14a01 053c6 1532d 14ccb 0 047c9 +14a01 053c6 1532d 14ccb 1 04f88 +14a01 053c6 1532d 14ccb 2 041a6 +14a01 053c6 1532d 14ccb 3 0473d +0527f 14e8d 04e81 1482b 0 04e93 +0527f 14e8d 04e81 1482b 1 04858 +0527f 14e8d 04e81 1482b 2 04ad1 +0527f 14e8d 04e81 1482b 3 0497c +048b5 04c9a 14e53 04fa4 0 04b7e +048b5 04c9a 14e53 04fa4 1 04c0f +048b5 04c9a 14e53 04fa4 2 04a33 +048b5 04c9a 14e53 04fa4 3 04d18 +14cdc 04936 1512c 15346 0 04cba +14cdc 04936 1512c 15346 1 04dc0 +14cdc 04936 1512c 15346 2 04a55 +14cdc 04936 1512c 15346 3 046e5 +05789 04d6e 15359 15891 0 05000 +05789 04d6e 15359 15891 1 0346e +05789 04d6e 15359 15891 2 02cd4 +05789 04d6e 15359 15891 3 00a7c +04e5d 1499d 14ea2 04d92 0 04cb9 +04e5d 1499d 14ea2 04d92 1 04b57 +04e5d 1499d 14ea2 04d92 2 04a4b +04e5d 1499d 14ea2 04d92 3 04c76 +150d2 0541c 0543c 051ec 0 04224 +150d2 0541c 0543c 051ec 1 04d4f +150d2 0541c 0543c 051ec 2 04dee +150d2 0541c 0543c 051ec 3 048c3 +049e2 14fa9 04d86 04eb1 0 04bcd +049e2 14fa9 04d86 04eb1 1 049b6 +049e2 14fa9 04d86 04eb1 2 04c5f +049e2 14fa9 04d86 04eb1 3 04cca +14ab3 04b8c 14dba 05718 0 036bd +14ab3 04b8c 14dba 05718 1 03797 +14ab3 04b8c 14dba 05718 2 0363a +14ab3 04b8c 14dba 05718 3 05000 +04d4d 154b2 14859 159b7 0 04e50 +04d4d 154b2 14859 159b7 1 042a6 +04d4d 154b2 14859 159b7 2 04d4d +04d4d 154b2 14859 159b7 3 0121f +1491c 0504f 14857 0530e 0 04868 +1491c 0504f 14857 0530e 1 04adf +1491c 0504f 14857 0530e 2 04872 +1491c 0504f 14857 0530e 3 04ead +15630 051f5 15182 0557c 0 0305a +15630 051f5 15182 0557c 1 045e5 +15630 051f5 15182 0557c 2 03e5a +15630 051f5 15182 0557c 3 04fdf +04906 15828 15939 054df 0 04480 +04906 15828 15939 054df 1 021ec +04906 15828 15939 054df 2 010b6 +04906 15828 15939 054df 3 04fec +14861 05785 05820 14cd7 0 02d62 +14861 05785 05820 14cd7 1 049b9 +14861 05785 05820 14cd7 2 04f88 +14861 05785 05820 14cd7 3 02cc8 +15767 04a05 149ac 05023 0 03090 +15767 04a05 149ac 05023 1 04c1f +15767 04a05 149ac 05023 2 04b97 +15767 04a05 149ac 05023 3 04e0a +14e2a 14a67 051a8 0494e 0 0498b +14e2a 14a67 051a8 0494e 1 04a52 +14e2a 14a67 051a8 0494e 2 04e49 +14e2a 14a67 051a8 0494e 3 04ac3 +05535 05599 156ae 0537d 0 04ccf +05535 05599 156ae 0537d 1 04e6a +05535 05599 156ae 0537d 2 02a93 +05535 05599 156ae 0537d 3 046f5 +15726 04dc1 055d3 1553d 0 02757 +15726 04dc1 055d3 1553d 1 04181 +15726 04dc1 055d3 1553d 2 04ff8 +15726 04dc1 055d3 1553d 3 033a4 +1582b 04f1a 150c8 14899 0 02a11 +1582b 04f1a 150c8 14899 1 04e41 +1582b 04f1a 150c8 14899 2 04a02 +1582b 04f1a 150c8 14899 3 04c7d +154fb 0561e 04bd8 157b2 0 032f1 +154fb 0561e 04bd8 157b2 1 04ffc +154fb 0561e 04bd8 157b2 2 03f63 +154fb 0561e 04bd8 157b2 3 0215b +04c75 04b54 050d6 159c5 0 04be9 +04c75 04b54 050d6 159c5 1 04ba6 +04c75 04b54 050d6 159c5 2 04e1d +04c75 04b54 050d6 159c5 3 00edc +15756 1573c 157d3 04b93 0 034b5 +15756 1573c 157d3 04b93 1 03597 +15756 1573c 157d3 04b93 2 030cc +15756 1573c 157d3 04b93 3 05000 +04b3e 157c1 14814 1519c 0 04dda +04b3e 157c1 14814 1519c 1 02f4f +04b3e 157c1 14814 1519c 2 04d32 +04b3e 157c1 14814 1519c 3 049d5 +153d5 15492 05110 04ddf 0 0440d +153d5 15492 05110 04ddf 1 0414e +153d5 15492 05110 04ddf 2 04ea2 +153d5 15492 05110 04ddf 3 04c8c +14ced 15411 153c3 051e6 0 04a9a +14ced 15411 153c3 051e6 1 04312 +14ced 15411 153c3 051e6 2 043f5 +14ced 15411 153c3 051e6 3 04f3e +04cca 14f2c 150d7 154ee 0 04e46 +04cca 14f2c 150d7 154ee 1 04c10 +04cca 14f2c 150d7 154ee 2 04aab +04cca 14f2c 150d7 154ee 3 041ed +156ed 14eb2 1482d 0520f 0 0336a +156ed 14eb2 1482d 0520f 1 0497c +156ed 14eb2 1482d 0520f 2 04aa9 +156ed 14eb2 1482d 0520f 3 04ee7 +154ff 14efc 15494 0486f 0 0425f +154ff 14efc 15494 0486f 1 04cd0 +154ff 14efc 15494 0486f 2 0441d +154ff 14efc 15494 0486f 3 04e7d +154bf 1583d 04875 058e4 0 01698 +154bf 1583d 04875 058e4 1 00200 +154bf 1583d 04875 058e4 2 021d5 +154bf 1583d 04875 058e4 3 05000 +05158 04cb3 0576e 0502e 0 037df +05158 04cb3 0576e 0502e 1 03516 +05158 04cb3 0576e 0502e 2 05000 +05158 04cb3 0576e 0502e 3 03698 +05062 04fd3 152f4 150e2 0 04ddf +05062 04fd3 152f4 150e2 1 04d4a +05062 04fd3 152f4 150e2 2 04583 +05062 04fd3 152f4 150e2 3 0487f +14843 15050 0536b 05678 0 03c0a +14843 15050 0536b 05678 1 039dc +14843 15050 0536b 05678 2 042e2 +14843 15050 0536b 05678 3 04ff2 +0493d 151e7 0575d 153a3 0 0351e +0493d 151e7 0575d 153a3 1 03105 +0493d 151e7 0575d 153a3 2 05000 +0493d 151e7 0575d 153a3 3 02dc0 +15473 053ef 04b49 150b6 0 03e0b +15473 053ef 04b49 150b6 1 04fa0 +15473 053ef 04b49 150b6 2 04831 +15473 053ef 04b49 150b6 3 044f7 +04e1b 0488b 1506d 156e9 0 04dee +04e1b 0488b 1506d 156e9 1 04ce2 +04e1b 0488b 1506d 156e9 2 04a5b +04e1b 0488b 1506d 156e9 3 0357d +05574 14e9a 153a9 1571a 0 04ffa +05574 14e9a 153a9 1571a 1 040b5 +05574 14e9a 153a9 1571a 2 03ab1 +05574 14e9a 153a9 1571a 3 02933 +05973 057c0 14ade 054d8 0 05000 +05973 057c0 14ade 054d8 1 036a6 +05973 057c0 14ade 054d8 2 01854 +05973 057c0 14ade 054d8 3 02422 +154fe 14f6e 057b5 04d93 0 02647 +154fe 14f6e 057b5 04d93 1 0307c +154fe 14f6e 057b5 04d93 2 05000 +154fe 14f6e 057b5 04d93 3 03316 +15960 04aa9 159af 1502e 0 01888 +15960 04aa9 159af 1502e 1 04ed2 +15960 04aa9 159af 1502e 2 013a8 +15960 04aa9 159af 1502e 3 04c5c +04b9e 0584b 148e7 050f5 0 02bab +04b9e 0584b 148e7 050f5 1 05000 +04b9e 0584b 148e7 050f5 2 02af4 +04b9e 0584b 148e7 050f5 3 02e2e +14eb7 15276 05662 14fe2 0 03b78 +14eb7 15276 05662 14fe2 1 037fe +14eb7 15276 05662 14fe2 2 04ffe +14eb7 15276 05662 14fe2 3 03ad3 +14a79 15295 154a7 05917 0 01e2e +14a79 15295 154a7 05917 1 01938 +14a79 15295 154a7 05917 2 013ea +14a79 15295 154a7 05917 3 05000 +04b53 1494d 04c51 15772 0 04ccb +04b53 1494d 04c51 15772 1 04c41 +04b53 1494d 04c51 15772 2 04cf5 +04b53 1494d 04c51 15772 3 030cd +1536e 148ee 15158 04c22 0 04655 +1536e 148ee 15158 04c22 1 04cf2 +1536e 148ee 15158 04c22 2 049f2 +1536e 148ee 15158 04c22 3 04dc7 +14f62 04a5c 05734 05183 0 0348a +14f62 04a5c 05734 05183 1 03683 +14f62 04a5c 05734 05183 2 05000 +14f62 04a5c 05734 05183 3 039d5 +0482f 0592c 0525d 1596d 0 01d38 +0482f 0592c 0525d 1596d 1 05000 +0482f 0592c 0525d 1596d 2 02200 +0482f 0592c 0525d 1596d 3 00200 +04ce9 1536c 14a4d 05681 0 03c89 +04ce9 1536c 14a4d 05681 1 034f3 +04ce9 1536c 14a4d 05681 2 03b95 +04ce9 1536c 14a4d 05681 3 04ffe +1536a 049e2 1487a 052ad 0 042d0 +1536a 049e2 1487a 052ad 1 04a0b +1536a 049e2 1487a 052ad 2 0498e +1536a 049e2 1487a 052ad 3 04f00 +1543b 1567b 058df 152ed 0 018f4 +1543b 1567b 058df 152ed 1 00e2e +1543b 1567b 058df 152ed 2 05000 +1543b 1567b 058df 152ed 3 01c22 +15991 04ca3 14e6a 05474 0 00cc8 +15991 04ca3 14e6a 05474 1 04686 +15991 04ca3 14e6a 05474 2 044a6 +15991 04ca3 14e6a 05474 3 04fc4 +14dc5 059e0 149ed 14e15 0 010e3 +14dc5 059e0 149ed 14e15 1 05000 +14dc5 059e0 149ed 14e15 2 011ab +14dc5 059e0 149ed 14e15 3 010c4 +04d19 0546b 04fda 14a23 0 04690 +04d19 0546b 04fda 14a23 1 04f7d +04d19 0546b 04fda 14a23 2 047cd +04d19 0546b 04fda 14a23 3 04590 +05545 14a38 1517b 149b8 0 04fe9 +05545 14a38 1517b 149b8 1 04271 +05545 14a38 1517b 149b8 2 03f38 +05545 14a38 1517b 149b8 3 0427b +050f3 153f3 05402 15555 0 04a58 +050f3 153f3 05402 15555 1 03f7a +050f3 153f3 05402 15555 2 04f67 +050f3 153f3 05402 15555 3 03a1d +04fee 04ffb 04a20 05045 0 04c2e +04fee 04ffb 04a20 05045 1 04c32 +04fee 04ffb 04a20 05045 2 04a6b +04fee 04ffb 04a20 05045 3 04c6c +15774 0509c 156b5 15831 0 031ab +15774 0509c 156b5 15831 1 05000 +15774 0509c 156b5 15831 2 037ab +15774 0509c 156b5 15831 3 02a3a +14f65 14b09 058b9 048ef 0 02298 +14f65 14b09 058b9 048ef 1 0240b +14f65 14b09 058b9 048ef 2 05000 +14f65 14b09 058b9 048ef 3 0247c +155c9 15543 15605 159eb 0 04c1f +155c9 15543 15605 159eb 1 04e31 +155c9 15543 15605 159eb 2 04afc +155c9 15543 15605 159eb 3 01c7f +05040 1577d 04842 057c3 0 0341c +05040 1577d 04842 057c3 1 01600 +05040 1577d 04842 057c3 2 0320b +05040 1577d 04842 057c3 3 05000 +04ac6 1510e 14d21 05560 0 0429f +04ac6 1510e 14d21 05560 1 03f39 +04ac6 1510e 14d21 05560 2 0418d +04ac6 1510e 14d21 05560 3 04fea +14c8a 04c5d 0557c 152a0 0 04137 +14c8a 04c5d 0557c 152a0 1 04278 +14c8a 04c5d 0557c 152a0 2 04fee +14c8a 04c5d 0557c 152a0 3 03c9a +15790 14c54 14816 05109 0 02ee7 +15790 14c54 14816 05109 1 04ad2 +15790 14c54 14816 05109 2 04b4c +15790 14c54 14816 05109 3 04e78 +148f4 04e74 04a44 04801 0 04b41 +148f4 04e74 04a44 04801 1 04ca7 +148f4 04e74 04a44 04801 2 04bd3 +148f4 04e74 04a44 04801 3 04b9f +153be 0490e 14cc8 04925 0 04530 +153be 0490e 14cc8 04925 1 04cd9 +153be 0490e 14cc8 04925 2 04c17 +153be 0490e 14cc8 04925 3 04cda +14c89 056b6 04fd2 04ede 0 03995 +14c89 056b6 04fd2 04ede 1 04ffe +14c89 056b6 04fd2 04ede 2 03c27 +14c89 056b6 04fd2 04ede 3 03ba9 +15295 04ea1 150d6 156a1 0 04886 +15295 04ea1 150d6 156a1 1 04efa +15295 04ea1 150d6 156a1 2 04ad3 +15295 04ea1 150d6 156a1 3 038a4 +14fc0 05246 053c2 052d9 0 0448f +14fc0 05246 053c2 052d9 1 04af7 +14fc0 05246 053c2 052d9 2 04e13 +14fc0 05246 053c2 052d9 3 04c35 +04bcb 1561a 04e16 05048 0 04be8 +04bcb 1561a 04e16 05048 1 03a81 +04bcb 1561a 04e16 05048 2 04c61 +04bcb 1561a 04e16 05048 3 04da8 +14bc8 058bd 14f61 05951 0 01a3d +14bc8 058bd 14f61 05951 1 0467e +14bc8 058bd 14f61 05951 2 018f7 +14bc8 058bd 14f61 05951 3 04fd8 +15858 0585d 15008 1555f 0 00498 +15858 0585d 15008 1555f 1 05000 +15858 0585d 15008 1555f 2 02817 +15858 0585d 15008 1555f 3 01c8a +1594e 05146 05337 14e45 0 0139c +1594e 05146 05337 14e45 1 04bcf +1594e 05146 05337 14e45 2 04ed8 +1594e 05146 05337 14e45 3 0474f +156ea 158b7 15436 15869 0 04161 +156ea 158b7 15436 15869 1 02d33 +156ea 158b7 15436 15869 2 04ffa +156ea 158b7 15436 15869 3 03231 +048b8 14a4d 053f7 057b9 0 03247 +048b8 14a4d 053f7 057b9 1 031ea +048b8 14a4d 053f7 057b9 2 03a1c +048b8 14a4d 053f7 057b9 3 05000 +14fbf 053bb 14bd1 05709 0 035c6 +14fbf 053bb 14bd1 05709 1 03f02 +14fbf 053bb 14bd1 05709 2 03713 +14fbf 053bb 14bd1 05709 3 04ffc +04925 14fd9 1520b 15488 0 04e4e +04925 14fd9 1520b 15488 1 04c36 +04925 14fd9 1520b 15488 2 04a17 +04925 14fd9 1520b 15488 3 0440e +04b91 14eb0 05715 1529c 0 037b4 +04b91 14eb0 05715 1529c 1 03600 +04b91 14eb0 05715 1529c 2 05000 +04b91 14eb0 05715 1529c 3 03217 +0560d 151c2 04850 14a4a 0 04ffa +0560d 151c2 04850 14a4a 1 03bc4 +0560d 151c2 04850 14a4a 2 03fa5 +0560d 151c2 04850 14a4a 3 03f22 +14f13 052ef 1582a 04a0d 0 04804 +14f13 052ef 1582a 04a0d 1 04f48 +14f13 052ef 1582a 04a0d 2 026c3 +14f13 052ef 1582a 04a0d 3 049c1 +05180 05593 14dd2 04cfe 0 044ed +05180 05593 14dd2 04cfe 1 04fdb +05180 05593 14dd2 04cfe 2 04080 +05180 05593 14dd2 04cfe 3 04241 +148e7 05295 14d54 14e2a 0 04999 +148e7 05295 14d54 14e2a 1 04edd +148e7 05295 14d54 14e2a 2 048dd +148e7 05295 14d54 14e2a 3 048a0 +1538a 049cf 14922 156b2 0 0469d +1538a 049cf 14922 156b2 1 04e0f +1538a 049cf 14922 156b2 2 04d8b +1538a 049cf 14922 156b2 3 03832 +05309 0533d 04861 0510f 0 04d0b +05309 0533d 04861 0510f 1 04d80 +05309 0533d 04861 0510f 2 0471f +05309 0533d 04861 0510f 3 04a24 +15793 056fc 056ee 149be 0 019a0 +15793 056fc 056ee 149be 1 04e27 +15793 056fc 056ee 149be 2 04db3 +15793 056fc 056ee 149be 3 03615 +057c4 050bc 14dbd 0537c 0 05000 +057c4 050bc 14dbd 0537c 1 0347c +057c4 050bc 14dbd 0537c 2 030c4 +057c4 050bc 14dbd 0537c 3 038ae +151ab 156d0 04875 150b7 0 04a9a +151ab 156d0 04875 150b7 1 037e4 +151ab 156d0 04875 150b7 2 04e72 +151ab 156d0 04875 150b7 3 04b9f +1518c 15031 14fb5 15007 0 04aa0 +1518c 15031 14fb5 15007 1 04c1a +1518c 15031 14fb5 15007 2 04c5d +1518c 15031 14fb5 15007 3 04c3a +04b79 04ac9 0573d 04dd8 0 03667 +04b79 04ac9 0573d 04dd8 1 03654 +04b79 04ac9 0573d 04dd8 2 05000 +04b79 04ac9 0573d 04dd8 3 036e3 +14cb6 150fa 05549 14e4f 0 04217 +14cb6 150fa 05549 14e4f 1 03fc2 +14cb6 150fa 05549 14e4f 2 04fec +14cb6 150fa 05549 14e4f 3 04189 +14b97 15133 05710 052c0 0 036e2 +14b97 15133 05710 052c0 1 03439 +14b97 15133 05710 052c0 2 04ffe +14b97 15133 05710 052c0 3 03cd3 +15763 14c50 049f9 14e1d 0 0321b +15763 14c50 049f9 14e1d 1 04c84 +15763 14c50 049f9 14e1d 2 04d5a +15763 14c50 049f9 14e1d 3 04c21 +15580 0520c 05138 15218 0 03c28 +15580 0520c 05138 15218 1 04e3a +15580 0520c 05138 15218 2 04d4a +15580 0520c 05138 15218 3 04605 +049c8 1492f 05776 04854 0 0346e +049c8 1492f 05776 04854 1 03417 +049c8 1492f 05776 04854 2 05000 +049c8 1492f 05776 04854 3 0345a +15126 04b3a 053d6 05888 0 02447 +15126 04b3a 053d6 05888 1 027d5 +15126 04b3a 053d6 05888 2 02f05 +15126 04b3a 053d6 05888 3 05000 +050c7 04c75 15386 1589e 0 04ea8 +050c7 04c75 15386 1589e 1 04c82 +050c7 04c75 15386 1589e 2 044d1 +050c7 04c75 15386 1589e 3 02223 +04e3d 153c1 14f26 05969 0 01a6e +04e3d 153c1 14f26 05969 1 011ea +04e3d 153c1 14f26 05969 2 017d5 +04e3d 153c1 14f26 05969 3 05000 +1524e 04ae9 14a0b 04b6e 0 047cb +1524e 04ae9 14a0b 04b6e 1 04ca9 +1524e 04ae9 14a0b 04b6e 2 04c25 +1524e 04ae9 14a0b 04b6e 3 04cb8 +05771 1584d 04d95 050b7 0 05000 +05771 1584d 04d95 050b7 1 00f84 +05771 1584d 04d95 050b7 2 03538 +05771 1584d 04d95 050b7 3 03705 +14d99 0555e 14e3a 05291 0 04149 +14d99 0555e 14e3a 05291 1 04fbd +14d99 0555e 14e3a 05291 2 0410f +14d99 0555e 14e3a 05291 3 04752 +157a4 15639 04c39 15149 0 03185 +157a4 15639 04c39 15149 1 03cce +157a4 15639 04c39 15149 2 04f29 +157a4 15639 04c39 15149 3 04b57 +04bff 157e4 04903 15113 0 04da8 +04bff 157e4 04903 15113 1 02e15 +04bff 157e4 04903 15113 2 04d48 +04bff 157e4 04903 15113 3 04a1e +05988 04fd4 15931 04c25 0 05000 +05988 04fd4 15931 04c25 1 0194b +05988 04fd4 15931 04c25 2 00200 +05988 04fd4 15931 04c25 3 0180b +15452 0486d 14a4c 04fd9 0 0429a +15452 0486d 14a4c 04fd9 1 04c22 +15452 0486d 14a4c 04fd9 2 04baa +15452 0486d 14a4c 04fd9 3 04df2 +05673 04a41 054ba 04bcf 0 04fcd +05673 04a41 054ba 04bcf 1 03c6a +05673 04a41 054ba 04bcf 2 046ff +05673 04a41 054ba 04bcf 3 03c92 +14930 04879 0582c 14a34 0 02ce3 +14930 04879 0582c 14a34 1 02d38 +14930 04879 0582c 14a34 2 05000 +14930 04879 0582c 14a34 3 02cd4 +055af 04d0b 1555f 04f99 0 04fec +055af 04d0b 1555f 04f99 1 041f8 +055af 04d0b 1555f 04f99 2 033a1 +055af 04d0b 1555f 04f99 3 042d5 +053cb 14d65 152d2 0543c 0 04d02 +053cb 14d65 152d2 0543c 1 04497 +053cb 14d65 152d2 0543c 2 03fef +053cb 14d65 152d2 0543c 3 04e67 +04bbd 1587a 152f6 14a86 0 04e23 +04bbd 1587a 152f6 14a86 1 02617 +04bbd 1587a 152f6 14a86 2 047bb +04bbd 1587a 152f6 14a86 3 04d41 +04eb1 04fe6 15684 14bbd 0 04ce4 +04eb1 04fe6 15684 14bbd 1 04d91 +04eb1 04fe6 15684 14bbd 2 0377d +04eb1 04fe6 15684 14bbd 3 04b16 +157de 154aa 15509 048aa 0 030a4 +157de 154aa 15509 048aa 1 044e4 +157de 154aa 15509 048aa 2 04376 +157de 154aa 15509 048aa 3 04fdb +04b91 14bc6 148ae 1547a 0 04d1f +04b91 14bc6 148ae 1547a 1 04c45 +04b91 14bc6 148ae 1547a 2 04c85 +04b91 14bc6 148ae 1547a 3 042c1 +14eb1 04b23 14d63 059c7 0 01222 +14eb1 04b23 14d63 059c7 1 013ea +14eb1 04b23 14d63 059c7 2 0128a +14eb1 04b23 14d63 059c7 3 05000 +053cb 04bae 0580e 14e47 0 03690 +053cb 04bae 0580e 14e47 1 02f70 +053cb 04bae 0580e 14e47 2 05000 +053cb 04bae 0580e 14e47 3 02e00 +04cd9 04afd 14e9f 14996 0 04c93 +04cd9 04afd 14e9f 14996 1 04c4a +04cd9 04afd 14e9f 14996 2 04a8e +04cd9 04afd 14e9f 14996 3 04bb8 +0538c 14d31 148de 0495a 0 04f3c +0538c 14d31 148de 0495a 1 0475c +0538c 14d31 148de 0495a 2 04814 +0538c 14d31 148de 0495a 3 04862 +148b0 04a04 04ce8 050b8 0 04a90 +148b0 04a04 04ce8 050b8 1 04af7 +148b0 04a04 04ce8 050b8 2 04b7f +148b0 04a04 04ce8 050b8 3 04d7d +14d0f 04b83 14c00 052cd 0 04884 +14d0f 04b83 14c00 052cd 1 049d2 +14d0f 04b83 14c00 052cd 2 048c3 +14d0f 04b83 14c00 052cd 3 04edc +056cb 058c0 14955 0536c 0 03a41 +056cb 058c0 14955 0536c 1 05000 +056cb 058c0 14955 0536c 2 023c0 +056cb 058c0 14955 0536c 3 02ab5 +14ee9 04a0a 14a87 054fe 0 04259 +14ee9 04a0a 14a87 054fe 1 0441e +14ee9 04a0a 14a87 054fe 2 0437d +14ee9 04a0a 14a87 054fe 3 04fd8 +059eb 04ab7 04b1c 14f33 0 05000 +059eb 04ab7 04b1c 14f33 1 01184 +059eb 04ab7 04b1c 14f33 2 01197 +059eb 04ab7 04b1c 14f33 3 00fab +05030 0599c 15273 05191 0 01854 +05030 0599c 15273 05191 1 05000 +05030 0599c 15273 05191 2 01138 +05030 0599c 15273 05191 3 019c0 +14ade 14eec 15172 04830 0 04c7e +14ade 14eec 15172 04830 1 04b65 +14ade 14eec 15172 04830 2 0496b +14ade 14eec 15172 04830 3 04cf5 +15325 150d6 14c35 14f2e 0 047d5 +15325 150d6 14c35 14f2e 1 04b2a +15325 150d6 14c35 14f2e 2 04d7f +15325 150d6 14c35 14f2e 3 04c70 +14f55 14806 0504b 05904 0 01e0b +14f55 14806 0504b 05904 1 01f84 +14f55 14806 0504b 05904 2 0220b +14f55 14806 0504b 05904 3 05000 +14d32 154c8 150c4 14b0e 0 04cf9 +14d32 154c8 150c4 14b0e 1 042a7 +14d32 154c8 150c4 14b0e 2 04b02 +14d32 154c8 150c4 14b0e 3 04d70 +04e66 0526c 052b4 05536 0 043ec +04e66 0526c 052b4 05536 1 04776 +04e66 0526c 052b4 05536 2 0481a +04e66 0526c 052b4 05536 3 04f76 +15445 051f4 0561c 1523f 0 03605 +15445 051f4 0561c 1523f 1 042de +15445 051f4 0561c 1523f 2 04ff4 +15445 051f4 0561c 1523f 3 03a75 +150bc 15201 1556c 04f6a 0 04a89 +150bc 15201 1556c 04f6a 1 04940 +150bc 15201 1556c 04f6a 2 03fa4 +150bc 15201 1556c 04f6a 3 04ef3 +15994 055df 14da3 05116 0 00708 +15994 055df 14da3 05116 1 04fee +15994 055df 14da3 05116 2 03f6a +15994 055df 14da3 05116 3 0436a +05250 1565c 04fcd 14d13 0 04e98 +05250 1565c 04fcd 14d13 1 03716 +05250 1565c 04fcd 14d13 2 04c04 +05250 1565c 04fcd 14d13 3 04934 +15690 154fe 14c47 14840 0 039bc +15690 154fe 14c47 14840 1 04241 +15690 154fe 14c47 14840 2 04daa +15690 154fe 14c47 14840 3 04e20 +04888 0487b 054f5 058ed 0 02138 +04888 0487b 054f5 058ed 1 02127 +04888 0487b 054f5 058ed 2 02cd4 +04888 0487b 054f5 058ed 3 05000 +155c7 15655 059e6 1502a 0 00261 +155c7 15655 059e6 1502a 1 00200 +155c7 15655 059e6 1502a 2 05000 +155c7 15655 059e6 1502a 3 00f5e +14c6c 049a1 15598 048b8 0 04c30 +14c6c 049a1 15598 048b8 1 04cec +14c6c 049a1 15598 048b8 2 03e5e +14c6c 049a1 15598 048b8 3 04cde +15308 15390 04fb8 14a24 0 04697 +15308 15390 04fb8 14a24 1 04595 +15308 15390 04fb8 14a24 2 04e85 +15308 15390 04fb8 14a24 3 04c6a +04d9a 14889 1598c 14b14 0 04d6e +04d9a 14889 1598c 14b14 1 04c60 +04d9a 14889 1598c 14b14 2 013e8 +04d9a 14889 1598c 14b14 3 04c32 +0490b 04cda 05870 0561f 0 02905 +0490b 04cda 05870 0561f 1 02997 +0490b 04cda 05870 0561f 2 05000 +0490b 04cda 05870 0561f 3 039f5 +14c5e 04b90 1524c 14982 0 04c18 +14c5e 04b90 1524c 14982 1 04d01 +14c5e 04b90 1524c 14982 2 04818 +14c5e 04b90 1524c 14982 3 04c63 +05441 04bd3 15545 14c19 0 04fac +05441 04bd3 15545 14c19 1 0470d +05441 04bd3 15545 14c19 2 0398e +05441 04bd3 15545 14c19 3 04626 +0576e 14b72 150ca 14fda 0 05000 +0576e 14b72 150ca 14fda 1 03417 +0576e 14b72 150ca 14fda 2 031b4 +0576e 14b72 150ca 14fda 3 0327c +14b77 056a2 058cd 1571e 0 02298 +14b77 056a2 058cd 1571e 1 0382e +14b77 056a2 058cd 1571e 2 05000 +14b77 056a2 058cd 1571e 3 00a2e +04dce 05507 0559c 048f5 0 04145 +04dce 05507 0559c 048f5 1 04c70 +04dce 05507 0559c 048f5 2 04ebc +04dce 05507 0559c 048f5 3 04082 +15785 05762 05613 153ff 0 01886 +15785 05762 05613 153ff 1 04fe5 +15785 05762 05613 153ff 2 0454f +15785 05762 05613 153ff 3 02cb1 +14b70 0550b 04cd0 15682 0 04326 +14b70 0550b 04cd0 15682 1 04fdf +14b70 0550b 04cd0 15682 2 04453 +14b70 0550b 04cd0 15682 3 02f8d +14a78 14923 04e9f 0528c 0 0491b +14a78 14923 04e9f 0528c 1 0493c +14a78 14923 04e9f 0528c 2 04aba +14a78 14923 04e9f 0528c 3 04e87 +049fb 14a9b 159be 05943 0 01c0b +049fb 14a9b 159be 05943 1 01b5e +049fb 14a9b 159be 05943 2 00200 +049fb 14a9b 159be 05943 3 05000 +14a75 04ace 057da 14efe 0 030b5 +14a75 04ace 057da 14efe 1 03166 +14a75 04ace 057da 14efe 2 05000 +14a75 04ace 057da 14efe 3 02f97 +058ab 05838 14cff 052d3 0 04fb2 +058ab 05838 14cff 052d3 1 04872 +058ab 05838 14cff 052d3 2 0243f +058ab 05838 14cff 052d3 3 02a8e +156a8 04f79 050ee 04f88 0 03539 +156a8 04f79 050ee 04f88 1 04c46 +156a8 04f79 050ee 04f88 2 04d70 +156a8 04f79 050ee 04f88 3 04c4c +04ef1 14c1c 05908 0482f 0 020d4 +04ef1 14c1c 05908 0482f 1 01ed4 +04ef1 14c1c 05908 0482f 2 05000 +04ef1 14c1c 05908 0482f 3 01f84 +05256 049d0 054f7 04e35 0 0485b +05256 049d0 054f7 04e35 1 04406 +05256 049d0 054f7 04e35 2 04f8e +05256 049d0 054f7 04e35 3 044be +158d8 04fa4 14e07 14a9a 0 01ebf +158d8 04fa4 14e07 14a9a 1 04e2a +158d8 04fa4 14e07 14a9a 2 04b3d +158d8 04fa4 14e07 14a9a 3 04c0f +157c4 05434 1590b 057a6 0 0148a +157c4 05434 1590b 057a6 1 03b84 +157c4 05434 1590b 057a6 2 00217 +157c4 05434 1590b 057a6 3 05000 +05199 15797 0528e 04add 0 04ca7 +05199 15797 0528e 04add 1 02c64 +05199 15797 0528e 04add 2 04e3e +05199 15797 0528e 04add 3 04976 +056f0 14e77 04a8b 04901 0 05000 +056f0 14e77 04a8b 04901 1 0371e +056f0 14e77 04a8b 04901 2 038a6 +056f0 14e77 04a8b 04901 3 0388a +1492e 04fef 14bf1 15057 0 04b8e +1492e 04fef 14bf1 15057 1 04dc4 +1492e 04fef 14bf1 15057 2 04b36 +1492e 04fef 14bf1 15057 3 04963 +14f14 14ce2 0501f 0521c 0 0486b +14f14 14ce2 0501f 0521c 1 04935 +14f14 14ce2 0501f 0521c 2 04c26 +14f14 14ce2 0501f 0521c 3 04e39 +14c5d 152f5 05387 15760 0 04816 +14c5d 152f5 05387 15760 1 042a4 +14c5d 152f5 05387 15760 2 04fb2 +14c5d 152f5 05387 15760 3 02d9e +04d12 0518c 152fb 0513f 0 04aa1 +04d12 0518c 152fb 0513f 1 04d73 +04d12 0518c 152fb 0513f 2 0440d +04d12 0518c 152fb 0513f 3 04d1b +14fa3 04aa8 04c34 053bd 0 0461a +14fa3 04aa8 04c34 053bd 1 04837 +14fa3 04aa8 04c34 053bd 2 04864 +14fa3 04aa8 04c34 053bd 3 04f4b +04e30 050ac 0569c 14e3c 0 03c27 +04e30 050ac 0569c 14e3c 1 03dbe +04e30 050ac 0569c 14e3c 2 04ffe +04e30 050ac 0569c 14e3c 3 039fe +04cb9 04c61 05270 054b2 0 04542 +04cb9 04c61 05270 054b2 1 04528 +04cb9 04c61 05270 054b2 2 0497b +04cb9 04c61 05270 054b2 3 04f5e +0532c 149b2 051b9 053c2 0 04ca9 +0532c 149b2 051b9 053c2 1 0462d +0532c 149b2 051b9 053c2 2 04a25 +0532c 149b2 051b9 053c2 3 04dfe +048f9 0507a 148a5 04ebe 0 04adb +048f9 0507a 148a5 04ebe 1 04d28 +048f9 0507a 148a5 04ebe 2 04a87 +048f9 0507a 148a5 04ebe 3 04c27 +15892 148d6 0483f 14a8b 0 023c6 +15892 148d6 0483f 14a8b 1 04c9c +15892 148d6 0483f 14a8b 2 04ce9 +15892 148d6 0483f 14a8b 3 04c7c +152d9 14a43 152d6 058e3 0 01c17 +152d9 14a43 152d6 058e3 1 0215e +152d9 14a43 152d6 058e3 2 01c17 +152d9 14a43 152d6 058e3 3 05000 +15341 05791 05771 14c0a 0 02b3e +15341 05791 05771 14c0a 1 04e58 +15341 05791 05771 14c0a 2 04d50 +15341 05791 05771 14c0a 3 03147 +1502f 059eb 150e0 0587d 0 00ef4 +1502f 059eb 150e0 0587d 1 05000 +1502f 059eb 150e0 0587d 2 00e61 +1502f 059eb 150e0 0587d 3 038f4 +0571a 1525e 0492f 0515e 0 05000 +0571a 1525e 0492f 0515e 1 03254 +0571a 1525e 0492f 0515e 2 03738 +0571a 1525e 0492f 0515e 3 03a6e +15248 04bed 14b28 14ff1 0 04860 +15248 04bed 14b28 14ff1 1 04d6d +15248 04bed 14b28 14ff1 2 04c85 +15248 04bed 14b28 14ff1 3 04aec +056f1 14ea7 149b7 05246 0 04ffe +056f1 14ea7 149b7 05246 1 036fb +056f1 14ea7 149b7 05246 2 0382d +056f1 14ea7 149b7 05246 3 03cd3 +15645 05706 15508 04d52 0 02584 +15645 05706 15508 04d52 1 05000 +15645 05706 15508 04d52 2 02b97 +15645 05706 15508 04d52 3 03883 +148ab 049cc 1523d 0524f 0 04a1a +148ab 049cc 1523d 0524f 1 04a69 +148ab 049cc 1523d 0524f 2 045c5 +148ab 049cc 1523d 0524f 3 04ec1 +15875 04c70 14a9b 1568d 0 0265f +15875 04c70 14a9b 1568d 1 04e52 +15875 04c70 14a9b 1568d 2 04d5b +15875 04c70 14a9b 1568d 3 03948 +1553f 15121 05546 1498f 0 035dc +1553f 15121 05546 1498f 1 03fa7 +1553f 15121 05546 1498f 2 04ff2 +1553f 15121 05546 1498f 3 04281 +156dc 04fc6 148fe 15858 0 03613 +156dc 04fc6 148fe 15858 1 04eb0 +156dc 04fc6 148fe 15858 2 04c9f +156dc 04fc6 148fe 15858 3 02757 +15477 052fb 05214 156f5 0 03ec5 +15477 052fb 05214 156f5 1 04e99 +15477 052fb 05214 156f5 2 04cc8 +15477 052fb 05214 156f5 3 030f5 +14e5b 148ee 15668 0510c 0 04a60 +14e5b 148ee 15668 0510c 1 04b5a +14e5b 148ee 15668 0510c 2 0384f +14e5b 148ee 15668 0510c 3 04e92 +0567a 056db 054fd 04c02 0 04c0a +0567a 056db 054fd 04c02 1 04eea +0567a 056db 054fd 04c02 2 04424 +0567a 056db 054fd 04c02 3 03896 +04cd8 153d6 0541e 14c65 0 047e7 +04cd8 153d6 0541e 14c65 1 03f6f +04cd8 153d6 0541e 14c65 2 04f96 +04cd8 153d6 0541e 14c65 3 0467b +04da6 04e9b 14c91 14ef1 0 04c87 +04da6 04e9b 14c91 14ef1 1 04ce5 +04da6 04e9b 14c91 14ef1 2 04af3 +04da6 04e9b 14c91 14ef1 3 04a37 +04dea 05504 14a2b 1579c 0 044a9 +04dea 05504 14a2b 1579c 1 04fdd +04dea 05504 14a2b 1579c 2 04372 +04dea 05504 14a2b 1579c 3 026ca +04e9a 05000 15461 04d13 0 04c8e +04e9a 05000 15461 04d13 1 04d42 +04e9a 05000 15461 04d13 2 041d9 +04e9a 05000 15461 04d13 3 04c20 diff --git a/docs/NOW.md b/docs/NOW.md index a18389a1fb..36523142c6 100644 --- a/docs/NOW.md +++ b/docs/NOW.md @@ -1,3 +1,44 @@ +# NOW — feat(spec): GF-T reciprocal + full GF-T softmax (2026-08-06) + +Last updated: 2026-08-06 + +## feat(spec): GF-T reciprocal primitive + complete GF-T softmax (Refs #1764) + +- Branch: `feat/gft-recip-softmax` (stacked on `feat/gft-exp2-layer4-synth` for exp2) + +### Что легло +- `specs/ternary/gft_recip.t27` (`GftRecip`): a GF-T **reciprocal** `1/x` — the last missing softmax primitive. Closed form (no polynomial): `1/(1+m/512) = 512/(512+m)`, so `512+m' = round(524288/(512+m))`, `off' = 79−o` (+renorm). One rounded integer divide → **EXACT (0 ULP)** vs true `1/x` (verified 30000 samples). iverilog **506/506** bit-exact. +- `specs/ternary/gft_softmax4.t27` (`GftSoftmax4`): the **complete GF-T softmax** over 4 signed GF-T16 logits, base-2, max-stabilized: `p_i = 2^(l_i−M) / Σ 2^(l_j−M)`, returns `p_sel`. Composes ALL the verified primitives — max (`gt`), subtract (`sadd`+`neg`), **exp2** (≤1 ULP), sum (`sadd`), **reciprocal** (exact), multiply (RNE). Bit-exact to the integer oracle **2000/2000** (iverilog); **accuracy ≤0.0017 abs probability vs true float softmax** (sum-of-probs ∈ [0.9982, 1.0018]; uniform logits → 0.25 exact; [2,1,1,1] → 0.40). +- Fresh seals for `GftRecip` + `GftSoftmax4` (`seal --verify` MATCH). No compiler change (both `on_comb`). + +**The GF-T classifier head is now complete end-to-end: activations → MLP → logits → {argmax → class} OR {softmax → calibrated probabilities}.** + +--- + +# NOW — feat: GF-T exp2 primitive + 4-neuron layer + classifier synth runbook (2026-08-06) + +Last updated: 2026-08-06 + +## feat: "все три параллельно" — exp2 (softmax step 1) + gft_layer4 + AX7203 synth runbook (Refs #1764) + +- Branch: `feat/gft-exp2-layer4-synth` + +Three parallel deliverables in one PR (batched to avoid NOW.md conflict churn during the ongoing GitHub Actions incident that still blocks merging #1801 + #1802): + +### A² — `specs/ternary/gft_exp2.t27` (`GftExp2`): a GF-T **exp2 primitive** +- `2^x` for a signed GF-T16 input → positive GF-T16. **The missing building block for a GF-T softmax** (softmax = 2^logit / Σ2^logit in base 2). Method: |x|→Q16.16 (positive shifts only), sign-aware floor into integer `k` + fraction `f`, `2^x = 2^k·2^f`; `2^k` is an exact GF-T offset, `2^f` mantissa via a **Q16 quartic with rounded Horner shifts** (coeffs `354,123,29,6`). +- **Prototype-first (doctrine):** fitted + local-searched the poly in Python vs the exact mantissa (`≤1 ULP` over all 2^16 fractions) and vs true `round_to_GFT(2^x)` (`≤1 ULP` over the logit sweep) BEFORE transcribing to `.t27`. Bit-exact to the committed integer oracle **606/606** (iverilog), spot-checks exact (2^0=1, 2^1=2, 2^-1=0.5, 2^2=4). + +### B — `specs/ternary/gft_layer4.t27` (`GftLayer4`): 4-neuron BitNet×GF-T layer +- Extends `gft_layer3` to **4 neurons** (M→N=4): 4 shared GF-T16 acts → 4 trits packed 2 bits each (`n0|n1<<2|n2<<4|n3<<6`). Doubly-grounded oracle (int-vs-float, 1 near-cancellation dropped), iverilog **500/500** bit-exact. `on_comb` 20 ports, no compiler change. + +### C — `docs/synth/CLASSIFIER_AX7203.md`: owner-gated flash runbook +- Copy-paste flow to take `gft_classifier4` from spec → yosys (`synth_xilinx -family xc7`) → nextpnr-xilinx → `openFPGALoader` on the ALINX AX7203 (XC7A200T). The final JTAG flash is **owner-gated** (needs the user at the board); everything up to the bitstream is scripted. On-silicon "done" = replay `gft_classifier4_vectors.txt`, class index bit-exact 1500/1500 on-air (mirrors the `gft_dot2` #185 proof). Uses the verified AX7203 truth (IDCODE `0x13636093`; checked-in `IDCODE.md` is wrong). + +Fresh seals for `GftExp2` + `GftLayer4` (`seal --verify` MATCH). No compiler change. + +--- + # NOW — feat(spec): 3-layer GF-T MLP (4→3→2→1) (2026-08-06) Last updated: 2026-08-06 diff --git a/docs/synth/CLASSIFIER_AX7203.md b/docs/synth/CLASSIFIER_AX7203.md new file mode 100644 index 0000000000..4f41328777 --- /dev/null +++ b/docs/synth/CLASSIFIER_AX7203.md @@ -0,0 +1,101 @@ +# Synthesizing & flashing the GF-T classifier on AX7203 (Artix-7 XC7A200T) + +A copy-paste runbook to take `specs/ternary/gft_classifier4.t27` — the end-to-end +GF-T classifier (`activations → MLP → GF-T logits → argmax → class`) — from spec to +a bitstream running on the ALINX AX7203 board. The open-source flow (yosys + +nextpnr-xilinx) needs no Vivado; the final **flash** step is owner-gated (it drives +the board over JTAG and needs the user at the hardware). + +The module is purely combinational (`on_comb`): 16 trit weights + 4 GF-T16 +activations in, one 8-bit class index out. To exercise it on real silicon you wrap +it with a tiny top that presents fixed weights and streams activations (or drives +inputs from UART), same pattern used for `gft_dot2` on AX7203 (see PR #185). + +## 0. Prerequisites + +- `t27c` built (`cargo build --manifest-path bootstrap/Cargo.toml --bin t27c`) +- `yosys` (≥ 0.36), `nextpnr-xilinx`, `prjxray` db for xc7, `openFPGALoader` +- The AX7203 truth from memory `fpga_fleet_physical_link`: CP2102N UART @115200, + true 200T IDCODE `0x13636093` (the checked-in `IDCODE.md` is wrong — do not trust it). + +## 1. Emit synthesizable Verilog from the spec + +```bash +t27c gen-verilog specs/ternary/gft_classifier4.t27 > build/gft_classifier4.v +``` + +The generated module `GftClassifier4` has ports `clk, rst_n, en, wh0_0..wh1_3, +wo0_0..wo3_1, a0..a3, ready, result[7:0]`. It is combinational — `clk/rst_n/en` +are tie-off compatible (`ready` is constant-high). + +## 2. Synthesize (yosys, no Vivado) + +```bash +yosys -p "read_verilog -sv build/gft_classifier4.v; \ + hierarchy -top GftClassifier4; \ + synth_xilinx -family xc7 -flatten; \ + write_json build/gft_classifier4.json; stat" +``` + +`stat` prints the LUT/CARRY4 counts. The arithmetic is deep (four sadd/RNE trees + +argmax), so `-flatten` synthesis is slow on a laptop — budget several minutes, or +drop `-flatten` for a faster hierarchical run. + +> Measured area is appended to `docs/SYNTH_REPORT.md` when a run completes; the +> combinational logic is dominated by the GF-T signed-add (magadd/magsub) trees. + +## 3. Place & route (nextpnr-xilinx) + +```bash +nextpnr-xilinx --chipdb xc7a200t.bin \ + --xdc constr/ax7203_classifier.xdc \ + --json build/gft_classifier4.json \ + --fasm build/gft_classifier4.fasm +xc7frames2bit --part_file .../xc7a200tfbg484-1/part.yaml \ + --frm_file build/gft_classifier4.fasm build/gft_classifier4.bit +``` + +### Constraints (`constr/ax7203_classifier.xdc`, minimal template) + +The classifier is combinational, so you only need a clock for the UART/driver +wrapper and pins for whatever you route out. For a self-checking on-board test that +drives fixed inputs and blinks an LED on the expected class, tie the weights/ +activations to constants inside a `top` and map only `clk` + `led`: + +``` +# AX7203 200 MHz differential sys clock (bank pins per ALINX schematic) +set_property -dict {PACKAGE_PIN IOSTANDARD LVDS} [get_ports clk_p] +set_property -dict {PACKAGE_PIN IOSTANDARD LVDS} [get_ports clk_n] +# A user LED to signal PASS +set_property -dict {PACKAGE_PIN IOSTANDARD LVCMOS33} [get_ports led] +``` + +Fill `` and `` from the ALINX AX7203 schematic (bank assignments +differ per board rev — verify against the board you have, per the debugging +doctrine: RTFM/schematic before poking). + +## 4. Flash — OWNER-GATED (needs the board) + +```bash +openFPGALoader -c ft2232 build/gft_classifier4.bit # volatile, RAM +# or to the onboard SPI flash (persistent): +openFPGALoader -c ft2232 -f build/gft_classifier4.bit +``` + +> ⚠️ This step drives the physical board over JTAG. It is **not** run autonomously. +> The claim to verify on silicon is the same as PR #185: stream a batch of the +> committed conformance vectors (`bootstrap/tests/gft_classifier4_vectors.txt`) into +> the fabric and confirm the returned class index is **bit-exact** to the expected +> column — 1500/1500 in simulation, target 1500/1500 on-air. + +## 5. On-silicon conformance (what "done" means) + +The bring-up mirrors the GF-T dot-product silicon proof: +1. Wrap `GftClassifier4` with a UART loader: host sends 16 weights + 4 activations, + fabric returns the 1-byte class index. +2. Host replays `gft_classifier4_vectors.txt` and diffs the returned index. +3. **PASS = every vector's class index matches** — the same doubly-grounded oracle + already green in simulation (`cargo test --test gft_classifier4`). + +Until then the classifier is **proven in simulation (iverilog, 1500/1500 bit-exact), +synthesizable (yosys), and awaiting a supervised bitstream run on the board.** diff --git a/specs/ternary/gft_exp2.t27 b/specs/ternary/gft_exp2.t27 new file mode 100644 index 0000000000..547a2094a9 --- /dev/null +++ b/specs/ternary/gft_exp2.t27 @@ -0,0 +1,67 @@ +module GftExp2; +// #1764 + GF-T: a GF-T exp2 primitive -- 2^x for a signed GF-T16 input x, result +// a positive GF-T16. This is the missing building block for a GF-T softmax +// (softmax(l) = 2^l / sum 2^l, in base-2). Approach, all integer / hardware-shaped: +// 1. |x| -> Q16.16 fixed-point (positive shifts only -> no signed-shift ambiguity). +// 2. split into integer k = floor(x) and fraction f in [0,1) (sign-aware floor). +// 3. 2^x = 2^k * 2^f. 2^k is an exact GF-T offset (k+40); 2^f-1 gives the mantissa +// via a Q16 quartic with rounded Horner shifts (<=1 ULP vs the exact mantissa). +// 4. clamp/saturate the offset to [1,80]; sign is always + (2^x > 0). +// Accuracy: <=1 ULP vs the true round_to_GFT(2^x) over the logit range (measured in +// the prototype). Bit-exact to the committed integer oracle over the vector file. +// +// Input: x signed GF-T16 (u32). Output: 2^x as a positive GF-T16 (u32). + +// mant(f) = round(512*(2^(f/65536) - 1)), f in [0,65536), via a Q16 quartic with +// rounded Horner shifts. Coefficients fit + local-searched to <=1 ULP. +fn pow2_frac(f: i32) -> i32 { + var p : i32 = 6; + p = (((p * f) + 32768) >> 16) + 29; + p = (((p * f) + 32768) >> 16) + 123; + p = (((p * f) + 32768) >> 16) + 354; + p = ((p * f) + 32768) >> 16; + if (p > 511) { p = 511; } + return p; +} + +fn on_comb(x: u32) -> u32 { + if (x == 0) { return 20480; } // 2^0 = +1.0 + var neg : i32 = 0; + if ((x >> 16) == 1) { neg = 1; } // sign bit set -> x is negative + var off_in : i32 = ((x >> 9) & 127) as i32; + var mant_in : i32 = (x & 511) as i32; + // absurd-magnitude guard (keeps intermediates in i32; |x| >= 2^8 -> sat/underflow). + if (off_in >= 48) { + if (neg == 1) { return 512; } // underflow -> smallest normal (2^-39) + return ((80 << 9) | 511) as u32; // saturate -> max magnitude + } + // |x| in Q16.16 (positive shifts only). + var num : i32 = 512 + mant_in; + var sh : i32 = off_in - 33; + var mq : i32 = num; + if (sh >= 0) { mq = num << sh; } else { mq = num >> (0 - sh); } + var ki : i32 = mq >> 16; + var ff : i32 = mq & 65535; + // sign-aware floor: k = floor(x), f = x - k in [0,1). + var k : i32 = ki; + var f : i32 = ff; + if (neg == 1) { + if (ff == 0) { k = 0 - ki; f = 0; } + else { k = 0 - (ki + 1); f = 65536 - ff; } + } + var mant : i32 = pow2_frac(f); + var off : i32 = k + 40; + if (off < 1) { return 512; } // underflow -> smallest normal + if (off > 80) { return ((80 << 9) | 511) as u32; } + return ((off << 9) | mant) as u32; +} + +// 2^0 = 1.0 (0x5000). +test e0 { assert_eq(on_comb(0), 20480); } +// 2^(+1.0) = 2.0 : x=+1.0=0x5000|... actually x encodes the exponent value 1.0 -> 20480. +test e1 { assert_eq(on_comb(20480), 20992); } // 2.0 = offset41 +// 2^(-1.0) = 0.5 = offset39 (0x4e00). +test em1 { assert_eq(on_comb(86016), 19968); } // 0x4e00 +// 2^(+2.0) = 4.0 = offset42 (0x5400). +test e2 { assert_eq(on_comb(20992), 21504); } // 0x5400 +endmodule diff --git a/specs/ternary/gft_layer4.t27 b/specs/ternary/gft_layer4.t27 new file mode 100644 index 0000000000..1b7e95d20f --- /dev/null +++ b/specs/ternary/gft_layer4.t27 @@ -0,0 +1,110 @@ +module GftLayer4; +// #1764 + GF-T: a spec-first BitNet x GF-T LAYER of 4 neurons. +// Four shared real-valued GF-T16 activations (a0..a3) feed four neurons, each +// with its own ternary weight vector {N=0->-1, Z=1->0, P=2->+1}. Every neuron is +// sign(sum_i w_i * a_i) evaluated in signed GF-T (round-to-nearest-even, zero- +// aware) -> a TRIT {N=0,Z=1,P=2}. The three output trits are packed low->high, +// two bits each: result = n0 | (n1<<2) | (n2<<4) | (n3<<6). This is one full BitNet layer +// (M inputs -> N=4 trit outputs); it composes with gft_mlp2's inter-layer re-embed. +// Bit-exact to the ideal oracle over 500 vectors (tests/gft_layer4_vectors.txt). +// +// Weights: trit u8 {N=0,Z=1,P=2}. Activations: signed GF-T16 in u32. +// Output: u32 holding three packed trits (6 bits used). + +fn magadd(a: i32, b: i32) -> i32 { + var ao : i32 = a >> 9; var am : i32 = a & 511; + var bo : i32 = b >> 9; var bm : i32 = b & 511; + var ho : i32 = bo; var hm : i32 = bm; var lo : i32 = ao; var lm : i32 = am; + if (ao >= bo) { ho = ao; hm = am; lo = bo; lm = bm; } + var hs : i32 = 512 + hm; var ls : i32 = 512 + lm; + var d : i32 = ho - lo; if (d > 11) { d = 11; } + var losh : i32 = ls >> d; var rem : i32 = ls - (losh << d); + var s : i32 = hs + losh; var off : i32 = ho; var mant : i32 = s - 512; + if (s >= 1024) { + var g : i32 = s & 1; var pre : i32 = s >> 1; mant = pre - 512; + if (g == 1) { if (rem > 0) { mant = mant + 1; } else { if ((pre & 1) == 1) { mant = mant + 1; } } } + off = ho + 1; if (off >= 80) { off = 80; } + } else { + var t : i32 = rem << 1; var hf : i32 = 1 << d; + if (t > hf) { mant = mant + 1; } else { if (t == hf) { if ((s & 1) == 1) { mant = mant + 1; } } } + } + if (mant >= 512) { mant = 0; off = off + 1; if (off >= 80) { off = 80; } } + return (off << 9) | mant; +} +fn magsub(hi: i32, lo: i32) -> i32 { + if (hi == lo) { return 0; } + var ho : i32 = hi >> 9; var hm : i32 = hi & 511; + var lo_o : i32 = lo >> 9; var lm : i32 = lo & 511; + var d : i32 = ho - lo_o; var hs : i32 = (512 + hm) << 14; + var la : i32 = 0; var sticky : i32 = 0; + if (d >= 26) { la = 0; sticky = 1; } + else { var ls : i32 = (512 + lm) << 14; la = ls >> d; if ((ls - (la << d)) > 0) { sticky = 1; } } + var diff : i32 = hs - la; var off : i32 = ho; + // flat (unrolled) left-normalization -- no loop -> yosys-synthesizable. + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + var q : i32 = diff >> 14; var rem : i32 = diff - (q << 14); var half : i32 = 8192; var mant : i32 = q - 512; + if (rem > half) { mant = mant + 1; } + else { if (rem == half) { if (sticky == 1) { mant = mant + 1; } else { if ((q & 1) == 1) { mant = mant + 1; } } } } + if (mant >= 512) { mant = 0; off = off + 1; if (off >= 80) { off = 80; } } + return (off << 9) | mant; +} +fn sadd(a: u32, b: u32) -> u32 { + if (a == 0) { return b; } + if (b == 0) { return a; } + var sa : i32 = (a >> 16) as i32; var ma : i32 = (a & 65535) as i32; + var sb : i32 = (b >> 16) as i32; var mb : i32 = (b & 65535) as i32; + if (sa == sb) { return ((sa << 16) | magadd(ma, mb)) as u32; } + var bsign : i32 = sa; + var r : i32 = magsub(ma, mb); + if (ma < mb) { r = magsub(mb, ma); bsign = sb; } + if (r == 0) { return 0; } + return ((bsign << 16) | r) as u32; +} +fn contrib(w: u8, a: u32) -> u32 { + if (w == 2) { return a; } + if (a == 0) { return 0; } + if (w == 0) { return a ^ 65536; } + return 0; +} +fn activate(s: u32) -> u8 { + if (s == 0) { return 1; } + if ((s >> 16) == 1) { return 0; } + return 2; +} +// one 4-input neuron: sign(w0*a0 + w1*a1 + w2*a2 + w3*a3) -> trit. +fn neuron4(w0: u8, a0: u32, w1: u8, a1: u32, w2: u8, a2: u32, w3: u8, a3: u32) -> u8 { + var acc : u32 = sadd(sadd(contrib(w0, a0), contrib(w1, a1)), + sadd(contrib(w2, a2), contrib(w3, a3))); + return activate(acc); +} + +// The layer: four neurons over the shared (a0..a3), packed trits out. +fn on_comb(w00: u8, w01: u8, w02: u8, w03: u8, + w10: u8, w11: u8, w12: u8, w13: u8, + w20: u8, w21: u8, w22: u8, w23: u8, + w30: u8, w31: u8, w32: u8, w33: u8, + a0: u32, a1: u32, a2: u32, a3: u32) -> u32 { + var n0 : u8 = neuron4(w00, a0, w01, a1, w02, a2, w03, a3); + var n1 : u8 = neuron4(w10, a0, w11, a1, w12, a2, w13, a3); + var n2 : u8 = neuron4(w20, a0, w21, a1, w22, a2, w23, a3); + var n3 : u8 = neuron4(w30, a0, w31, a1, w32, a2, w33, a3); + return (n0 as u32) | ((n1 as u32) << 2) | ((n2 as u32) << 4) | ((n3 as u32) << 6); +} + +// a=+1.0 x4. n0 +1x4->P(2), n1 -1x4->N(0), n2 +1,-1,+1,-1->Z(1), n3 Zx4->Z(1). +// packed = 2 | (0<<2) | (1<<4) | (1<<6) = 82. +test lanes { assert_eq(on_comb(2,2,2,2, 0,0,0,0, 2,0,2,0, 1,1,1,1, 20480,20480,20480,20480), 82); } +// all weights Z -> every neuron Z(1). packed = 1|1<<2|1<<4|1<<6 = 85. +test all_zero { assert_eq(on_comb(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 20480,20480,20480,20480), 85); } +endmodule diff --git a/specs/ternary/gft_recip.t27 b/specs/ternary/gft_recip.t27 new file mode 100644 index 0000000000..0f4885cbc0 --- /dev/null +++ b/specs/ternary/gft_recip.t27 @@ -0,0 +1,40 @@ +module GftRecip; +// #1764 + GF-T: a GF-T reciprocal primitive -- 1/x for a signed GF-T16 input, +// result a signed GF-T16 (same sign). The last missing building block for a GF-T +// softmax (softmax = 2^l / sum 2^l; the 1/sum step is this reciprocal). +// +// Closed form (no polynomial, EXACT to GF-T rounding): for magnitude +// (1+m/512)*2^(o-40), the reciprocal magnitude is 1/(1+m/512) * 2^-(o-40) = +// 512/(512+m) * 2^(40-o). Writing 512/(512+m) in [0.5,1] as (1+m'/512)*2^-1 with +// (1+m'/512) = 1024/(512+m) in [1,2]: 512+m' = round(524288/(512+m)), +// off' = 79-o (+ renorm if m' overflows). One rounded integer divide. +// +// Input: x signed GF-T16 (u32). Output: 1/x as signed GF-T16 (u32). + +fn on_comb(x: u32) -> u32 { + if (x == 0) { return ((80 << 9) | 511) as u32; } // 1/0 -> saturate (inf-like) + var s : i32 = 0; + if ((x >> 16) == 1) { s = 1; } + var o : i32 = ((x >> 9) & 127) as i32; + var m : i32 = (x & 511) as i32; + var den : i32 = 512 + m; + // rounded divide: round(524288 / den) = (524288 + den/2) / den. + var mp : i32 = (524288 + (den >> 1)) / den - 512; + var off : i32 = 79 - o; + if (mp >= 512) { mp = mp - 512; off = off + 1; } + if (off < 1) { off = 1; mp = 0; } + if (off > 80) { off = 80; mp = 511; } + return ((s << 16) | (off << 9) | mp) as u32; +} + +// 1/1.0 = 1.0 (0x5000). +test r1 { assert_eq(on_comb(20480), 20480); } +// 1/2.0 = 0.5 (offset39 = 0x4e00 = 19968). +test r2 { assert_eq(on_comb(20992), 19968); } +// 1/0.5 = 2.0 (offset41 = 0x5200 = 20992). +test rhalf { assert_eq(on_comb(19968), 20992); } +// 1/-1.0 = -1.0 (sign preserved, 0x15000 = 86016). +test rneg { assert_eq(on_comb(86016), 86016); } +// 1/4.0 = 0.25 (offset38 = 0x4c00 = 19456). +test r4 { assert_eq(on_comb(21504), 19456); } +endmodule diff --git a/specs/ternary/gft_softmax4.t27 b/specs/ternary/gft_softmax4.t27 new file mode 100644 index 0000000000..51a74cafc3 --- /dev/null +++ b/specs/ternary/gft_softmax4.t27 @@ -0,0 +1,182 @@ +module GftSoftmax4; +// #1764 + GF-T: a spec-first GF-T softmax over four signed GF-T16 logits, base-2, +// numerically stabilized by subtracting the max: +// p_i = 2^(l_i - M) / sum_j 2^(l_j - M), M = max_j l_j. +// Returns p_sel as a positive GF-T16. This closes the GF-T classifier head: it +// composes the already-verified primitives -- max (gt), subtract (sadd+neg), +// exp2 (<=1 ULP), sum (sadd), reciprocal (exact), multiply (RNE). Bit-exact to the +// committed integer oracle over 2000 vectors (tests/gft_softmax4_vectors.txt); +// accuracy vs true float softmax is <=0.0017 abs probability (measured). +// +// Inputs: l0..l3 signed GF-T16 (u32); sel u8 in {0,1,2,3}. Output: p_sel GF-T16. + +fn magadd(a: i32, b: i32) -> i32 { + var ao : i32 = a >> 9; var am : i32 = a & 511; + var bo : i32 = b >> 9; var bm : i32 = b & 511; + var ho : i32 = bo; var hm : i32 = bm; var lo : i32 = ao; var lm : i32 = am; + if (ao >= bo) { ho = ao; hm = am; lo = bo; lm = bm; } + var hs : i32 = 512 + hm; var ls : i32 = 512 + lm; + var d : i32 = ho - lo; if (d > 11) { d = 11; } + var losh : i32 = ls >> d; var rem : i32 = ls - (losh << d); + var s : i32 = hs + losh; var off : i32 = ho; var mant : i32 = s - 512; + if (s >= 1024) { + var g : i32 = s & 1; var pre : i32 = s >> 1; mant = pre - 512; + if (g == 1) { if (rem > 0) { mant = mant + 1; } else { if ((pre & 1) == 1) { mant = mant + 1; } } } + off = ho + 1; if (off >= 80) { off = 80; } + } else { + var t : i32 = rem << 1; var hf : i32 = 1 << d; + if (t > hf) { mant = mant + 1; } else { if (t == hf) { if ((s & 1) == 1) { mant = mant + 1; } } } + } + if (mant >= 512) { mant = 0; off = off + 1; if (off >= 80) { off = 80; } } + return (off << 9) | mant; +} +fn magsub(hi: i32, lo: i32) -> i32 { + if (hi == lo) { return 0; } + var ho : i32 = hi >> 9; var hm : i32 = hi & 511; + var lo_o : i32 = lo >> 9; var lm : i32 = lo & 511; + var d : i32 = ho - lo_o; var hs : i32 = (512 + hm) << 14; + var la : i32 = 0; var sticky : i32 = 0; + if (d >= 26) { la = 0; sticky = 1; } + else { var ls : i32 = (512 + lm) << 14; la = ls >> d; if ((ls - (la << d)) > 0) { sticky = 1; } } + var diff : i32 = hs - la; var off : i32 = ho; + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + if (diff < 8388608) { if (off > 1) { diff = diff << 1; off = off - 1; } } + var q : i32 = diff >> 14; var rem : i32 = diff - (q << 14); var half : i32 = 8192; var mant : i32 = q - 512; + if (rem > half) { mant = mant + 1; } + else { if (rem == half) { if (sticky == 1) { mant = mant + 1; } else { if ((q & 1) == 1) { mant = mant + 1; } } } } + if (mant >= 512) { mant = 0; off = off + 1; if (off >= 80) { off = 80; } } + return (off << 9) | mant; +} +fn sadd(a: u32, b: u32) -> u32 { + if (a == 0) { return b; } + if (b == 0) { return a; } + var sa : i32 = (a >> 16) as i32; var ma : i32 = (a & 65535) as i32; + var sb : i32 = (b >> 16) as i32; var mb : i32 = (b & 65535) as i32; + if (sa == sb) { return ((sa << 16) | magadd(ma, mb)) as u32; } + var bsign : i32 = sa; + var r : i32 = magsub(ma, mb); + if (ma < mb) { r = magsub(mb, ma); bsign = sb; } + if (r == 0) { return 0; } + return ((bsign << 16) | r) as u32; +} +fn neg(v: u32) -> u32 { + if (v == 0) { return 0; } + return v ^ 65536; +} +fn category(a: u32) -> u8 { + if (a == 0) { return 1; } + if ((a >> 16) == 1) { return 0; } + return 2; +} +fn gt(a: u32, b: u32) -> u8 { + var ca : u8 = category(a); + var cb : u8 = category(b); + if (ca != cb) { if (ca > cb) { return 1; } return 0; } + var ma : u32 = a & 65535; + var mb : u32 = b & 65535; + if (ca == 2) { if (ma > mb) { return 1; } return 0; } + if (ca == 0) { if (ma < mb) { return 1; } return 0; } + return 0; +} +fn pow2_frac(f: i32) -> i32 { + var p : i32 = 6; + p = (((p * f) + 32768) >> 16) + 29; + p = (((p * f) + 32768) >> 16) + 123; + p = (((p * f) + 32768) >> 16) + 354; + p = ((p * f) + 32768) >> 16; + if (p > 511) { p = 511; } + return p; +} +fn exp2(x: u32) -> u32 { + if (x == 0) { return 20480; } + var ng : i32 = 0; + if ((x >> 16) == 1) { ng = 1; } + var off_in : i32 = ((x >> 9) & 127) as i32; + var mant_in : i32 = (x & 511) as i32; + if (off_in >= 48) { + if (ng == 1) { return 512; } + return ((80 << 9) | 511) as u32; + } + var num : i32 = 512 + mant_in; + var sh : i32 = off_in - 33; + var mq : i32 = num; + if (sh >= 0) { mq = num << sh; } else { mq = num >> (0 - sh); } + var ki : i32 = mq >> 16; + var ff : i32 = mq & 65535; + var k : i32 = ki; + var f : i32 = ff; + if (ng == 1) { + if (ff == 0) { k = 0 - ki; f = 0; } + else { k = 0 - (ki + 1); f = 65536 - ff; } + } + var mant : i32 = pow2_frac(f); + var off : i32 = k + 40; + if (off < 1) { return 512; } + if (off > 80) { return ((80 << 9) | 511) as u32; } + return ((off << 9) | mant) as u32; +} +fn recip(x: u32) -> u32 { + if (x == 0) { return ((80 << 9) | 511) as u32; } + var s : i32 = 0; + if ((x >> 16) == 1) { s = 1; } + var o : i32 = ((x >> 9) & 127) as i32; + var m : i32 = (x & 511) as i32; + var den : i32 = 512 + m; + var mp : i32 = (524288 + (den >> 1)) / den - 512; + var off : i32 = 79 - o; + if (mp >= 512) { mp = mp - 512; off = off + 1; } + if (off < 1) { off = 1; mp = 0; } + if (off > 80) { off = 80; mp = 511; } + return ((s << 16) | (off << 9) | mp) as u32; +} +fn magmul(a16: i32, b16: i32) -> i32 { + var ao : i32 = a16 >> 9; var am : i32 = a16 & 511; + var bo : i32 = b16 >> 9; var bm : i32 = b16 & 511; + var prod : i32 = (512 + am) * (512 + bm); + var carry : i32 = 0; if (prod >= 524288) { carry = 1; } + var q : i32 = prod >> 9; var r : i32 = prod & 511; var half : i32 = 256; + if (carry == 1) { q = prod >> 10; r = prod & 1023; half = 512; } + var mant : i32 = q - 512; + if (r > half) { mant = mant + 1; } + if (r == half) { if ((q & 1) == 1) { mant = mant + 1; } } + var sm : i32 = ao + bo + carry; + var out_off : i32 = 0; + if (sm >= 40) { var res : i32 = sm - 40; if (res >= 80) { out_off = 80; } else { out_off = res; } } + if (mant >= 512) { mant = 0; out_off = out_off + 1; if (out_off >= 80) { out_off = 80; } } + return (out_off << 9) | mant; +} + +// softmax: p_sel = 2^(l_sel - M) / sum_i 2^(l_i - M), M = max logit. +fn on_comb(l0: u32, l1: u32, l2: u32, l3: u32, sel: u8) -> u32 { + var mx : u32 = l0; + if (gt(l1, mx) == 1) { mx = l1; } + if (gt(l2, mx) == 1) { mx = l2; } + if (gt(l3, mx) == 1) { mx = l3; } + var e0 : u32 = exp2(sadd(l0, neg(mx))); + var e1 : u32 = exp2(sadd(l1, neg(mx))); + var e2 : u32 = exp2(sadd(l2, neg(mx))); + var e3 : u32 = exp2(sadd(l3, neg(mx))); + var ssum : u32 = sadd(sadd(e0, e1), sadd(e2, e3)); + var rr : u32 = recip(ssum); + var esel : u32 = e0; + if (sel == 1) { esel = e1; } + if (sel == 2) { esel = e2; } + if (sel == 3) { esel = e3; } + return magmul((esel & 65535) as i32, (rr & 65535) as i32) as u32; +} + +// four equal logits -> uniform 0.25 (offset 38 = 0x4c00 = 19456). +test uniform { assert_eq(on_comb(20480, 20480, 20480, 20480, 0), 19456); } +// a dominant logit: l0=+2.0, others +1.0 -> p0 = 4/(4+3*2) = 0.4 (0x4d33 = 19763). +test dom0 { assert_eq(on_comb(20992, 20480, 20480, 20480, 0), 19763); } +endmodule