diff --git a/Cargo.lock b/Cargo.lock index 326ad3e7..6467c244 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -96,9 +96,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" +checksum = "c1fd03a028ef38ba2276dce7e33fcd6369c158a1bca17946c4b1b701891c1ff7" dependencies = [ "backtrace", ] @@ -168,9 +168,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cargo-zisk" @@ -198,9 +198,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.1" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" dependencies = [ "jobserver", "libc", @@ -248,9 +248,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -258,9 +258,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.21" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -282,9 +282,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" @@ -294,25 +294,25 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "console" -version = "0.15.8" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" dependencies = [ "encode_unicode", - "lazy_static", "libc", - "unicode-width 0.1.14", - "windows-sys 0.52.0", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", ] [[package]] @@ -368,9 +368,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -387,9 +387,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -461,9 +461,9 @@ checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" [[package]] name = "encode_unicode" -version = "0.3.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "env_filter" @@ -496,19 +496,42 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "executor" +version = "0.1.0" +dependencies = [ + "log", + "p3-field", + "pil-std-lib", + "proofman-common", + "proofman-util", + "rayon", + "sm-arith", + "sm-binary", + "sm-common", + "sm-main", + "sm-mem", + "sm-rom", + "witness", + "zisk-common", + "zisk-core", + "zisk-pil", + "ziskemu", ] [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "findshlibs" @@ -682,9 +705,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -692,12 +715,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "hermit-abi" version = "0.4.0" @@ -706,9 +723,9 @@ checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -947,9 +964,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -965,7 +982,7 @@ dependencies = [ "console", "number_prefix", "portable-atomic", - "unicode-width 0.2.0", + "unicode-width", "web-time", ] @@ -999,7 +1016,7 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi 0.4.0", + "hermit-abi", "libc", "windows-sys 0.52.0", ] @@ -1039,9 +1056,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a73e9fe3c49d7afb2ace819fa181a287ce54a0983eda4e0eb05c22f82ffe534" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jobserver" @@ -1054,10 +1071,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1075,9 +1093,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.164" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libgit2-sys" @@ -1093,9 +1111,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -1131,9 +1149,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "lock_api" @@ -1183,11 +1201,10 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", @@ -1467,7 +1484,7 @@ dependencies = [ [[package]] name = "pil-std-lib" version = "0.1.0" -source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?rev=0.0.10#cb182461a9e8dc4077be76b81733b5384d640a21" +source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?branch=feature%2Fminor_clean#c21166b075d6cbaf93cd8fe81820e35af66847a2" dependencies = [ "log", "num-bigint", @@ -1475,17 +1492,17 @@ dependencies = [ "p3-field", "p3-goldilocks", "pilout", - "proofman", "proofman-common", "proofman-hints", "proofman-util", "rayon", + "witness", ] [[package]] name = "pilout" version = "0.1.0" -source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?rev=0.0.10#cb182461a9e8dc4077be76b81733b5384d640a21" +source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?branch=feature%2Fminor_clean#c21166b075d6cbaf93cd8fe81820e35af66847a2" dependencies = [ "bytes", "log", @@ -1542,9 +1559,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" [[package]] name = "powerfmt" @@ -1595,42 +1612,22 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] -[[package]] -name = "proofman" -version = "0.1.0" -source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?rev=0.0.10#cb182461a9e8dc4077be76b81733b5384d640a21" -dependencies = [ - "colored", - "env_logger", - "libloading", - "log", - "p3-field", - "p3-goldilocks", - "pilout", - "proofman-common", - "proofman-hints", - "proofman-starks-lib-c", - "proofman-util", - "serde_json", - "stark", - "transcript", -] - [[package]] name = "proofman-common" version = "0.1.0" -source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?rev=0.0.10#cb182461a9e8dc4077be76b81733b5384d640a21" +source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?branch=feature%2Fminor_clean#c21166b075d6cbaf93cd8fe81820e35af66847a2" dependencies = [ "env_logger", "log", "p3-field", + "p3-goldilocks", "pilout", "proofman-macros", "proofman-starks-lib-c", @@ -1644,8 +1641,9 @@ dependencies = [ [[package]] name = "proofman-hints" version = "0.1.0" -source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?rev=0.0.10#cb182461a9e8dc4077be76b81733b5384d640a21" +source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?branch=feature%2Fminor_clean#c21166b075d6cbaf93cd8fe81820e35af66847a2" dependencies = [ + "log", "p3-field", "proofman-common", "proofman-starks-lib-c", @@ -1654,7 +1652,7 @@ dependencies = [ [[package]] name = "proofman-macros" version = "0.1.0" -source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?rev=0.0.10#cb182461a9e8dc4077be76b81733b5384d640a21" +source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?branch=feature%2Fminor_clean#c21166b075d6cbaf93cd8fe81820e35af66847a2" dependencies = [ "proc-macro2", "quote", @@ -1664,7 +1662,7 @@ dependencies = [ [[package]] name = "proofman-starks-lib-c" version = "0.1.0" -source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?rev=0.0.10#cb182461a9e8dc4077be76b81733b5384d640a21" +source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?branch=feature%2Fminor_clean#c21166b075d6cbaf93cd8fe81820e35af66847a2" dependencies = [ "log", ] @@ -1672,7 +1670,7 @@ dependencies = [ [[package]] name = "proofman-util" version = "0.1.0" -source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?rev=0.0.10#cb182461a9e8dc4077be76b81733b5384d640a21" +source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?branch=feature%2Fminor_clean#c21166b075d6cbaf93cd8fe81820e35af66847a2" dependencies = [ "colored", "sysinfo 0.31.4", @@ -1680,9 +1678,9 @@ dependencies = [ [[package]] name = "prost" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0487d90e047de87f984913713b85c601c05609aad5b0df4b4573fbf69aa13f" +checksum = "2c0fef6c4230e4ccf618a35c59d7ede15dea37de8427500f50aff708806e42ec" dependencies = [ "bytes", "prost-derive", @@ -1690,11 +1688,10 @@ dependencies = [ [[package]] name = "prost-build" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" +checksum = "d0f3e5beed80eb580c68e2c600937ac2c4eedabdfd5ef1e5b7ea4f3fba84497b" dependencies = [ - "bytes", "heck", "itertools 0.13.0", "log", @@ -1711,9 +1708,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9552f850d5f0964a4e4d0bf306459ac29323ddfbae05e35a7c0d35cb0803cc5" +checksum = "157c5a9d7ea5c2ed2d9fb8f495b64759f7816c7eaea54ba3978f0d63000162e3" dependencies = [ "anyhow", "itertools 0.13.0", @@ -1724,9 +1721,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4759aa0d3a6232fb8dbdb97b61de2c20047c68aca932c7ed76da9d788508d670" +checksum = "cc2f1e56baa61e93533aebc21af4d2134b70f66275e0fcdf3cbe43d77ff7e8fc" dependencies = [ "prost", ] @@ -1753,7 +1750,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.3", + "thiserror 2.0.7", "tokio", "tracing", ] @@ -1772,7 +1769,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.3", + "thiserror 2.0.7", "tinyvec", "tracing", "web-time", @@ -1780,9 +1777,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" +checksum = "52cd4b1eff68bf27940dd39811292c49e007f4d0b4c357358dc9b0197be6b527" dependencies = [ "cfg_aliases", "libc", @@ -1853,9 +1850,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -1987,9 +1984,10 @@ dependencies = [ "p3-field", "p3-goldilocks", "proofman-common", + "proofman-util", "sm-rom", - "stark", - "sysinfo 0.32.0", + "sysinfo 0.32.1", + "zisk-pil", ] [[package]] @@ -2000,28 +1998,28 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "rustls" -version = "0.23.17" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f1a745511c54ba6d4465e8d5dfbd81b45791756de28d4981af70d6dca128f1e" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "once_cell", "ring", @@ -2042,9 +2040,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" dependencies = [ "web-time", ] @@ -2089,18 +2087,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -2164,14 +2162,15 @@ dependencies = [ "num-bigint", "p3-field", "pil-std-lib", - "proofman", "proofman-common", "proofman-macros", "proofman-util", "rayon", "sm-common", + "zisk-common", "zisk-core", "zisk-pil", + "ziskemu", ] [[package]] @@ -2182,48 +2181,36 @@ dependencies = [ "num-bigint", "p3-field", "pil-std-lib", - "proofman", "proofman-common", "proofman-macros", "proofman-util", "rayon", "sm-common", + "zisk-common", "zisk-core", "zisk-pil", + "ziskemu", ] [[package]] name = "sm-common" version = "0.1.0" dependencies = [ + "p3-field", "proofman-common", "proofman-util", "rayon", + "zisk-common", "zisk-core", "ziskemu", ] -[[package]] -name = "sm-freq-ops" -version = "0.1.0" -dependencies = [ - "log", - "p3-field", - "proofman", - "proofman-common", - "proofman-macros", - "rayon", - "sm-common", - "zisk-core", -] - [[package]] name = "sm-main" version = "0.1.0" dependencies = [ "log", "p3-field", - "proofman", "proofman-common", "proofman-util", "rayon", @@ -2243,43 +2230,47 @@ version = "0.1.0" dependencies = [ "log", "p3-field", - "proofman", "proofman-common", "proofman-macros", "rayon", "sm-common", + "witness", "zisk-core", "zisk-pil", ] [[package]] -name = "sm-quick-ops" +name = "sm-rom" version = "0.1.0" dependencies = [ + "itertools 0.13.0", "log", "p3-field", - "proofman", "proofman-common", "proofman-macros", + "proofman-util", "rayon", "sm-common", + "zisk-common", "zisk-core", "zisk-pil", + "ziskemu", ] [[package]] -name = "sm-rom" +name = "sm-std" version = "0.1.0" dependencies = [ "itertools 0.13.0", "log", "p3-field", - "proofman", + "pil-std-lib", "proofman-common", "proofman-macros", "proofman-util", "rayon", "sm-common", + "zisk-common", "zisk-core", "zisk-pil", "ziskemu", @@ -2293,9 +2284,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", @@ -2313,24 +2304,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" -[[package]] -name = "stark" -version = "0.1.0" -source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?rev=0.0.10#cb182461a9e8dc4077be76b81733b5384d640a21" -dependencies = [ - "log", - "p3-field", - "p3-goldilocks", - "proofman-common", - "proofman-hints", - "proofman-starks-lib-c", - "proofman-util", - "serde", - "serde_derive", - "serde_json", - "transcript", -] - [[package]] name = "str_stack" version = "0.1.0" @@ -2357,9 +2330,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "symbolic-common" -version = "12.12.1" +version = "12.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4d73159efebfb389d819fd479afb2dbd57dcb3e3f4b7fcfa0e675f5a46c1cb" +checksum = "e5ba5365997a4e375660bed52f5b42766475d5bc8ceb1bb13fea09c469ea0f49" dependencies = [ "debugid", "memmap2", @@ -2369,9 +2342,9 @@ dependencies = [ [[package]] name = "symbolic-demangle" -version = "12.12.1" +version = "12.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a767859f6549c665011970874c3f541838b4835d5aaaa493d3ee383918be9f10" +checksum = "beff338b2788519120f38c59ff4bb15174f52a183e547bac3d6072c2c0aa48aa" dependencies = [ "cpp_demangle", "rustc-demangle", @@ -2380,9 +2353,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -2391,9 +2364,9 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] @@ -2425,9 +2398,23 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.32.0" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c33cd241af0f2e9e3b5c32163b873b29956890b5342e6745b917ce9d490f4af" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "rayon", + "windows", +] + +[[package]] +name = "sysinfo" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ae3f4f7d64646c46c4cae4e3f01d1c5d255c7406fdd7c7f999a94e488791" +checksum = "948512566b1895f93b1592c7574baeb2de842f224f2aab158799ecadb8ebbb46" dependencies = [ "core-foundation-sys", "libc", @@ -2467,11 +2454,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.3" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" dependencies = [ - "thiserror-impl 2.0.3", + "thiserror-impl 2.0.7", ] [[package]] @@ -2487,9 +2474,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.3" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" dependencies = [ "proc-macro2", "quote", @@ -2498,9 +2485,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -2521,9 +2508,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -2575,9 +2562,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.1" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", @@ -2604,20 +2591,19 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ "rustls", - "rustls-pki-types", "tokio", ] [[package]] name = "tokio-util" -version = "0.7.12" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -2634,9 +2620,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -2645,9 +2631,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -2656,9 +2642,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] @@ -2666,7 +2652,7 @@ dependencies = [ [[package]] name = "transcript" version = "0.1.0" -source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?rev=0.0.10#cb182461a9e8dc4077be76b81733b5384d640a21" +source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?branch=feature%2Fminor_clean#c21166b075d6cbaf93cd8fe81820e35af66847a2" dependencies = [ "proofman-starks-lib-c", ] @@ -2693,12 +2679,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "unicode-width" version = "0.2.0" @@ -2713,9 +2693,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.3" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", @@ -2798,9 +2778,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -2809,13 +2789,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -2824,21 +2803,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2846,9 +2826,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", @@ -2859,9 +2839,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wasm-streams" @@ -2878,9 +2858,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -2898,9 +2878,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.6" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] @@ -3167,6 +3147,22 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "witness" +version = "0.1.0" +source = "git+https://github.com/0xPolygonHermez/pil2-proofman.git?branch=feature%2Fminor_clean#c21166b075d6cbaf93cd8fe81820e35af66847a2" +dependencies = [ + "colored", + "env_logger", + "libloading", + "log", + "p3-field", + "p3-goldilocks", + "proofman-common", + "proofman-util", + "serde_json", +] + [[package]] name = "write16" version = "1.0.0" @@ -3187,9 +3183,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -3199,9 +3195,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", @@ -3232,18 +3228,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", @@ -3279,6 +3275,13 @@ dependencies = [ "syn", ] +[[package]] +name = "zisk-common" +version = "0.1.0" +dependencies = [ + "zisk-core", +] + [[package]] name = "zisk-core" version = "0.1.0" @@ -3296,9 +3299,9 @@ dependencies = [ name = "zisk-pil" version = "0.1.0" dependencies = [ - "proofman", "proofman-common", "proofman-macros", + "serde", ] [[package]] @@ -3306,22 +3309,22 @@ name = "zisk-witness" version = "0.1.0" dependencies = [ "env_logger", + "executor", "log", "p3-field", "p3-goldilocks", "pil-std-lib", - "proofman", "proofman-common", "proofman-util", "rayon", "sm-arith", "sm-binary", "sm-common", - "sm-freq-ops", "sm-main", "sm-mem", - "sm-quick-ops", "sm-rom", + "sm-std", + "witness", "zisk-core", "zisk-pil", "ziskemu", @@ -3337,8 +3340,9 @@ dependencies = [ "pprof", "rayon", "riscv", - "sysinfo 0.31.4", + "sysinfo 0.33.0", "vergen", + "zisk-common", "zisk-core", "zisk-pil", ] diff --git a/Cargo.toml b/Cargo.toml index b97f5cb2..81319f42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,18 +1,18 @@ [workspace] members = [ - "cli", + "cli", "common", "core", - "emulator", + "emulator", "executor", "pil", "riscv", "rom-merkle", "state-machines/arith", "state-machines/binary", "state-machines/common", - "state-machines/freq-ops", "state-machines/main", "state-machines/mem", "state-machines/rom", + "state-machines/std", "witness-computation", "ziskos/entrypoint", ] @@ -26,19 +26,17 @@ opt-level = 3 opt-level = 3 [workspace.dependencies] -proofman-common = { git = "https://github.com/0xPolygonHermez/pil2-proofman.git", rev = "0.0.10" } -proofman-macros = { git = "https://github.com/0xPolygonHermez/pil2-proofman.git", rev = "0.0.10" } -proofman-util = { git = "https://github.com/0xPolygonHermez/pil2-proofman.git", rev = "0.0.10" } -proofman = { git = "https://github.com/0xPolygonHermez/pil2-proofman.git", rev = "0.0.10" } -pil-std-lib = { git = "https://github.com/0xPolygonHermez/pil2-proofman.git", rev = "0.0.10" } -stark = { git = "https://github.com/0xPolygonHermez/pil2-proofman.git", rev = "0.0.10" } +proofman-common = { git = "https://github.com/0xPolygonHermez/pil2-proofman.git", branch = "feature/minor_clean" } +proofman-macros = { git = "https://github.com/0xPolygonHermez/pil2-proofman.git", branch = "feature/minor_clean" } +proofman-util = { git = "https://github.com/0xPolygonHermez/pil2-proofman.git", branch = "feature/minor_clean" } +pil-std-lib = { git = "https://github.com/0xPolygonHermez/pil2-proofman.git", branch = "feature/minor_clean" } +witness = { git = "https://github.com/0xPolygonHermez/pil2-proofman.git", branch = "feature/minor_clean" } # Local development # proofman-common = { path = "../pil2-proofman/common" } # proofman-macros = { path = "../pil2-proofman/macros" } # proofman-util = { path = "../pil2-proofman/util" } -# proofman = { path = "../pil2-proofman/proofman" } # pil-std-lib = { path = "../pil2-proofman/pil2-components/lib/std/rs" } -# stark = { path = "../pil2-proofman/provers/stark" } +# witness = { path = "../pil2-proofman/witness" } p3-field = { git = "https://github.com/Plonky3/Plonky3.git", rev = "c3d754ef77b9fce585b46b972af751fe6e7a9803" } log = "0.4" diff --git a/book/getting_started/quickstart_dev.md b/book/getting_started/quickstart_dev.md index dfa921e9..68f620a1 100644 --- a/book/getting_started/quickstart_dev.md +++ b/book/getting_started/quickstart_dev.md @@ -127,7 +127,7 @@ Run this whenever the `.pilout` file changes: ### Generate Setup Data Run this whenever the `.pilout` file changes: -```bash +```bash[] node --max-old-space-size=65536 ../pil2-proofman-js/src/main_setup.js -a pil/zisk.pilout -b build -t ../pil2-proofman/pil2-stark/build/bctree ``` diff --git a/common/Cargo.toml b/common/Cargo.toml new file mode 100644 index 00000000..9de5ae8e --- /dev/null +++ b/common/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "zisk-common" +version = "0.1.0" +edition = "2021" + +[dependencies] +zisk-core = { path = "../core" } diff --git a/common/src/inst_observer.rs b/common/src/inst_observer.rs new file mode 100644 index 00000000..b0577c16 --- /dev/null +++ b/common/src/inst_observer.rs @@ -0,0 +1,5 @@ +use zisk_core::{InstContext, ZiskInst}; + +pub trait InstObserver { + fn on_instruction(&mut self, inst: &ZiskInst, inst_ctx: &InstContext) -> bool; +} diff --git a/common/src/lib.rs b/common/src/lib.rs new file mode 100644 index 00000000..9dab1ea3 --- /dev/null +++ b/common/src/lib.rs @@ -0,0 +1,3 @@ +mod inst_observer; + +pub use inst_observer::*; diff --git a/core/src/inst_context.rs b/core/src/inst_context.rs index 82c1cb98..91a13aaf 100644 --- a/core/src/inst_context.rs +++ b/core/src/inst_context.rs @@ -34,6 +34,7 @@ pub struct InstContext { /// End flag, set to true only by the last instruction to execute pub end: bool, + pub regs: [u64; 32], } /// RisK instruction context implementation @@ -50,6 +51,7 @@ impl InstContext { pc: ROM_ENTRY, step: 0, end: false, + regs: [0; 32], } } diff --git a/core/src/mem.rs b/core/src/mem.rs index f5febf93..cf09fa6a 100644 --- a/core/src/mem.rs +++ b/core/src/mem.rs @@ -79,6 +79,8 @@ //! * The third RW memory region going from `AVAILABLE_MEM_ADDR` onwards can be used during the //! program execution a general purpose memory. +use crate::{REG_FIRST, REG_LAST}; + /// Fist input data memory address pub const INPUT_ADDR: u64 = 0x90000000; /// Maximum size of the input data @@ -203,7 +205,9 @@ impl Mem { /// address and width #[inline(always)] pub fn read(&self, addr: u64, width: u64) -> u64 { - // First try to read from the write section + debug_assert!(!Mem::address_is_register(addr)); + + // First try to read in the write section if (addr >= self.write_section.start) && (addr <= (self.write_section.end - width)) { // Calculate the read position let read_position: usize = (addr - self.write_section.start) as usize; @@ -265,6 +269,8 @@ impl Mem { /// Write a u64 value to the memory write section, based on the provided address and width #[inline(always)] pub fn write(&mut self, addr: u64, val: u64, width: u64) { + debug_assert!(!Mem::address_is_register(addr)); + // Call write_silent to perform the real work self.write_silent(addr, val, width); @@ -277,6 +283,8 @@ impl Mem { /// Write a u64 value to the memory write section, based on the provided address and width #[inline(always)] pub fn write_silent(&mut self, addr: u64, val: u64, width: u64) { + debug_assert!(!Mem::address_is_register(addr)); + //println!("Mem::write() addr={:x}={} width={} value={:x}={}", addr, addr, width, val, // val); @@ -306,4 +314,15 @@ impl Mem { _ => panic!("Mem::write_silent() invalid width={}", width), } } + + #[inline(always)] + pub fn address_is_register(address: u64) -> bool { + ((address & 0x7) == 0) && (REG_FIRST..=REG_LAST).contains(&address) + } + + #[inline(always)] + pub fn address_to_register_index(address: u64) -> usize { + debug_assert!(Mem::address_is_register(address)); + ((address - REG_FIRST) >> 3) as usize + } } diff --git a/core/src/zisk_inst.rs b/core/src/zisk_inst.rs index 885add48..be6e575c 100644 --- a/core/src/zisk_inst.rs +++ b/core/src/zisk_inst.rs @@ -61,7 +61,7 @@ pub const STORE_IND: u64 = 2; /// Internal operations are proven as part of the main state machine itself, given their /// simplicity. External operations (rest of types) are proven in their corresponding secondary /// state machine. -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd)] #[repr(u32)] pub enum ZiskOperationType { None, @@ -73,11 +73,9 @@ pub enum ZiskOperationType { PubOut, } -/// Defines the length of the enumerated ZiskOperationType, required to build some structures to -/// store data splitted by operation type. -pub const ZISK_OPERATION_TYPE_VARIANTS: usize = 7; +pub const ZISK_OP_TYPE_COUNT: usize = 7; -/// Zisk instruction structure. +/// ZisK instruction definition /// /// ZisK instructions are defined as a binary operation with 2 results: op(a, b) -> (c, flag) /// a, b and c are u64 registers; flag is a boolean. @@ -157,7 +155,7 @@ impl ZiskInst { pub fn to_text(&self) -> String { let mut s = String::new(); if self.paddr != 0 { - s += &(" paddr=".to_string() + &self.paddr.to_string()); + s += &format!(" paddr=0x{:x}", self.paddr); } if self.store_ra { s += &(" store_ra=".to_string() + &self.store_ra.to_string()); @@ -169,7 +167,7 @@ impl ZiskInst { s += &format!(" store={}={}", self.store, store_to_str(self.store)); } if self.store_offset != 0 { - s += &(" store_offset=".to_string() + &self.store_offset.to_string()); + s += &format!(" store_offset=0x{:x}", self.store_offset); } if self.set_pc { s += &(" set_pc=".to_string() + &self.set_pc.to_string()); @@ -192,19 +190,19 @@ impl ZiskInst { s += &format!(" a_src={}={}", self.a_src, source_to_str(self.a_src)); } if self.a_use_sp_imm1 != 0 { - s += &(" a_use_sp_imm1=".to_string() + &self.a_use_sp_imm1.to_string()); + s += &format!(" a_use_sp_imm1=0x{:x}", self.a_use_sp_imm1); } if self.a_offset_imm0 != 0 { - s += &(" a_offset_imm0=".to_string() + &self.a_offset_imm0.to_string()); + s += &format!(" a_offset_imm0=0x{:x}", self.a_offset_imm0); } if self.b_src != 0 { s += &format!(" b_src={}={}", self.b_src, source_to_str(self.b_src)); } if self.b_use_sp_imm1 != 0 { - s += &(" b_use_sp_imm1=".to_string() + &self.b_use_sp_imm1.to_string()); + s += &format!(" b_use_sp_imm1=0x{:x}", self.b_use_sp_imm1); } if self.b_offset_imm0 != 0 { - s += &(" b_offset_imm0=".to_string() + &self.b_offset_imm0.to_string()); + s += &format!(" b_offset_imm0=0x{:x}", self.b_offset_imm0); } if self.jmp_offset1 != 0 { s += &(" jmp_offset1=".to_string() + &self.jmp_offset1.to_string()); diff --git a/core/src/zisk_required_operation.rs b/core/src/zisk_required_operation.rs index d82644da..11ba5be2 100644 --- a/core/src/zisk_required_operation.rs +++ b/core/src/zisk_required_operation.rs @@ -1,7 +1,5 @@ //! Data required to prove the different Zisk operations -use std::collections::HashMap; - /// Required data to make an operation. /// /// Stores the minimum information to reproduce an operation execution: @@ -27,23 +25,3 @@ pub struct ZiskRequiredMemory { pub width: u64, pub value: u64, } - -/// Data required to get some operations proven by the secondary state machine -#[derive(Clone, Default)] -pub struct ZiskRequired { - pub arith: Vec, - pub binary: Vec, - pub binary_extension: Vec, - pub memory: Vec, -} - -/// Histogram of the program counter values used during the program execution. -/// -/// Each pc value has a u64 counter, associated to it via a hash map. -/// The counter is increased every time the corresponding instruction is executed. -#[derive(Clone, Default)] -pub struct ZiskPcHistogram { - pub map: HashMap, - pub end_pc: u64, - pub steps: u64, -} diff --git a/emulator/Cargo.toml b/emulator/Cargo.toml index 3673d9f2..69feffb9 100644 --- a/emulator/Cargo.toml +++ b/emulator/Cargo.toml @@ -15,11 +15,12 @@ path = "src/bin/ziskemu.rs" zisk-core = { path = "../core" } riscv = { path="../riscv" } zisk-pil = { path="../pil" } +zisk-common = { path="../common" } rayon = { workspace = true } p3-field = { workspace=true } clap = { version = "4.5.9", features = ["derive", "env"] } -sysinfo = "0.31.2" +sysinfo = "0.33" [build-dependencies] vergen = { version = "8", default-features = false, features = [ diff --git a/emulator/src/emu.rs b/emulator/src/emu.rs index a5f78a6a..4b7c630b 100644 --- a/emulator/src/emu.rs +++ b/emulator/src/emu.rs @@ -1,17 +1,17 @@ use std::mem; use crate::{ - EmuContext, EmuFullTraceStep, EmuOptions, EmuStartingPoints, EmuTrace, EmuTraceEnd, - EmuTraceStart, EmuTraceStep, ParEmuOptions, + EmuContext, EmuFullTraceStep, EmuOptions, EmuTrace, EmuTraceEnd, EmuTraceStart, EmuTraceSteps, + ParEmuOptions, }; use p3_field::{AbstractField, PrimeField}; use riscv::RiscVRegisters; +use zisk_common::InstObserver; // #[cfg(feature = "sp")] // use zisk_core::SRC_SP; use zisk_core::{ - InstContext, ZiskInst, ZiskOperationType, ZiskPcHistogram, ZiskRequiredOperation, ZiskRom, - OUTPUT_ADDR, ROM_ENTRY, SRC_C, SRC_IMM, SRC_IND, SRC_MEM, SRC_STEP, STORE_IND, STORE_MEM, - STORE_NONE, SYS_ADDR, ZISK_OPERATION_TYPE_VARIANTS, + InstContext, Mem, ZiskInst, ZiskOperationType, ZiskRom, OUTPUT_ADDR, ROM_ENTRY, SRC_C, SRC_IMM, + SRC_IND, SRC_MEM, SRC_STEP, STORE_IND, STORE_MEM, STORE_NONE, }; /// ZisK emulator structure, containing the ZisK rom, the list of ZisK operations, and the @@ -42,6 +42,7 @@ impl<'a> Emu<'a> { emu.ctx.inst_ctx.sp = trace_start.sp; emu.ctx.inst_ctx.step = trace_start.step; emu.ctx.inst_ctx.c = trace_start.c; + emu.ctx.inst_ctx.regs = trace_start.regs; emu } @@ -70,11 +71,125 @@ impl<'a> Emu<'a> { match instruction.a_src { SRC_C => self.ctx.inst_ctx.a = self.ctx.inst_ctx.c, SRC_MEM => { + // Calculate memory address + let mut address = instruction.a_offset_imm0; + if instruction.a_use_sp_imm1 != 0 { + address += self.ctx.inst_ctx.sp; + } + + // If the operation is a register operation, get it from the context registers + if Mem::address_is_register(address) { + self.ctx.inst_ctx.a = self.get_reg(Mem::address_to_register_index(address)); + } + // Otherwise, get it from memory + else { + self.ctx.inst_ctx.a = self.ctx.inst_ctx.mem.read(address, 8); + self.ctx.trace.steps.mem_reads.push(self.ctx.inst_ctx.a); + } + + // Feed the stats + if self.ctx.do_stats { + self.ctx.stats.on_memory_read(address, 8); + } + } + SRC_IMM => { + self.ctx.inst_ctx.a = instruction.a_offset_imm0 | (instruction.a_use_sp_imm1 << 32) + } + SRC_STEP => self.ctx.inst_ctx.a = self.ctx.inst_ctx.step, + // #[cfg(feature = "sp")] + // SRC_SP => self.ctx.inst_ctx.a = self.ctx.inst_ctx.sp, + _ => panic!( + "Emu::source_a() Invalid a_src={} pc={}", + instruction.a_src, self.ctx.inst_ctx.pc + ), + } + } + + /// Calculate the 'a' register value based on the source specified by the current instruction + /// and generate memory reads data + #[inline(always)] + pub fn source_a_mem_reads_generate( + &mut self, + instruction: &ZiskInst, + mem_reads: &mut Vec, + _mem_reads_index: &mut usize, + ) { + match instruction.a_src { + SRC_C => self.ctx.inst_ctx.a = self.ctx.inst_ctx.c, + SRC_MEM => { + // Calculate memory address + let mut address = instruction.a_offset_imm0; + if instruction.a_use_sp_imm1 != 0 { + address += self.ctx.inst_ctx.sp; + } + + // If the operation is a register operation, get it from the context registers + if Mem::address_is_register(address) { + self.ctx.inst_ctx.a = self.get_reg(Mem::address_to_register_index(address)); + } + // Otherwise, get it from memory + else { + self.ctx.inst_ctx.a = self.ctx.inst_ctx.mem.read(address, 8); + mem_reads.push(self.ctx.inst_ctx.a); + /*println!( + "Emu::source_a_mem_reads_generate() mem_leads.len={} value={:x}", + mem_reads.len(), + self.ctx.inst_ctx.a + );*/ + } + + // Feed the stats + if self.ctx.do_stats { + self.ctx.stats.on_memory_read(address, 8); + } + } + SRC_IMM => { + self.ctx.inst_ctx.a = instruction.a_offset_imm0 | (instruction.a_use_sp_imm1 << 32) + } + SRC_STEP => self.ctx.inst_ctx.a = self.ctx.inst_ctx.step, + // #[cfg(feature = "sp")] + // SRC_SP => self.ctx.inst_ctx.a = self.ctx.inst_ctx.sp, + _ => panic!( + "Emu::source_a_mem_reads_generate() Invalid a_src={} pc={}", + instruction.a_src, self.ctx.inst_ctx.pc + ), + } + } + + /// Calculate the 'a' register value based on the source specified by the current instruction, + /// using formerly generated memory reads from a previous emulation + #[inline(always)] + pub fn source_a_mem_reads_consume( + &mut self, + instruction: &ZiskInst, + mem_reads: &[u64], + mem_reads_index: &mut usize, + ) { + match instruction.a_src { + SRC_C => self.ctx.inst_ctx.a = self.ctx.inst_ctx.c, + SRC_MEM => { + // Calculate memory address let mut addr = instruction.a_offset_imm0; if instruction.a_use_sp_imm1 != 0 { addr += self.ctx.inst_ctx.sp; } - self.ctx.inst_ctx.a = self.ctx.inst_ctx.mem.read(addr, 8); + + // If the operation is a register operation, get it from the context registers + if Mem::address_is_register(addr) { + self.ctx.inst_ctx.a = self.get_reg(Mem::address_to_register_index(addr)); + } + // Otherwise, get it from memory + else { + assert!(*mem_reads_index < mem_reads.len()); + self.ctx.inst_ctx.a = mem_reads[*mem_reads_index]; + /*println!( + "Emu::source_a_mem_reads_consume() mem_leads_index={} value={:x}", + *mem_reads_index, self.ctx.inst_ctx.a + );*/ + *mem_reads_index += 1; + } + + // Feed the stats if self.ctx.do_stats { self.ctx.stats.on_memory_read(addr, 8); } @@ -86,7 +201,7 @@ impl<'a> Emu<'a> { // #[cfg(feature = "sp")] // SRC_SP => self.ctx.inst_ctx.a = self.ctx.inst_ctx.sp, _ => panic!( - "Emu::source_a() Invalid a_src={} pc={}", + "Emu::source_a_mem_reads_consume() Invalid a_src={} pc={}", instruction.a_src, self.ctx.inst_ctx.pc ), } @@ -98,11 +213,21 @@ impl<'a> Emu<'a> { match instruction.b_src { SRC_C => self.ctx.inst_ctx.b = self.ctx.inst_ctx.c, SRC_MEM => { + // Calculate memory address let mut addr = instruction.b_offset_imm0; if instruction.b_use_sp_imm1 != 0 { addr += self.ctx.inst_ctx.sp; } - self.ctx.inst_ctx.b = self.ctx.inst_ctx.mem.read(addr, 8); + + // If the operation is a register operation, get it from the context registers + if Mem::address_is_register(addr) { + self.ctx.inst_ctx.b = self.get_reg(Mem::address_to_register_index(addr)); + } + // Otherwise, get it from memory + else { + self.ctx.inst_ctx.b = self.ctx.inst_ctx.mem.read(addr, 8); + self.ctx.trace.steps.mem_reads.push(self.ctx.inst_ctx.b); + } if self.ctx.do_stats { self.ctx.stats.on_memory_read(addr, 8); } @@ -111,12 +236,22 @@ impl<'a> Emu<'a> { self.ctx.inst_ctx.b = instruction.b_offset_imm0 | (instruction.b_use_sp_imm1 << 32) } SRC_IND => { + // Calculate memory address let mut addr = (self.ctx.inst_ctx.a as i64 + instruction.b_offset_imm0 as i64) as u64; if instruction.b_use_sp_imm1 != 0 { addr += self.ctx.inst_ctx.sp; } - self.ctx.inst_ctx.b = self.ctx.inst_ctx.mem.read(addr, instruction.ind_width); + + // If the operation is a register operation, get it from the context registers + if Mem::address_is_register(addr) { + self.ctx.inst_ctx.b = self.get_reg(Mem::address_to_register_index(addr)); + } + // Otherwise, get it from memory + else { + self.ctx.inst_ctx.b = self.ctx.inst_ctx.mem.read(addr, instruction.ind_width); + self.ctx.trace.steps.mem_reads.push(self.ctx.inst_ctx.b); + } if self.ctx.do_stats { self.ctx.stats.on_memory_read(addr, instruction.ind_width); } @@ -128,40 +263,211 @@ impl<'a> Emu<'a> { } } + /// Calculate the 'b' register value based on the source specified by the current instruction + #[inline(always)] + pub fn source_b_mem_reads_generate( + &mut self, + instruction: &ZiskInst, + mem_reads: &mut Vec, + _mem_reads_index: &mut usize, + ) { + match instruction.b_src { + SRC_C => self.ctx.inst_ctx.b = self.ctx.inst_ctx.c, + SRC_MEM => { + // Calculate memory address + let mut addr = instruction.b_offset_imm0; + if instruction.b_use_sp_imm1 != 0 { + addr += self.ctx.inst_ctx.sp; + } + + // If the operation is a register operation, get it from the context registers + if Mem::address_is_register(addr) { + self.ctx.inst_ctx.b = self.get_reg(Mem::address_to_register_index(addr)); + } + // Otherwise, get it from memory + else { + self.ctx.inst_ctx.b = self.ctx.inst_ctx.mem.read(addr, 8); + mem_reads.push(self.ctx.inst_ctx.b); + /*println!( + "Emu::source_b_mem_reads_generate() mem_leads.len={} value={:x}", + mem_reads.len(), + self.ctx.inst_ctx.b + );*/ + } + if self.ctx.do_stats { + self.ctx.stats.on_memory_read(addr, 8); + } + } + SRC_IMM => { + self.ctx.inst_ctx.b = instruction.b_offset_imm0 | (instruction.b_use_sp_imm1 << 32) + } + SRC_IND => { + // Calculate memory address + let mut addr = + (self.ctx.inst_ctx.a as i64 + instruction.b_offset_imm0 as i64) as u64; + if instruction.b_use_sp_imm1 != 0 { + addr += self.ctx.inst_ctx.sp; + } + + // If the operation is a register operation, get it from the context registers + if Mem::address_is_register(addr) { + self.ctx.inst_ctx.b = self.get_reg(Mem::address_to_register_index(addr)); + } + // Otherwise, get it from memory + else { + self.ctx.inst_ctx.b = self.ctx.inst_ctx.mem.read(addr, instruction.ind_width); + mem_reads.push(self.ctx.inst_ctx.b); + /*println!( + "Emu::source_b_mem_reads_generate() mem_leads.len={} value={:x}", + mem_reads.len(), + self.ctx.inst_ctx.b + );*/ + } + if self.ctx.do_stats { + self.ctx.stats.on_memory_read(addr, instruction.ind_width); + } + } + _ => panic!( + "Emu::source_b_mem_reads_generate() Invalid b_src={} pc={}", + instruction.b_src, self.ctx.inst_ctx.pc + ), + } + } + + /// Calculate the 'b' register value based on the source specified by the current instruction, + /// using formerly generated memory reads from a previous emulation + #[inline(always)] + pub fn source_b_mem_reads_consume( + &mut self, + instruction: &ZiskInst, + mem_reads: &[u64], + mem_reads_index: &mut usize, + ) { + match instruction.b_src { + SRC_C => self.ctx.inst_ctx.b = self.ctx.inst_ctx.c, + SRC_MEM => { + // Calculate memory address + let mut addr = instruction.b_offset_imm0; + if instruction.b_use_sp_imm1 != 0 { + addr += self.ctx.inst_ctx.sp; + } + + // If the operation is a register operation, get it from the context registers + if Mem::address_is_register(addr) { + self.ctx.inst_ctx.b = self.get_reg(Mem::address_to_register_index(addr)); + } + // Otherwise, get it from memory + else { + assert!(*mem_reads_index < mem_reads.len()); + self.ctx.inst_ctx.b = mem_reads[*mem_reads_index]; + /*println!( + "Emu::source_b_mem_reads_consume() mem_leads_index={} value={:x}", + *mem_reads_index, self.ctx.inst_ctx.b + );*/ + *mem_reads_index += 1; + } + if self.ctx.do_stats { + self.ctx.stats.on_memory_read(addr, 8); + } + } + SRC_IMM => { + self.ctx.inst_ctx.b = instruction.b_offset_imm0 | (instruction.b_use_sp_imm1 << 32) + } + SRC_IND => { + // Calculate memory address + let mut addr = + (self.ctx.inst_ctx.a as i64 + instruction.b_offset_imm0 as i64) as u64; + if instruction.b_use_sp_imm1 != 0 { + addr += self.ctx.inst_ctx.sp; + } + + // If the operation is a register operation, get it from the context registers + if Mem::address_is_register(addr) { + self.ctx.inst_ctx.b = self.get_reg(Mem::address_to_register_index(addr)); + } + // Otherwise, get it from memory + else { + assert!(*mem_reads_index < mem_reads.len()); + self.ctx.inst_ctx.b = mem_reads[*mem_reads_index]; + /*println!( + "Emu::source_b_mem_reads_consume() mem_leads_index={} value={:x}", + *mem_reads_index, self.ctx.inst_ctx.b + );*/ + *mem_reads_index += 1; + } + if self.ctx.do_stats { + self.ctx.stats.on_memory_read(addr, instruction.ind_width); + } + } + _ => panic!( + "Emu::source_b_mem_reads_consume() Invalid b_src={} pc={}", + instruction.b_src, self.ctx.inst_ctx.pc + ), + } + } + /// Store the 'c' register value based on the storage specified by the current instruction #[inline(always)] pub fn store_c(&mut self, instruction: &ZiskInst) { match instruction.store { STORE_NONE => {} STORE_MEM => { + // Calculate value let val: i64 = if instruction.store_ra { self.ctx.inst_ctx.pc as i64 + instruction.jmp_offset2 } else { self.ctx.inst_ctx.c as i64 }; + let val = val as u64; + + // Calculate memory address let mut addr: i64 = instruction.store_offset; if instruction.store_use_sp { addr += self.ctx.inst_ctx.sp as i64; } - self.ctx.inst_ctx.mem.write(addr as u64, val as u64, 8); + debug_assert!(addr >= 0); + let addr = addr as u64; + + // If the operation is a register operation, write it to the context registers + if Mem::address_is_register(addr) { + self.set_reg(Mem::address_to_register_index(addr), val); + } + // Otherwise, get it from memory + else { + self.ctx.inst_ctx.mem.write(addr, val, 8); + } if self.ctx.do_stats { - self.ctx.stats.on_memory_write(addr as u64, 8); + self.ctx.stats.on_memory_write(addr, 8); } } STORE_IND => { + // Calculate value let val: i64 = if instruction.store_ra { self.ctx.inst_ctx.pc as i64 + instruction.jmp_offset2 } else { self.ctx.inst_ctx.c as i64 }; + let val = val as u64; + + // Calculate memory address let mut addr = instruction.store_offset; if instruction.store_use_sp { addr += self.ctx.inst_ctx.sp as i64; } addr += self.ctx.inst_ctx.a as i64; - self.ctx.inst_ctx.mem.write(addr as u64, val as u64, instruction.ind_width); + debug_assert!(addr >= 0); + let addr = addr as u64; + + // If the operation is a register operation, write it to the context registers + if Mem::address_is_register(addr) { + self.set_reg(Mem::address_to_register_index(addr), val); + } + // Otherwise, get it from memory + else { + self.ctx.inst_ctx.mem.write(addr, val, instruction.ind_width); + } if self.ctx.do_stats { - self.ctx.stats.on_memory_write(addr as u64, instruction.ind_width); + self.ctx.stats.on_memory_write(addr, instruction.ind_width); } } _ => panic!( @@ -178,29 +484,57 @@ impl<'a> Emu<'a> { match instruction.store { STORE_NONE => {} STORE_MEM => { + // Calculate the value let val: i64 = if instruction.store_ra { self.ctx.inst_ctx.pc as i64 + instruction.jmp_offset2 } else { self.ctx.inst_ctx.c as i64 }; + let val = val as u64; + + // Calculate the memory address let mut addr: i64 = instruction.store_offset; if instruction.store_use_sp { addr += self.ctx.inst_ctx.sp as i64; } - self.ctx.inst_ctx.mem.write_silent(addr as u64, val as u64, 8); + debug_assert!(addr >= 0); + let addr = addr as u64; + + // If the operation is a register operation, write it to the context registers + if Mem::address_is_register(addr) { + self.set_reg(Mem::address_to_register_index(addr), val); + } + // Otherwise, get it from memory + else { + self.ctx.inst_ctx.mem.write_silent(addr, val, 8); + } } STORE_IND => { + // Calculate the value let val: i64 = if instruction.store_ra { self.ctx.inst_ctx.pc as i64 + instruction.jmp_offset2 } else { self.ctx.inst_ctx.c as i64 }; + let val = val as u64; + + // Calculate the memory address let mut addr = instruction.store_offset; if instruction.store_use_sp { addr += self.ctx.inst_ctx.sp as i64; } addr += self.ctx.inst_ctx.a as i64; - self.ctx.inst_ctx.mem.write_silent(addr as u64, val as u64, instruction.ind_width); + debug_assert!(addr >= 0); + let addr = addr as u64; + + // If the operation is a register operation, write it to the context registers + if (instruction.ind_width == 8) && Mem::address_is_register(addr) { + self.set_reg(Mem::address_to_register_index(addr), val); + } + // Otherwise, get it from memory + else { + self.ctx.inst_ctx.mem.write_silent(addr, val, instruction.ind_width); + } } _ => panic!( "Emu::store_c_slice() Invalid store={} pc={}", @@ -219,7 +553,6 @@ impl<'a> Emu<'a> { // self.ctx.inst_ctx.sp += instruction.inc_sp; // } // } - /// Set PC, based on current PC, current flag and current instruction #[inline(always)] pub fn set_pc(&mut self, instruction: &ZiskInst) { @@ -255,30 +588,6 @@ impl<'a> Emu<'a> { self.ctx.inst_ctx.step += 1; } - /// Run the whole program, getting pc histogram - #[inline(always)] - pub fn run_pc_histogram(&mut self, inputs: Vec, options: &EmuOptions) -> ZiskPcHistogram { - // Create an empty pc histogram - let mut histogram = ZiskPcHistogram::default(); - - // Context, where the state of the execution is stored and modified at every execution step - self.ctx = self.create_emu_context(inputs); - - // Run the steps - while !self.ctx.inst_ctx.end && (self.ctx.inst_ctx.step < options.max_steps) { - let count = histogram.map.entry(self.ctx.inst_ctx.pc).or_default(); - *count += 1; - //println!("Emu::run_pc_histogram() adding pc={}", self.ctx.inst_ctx.pc); - self.step_fast(); - if self.ctx.inst_ctx.end { - histogram.end_pc = self.ctx.inst_ctx.pc; - histogram.steps = self.ctx.inst_ctx.step; - } - } - - histogram - } - /// Run the whole program pub fn run( &mut self, @@ -306,7 +615,7 @@ impl<'a> Emu<'a> { } // Reserve enough entries for all the requested steps between callbacks - self.ctx.trace.steps.reserve(self.ctx.callback_steps as usize); + self.ctx.trace.steps.mem_reads.reserve(self.ctx.callback_steps as usize); // Init pc to the rom entry address self.ctx.trace.start_state.pc = ROM_ENTRY; @@ -399,7 +708,7 @@ impl<'a> Emu<'a> { inputs: Vec, options: &EmuOptions, par_options: &ParEmuOptions, - ) -> (Vec, EmuStartingPoints) { + ) -> Vec { // Context, where the state of the execution is stored and modified at every execution step self.ctx = self.create_emu_context(inputs); @@ -410,9 +719,6 @@ impl<'a> Emu<'a> { self.ctx.do_stats = options.stats; let mut emu_traces = Vec::new(); - let mut emu_segments = EmuStartingPoints::default(); - - let mut segment_count = [0u64; ZISK_OPERATION_TYPE_VARIANTS]; while !self.ctx.inst_ctx.end { let block_idx = self.ctx.inst_ctx.step / par_options.num_steps as u64; @@ -420,7 +726,7 @@ impl<'a> Emu<'a> { block_idx % par_options.num_threads as u64 == par_options.thread_id as u64; if !is_my_block { - self.par_step_2::(options, par_options, &mut emu_segments, &mut segment_count); + self.par_step_2(); } else { // Check if is the first step of a new block if self.ctx.inst_ctx.step % par_options.num_steps as u64 == 0 { @@ -430,23 +736,22 @@ impl<'a> Emu<'a> { sp: self.ctx.inst_ctx.sp, c: self.ctx.inst_ctx.c, step: self.ctx.inst_ctx.step, + regs: self.ctx.inst_ctx.regs, + mem_reads_index: 0, }, last_state: EmuTraceStart::default(), - steps: Vec::with_capacity(par_options.num_steps), + steps: EmuTraceSteps { + mem_reads: Vec::with_capacity(par_options.num_steps), + steps: 0, + }, end: EmuTraceEnd { end: false }, }); } - self.par_step::( - options, - par_options, - emu_traces.last_mut().unwrap(), - &mut emu_segments, - &mut segment_count, - ); + self.par_step::(emu_traces.last_mut().unwrap()); } } - (emu_traces, emu_segments) + emu_traces } /// Performs one single step of the emulation @@ -495,7 +800,7 @@ impl<'a> Emu<'a> { #[cfg(debug_assertions)] if options.log_step { println!( - "step={} pc={} next={} op={}={} a={} b={} c={} flag={} inst={}", + "step={} pc={:x} next={:x} op={}={} a={:x} b={:x} c={:x} flag={} inst={}", self.ctx.inst_ctx.step, pc, self.ctx.inst_ctx.pc, @@ -513,10 +818,6 @@ impl<'a> Emu<'a> { // Store an emulator trace, if requested if self.ctx.do_callback { - let trace_step = EmuTraceStep { a: self.ctx.inst_ctx.a, b: self.ctx.inst_ctx.b }; - - self.ctx.trace.steps.push(trace_step); - // Increment step counter self.ctx.inst_ctx.step += 1; @@ -532,7 +833,7 @@ impl<'a> Emu<'a> { // Swap the emulator trace to avoid memory copies let mut trace = EmuTrace::default(); - trace.steps.reserve(self.ctx.callback_steps as usize); + trace.steps.mem_reads.reserve(self.ctx.callback_steps as usize); mem::swap(&mut self.ctx.trace, &mut trace); (callback)(trace); @@ -541,6 +842,7 @@ impl<'a> Emu<'a> { self.ctx.trace.start_state.sp = self.ctx.inst_ctx.sp; self.ctx.trace.start_state.c = self.ctx.inst_ctx.c; self.ctx.trace.start_state.step = self.ctx.inst_ctx.step; + self.ctx.trace.start_state.regs = self.ctx.inst_ctx.regs; // Increment the last callback step counter self.ctx.last_callback_step += self.ctx.callback_steps; @@ -553,32 +855,32 @@ impl<'a> Emu<'a> { /// Performs one single step of the emulation #[inline(always)] - #[allow(unused_variables)] - pub fn par_step( - &mut self, - options: &EmuOptions, - par_options: &ParEmuOptions, - emu_full_trace_vec: &mut EmuTrace, - emu_segments: &mut EmuStartingPoints, - segment_count: &mut [u64; ZISK_OPERATION_TYPE_VARIANTS], - ) { - let last_pc = self.ctx.inst_ctx.pc; - let last_c = self.ctx.inst_ctx.c; - + pub fn par_step(&mut self, emu_full_trace_vec: &mut EmuTrace) { + let mut mem_reads_index = emu_full_trace_vec.steps.mem_reads.len(); emu_full_trace_vec.last_state = EmuTraceStart { pc: self.ctx.inst_ctx.pc, sp: self.ctx.inst_ctx.sp, c: self.ctx.inst_ctx.c, step: self.ctx.inst_ctx.step, + regs: self.ctx.inst_ctx.regs, + mem_reads_index, }; let instruction = self.rom.get_instruction(self.ctx.inst_ctx.pc); // Build the 'a' register value based on the source specified by the current instruction - self.source_a(instruction); + self.source_a_mem_reads_generate( + instruction, + &mut emu_full_trace_vec.steps.mem_reads, + &mut mem_reads_index, + ); // Build the 'b' register value based on the source specified by the current instruction - self.source_b(instruction); + self.source_b_mem_reads_generate( + instruction, + &mut emu_full_trace_vec.steps.mem_reads, + &mut mem_reads_index, + ); // Call the operation (instruction.func)(&mut self.ctx.inst_ctx); @@ -596,45 +898,14 @@ impl<'a> Emu<'a> { // If this is the last instruction, stop executing self.ctx.inst_ctx.end = instruction.end; - emu_full_trace_vec - .steps - .push(EmuTraceStep { a: self.ctx.inst_ctx.a, b: self.ctx.inst_ctx.b }); - - let op_type = instruction.op_type as usize; - segment_count[op_type] += 1; - emu_segments.total_steps[op_type] += 1; - - if par_options.segment_sizes[op_type] != 0 { - if segment_count[op_type] == 1 { - emu_segments.add( - instruction.op_type, - last_pc, - self.ctx.inst_ctx.sp, - last_c, - self.ctx.inst_ctx.step, - ); - } else if segment_count[op_type] == par_options.segment_sizes[op_type] { - segment_count[op_type] = 0; - } - } - // Increment step counter self.ctx.inst_ctx.step += 1; + emu_full_trace_vec.steps.steps += 1; } /// Performs one single step of the emulation #[inline(always)] - #[allow(unused_variables)] - pub fn par_step_2( - &mut self, - options: &EmuOptions, - par_options: &ParEmuOptions, - emu_segments: &mut EmuStartingPoints, - segment_count: &mut [u64; ZISK_OPERATION_TYPE_VARIANTS], - ) { - let last_pc = self.ctx.inst_ctx.pc; - let last_c = self.ctx.inst_ctx.c; - + pub fn par_step_2(&mut self) { let instruction = self.rom.get_instruction(self.ctx.inst_ctx.pc); // Build the 'a' register value based on the source specified by the current instruction @@ -659,134 +930,138 @@ impl<'a> Emu<'a> { // If this is the last instruction, stop executing self.ctx.inst_ctx.end = instruction.end; - let op_type = instruction.op_type as usize; - segment_count[op_type] += 1; - emu_segments.total_steps[op_type] += 1; - - if par_options.segment_sizes[op_type] != 0 { - if segment_count[op_type] == 1 { - emu_segments.add( - instruction.op_type, - last_pc, - self.ctx.inst_ctx.sp, - last_c, - self.ctx.inst_ctx.step, - ); - } else if segment_count[op_type] == par_options.segment_sizes[op_type] { - segment_count[op_type] = 0; - } - } // Increment step counter self.ctx.inst_ctx.step += 1; } + /// Performs one single step of the emulation + #[inline(always)] + pub fn step_observer( + &mut self, + trace_step: &EmuTraceSteps, + mem_reads_index: &mut usize, + inst_observer: &mut dyn InstObserver, + ) -> bool { + let instruction = self.rom.get_instruction(self.ctx.inst_ctx.pc); + self.source_a_mem_reads_consume(instruction, &trace_step.mem_reads, mem_reads_index); + self.source_b_mem_reads_consume(instruction, &trace_step.mem_reads, mem_reads_index); + (instruction.func)(&mut self.ctx.inst_ctx); + self.store_c_slice(instruction); + + let finished = inst_observer.on_instruction(instruction, &self.ctx.inst_ctx); + + // #[cfg(feature = "sp")] + // self.set_sp(instruction); + self.set_pc(instruction); + self.ctx.inst_ctx.end = instruction.end; + + self.ctx.inst_ctx.step += 1; + //trace_step.steps += 1; + + finished + } + /// Run a slice of the program to generate full traces #[inline(always)] - pub fn run_slice_required( + pub fn run_slice_observer2( &mut self, - vec_traces: &[EmuTrace], - op_type: ZiskOperationType, - emu_trace_start: &EmuTraceStart, - num_rows: usize, - ) -> Vec { - let mut result = Vec::new(); + emu_trace: &EmuTrace, + inst_observer: &mut dyn InstObserver, + ) { + // Set initial state + self.ctx.inst_ctx.pc = emu_trace.start_state.pc; + self.ctx.inst_ctx.sp = emu_trace.start_state.sp; + self.ctx.inst_ctx.step = emu_trace.start_state.step; + self.ctx.inst_ctx.c = emu_trace.start_state.c; + self.ctx.inst_ctx.regs = emu_trace.start_state.regs; + + let mut mem_reads_index: usize = 0; + let emu_trace_steps = &emu_trace.steps; + for _step in 0..emu_trace.steps.steps { + self.step_observer::(emu_trace_steps, &mut mem_reads_index, inst_observer); + } + } + /// Run a slice of the program to generate full traces + #[inline(always)] + pub fn run_slice_plan( + &mut self, + vec_traces: &[EmuTrace], + chunk_id: usize, + inst_observer: &mut dyn InstObserver, + ) { + let emu_trace_start = &vec_traces[chunk_id].start_state; // Set initial state self.ctx.inst_ctx.pc = emu_trace_start.pc; self.ctx.inst_ctx.sp = emu_trace_start.sp; self.ctx.inst_ctx.step = emu_trace_start.step; self.ctx.inst_ctx.c = emu_trace_start.c; + self.ctx.inst_ctx.regs = emu_trace_start.regs; - let mut current_box_id = 0; - let mut current_step_idx = loop { - if current_box_id == vec_traces.len() - 1 || - vec_traces[current_box_id + 1].start_state.step >= emu_trace_start.step - { - break emu_trace_start.step as usize - - vec_traces[current_box_id].start_state.step as usize; - } - current_box_id += 1; - }; - - let last_trace = vec_traces.last().unwrap(); - let last_step = last_trace.start_state.step + last_trace.steps.len() as u64; - let mut current_step = emu_trace_start.step; + let mut current_box_id = chunk_id; + let mut current_step_idx = 0; - while current_step < last_step && result.len() < num_rows { - let step = &vec_traces[current_box_id].steps[current_step_idx]; + let mut emu_trace_steps = &vec_traces[current_box_id].steps; + let mut mem_reads_index: usize = 0; + loop { + //let step = &vec_traces[current_box_id].steps[current_step_idx]; - self.step_slice_required::(step, &op_type, &mut result); + if self.step_slice_plan(emu_trace_steps, &mut mem_reads_index, inst_observer) { + break; + } + if self.ctx.inst_ctx.end { + break; + } current_step_idx += 1; - if current_step_idx == vec_traces[current_box_id].steps.len() { + if current_step_idx == vec_traces[current_box_id].steps.steps { current_box_id += 1; current_step_idx = 0; + emu_trace_steps = &vec_traces[current_box_id].steps; + mem_reads_index = 0; } - - current_step += 1; } - - // Return emulator slice - result } /// Performs one single step of the emulation #[inline(always)] - pub fn step_slice_required( + pub fn step_slice_plan( &mut self, - trace_step: &EmuTraceStep, - op_type: &ZiskOperationType, - required: &mut Vec, - ) { + trace_step: &EmuTraceSteps, + mem_reads_index: &mut usize, + inst_observer: &mut dyn InstObserver, + ) -> bool { let instruction = self.rom.get_instruction(self.ctx.inst_ctx.pc); - self.ctx.inst_ctx.a = trace_step.a; - self.ctx.inst_ctx.b = trace_step.b; + self.source_a_mem_reads_consume(instruction, &trace_step.mem_reads, mem_reads_index); + self.source_b_mem_reads_consume(instruction, &trace_step.mem_reads, mem_reads_index); (instruction.func)(&mut self.ctx.inst_ctx); self.store_c_slice(instruction); + + let finished = inst_observer.on_instruction(instruction, &self.ctx.inst_ctx); + // #[cfg(feature = "sp")] // self.set_sp(instruction); self.set_pc(instruction); self.ctx.inst_ctx.end = instruction.end; self.ctx.inst_ctx.step += 1; + //trace_step.steps += 1; - // Build and store the operation required data - if op_type != &instruction.op_type { - return; - } - match instruction.op_type { - ZiskOperationType::Arith | ZiskOperationType::Binary | ZiskOperationType::BinaryE => { - let required_operation = ZiskRequiredOperation { - step: self.ctx.inst_ctx.step - 1, - opcode: instruction.op, - a: if instruction.m32 { - self.ctx.inst_ctx.a & 0xffffffff - } else { - self.ctx.inst_ctx.a - }, - b: if instruction.m32 { - self.ctx.inst_ctx.b & 0xffffffff - } else { - self.ctx.inst_ctx.b - }, - }; - required.push(required_operation); - } - _ => panic!("Emu::step_slice() found invalid op_type"), - } + finished } /// Performs one single step of the emulation #[inline(always)] pub fn step_slice_full_trace( &mut self, - trace_step: &EmuTraceStep, + trace_step: &EmuTraceSteps, + trace_step_index: &mut usize, ) -> EmuFullTraceStep { let last_pc = self.ctx.inst_ctx.pc; let last_c = self.ctx.inst_ctx.c; let instruction = self.rom.get_instruction(self.ctx.inst_ctx.pc); - self.ctx.inst_ctx.a = trace_step.a; - self.ctx.inst_ctx.b = trace_step.b; + self.source_a_mem_reads_consume(instruction, &trace_step.mem_reads, trace_step_index); + self.source_b_mem_reads_consume(instruction, &trace_step.mem_reads, trace_step_index); (instruction.func)(&mut self.ctx.inst_ctx); self.store_c_slice(instruction); // #[cfg(feature = "sp")] @@ -799,6 +1074,7 @@ impl<'a> Emu<'a> { Self::build_full_trace_step(instruction, &self.ctx.inst_ctx, last_c, last_pc); self.ctx.inst_ctx.step += 1; + //trace_step.steps += 1; full_trace_step } @@ -961,11 +1237,75 @@ impl<'a> Emu<'a> { pub fn get_regs_array(&self) -> [u64; 32] { let mut regs_array: [u64; 32] = [0; 32]; for (i, reg) in regs_array.iter_mut().enumerate() { - *reg = self.ctx.inst_ctx.mem.read(SYS_ADDR + (i as u64) * 8, 8); + *reg = self.ctx.inst_ctx.regs[i]; } regs_array } + #[inline(always)] + pub fn get_reg(&self, index: usize) -> u64 { + debug_assert!(index < 32); + self.ctx.inst_ctx.regs[index] + //println!("Emu::get_reg() index={} value={:x}", index, value); + } + + #[inline(always)] + pub fn set_reg(&mut self, index: usize, value: u64) { + debug_assert!(index < 32); + self.ctx.inst_ctx.regs[index] = value; + //println!("Emu::set_reg() index={} value={:x}", index, value); + } + + // #[inline(always)] + // pub fn memory_read(&mut self, address: u64, width: u64) -> u64 { + // let value: u64; + + // // If the operation is a register operation, get it from the context registers + // if (width == 8) && Mem::address_is_register(address) { + // value = self.get_reg(Mem::address_to_register_index(address)); + // } + // // Otherwise, get it from memory + // else { + // assert!(*mem_reads_index < mem_reads.len()); + // value = mem_reads[*mem_reads_index]; + // *mem_reads_index += 1; + // } + // // Update stats + // if self.ctx.do_stats { + // self.ctx.stats.on_memory_read(address, width); + // } + + // value + // } + + // #[inline(always)] + // pub fn memory_read_mem_reads( + // &mut self, + // address: u64, + // width: u64, + // mem_reads: &Vec, + // mem_reads_index: &mut usize, + // ) -> u64 { + // let value: u64; + + // // If the operation is a register operation, get it from the context registers + // if (width == 8) && Mem::address_is_register(address) { + // value = self.get_reg(Mem::address_to_register_index(address)); + // } + // // Otherwise, get it from memory + // else { + // assert!(*mem_reads_index < mem_reads.len()); + // value = mem_reads[*mem_reads_index]; + // *mem_reads_index += 1; + // } + // // Update stats + // if self.ctx.do_stats { + // self.ctx.stats.on_memory_read(address, width); + // } + + // value + // } + pub fn print_regs(&self) { let regs_array: [u64; 32] = self.get_regs_array(); print!("Emu::print_regs(): "); diff --git a/emulator/src/emu_context.rs b/emulator/src/emu_context.rs index 811baa6c..b171464b 100644 --- a/emulator/src/emu_context.rs +++ b/emulator/src/emu_context.rs @@ -32,6 +32,7 @@ impl EmuContext { pc: ROM_ENTRY, step: 0, end: false, + regs: [0; 32], }, tracerv: Vec::new(), tracerv_step: 0, diff --git a/emulator/src/emu_full_trace.rs b/emulator/src/emu_full_trace.rs index 343e0c05..7955bf61 100644 --- a/emulator/src/emu_full_trace.rs +++ b/emulator/src/emu_full_trace.rs @@ -1,3 +1,3 @@ -use zisk_pil::MainRow; +use zisk_pil::MainTraceRow; -pub type EmuFullTraceStep = MainRow; +pub type EmuFullTraceStep = MainTraceRow; diff --git a/emulator/src/emu_options.rs b/emulator/src/emu_options.rs index 0f9996ff..acd7bae1 100644 --- a/emulator/src/emu_options.rs +++ b/emulator/src/emu_options.rs @@ -99,7 +99,7 @@ impl EmuOptions { /// Returns true if the configuration allows to emulate in fast mode, maximizing the performance pub fn is_fast(&self) -> bool { self.trace_steps.is_none() && - self.print_step.is_none() && + (self.print_step.is_none() || (self.print_step.unwrap() == 0)) && self.trace.is_none() && !self.log_step && !self.verbose && diff --git a/emulator/src/emu_par_options.rs b/emulator/src/emu_par_options.rs index 5c3b0ea3..a614b56d 100644 --- a/emulator/src/emu_par_options.rs +++ b/emulator/src/emu_par_options.rs @@ -1,5 +1,3 @@ -use zisk_core::ZISK_OPERATION_TYPE_VARIANTS; - #[derive(Clone, Debug, PartialEq)] pub enum ParEmuExecutionType { MainTrace, @@ -10,16 +8,10 @@ pub struct ParEmuOptions { pub num_threads: usize, pub thread_id: usize, pub num_steps: usize, - pub segment_sizes: [u64; ZISK_OPERATION_TYPE_VARIANTS], } impl ParEmuOptions { - pub fn new( - num_threads: usize, - thread_id: usize, - num_steps: usize, - segment_sizes: [u64; ZISK_OPERATION_TYPE_VARIANTS], - ) -> Self { - Self { num_threads, thread_id, num_steps, segment_sizes } + pub fn new(num_threads: usize, thread_id: usize, num_steps: usize) -> Self { + Self { num_threads, thread_id, num_steps } } } diff --git a/emulator/src/emu_segment.rs b/emulator/src/emu_segment.rs index 7f8703de..97bb9b59 100644 --- a/emulator/src/emu_segment.rs +++ b/emulator/src/emu_segment.rs @@ -1,21 +1,7 @@ -use zisk_core::{ZiskOperationType, ZISK_OPERATION_TYPE_VARIANTS}; +use zisk_core::ZiskOperationType; use crate::EmuTraceStart; -#[derive(Debug, Default)] -pub struct EmuStartingPoints { - pub points: Vec, - pub num_points: [u64; ZISK_OPERATION_TYPE_VARIANTS], - pub total_steps: [u64; ZISK_OPERATION_TYPE_VARIANTS], -} - -impl EmuStartingPoints { - pub fn add(&mut self, op_type: ZiskOperationType, pc: u64, sp: u64, c: u64, step: u64) { - self.points.push(EmuStartingPoint::new(op_type, pc, sp, c, step)); - self.num_points[op_type as usize] += 1; - } -} - #[derive(Debug, Clone)] pub struct EmuStartingPoint { pub op_type: ZiskOperationType, @@ -24,6 +10,9 @@ pub struct EmuStartingPoint { impl EmuStartingPoint { pub fn new(segment_type: ZiskOperationType, pc: u64, sp: u64, c: u64, step: u64) -> Self { - Self { op_type: segment_type, emu_trace_start: EmuTraceStart { pc, sp, c, step } } + Self { + op_type: segment_type, + emu_trace_start: EmuTraceStart { pc, sp, c, step, regs: [0; 32], mem_reads_index: 0 }, + } } } diff --git a/emulator/src/emu_slice.rs b/emulator/src/emu_slice.rs deleted file mode 100644 index 95fa3b4c..00000000 --- a/emulator/src/emu_slice.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Emulator slice. -//! After executing the program during the witness computation, the main state machine generates -//! two data sets: -//! * The trace of field elements required to prove the main state machine operations -//! * The data required to prove the operations delegated to the secondary state machines - -use p3_field::AbstractField; -use zisk_core::ZiskRequired; - -use crate::EmuFullTraceStep; - -/// Emulator slice -pub struct EmuSlice { - /// Vector of field element traces, one per step, required to prove the main state machine - /// operations - pub full_trace: Vec>, - /// Data required to prove the operations delegated to the secondary state machines - pub required: ZiskRequired, -} - -impl EmuSlice { - /// Constructor of EmuSlice based on the size of the vector - pub fn new(size: usize) -> Self { - EmuSlice { full_trace: Vec::with_capacity(size), required: ZiskRequired::default() } - } -} diff --git a/emulator/src/emu_trace.rs b/emulator/src/emu_trace.rs index 7baff978..800ed402 100644 --- a/emulator/src/emu_trace.rs +++ b/emulator/src/emu_trace.rs @@ -11,6 +11,8 @@ pub struct EmuTraceStart { pub c: u64, /// Initial value of the step pub step: u64, + pub regs: [u64; 32], + pub mem_reads_index: usize, } /// Trace data at every step. @@ -19,25 +21,11 @@ pub struct EmuTraceStart { /// The value of c and flag can be obtained by executing the ROM instruction corresponding to the /// current value of pc and taking a and b as the input. #[derive(Default, Debug, Clone)] -pub struct EmuTraceStep { - /// Value of register a, built from the source specified by the Zisk instruction - pub a: u64, - /// Value of register b, built from the source specified by the Zisk instruction - pub b: u64, +pub struct EmuTraceSteps { + pub mem_reads: Vec, + pub steps: u64, } -/// Trace data at the end of the program execution, including only the `end` flag. -/// If the `end` flag is true, the program executed completely. -/// This does not mean that the program ended successfully; it could have found an error condition -/// due to, for example, invalid input data, and then jump directly to the end of the ROM. -/// In this error situation, the output data should reveal the success or fail of the completed -/// execution. -/// These are the possible combinations: -/// * end = false --> program did not complete, e.g. the emulator run out of steps (you can -/// configure more steps) -/// * end = true --> program completed -/// * output data correct --> program completed successfully -/// * output data incorrect --> program completed with an error #[derive(Default, Debug, Clone)] pub struct EmuTraceEnd { /// Value of the `end` flag at the end of the execution @@ -52,8 +40,6 @@ pub struct EmuTrace { pub start_state: EmuTraceStart, /// State at the end of the execution pub last_state: EmuTraceStart, - /// Trace data at every step of the execution - pub steps: Vec, - /// End trace + pub steps: EmuTraceSteps, pub end: EmuTraceEnd, } diff --git a/emulator/src/emulator.rs b/emulator/src/emulator.rs index 36d3bceb..c2654df3 100644 --- a/emulator/src/emulator.rs +++ b/emulator/src/emulator.rs @@ -15,22 +15,17 @@ //! Emu::run() //! ``` -use crate::{ - Emu, EmuOptions, EmuStartingPoints, EmuTrace, EmuTraceStart, ErrWrongArguments, ParEmuOptions, - ZiskEmulatorErr, -}; +use crate::{Emu, EmuOptions, EmuTrace, ErrWrongArguments, ParEmuOptions, ZiskEmulatorErr}; + use p3_field::PrimeField; use std::{ fs, path::{Path, PathBuf}, - sync::Mutex, time::Instant, }; use sysinfo::System; -use zisk_core::{ - Riscv2zisk, ZiskOperationType, ZiskPcHistogram, ZiskRequiredOperation, ZiskRom, - ZISK_OPERATION_TYPE_VARIANTS, -}; +use zisk_common::InstObserver; +use zisk_core::{Riscv2zisk, ZiskRom}; pub trait Emulator { fn emulate( @@ -177,45 +172,21 @@ impl ZiskEmulator { Ok(output) } - /// Process a Zisk rom with the provided input data, according to the configured options, in - /// order to generate a histogram of the program counters used during the emulation. - pub fn process_rom_pc_histogram( - rom: &ZiskRom, - inputs: &[u8], - options: &EmuOptions, - ) -> Result { - // Create a emulator instance with the rom - let mut emu = Emu::new(rom); - - // Run the emulation and get the pc histogram - let pc_histogram = emu.run_pc_histogram(inputs.to_owned(), options); - - // Check that the emulation completed, either successfully or not, but it must reach the end - // of the program - if !emu.terminated() { - return Err(ZiskEmulatorErr::EmulationNoCompleted); - } - - Ok(pc_histogram) - } - - pub fn par_process_rom( + /// EXECUTE phase + /// First phase of the witness computation + /// 8 threads in waterfall (# threads to be re-calibrated after memory reads refactor) + /// Must be fast + pub fn process_rom_min_trace( rom: &ZiskRom, inputs: &[u8], options: &EmuOptions, num_threads: usize, - op_sizes: [u64; ZISK_OPERATION_TYPE_VARIANTS], - ) -> Result<(Vec, EmuStartingPoints), ZiskEmulatorErr> { - let mut emu_traces = vec![Vec::new(); num_threads]; - let emu_slices = Mutex::new(EmuStartingPoints::default()); - - emu_traces.par_iter_mut().enumerate().for_each(|(thread_id, emu_trace)| { - let par_emu_options = ParEmuOptions::new( - num_threads, - thread_id, - options.trace_steps.unwrap() as usize, - op_sizes, - ); + ) -> Result, ZiskEmulatorErr> { + let mut minimal_traces = vec![Vec::new(); num_threads]; + + minimal_traces.par_iter_mut().enumerate().for_each(|(thread_id, emu_trace)| { + let par_emu_options = + ParEmuOptions::new(num_threads, thread_id, options.trace_steps.unwrap() as usize); // Run the emulation let mut emu = Emu::new(rom); @@ -227,55 +198,53 @@ impl ZiskEmulator { // return Err(ZiskEmulatorErr::EmulationNoCompleted); } - *emu_trace = result.0; - - if thread_id == 0 { - *emu_slices.lock().unwrap() = result.1; - } + *emu_trace = result; }); - let capacity = emu_traces.iter().map(|trace| trace.len()).sum::(); + let capacity = minimal_traces.iter().map(|trace| trace.len()).sum::(); let mut vec_traces = Vec::with_capacity(capacity); for i in 0..capacity { let x = i % num_threads; let y = i / num_threads; - vec_traces.push(std::mem::take(&mut emu_traces[x][y])); + vec_traces.push(std::mem::take(&mut minimal_traces[x][y])); } - // For performance reasons we didn't collect main operation starting points because we - // can generate them from the execution trace. - let mut emu_slices = emu_slices.into_inner().unwrap(); - emu_slices.total_steps[ZiskOperationType::None as usize] = - vec_traces.iter().map(|trace| trace.steps.len()).sum::() as u64; - for vec_trace in &vec_traces { - emu_slices.add( - ZiskOperationType::None, - vec_trace.start_state.pc, - vec_trace.start_state.sp, - vec_trace.start_state.c, - vec_trace.start_state.step, - ); - } + Ok(vec_traces) + } - Ok((vec_traces, emu_slices)) + /// COUNT phase + /// Second phase of the witness computation + /// Executes in parallel the different blocks of wc + /// Good to be fast + #[inline] + pub fn process_rom_slice_counters( + rom: &ZiskRom, + emu_trace: &EmuTrace, + inst_observer: &mut dyn InstObserver, + ) { + // Create a emulator instance with this rom + let mut emu = Emu::new(rom); + + // Run the emulation + emu.run_slice_observer2::(emu_trace, inst_observer); } - /// Process a Zisk rom with the provided input data, according to the configured options, in - /// order to generate a set of required operation data. + /// EXPAND phase + /// Third phase of the witness computation + /// I have a #[inline] - pub fn process_slice_required( + pub fn process_rom_slice_plan( rom: &ZiskRom, - vec_traces: &[EmuTrace], - op_type: ZiskOperationType, - emu_trace_start: &EmuTraceStart, - num_rows: usize, - ) -> Vec { - // Create a emulator instance with the rom + min_traces: &[EmuTrace], + chunk_id: usize, + inst_observer: &mut dyn InstObserver, + ) { + // Create a emulator instance with this rom let mut emu = Emu::new(rom); // Run the emulation - emu.run_slice_required::(vec_traces, op_type, emu_trace_start, num_rows) + emu.run_slice_plan(min_traces, chunk_id, inst_observer); } /// Finds all files in a directory and returns a vector with their full paths diff --git a/emulator/src/lib.rs b/emulator/src/lib.rs index 61e55e87..96a8e48f 100644 --- a/emulator/src/lib.rs +++ b/emulator/src/lib.rs @@ -18,9 +18,8 @@ mod emu_full_trace; pub mod emu_options; mod emu_par_options; mod emu_segment; -pub mod emu_slice; -pub mod emu_trace; -pub mod emulator; +mod emu_trace; +mod emulator; mod emulator_errors; pub mod stats; @@ -30,7 +29,6 @@ pub use emu_full_trace::*; pub use emu_options::*; pub use emu_par_options::*; pub use emu_segment::*; -pub use emu_slice::*; pub use emu_trace::*; pub use emulator::*; pub use emulator_errors::*; diff --git a/executor/Cargo.toml b/executor/Cargo.toml new file mode 100644 index 00000000..2d2cec68 --- /dev/null +++ b/executor/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "executor" +version = "0.1.0" +edition = "2021" + +[dependencies] +sm-arith = { path = "../state-machines/arith" } +sm-binary = { path = "../state-machines/binary" } +sm-common = { path = "../state-machines/common" } +sm-main = { path = "../state-machines/main" } +sm-mem = { path = "../state-machines/mem" } +sm-rom = { path = "../state-machines/rom" } +zisk-pil = { path = "../pil" } +ziskemu = { path = "../emulator" } +zisk-core = { path = "../core" } +zisk-common = { path = "../common" } + + +proofman-common = { workspace = true } +proofman-util = { workspace = true } +witness = { workspace = true } +p3-field = { workspace=true } +pil-std-lib = { workspace = true } +log = { workspace = true } + +rayon = { workspace = true } \ No newline at end of file diff --git a/executor/src/executor.rs b/executor/src/executor.rs new file mode 100644 index 00000000..82d990ee --- /dev/null +++ b/executor/src/executor.rs @@ -0,0 +1,236 @@ +use p3_field::PrimeField; +use proofman_common::ProofCtx; +use proofman_util::{timer_start_debug, timer_stop_and_log_debug}; +use witness::WitnessComponent; + +use rayon::prelude::*; + +use sm_common::{CheckPoint, ComponentProvider, InstanceExpanderCtx, InstanceType, Plan}; +use sm_main::{MainInstance, MainSM}; + +use std::{fs, path::PathBuf, sync::Arc}; +use zisk_core::ZiskRom; +use zisk_pil::{MainTrace, MAIN_AIR_IDS, ZISK_AIRGROUP_ID}; +use ziskemu::{EmuOptions, EmuTrace, ZiskEmulator}; + +use crate::MetricsProxy; + +pub struct ZiskExecutor { + pub public_inputs_path: PathBuf, + + /// ZisK ROM, a binary file that contains the ZisK program to be executed + pub zisk_rom: Arc, + + /// Main State Machine + pub main_sm: Arc>, + + /// Secondary State Machines + secondary_sm: Vec>>, +} + +impl ZiskExecutor { + const NUM_THREADS: usize = 8; + + pub fn new(public_inputs_path: PathBuf, zisk_rom: Arc) -> Self { + let main_sm = MainSM::new(); + + Self { public_inputs_path, zisk_rom, main_sm, secondary_sm: Vec::new() } + } + + pub fn register_sm(&mut self, sm: Arc>) { + self.secondary_sm.push(sm); + } + + fn compute_plans(&self, min_traces: Arc>) -> Vec> { + timer_start_debug!(PROCESS_OBSERVER); + let mut metrics_slices = min_traces + .par_iter() + .map(|minimal_trace| { + let mut metrics_proxy = MetricsProxy::new(); + self.secondary_sm.iter().for_each(|sm| { + metrics_proxy.register_metrics(sm.get_counter()); + }); + + ZiskEmulator::process_rom_slice_counters::( + &self.zisk_rom, + minimal_trace, + &mut metrics_proxy, + ); + metrics_proxy + }) + .collect::>(); + timer_stop_and_log_debug!(PROCESS_OBSERVER); + + // Group counters by chunk_id and counter type + let mut vec_counters = + (0..metrics_slices[0].metrics.len()).map(|_| Vec::new()).collect::>(); + + for (chunk_id, counter_slice) in metrics_slices.iter_mut().enumerate() { + for (i, counter) in counter_slice.metrics.drain(..).enumerate() { + vec_counters[i].push((chunk_id, counter)); + } + } + + self.secondary_sm + .iter() + .map(|sm| sm.get_planner().plan(vec_counters.drain(..1).next().unwrap())) + .collect() + } + + fn compute_minimal_traces(&self, public_inputs: Vec, num_threads: usize) -> Vec { + timer_start_debug!(PHASE1_FAST_PROCESS_ROM); + + // Prepare the settings for the emulator + let emu_options = EmuOptions { + elf: None, //Some(rom_path.to_path_buf().display().to_string()), + inputs: None, //Some(public_inputs_path.display().to_string()), + trace_steps: Some(MainTrace::::NUM_ROWS as u64 - 1), + ..EmuOptions::default() + }; + + let min_traces = ZiskEmulator::process_rom_min_trace::( + &self.zisk_rom, + &public_inputs, + &emu_options, + num_threads, + ) + .expect("Error during emulator execution"); + timer_stop_and_log_debug!(PHASE1_FAST_PROCESS_ROM); + + min_traces + } + + fn create_main_plans(&self, min_traces: &[EmuTrace]) -> Vec { + min_traces + .iter() + .enumerate() + .map(|(segment_id, _minimal_trace)| { + Plan::new( + ZISK_AIRGROUP_ID, + MAIN_AIR_IDS[0], + Some(segment_id), + InstanceType::Instance, + Some(CheckPoint::new(segment_id, 0)), + None, + ) + }) + .collect() + } + + fn create_main_instances( + &self, + pctx: Arc>, + main_planning: &mut Vec, + ) -> Vec> { + let mut main_instances = Vec::new(); + + for plan in main_planning.drain(..) { + if let (true, global_idx) = pctx.dctx_add_instance(plan.airgroup_id, plan.air_id, 1) { + let iectx = InstanceExpanderCtx::new(global_idx, plan); + main_instances.push(self.main_sm.get_instance(iectx)); + } + } + + main_instances + } +} + +impl WitnessComponent for ZiskExecutor { + fn execute(&self, pctx: Arc>) { + // Call emulate with these options + let public_inputs = { + // Read inputs data from the provided inputs path + let path = PathBuf::from(self.public_inputs_path.display().to_string()); + fs::read(path).expect("Could not read inputs file") + }; + + // PHASE 1. MINIMAL TRACES. Process the ROM super fast to collect the Minimal Traces + // --------------------------------------------------------------------------------- + let min_traces = self.compute_minimal_traces(public_inputs, Self::NUM_THREADS); + let min_traces = Arc::new(min_traces); + + // ================================================================================= + // PATH A Main SM instances + // ================================================================================= + + // PATH A PHASE 2. Count & Reduce the Minimal Traces to get the Plans + // --------------------------------------------------------------------------------- + let mut main_planning = self.create_main_plans(&min_traces); + let mut main_layouts = self.create_main_instances(pctx.clone(), &mut main_planning); + + // PATH A PHASE 3. Expand the Minimal Traces to fill the Main Traces + // --------------------------------------------------------------------------------- + let pctx_clone = pctx.clone(); + let main_task = { + let main_sm = self.main_sm.clone(); + let zisk_rom = self.zisk_rom.clone(); + let minimal_traces = min_traces.clone(); + std::thread::spawn(move || { + main_layouts.par_iter_mut().for_each(|main_instance| { + main_sm.prove_main( + pctx_clone.clone(), + &zisk_rom, + &minimal_traces, + main_instance, + ); + }); + main_layouts + }) + }; + + // ================================================================================= + // PATH B Secondary SM instances + // ================================================================================= + + // PATH B PHASE 2. Count & Reduce the Minimal Traces to get the Plans + // --------------------------------------------------------------------------------- + // Compute counters for each minimal trace + let mut plans = self.compute_plans(min_traces.clone()); + + // Create the buffer ta the distribution context + let mut sec_instances = Vec::new(); + let pctx_clone = pctx.clone(); + for (i, plans_by_sm) in plans.iter_mut().enumerate() { + for plan in plans_by_sm.drain(..) { + let (is_mine, global_idx) = + pctx_clone.clone().dctx_add_instance(plan.airgroup_id, plan.air_id, 1); + + if is_mine || plan.instance_type == InstanceType::Table { + let iectx = InstanceExpanderCtx::new(global_idx, plan); + + let instance = self.secondary_sm[i].get_instance(iectx); + sec_instances.push((global_idx, instance)); + } + } + } + + // PATH B PHASE 3. Expand the Minimal Traces to fill the Secondary SM Traces + // --------------------------------------------------------------------------------- + sec_instances.par_iter_mut().for_each(|(global_idx, sec_instance)| { + if sec_instance.instance_type() == InstanceType::Instance { + let _ = sec_instance.collect_inputs(&self.zisk_rom, &min_traces); + if let Some(air_instance) = sec_instance.compute_witness(&pctx) { + pctx.clone() + .air_instance_repo + .add_air_instance(air_instance, Some(*global_idx)); + } + } + }); + + sec_instances.par_iter_mut().for_each(|(global_idx, sec_instance)| { + if sec_instance.instance_type() == InstanceType::Table { + if let Some(air_instance) = sec_instance.compute_witness(&pctx) { + pctx.air_instance_repo.add_air_instance(air_instance, Some(*global_idx)); + } + } + }); + + // Drop memory + std::thread::spawn(move || { + drop(min_traces); + }); + + // Wait for the main task to finish + main_task.join().unwrap(); + } +} diff --git a/executor/src/lib.rs b/executor/src/lib.rs new file mode 100644 index 00000000..ad26f799 --- /dev/null +++ b/executor/src/lib.rs @@ -0,0 +1,5 @@ +mod executor; +mod metrics_proxy; + +pub use executor::*; +pub use metrics_proxy::*; diff --git a/executor/src/metrics_proxy.rs b/executor/src/metrics_proxy.rs new file mode 100644 index 00000000..a30c15c4 --- /dev/null +++ b/executor/src/metrics_proxy.rs @@ -0,0 +1,40 @@ +use sm_common::Metrics; +use zisk_common::InstObserver; +use zisk_core::{InstContext, ZiskInst, ZiskOperationType, ZISK_OP_TYPE_COUNT}; + +#[derive(Default)] +pub struct MetricsProxy { + pub metrics: Vec>, + pub metrics_by_op: [Vec; ZISK_OP_TYPE_COUNT], +} + +impl MetricsProxy { + pub fn new() -> Self { + let metrics_by_op: [Vec<_>; ZISK_OP_TYPE_COUNT] = std::array::from_fn(|_| Vec::new()); + + Self { metrics: Vec::new(), metrics_by_op } + } + + pub fn register_metrics(&mut self, observer: Box) { + let op_types = observer.op_type(); + self.metrics.push(observer); + let idx = self.metrics.len() - 1; + + for op_type in op_types { + self.metrics_by_op[op_type as usize].push(idx); + } + } +} + +impl InstObserver for MetricsProxy { + #[inline(always)] + fn on_instruction(&mut self, zisk_inst: &ZiskInst, inst_ctx: &InstContext) -> bool { + for op_type in [&zisk_inst.op_type, &ZiskOperationType::None] { + for idx in self.metrics_by_op[*op_type as usize].iter() { + self.metrics[*idx].measure(zisk_inst, inst_ctx); + } + } + + false + } +} diff --git a/pil/Cargo.toml b/pil/Cargo.toml index 16a3d3b8..a2a0cf3e 100644 --- a/pil/Cargo.toml +++ b/pil/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" [dependencies] proofman-common = { workspace = true } proofman-macros = { workspace = true } -proofman = { workspace = true } +serde = { version = "1.0.204", features = ["derive"] } [features] default = [] -no_lib_link = ["proofman-common/no_lib_link", "proofman/no_lib_link"] \ No newline at end of file +no_lib_link = ["proofman-common/no_lib_link"] \ No newline at end of file diff --git a/pil/src/lib.rs b/pil/src/lib.rs index aee8bab5..a2c4bd05 100644 --- a/pil/src/lib.rs +++ b/pil/src/lib.rs @@ -3,9 +3,6 @@ mod pil_helpers; pub use pil_helpers::*; //TODO To be removed when ready in ZISK_PIL -pub const ARITH32_AIR_IDS: &[usize] = &[4, 5]; -pub const ARITH64_AIR_IDS: &[usize] = &[6]; -pub const ARITH3264_AIR_IDS: &[usize] = &[7]; pub const MEM_AIRGROUP_ID: usize = 105; pub const MEM_ALIGN_AIR_IDS: &[usize] = &[1]; pub const MEM_UNALIGNED_AIR_IDS: &[usize] = &[2, 3]; diff --git a/pil/src/pil_helpers/mod.rs b/pil/src/pil_helpers/mod.rs index 8273843a..8e9f77af 100644 --- a/pil/src/pil_helpers/mod.rs +++ b/pil/src/pil_helpers/mod.rs @@ -1,7 +1,6 @@ // WARNING: This file has been autogenerated from the PILOUT file. // Manual modifications are not recommended and may be overwritten. -mod pilout; +#[rustfmt::skip] mod traces; -pub use pilout::*; pub use traces::*; diff --git a/pil/src/pil_helpers/pilout.rs b/pil/src/pil_helpers/pilout.rs deleted file mode 100644 index 9a796335..00000000 --- a/pil/src/pil_helpers/pilout.rs +++ /dev/null @@ -1,54 +0,0 @@ -// WARNING: This file has been autogenerated from the PILOUT file. -// Manual modifications are not recommended and may be overwritten. -use proofman_common::WitnessPilout; - -pub const PILOUT_HASH: &[u8] = b"Zisk-hash"; - -//AIRGROUP CONSTANTS - -pub const ZISK_AIRGROUP_ID: usize = 0; - -//AIR CONSTANTS - -pub const MAIN_AIR_IDS: &[usize] = &[0]; - -pub const ROM_AIR_IDS: &[usize] = &[1]; - -pub const ARITH_AIR_IDS: &[usize] = &[2]; - -pub const ARITH_TABLE_AIR_IDS: &[usize] = &[3]; - -pub const ARITH_RANGE_TABLE_AIR_IDS: &[usize] = &[4]; - -pub const BINARY_AIR_IDS: &[usize] = &[5]; - -pub const BINARY_TABLE_AIR_IDS: &[usize] = &[6]; - -pub const BINARY_EXTENSION_AIR_IDS: &[usize] = &[7]; - -pub const BINARY_EXTENSION_TABLE_AIR_IDS: &[usize] = &[8]; - -pub const SPECIFIED_RANGES_AIR_IDS: &[usize] = &[9]; - -pub struct Pilout; - -impl Pilout { - pub fn pilout() -> WitnessPilout { - let mut pilout = WitnessPilout::new("Zisk", 2, PILOUT_HASH.to_vec()); - - let air_group = pilout.add_air_group(Some("Zisk")); - - air_group.add_air(Some("Main"), 2097152); - air_group.add_air(Some("Rom"), 1048576); - air_group.add_air(Some("Arith"), 2097152); - air_group.add_air(Some("ArithTable"), 128); - air_group.add_air(Some("ArithRangeTable"), 4194304); - air_group.add_air(Some("Binary"), 2097152); - air_group.add_air(Some("BinaryTable"), 4194304); - air_group.add_air(Some("BinaryExtension"), 2097152); - air_group.add_air(Some("BinaryExtensionTable"), 4194304); - air_group.add_air(Some("SpecifiedRanges"), 16777216); - - pilout - } -} diff --git a/pil/src/pil_helpers/traces.rs b/pil/src/pil_helpers/traces.rs index 32cfe09f..de2aeaf6 100644 --- a/pil/src/pil_helpers/traces.rs +++ b/pil/src/pil_helpers/traces.rs @@ -2,43 +2,98 @@ // Manual modifications are not recommended and may be overwritten. use proofman_common as common; pub use proofman_macros::trace; +pub use proofman_macros::values; -trace!(MainRow, MainTrace { - a: [F; 2], b: [F; 2], c: [F; 2], flag: F, pc: F, a_src_imm: F, a_src_mem: F, a_offset_imm0: F, a_imm1: F, a_src_step: F, b_src_imm: F, b_src_mem: F, b_offset_imm0: F, b_imm1: F, b_src_ind: F, ind_width: F, is_external_op: F, op: F, store_ra: F, store_mem: F, store_ind: F, store_offset: F, set_pc: F, jmp_offset1: F, jmp_offset2: F, m32: F, addr1: F, __debug_operation_bus_enabled: F, -}); +#[allow(dead_code)] +type FieldExtension = [F; 3]; + +pub const PILOUT_HASH: &[u8] = b"Zisk-hash"; + +//AIRGROUP CONSTANTS + +pub const ZISK_AIRGROUP_ID: usize = 0; + +//AIR CONSTANTS + +pub const MAIN_AIR_IDS: &[usize] = &[0]; + +pub const ROM_AIR_IDS: &[usize] = &[1]; + +pub const ARITH_AIR_IDS: &[usize] = &[2]; + +pub const ARITH_TABLE_AIR_IDS: &[usize] = &[3]; + +pub const ARITH_RANGE_TABLE_AIR_IDS: &[usize] = &[4]; + +pub const BINARY_AIR_IDS: &[usize] = &[5]; + +pub const BINARY_TABLE_AIR_IDS: &[usize] = &[6]; + +pub const BINARY_EXTENSION_AIR_IDS: &[usize] = &[7]; + +pub const BINARY_EXTENSION_TABLE_AIR_IDS: &[usize] = &[8]; -trace!(RomRow, RomTrace { - line: F, a_offset_imm0: F, a_imm1: F, b_offset_imm0: F, b_imm1: F, ind_width: F, op: F, store_offset: F, jmp_offset1: F, jmp_offset2: F, flags: F, multiplicity: F, +pub const SPECIFIED_RANGES_AIR_IDS: &[usize] = &[9]; + + +//PUBLICS +use serde::Deserialize; +use serde::Serialize; +#[derive(Default, Debug, Serialize, Deserialize)] +pub struct ZiskPublics { + #[serde(default)] + pub rom_root: [u64; 4], + +} + +values!(ZiskPublicValues { + rom_root: [F; 4], }); + +trace!(MainTrace { + a: [F; 2], b: [F; 2], c: [F; 2], flag: F, pc: F, a_src_imm: F, a_src_mem: F, a_offset_imm0: F, a_imm1: F, a_src_step: F, b_src_imm: F, b_src_mem: F, b_offset_imm0: F, b_imm1: F, b_src_ind: F, ind_width: F, is_external_op: F, op: F, store_ra: F, store_mem: F, store_ind: F, store_offset: F, set_pc: F, jmp_offset1: F, jmp_offset2: F, m32: F, addr1: F, __debug_operation_bus_enabled: F, +}, 0, 0, 2097152 ); -trace!(ArithRow, ArithTrace { +trace!(RomTrace { + multiplicity: F, +}, 0, 1, 1048576 ); + +trace!(ArithTrace { carry: [F; 7], a: [F; 4], b: [F; 4], c: [F; 4], d: [F; 4], na: F, nb: F, nr: F, np: F, sext: F, m32: F, div: F, fab: F, na_fb: F, nb_fa: F, debug_main_step: F, main_div: F, main_mul: F, signed: F, div_by_zero: F, div_overflow: F, inv_sum_all_bs: F, op: F, bus_res1: F, multiplicity: F, range_ab: F, range_cd: F, -}); +}, 0, 2, 2097152 ); -trace!(ArithTableRow, ArithTableTrace { +trace!(ArithTableTrace { multiplicity: F, -}); +}, 0, 3, 128 ); -trace!(ArithRangeTableRow, ArithRangeTableTrace { +trace!(ArithRangeTableTrace { multiplicity: F, -}); +}, 0, 4, 4194304 ); -trace!(BinaryRow, BinaryTrace { +trace!(BinaryTrace { m_op: F, mode32: F, free_in_a: [F; 8], free_in_b: [F; 8], free_in_c: [F; 8], carry: [F; 8], use_last_carry: F, op_is_min_max: F, multiplicity: F, main_step: F, -}); +}, 0, 5, 2097152 ); -trace!(BinaryTableRow, BinaryTableTrace { +trace!(BinaryTableTrace { multiplicity: F, -}); +}, 0, 6, 4194304 ); -trace!(BinaryExtensionRow, BinaryExtensionTrace { +trace!(BinaryExtensionTrace { op: F, in1: [F; 8], in2_low: F, out: [[F; 2]; 8], op_is_shift: F, in2: [F; 2], main_step: F, multiplicity: F, -}); +}, 0, 7, 2097152 ); -trace!(BinaryExtensionTableRow, BinaryExtensionTableTrace { +trace!(BinaryExtensionTableTrace { multiplicity: F, -}); +}, 0, 8, 4194304 ); -trace!(SpecifiedRangesRow, SpecifiedRangesTrace { +trace!(SpecifiedRangesTrace { mul: [F; 1], +}, 0, 9, 16777216 ); + +trace!(RomRomTrace { + line: F, a_offset_imm0: F, a_imm1: F, b_offset_imm0: F, b_imm1: F, ind_width: F, op: F, store_offset: F, jmp_offset1: F, jmp_offset2: F, flags: F, +}, 0, 1, 1048576, 0 ); + +values!(MainAirValues { + main_last_segment: F, main_segment: F, }); diff --git a/pil/zisk.pil b/pil/zisk.pil index 0e97aeb6..e8c2b3ad 100644 --- a/pil/zisk.pil +++ b/pil/zisk.pil @@ -1,5 +1,5 @@ -require "constants.pil" +require "std_constants.pil" require "rom/pil/rom.pil" require "main/pil/main.pil" require "binary/pil/binary.pil" diff --git a/rom-merkle/Cargo.toml b/rom-merkle/Cargo.toml index 4558eda3..13af50c1 100644 --- a/rom-merkle/Cargo.toml +++ b/rom-merkle/Cargo.toml @@ -6,8 +6,9 @@ edition = "2021" [dependencies] sm-rom = { path = "../state-machines/rom" } log = { workspace = true } -stark = { workspace = true } proofman-common = { workspace = true } +proofman-util = { workspace = true } +zisk-pil = { path="../pil" } p3-goldilocks = { git = "https://github.com/Plonky3/Plonky3.git", rev = "c3d754ef77b9fce585b46b972af751fe6e7a9803" } p3-field = { workspace = true } diff --git a/rom-merkle/src/main.rs b/rom-merkle/src/main.rs index fa856247..7aa5dd5c 100644 --- a/rom-merkle/src/main.rs +++ b/rom-merkle/src/main.rs @@ -1,30 +1,33 @@ use clap::{Arg, Command}; use colored::Colorize; use p3_goldilocks::Goldilocks; -use proofman_common::{GlobalInfo, ProofType, SetupCtx}; +use proofman_common::{get_custom_commit_trace, GlobalInfo, ProofType, SetupCtx}; +use proofman_util::create_buffer_fast; use sm_rom::RomSM; -use stark::StarkBufferAllocator; use std::{path::Path, sync::Arc}; use sysinfo::System; +use zisk_pil::RomRomTrace; fn main() { let matches = Command::new("ROM Handler") .version("1.0") .about("Compute the Merkle Root of a ROM file") - .arg(Arg::new("rom").value_name("FILE").help("The ROM file path").required(true).index(1)) + .arg( + Arg::new("rom").long("rom").value_name("FILE").help("The ROM file path").required(true), + ) .arg( Arg::new("proving_key") + .long("proving-key") .value_name("FILE") .help("The proving key folder path") - .required(true) - .index(2), + .required(true), ) .arg( - Arg::new("global_info") + Arg::new("rom_buffer") + .long("rom-buffer") .value_name("FILE") - .help("The global info file path") - .required(true) - .index(3), + .help("The rom buffer path") + .required(true), ) .get_matches(); @@ -34,9 +37,8 @@ fn main() { let proving_key_path_str = matches.get_one::("proving_key").expect("Proving key path is required"); let proving_key_path = Path::new(proving_key_path_str); - let global_info_path_str = - matches.get_one::("global_info").expect("Global info path is required"); - let global_info_path = Path::new(global_info_path_str); + let rom_buffer_str = + matches.get_one::("rom_buffer").expect("Buffer file path is required"); env_logger::builder() .format_timestamp(None) @@ -78,23 +80,25 @@ fn main() { std::process::exit(1); } - // If all checks pass, continue with the program - println!("ROM Path is valid: {}", rom_path.display()); - - let buffer_allocator: Arc = - Arc::new(StarkBufferAllocator::new(proving_key_path.to_path_buf())); - let global_info = GlobalInfo::new(global_info_path); + let global_info = GlobalInfo::new(proving_key_path); let sctx = Arc::new(SetupCtx::new(&global_info, &ProofType::Basic)); - if let Err(e) = - RomSM::::compute_trace(rom_path.to_path_buf(), buffer_allocator, &sctx) - { - log::error!("Error: {}", e); - std::process::exit(1); - } + let mut custom_rom_trace: RomRomTrace = RomRomTrace::new(); + let setup = sctx.get_setup(custom_rom_trace.airgroup_id(), custom_rom_trace.air_id); + + RomSM::compute_custom_trace_rom(rom_path.to_path_buf(), &mut custom_rom_trace); - // Compute LDE and Merkelize and get the root of the rom - // TODO: Implement the logic to compute the trace + let n_ext = (1 << setup.stark_info.stark_struct.n_bits_ext) as usize; + let n_cols = custom_rom_trace.num_rows(); - log::info!("ROM proof successful"); + let buffer_ext = create_buffer_fast(n_ext * n_cols); + + get_custom_commit_trace( + custom_rom_trace.commit_id.unwrap() as u64, + 0, + setup, + custom_rom_trace.get_buffer(), + buffer_ext, + rom_buffer_str.as_str(), + ); } diff --git a/state-machines/arith/Cargo.toml b/state-machines/arith/Cargo.toml index 7c0859b8..d20568bb 100644 --- a/state-machines/arith/Cargo.toml +++ b/state-machines/arith/Cargo.toml @@ -5,14 +5,15 @@ edition = "2021" [dependencies] zisk-core = { path = "../../core" } +zisk-common = { path = "../../common" } zisk-pil = { path="../../pil" } +ziskemu = { path = "../../emulator" } sm-common = { path = "../common" } p3-field = { workspace=true } proofman-common = { workspace = true } proofman-macros = { workspace = true } proofman-util = { workspace = true } -proofman = { workspace = true } pil-std-lib = { workspace = true } log = { workspace = true } @@ -23,4 +24,4 @@ num-bigint = { workspace = true } [features] default = [] generate_code_arith_range_table = [] -no_lib_link = ["proofman-common/no_lib_link", "proofman/no_lib_link"] \ No newline at end of file +no_lib_link = ["proofman-common/no_lib_link"] \ No newline at end of file diff --git a/state-machines/arith/src/arith.rs b/state-machines/arith/src/arith.rs index 2e2a4d5e..64f07cff 100644 --- a/state-machines/arith/src/arith.rs +++ b/state-machines/arith/src/arith.rs @@ -1,68 +1,56 @@ -use std::sync::{ - atomic::{AtomicU32, Ordering}, - Arc, -}; - -use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; -use zisk_core::ZiskRequiredOperation; -use zisk_pil::{ARITH_AIR_IDS, ARITH_RANGE_TABLE_AIR_IDS, ARITH_TABLE_AIR_IDS, ZISK_AIRGROUP_ID}; +use std::sync::Arc; -use crate::{ArithFullSM, ArithRangeTableSM, ArithTableSM}; +use p3_field::PrimeField; +use sm_common::{ + ComponentProvider, Instance, InstanceExpanderCtx, Metrics, Planner, RegularCounter, +}; +use zisk_pil::{ARITH_AIR_IDS, ARITH_RANGE_TABLE_AIR_IDS, ARITH_TABLE_AIR_IDS}; -#[allow(dead_code)] -pub struct ArithSM { - // Count of registered predecessors - registered_predecessors: AtomicU32, +use crate::{ + ArithFullInstance, ArithFullSM, ArithPlanner, ArithRangeTableInstance, ArithRangeTableSM, + ArithTableInstance, ArithTableSM, +}; - arith_full_sm: Arc>, - arith_table_sm: Arc>, - arith_range_table_sm: Arc>, +pub struct ArithSM { + arith_full_sm: Arc, + arith_table_sm: Arc, + arith_range_table_sm: Arc, } -impl ArithSM { - pub fn new(wcm: Arc>) -> Arc { - let arith_table_sm = ArithTableSM::new(wcm.clone(), ZISK_AIRGROUP_ID, ARITH_TABLE_AIR_IDS); - let arith_range_table_sm = - ArithRangeTableSM::new(wcm.clone(), ZISK_AIRGROUP_ID, ARITH_RANGE_TABLE_AIR_IDS); - let arith_full_sm = ArithFullSM::new( - wcm.clone(), - arith_table_sm.clone(), - arith_range_table_sm.clone(), - ZISK_AIRGROUP_ID, - ARITH_AIR_IDS, - ); - let arith_sm = Self { - registered_predecessors: AtomicU32::new(0), - arith_full_sm, - arith_table_sm, - arith_range_table_sm, - }; - let arith_sm = Arc::new(arith_sm); +impl ArithSM { + pub fn new() -> Arc { + let arith_table_sm = ArithTableSM::new(); + let arith_range_table_sm = ArithRangeTableSM::new(); + + let arith_full_sm = ArithFullSM::new(arith_table_sm.clone(), arith_range_table_sm.clone()); - wcm.register_component(arith_sm.clone(), None, None); + let arith_sm = Self { arith_full_sm, arith_table_sm, arith_range_table_sm }; - arith_sm.arith_full_sm.register_predecessor(); + Arc::new(arith_sm) + } +} - arith_sm +impl ComponentProvider for ArithSM { + fn get_counter(&self) -> Box { + Box::new(RegularCounter::new(zisk_core::ZiskOperationType::Arith)) } - pub fn register_predecessor(&self) { - self.registered_predecessors.fetch_add(1, Ordering::SeqCst); + + fn get_planner(&self) -> Box { + Box::new(ArithPlanner::::default()) } - pub fn unregister_predecessor(&self) { - if self.registered_predecessors.fetch_sub(1, Ordering::SeqCst) == 1 { - self.arith_full_sm.unregister_predecessor(); + fn get_instance(&self, iectx: InstanceExpanderCtx) -> Box> { + match iectx.plan.air_id { + id if id == ARITH_AIR_IDS[0] => { + Box::new(ArithFullInstance::new(self.arith_full_sm.clone(), iectx)) + } + id if id == ARITH_TABLE_AIR_IDS[0] => { + Box::new(ArithTableInstance::new(self.arith_table_sm.clone(), iectx)) + } + id if id == ARITH_RANGE_TABLE_AIR_IDS[0] => { + Box::new(ArithRangeTableInstance::new(self.arith_range_table_sm.clone(), iectx)) + } + _ => panic!("BinarySM::get_instance() Unsupported air_id: {:?}", iectx.plan.air_id), } } - pub fn prove_instance( - &self, - operations: Vec, - prover_buffer: &mut [F], - offset: u64, - ) { - self.arith_full_sm.prove_instance(operations, prover_buffer, offset); - } } - -impl WitnessComponent for ArithSM {} diff --git a/state-machines/arith/src/arith_full.rs b/state-machines/arith/src/arith_full.rs index 082fb452..93d3019f 100644 --- a/state-machines/arith/src/arith_full.rs +++ b/state-machines/arith/src/arith_full.rs @@ -1,95 +1,61 @@ -use std::sync::{ - atomic::{AtomicU32, Ordering}, - Arc, -}; +use std::sync::Arc; use crate::{ ArithOperation, ArithRangeTableInputs, ArithRangeTableSM, ArithTableInputs, ArithTableSM, }; use log::info; -use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; +use p3_field::PrimeField; use proofman_util::{timer_start_trace, timer_stop_and_log_trace}; use sm_common::i64_to_u64_field; use zisk_core::{zisk_ops::ZiskOp, ZiskRequiredOperation}; use zisk_pil::*; -pub struct ArithFullSM { - wcm: Arc>, - - // Count of registered predecessors - registered_predecessors: AtomicU32, - - // Inputs - arith_table_sm: Arc>, - arith_range_table_sm: Arc>, +pub struct ArithFullSM { + arith_table_sm: Arc, + arith_range_table_sm: Arc, } -impl ArithFullSM { +impl ArithFullSM { const MY_NAME: &'static str = "Arith "; + pub fn new( - wcm: Arc>, - arith_table_sm: Arc>, - arith_range_table_sm: Arc>, - airgroup_id: usize, - air_ids: &[usize], + arith_table_sm: Arc, + arith_range_table_sm: Arc, ) -> Arc { - let arith_full_sm = Self { - wcm: wcm.clone(), - registered_predecessors: AtomicU32::new(0), - arith_table_sm, - arith_range_table_sm, - }; - let arith_full_sm = Arc::new(arith_full_sm); - - wcm.register_component(arith_full_sm.clone(), Some(airgroup_id), Some(air_ids)); - - arith_full_sm.arith_table_sm.register_predecessor(); - arith_full_sm.arith_range_table_sm.register_predecessor(); - - arith_full_sm - } - - pub fn register_predecessor(&self) { - self.registered_predecessors.fetch_add(1, Ordering::SeqCst); + Arc::new(Self { arith_table_sm, arith_range_table_sm }) } - pub fn unregister_predecessor(&self) { - if self.registered_predecessors.fetch_sub(1, Ordering::SeqCst) == 1 { - self.arith_table_sm.unregister_predecessor(); - self.arith_range_table_sm.unregister_predecessor(); - } - } - pub fn prove_instance( + pub fn prove_instance( &self, - input: Vec, - prover_buffer: &mut [F], - offset: u64, + inputs: &[ZiskRequiredOperation], + arith_trace: &mut ArithTrace, ) { let mut range_table_inputs = ArithRangeTableInputs::new(); let mut table_inputs = ArithTableInputs::new(); - let pctx = self.wcm.get_pctx(); - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, ARITH_AIR_IDS[0]); - let num_rows = air.num_rows(); + let num_rows = ArithTrace::::NUM_ROWS; + timer_start_trace!(ARITH_TRACE); info!( - "{}: ยทยทยท Creating Arith instance KKKKK [{} / {} rows filled {:.2}%]", + "{}: ยทยทยท Creating Arith instance [{} / {} rows filled {:.2}%]", Self::MY_NAME, - input.len(), + inputs.len(), num_rows, - input.len() as f64 / num_rows as f64 * 100.0 + inputs.len() as f64 / num_rows as f64 * 100.0 ); - assert!(input.len() <= num_rows); - - let mut traces = - ArithTrace::::map_buffer(prover_buffer, num_rows, offset as usize).unwrap(); + assert!(inputs.len() <= num_rows); let mut aop = ArithOperation::new(); - for (irow, input) in input.iter().enumerate() { - println!("#{} ARITH op:0x{:X} a:0x{:X} b:0x{:X}", irow, input.opcode, input.a, input.b); + for (irow, input) in inputs.iter().enumerate() { + log::debug!( + "#{} ARITH op:0x{:X} a:0x{:X} b:0x{:X}", + irow, + input.opcode, + input.a, + input.b + ); aop.calculate(input.opcode, input.a, input.b); - let mut t: ArithRow = Default::default(); + let mut t: ArithTraceRow = Default::default(); for i in [0, 2] { t.a[i] = F::from_canonical_u64(aop.a[i]); t.b[i] = F::from_canonical_u64(aop.b[i]); @@ -185,21 +151,21 @@ impl ArithFullSM { } else { aop.d[2] + (aop.d[3] << 16) }); - traces[irow] = t; + arith_trace[irow] = t; } timer_stop_and_log_trace!(ARITH_TRACE); timer_start_trace!(ARITH_PADDING); - let padding_offset = input.len(); + let padding_offset = inputs.len(); let padding_rows: usize = num_rows.saturating_sub(padding_offset); if padding_rows > 0 { - let mut t: ArithRow = Default::default(); + let mut t: ArithTraceRow = Default::default(); let padding_opcode = ZiskOp::Muluh.code(); t.op = F::from_canonical_u8(padding_opcode); t.fab = F::one(); for i in padding_offset..num_rows { - traces[i] = t; + arith_trace[i] = t; } range_table_inputs.multi_use_chunk_range_check(padding_rows * 10, 0, 0); range_table_inputs.multi_use_chunk_range_check(padding_rows * 2, 26, 0); @@ -219,14 +185,13 @@ impl ArithFullSM { ); } timer_stop_and_log_trace!(ARITH_PADDING); + timer_start_trace!(ARITH_TABLE); - info!("{}: ยทยทยท calling arit_table_sm", Self::MY_NAME); self.arith_table_sm.process_slice(&table_inputs); timer_stop_and_log_trace!(ARITH_TABLE); + timer_start_trace!(ARITH_RANGE_TABLE); self.arith_range_table_sm.process_slice(&range_table_inputs); timer_stop_and_log_trace!(ARITH_RANGE_TABLE); } } - -impl WitnessComponent for ArithFullSM {} diff --git a/state-machines/arith/src/arith_full_instance.rs b/state-machines/arith/src/arith_full_instance.rs new file mode 100644 index 00000000..21537a92 --- /dev/null +++ b/state-machines/arith/src/arith_full_instance.rs @@ -0,0 +1,61 @@ +use std::sync::Arc; + +use p3_field::PrimeField; + +use proofman_common::{AirInstance, FromTrace, ProofCtx}; +use sm_common::{InputsCollector, Instance, InstanceExpanderCtx, InstanceType}; +use zisk_core::{ZiskRequiredOperation, ZiskRom}; +use zisk_pil::ArithTrace; +use ziskemu::EmuTrace; + +use crate::ArithFullSM; + +pub struct ArithFullInstance { + /// Arith full state machine + arith_full_sm: Arc, + + /// Instance expander context + iectx: InstanceExpanderCtx, + + /// Arith trace + trace: ArithTrace, + + /// Inputs + inputs: Vec, +} + +impl ArithFullInstance { + pub fn new(arith_full_sm: Arc, iectx: InstanceExpanderCtx) -> Self { + Self { arith_full_sm, iectx, trace: ArithTrace::new(), inputs: Vec::new() } + } +} + +impl Instance for ArithFullInstance { + fn collect_inputs( + &mut self, + zisk_rom: &ZiskRom, + min_traces: &[EmuTrace], + ) -> Result<(), Box> { + self.inputs = InputsCollector::collect( + self.iectx.plan.check_point.unwrap(), + ArithTrace::::NUM_ROWS, + zisk_rom, + min_traces, + zisk_core::ZiskOperationType::Arith, + )?; + + Ok(()) + } + + fn compute_witness(&mut self, _pctx: &ProofCtx) -> Option> { + self.arith_full_sm.prove_instance(&self.inputs, &mut self.trace); + + Some(AirInstance::new_from_trace(FromTrace::new(&mut self.trace))) + } + + fn instance_type(&self) -> InstanceType { + InstanceType::Instance + } +} + +unsafe impl Sync for ArithFullInstance {} diff --git a/state-machines/arith/src/arith_planner.rs b/state-machines/arith/src/arith_planner.rs new file mode 100644 index 00000000..2f13f890 --- /dev/null +++ b/state-machines/arith/src/arith_planner.rs @@ -0,0 +1,53 @@ +use p3_field::PrimeField; +use sm_common::{plan, ChunkId, InstCount, InstanceType, Metrics, Plan, Planner, RegularCounter}; +use zisk_pil::{ + ArithTrace, ARITH_AIR_IDS, ARITH_RANGE_TABLE_AIR_IDS, ARITH_TABLE_AIR_IDS, ZISK_AIRGROUP_ID, +}; + +pub struct ArithPlanner(std::marker::PhantomData); + +impl Default for ArithPlanner { + fn default() -> Self { + Self(std::marker::PhantomData) + } +} + +impl Planner for ArithPlanner { + fn plan(&self, counters: Vec<(ChunkId, Box)>) -> Vec { + // Prepare counts for arith + let count_arith: Vec<_> = counters + .iter() + .map(|(chunk_id, counter)| { + let arith_counter = counter.as_any().downcast_ref::().unwrap(); + InstCount::new(*chunk_id, arith_counter.inst_count()) + }) + .collect(); + + let mut plan_result: Vec<_> = plan(&count_arith, ArithTrace::::NUM_ROWS as u64) + .into_iter() + .map(|checkpoint| { + Plan::new( + ZISK_AIRGROUP_ID, + ARITH_AIR_IDS[0], + None, + InstanceType::Instance, + Some(checkpoint), + None, + ) + }) + .collect(); + + for &air_id in &[ARITH_TABLE_AIR_IDS[0], ARITH_RANGE_TABLE_AIR_IDS[0]] { + plan_result.push(Plan::new( + ZISK_AIRGROUP_ID, + air_id, + None, + InstanceType::Table, + None, + None, + )); + } + + plan_result + } +} diff --git a/state-machines/arith/src/arith_range_table.rs b/state-machines/arith/src/arith_range_table.rs index 4b3dcf1f..8c9ddcc4 100644 --- a/state-machines/arith/src/arith_range_table.rs +++ b/state-machines/arith/src/arith_range_table.rs @@ -1,118 +1,29 @@ -use std::sync::{ - atomic::{AtomicU32, Ordering}, - Arc, Mutex, -}; +use std::sync::{Arc, Mutex}; use crate::ArithRangeTableInputs; -use log::info; -use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::{AirInstance, ExecutionCtx, ProofCtx, SetupCtx}; -use rayon::prelude::*; -use sm_common::create_prover_buffer; -use zisk_pil::{ARITH_RANGE_TABLE_AIR_IDS, ZISK_AIRGROUP_ID}; +use zisk_pil::ArithRangeTableTrace; -pub struct ArithRangeTableSM { - wcm: Arc>, - - // Count of registered predecessors - registered_predecessors: AtomicU32, - - // Inputs - num_rows: usize, +pub struct ArithRangeTableSM { multiplicity: Mutex>, } -impl ArithRangeTableSM { - const MY_NAME: &'static str = "ArithRT "; - - pub fn new(wcm: Arc>, airgroup_id: usize, air_ids: &[usize]) -> Arc { - let pctx = wcm.get_pctx(); - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, ARITH_RANGE_TABLE_AIR_IDS[0]); - let arith_range_table_sm = Self { - wcm: wcm.clone(), - registered_predecessors: AtomicU32::new(0), - num_rows: air.num_rows(), - multiplicity: Mutex::new(vec![0; air.num_rows()]), - }; - let arith_range_table_sm = Arc::new(arith_range_table_sm); - - wcm.register_component(arith_range_table_sm.clone(), Some(airgroup_id), Some(air_ids)); - - arith_range_table_sm +impl ArithRangeTableSM { + pub fn new() -> Arc { + Arc::new(Self { + multiplicity: Mutex::new(vec![0; ArithRangeTableTrace::::NUM_ROWS]), + }) } - pub fn register_predecessor(&self) { - self.registered_predecessors.fetch_add(1, Ordering::SeqCst); - } - - pub fn unregister_predecessor(&self) { - if self.registered_predecessors.fetch_sub(1, Ordering::SeqCst) == 1 { - self.create_air_instance(); - } - } pub fn process_slice(&self, inputs: &ArithRangeTableInputs) { - // Create the trace vector - let mut _multiplicity = self.multiplicity.lock().unwrap(); - - for (row, value) in inputs { - _multiplicity[row] += value; - } - } - pub fn create_air_instance(&self) { - let ectx = self.wcm.get_ectx(); - let mut dctx: std::sync::RwLockWriteGuard<'_, proofman_common::DistributionCtx> = - ectx.dctx.write().unwrap(); let mut multiplicity = self.multiplicity.lock().unwrap(); - let (is_myne, instance_global_idx) = - dctx.add_instance(ZISK_AIRGROUP_ID, ARITH_RANGE_TABLE_AIR_IDS[0], 1); - let owner: usize = dctx.owner(instance_global_idx); - - let mut multiplicity_ = std::mem::take(&mut *multiplicity); - dctx.distribute_multiplicity(&mut multiplicity_, owner); - - if is_myne { - // Create the prover buffer - let (mut prover_buffer, offset) = create_prover_buffer( - &self.wcm.get_ectx(), - &self.wcm.get_sctx(), - ZISK_AIRGROUP_ID, - ARITH_RANGE_TABLE_AIR_IDS[0], - ); - prover_buffer[offset as usize..offset as usize + self.num_rows] - .par_iter_mut() - .enumerate() - .for_each(|(i, input)| *input = F::from_canonical_u64(multiplicity_[i])); - - info!( - "{}: ยทยทยท Creating Binary basic table instance [{} rows filled 100%]", - Self::MY_NAME, - self.num_rows, - ); - let air_instance = AirInstance::new( - self.wcm.get_sctx(), - ZISK_AIRGROUP_ID, - ARITH_RANGE_TABLE_AIR_IDS[0], - None, - prover_buffer, - ); - self.wcm - .get_pctx() - .air_instance_repo - .add_air_instance(air_instance, Some(instance_global_idx)); + for (row, value) in inputs { + multiplicity[row] += value; } } -} -impl WitnessComponent for ArithRangeTableSM { - fn calculate_witness( - &self, - _stage: u32, - _air_instance: Option, - _pctx: Arc>, - _ectx: Arc>, - _sctx: Arc>, - ) { + pub fn detach_multiplicity(&self) -> Vec { + let mut multiplicity = self.multiplicity.lock().unwrap(); + std::mem::take(&mut *multiplicity) } } diff --git a/state-machines/arith/src/arith_range_table_instance.rs b/state-machines/arith/src/arith_range_table_instance.rs new file mode 100644 index 00000000..41af641b --- /dev/null +++ b/state-machines/arith/src/arith_range_table_instance.rs @@ -0,0 +1,49 @@ +use std::sync::Arc; + +use p3_field::PrimeField; + +use proofman_common::{AirInstance, FromTrace, ProofCtx}; +use sm_common::{Instance, InstanceExpanderCtx, InstanceType}; +use zisk_pil::ArithRangeTableTrace; + +use rayon::prelude::*; + +use crate::ArithRangeTableSM; + +pub struct ArithRangeTableInstance { + /// Arith range table state machine + arith_range_table_sm: Arc, + + /// Instance expander context + iectx: InstanceExpanderCtx, + + /// Arith range table trace + trace: ArithRangeTableTrace, +} + +impl ArithRangeTableInstance { + pub fn new(arith_range_table_sm: Arc, iectx: InstanceExpanderCtx) -> Self { + Self { arith_range_table_sm, iectx, trace: ArithRangeTableTrace::::new() } + } +} + +unsafe impl Sync for ArithRangeTableInstance {} + +impl Instance for ArithRangeTableInstance { + fn compute_witness(&mut self, pctx: &ProofCtx) -> Option> { + let mut multiplicity = self.arith_range_table_sm.detach_multiplicity(); + + pctx.dctx_distribute_multiplicity(&mut multiplicity, self.iectx.global_idx); + + self.trace.buffer[0..ArithRangeTableTrace::::NUM_ROWS] + .par_iter_mut() + .enumerate() + .for_each(|(i, input)| input.multiplicity = F::from_canonical_u64(multiplicity[i])); + + Some(AirInstance::new_from_trace(FromTrace::new(&mut self.trace))) + } + + fn instance_type(&self) -> InstanceType { + InstanceType::Table + } +} diff --git a/state-machines/arith/src/arith_table.rs b/state-machines/arith/src/arith_table.rs index 6805f407..ec712ec4 100644 --- a/state-machines/arith/src/arith_table.rs +++ b/state-machines/arith/src/arith_table.rs @@ -1,120 +1,27 @@ -use std::sync::{ - atomic::{AtomicU32, Ordering}, - Arc, Mutex, -}; +use std::sync::{Arc, Mutex}; use crate::ArithTableInputs; -use log::info; -use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::{AirInstance, ExecutionCtx, ProofCtx, SetupCtx}; -use rayon::prelude::*; -use sm_common::create_prover_buffer; -use zisk_pil::{ARITH_TABLE_AIR_IDS, ZISK_AIRGROUP_ID}; +use zisk_pil::ArithTableTrace; -pub struct ArithTableSM { - wcm: Arc>, - - // Count of registered predecessors - registered_predecessors: AtomicU32, - - // Inputs - num_rows: usize, +pub struct ArithTableSM { multiplicity: Mutex>, } -impl ArithTableSM { - const MY_NAME: &'static str = "ArithT "; - - pub fn new(wcm: Arc>, airgroup_id: usize, air_ids: &[usize]) -> Arc { - let pctx = wcm.get_pctx(); - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, ARITH_TABLE_AIR_IDS[0]); - let _arith_table_sm = Self { - wcm: wcm.clone(), - registered_predecessors: AtomicU32::new(0), - num_rows: air.num_rows(), - multiplicity: Mutex::new(vec![0; air.num_rows()]), - }; - let arith_table_sm = Arc::new(_arith_table_sm); - - wcm.register_component(arith_table_sm.clone(), Some(airgroup_id), Some(air_ids)); - - arith_table_sm +impl ArithTableSM { + pub fn new() -> Arc { + Arc::new(Self { multiplicity: Mutex::new(vec![0; ArithTableTrace::::NUM_ROWS]) }) } - pub fn register_predecessor(&self) { - self.registered_predecessors.fetch_add(1, Ordering::SeqCst); - } - - pub fn unregister_predecessor(&self) { - if self.registered_predecessors.fetch_sub(1, Ordering::SeqCst) == 1 { - self.create_air_instance(); - } - } pub fn process_slice(&self, inputs: &ArithTableInputs) { - // Create the trace vector - let mut _multiplicity = self.multiplicity.lock().unwrap(); - - info!("{}: ยทยทยท process multiplicity", Self::MY_NAME); - for (row, value) in inputs { - info!("{}: ยทยทยท Processing row {} with value {}", Self::MY_NAME, row, value); - _multiplicity[row] += value; - } - } - pub fn create_air_instance(&self) { - let ectx = self.wcm.get_ectx(); - let mut dctx: std::sync::RwLockWriteGuard<'_, proofman_common::DistributionCtx> = - ectx.dctx.write().unwrap(); let mut multiplicity = self.multiplicity.lock().unwrap(); - let (is_myne, instance_global_idx) = - dctx.add_instance(ZISK_AIRGROUP_ID, ARITH_TABLE_AIR_IDS[0], 1); - let owner: usize = dctx.owner(instance_global_idx); - - let mut multiplicity_ = std::mem::take(&mut *multiplicity); - dctx.distribute_multiplicity(&mut multiplicity_, owner); - - if is_myne { - // Create the prover buffer - let (mut prover_buffer, offset) = create_prover_buffer( - &self.wcm.get_ectx(), - &self.wcm.get_sctx(), - ZISK_AIRGROUP_ID, - ARITH_TABLE_AIR_IDS[0], - ); - prover_buffer[offset as usize..offset as usize + self.num_rows] - .par_iter_mut() - .enumerate() - .for_each(|(i, input)| *input = F::from_canonical_u64(multiplicity_[i])); - - info!( - "{}: ยทยทยท Creating Binary basic table instance [{} rows filled 100%]", - Self::MY_NAME, - self.num_rows, - ); - let air_instance = AirInstance::new( - self.wcm.get_sctx(), - ZISK_AIRGROUP_ID, - ARITH_TABLE_AIR_IDS[0], - None, - prover_buffer, - ); - self.wcm - .get_pctx() - .air_instance_repo - .add_air_instance(air_instance, Some(instance_global_idx)); + for (row, value) in inputs { + multiplicity[row] += value; } } -} -impl WitnessComponent for ArithTableSM { - fn calculate_witness( - &self, - _stage: u32, - _air_instance: Option, - _pctx: Arc>, - _ectx: Arc>, - _sctx: Arc>, - ) { + pub fn detach_multiplicity(&self) -> Vec { + let mut multiplicity = self.multiplicity.lock().unwrap(); + std::mem::take(&mut *multiplicity) } } diff --git a/state-machines/arith/src/arith_table_instance.rs b/state-machines/arith/src/arith_table_instance.rs new file mode 100644 index 00000000..91b6de91 --- /dev/null +++ b/state-machines/arith/src/arith_table_instance.rs @@ -0,0 +1,49 @@ +use std::sync::Arc; + +use p3_field::PrimeField; + +use proofman_common::{AirInstance, FromTrace, ProofCtx}; +use sm_common::{Instance, InstanceExpanderCtx, InstanceType}; +use zisk_pil::ArithTableTrace; + +use rayon::prelude::*; + +use crate::ArithTableSM; + +pub struct ArithTableInstance { + /// Arith table state machine + arith_table_sm: Arc, + + /// Instance expander context + iectx: InstanceExpanderCtx, + + /// Arith table trace + trace: ArithTableTrace, +} + +impl ArithTableInstance { + pub fn new(arith_table_sm: Arc, iectx: InstanceExpanderCtx) -> Self { + Self { arith_table_sm, iectx, trace: ArithTableTrace::::new() } + } +} + +unsafe impl Sync for ArithTableInstance {} + +impl Instance for ArithTableInstance { + fn compute_witness(&mut self, pctx: &ProofCtx) -> Option> { + let mut multiplicity = self.arith_table_sm.detach_multiplicity(); + + pctx.dctx_distribute_multiplicity(&mut multiplicity, self.iectx.global_idx); + + self.trace.buffer[0..ArithTableTrace::::NUM_ROWS] + .par_iter_mut() + .enumerate() + .for_each(|(i, input)| input.multiplicity = F::from_canonical_u64(multiplicity[i])); + + Some(AirInstance::new_from_trace(FromTrace::new(&mut self.trace))) + } + + fn instance_type(&self) -> InstanceType { + InstanceType::Table + } +} diff --git a/state-machines/arith/src/lib.rs b/state-machines/arith/src/lib.rs index 714731cd..b04bd4ed 100644 --- a/state-machines/arith/src/lib.rs +++ b/state-machines/arith/src/lib.rs @@ -1,20 +1,28 @@ mod arith; mod arith_full; +mod arith_full_instance; mod arith_operation; +mod arith_planner; mod arith_range_table; mod arith_range_table_helpers; +mod arith_range_table_instance; mod arith_table; mod arith_table_data; mod arith_table_helpers; - -#[cfg(test)] -mod arith_operation_test; +mod arith_table_instance; pub use arith::*; pub use arith_full::*; +pub use arith_full_instance::*; pub use arith_operation::*; +pub use arith_planner::*; pub use arith_range_table::*; pub use arith_range_table_helpers::*; +pub use arith_range_table_instance::*; pub use arith_table::*; pub use arith_table_data::*; pub use arith_table_helpers::*; +pub use arith_table_instance::*; + +#[cfg(test)] +mod arith_operation_test; diff --git a/state-machines/binary/Cargo.toml b/state-machines/binary/Cargo.toml index 33d2b3f2..167b0b37 100644 --- a/state-machines/binary/Cargo.toml +++ b/state-machines/binary/Cargo.toml @@ -5,14 +5,15 @@ edition = "2021" [dependencies] zisk-core = { path = "../../core" } +zisk-common = { path = "../../common" } zisk-pil = { path="../../pil" } +ziskemu = { path = "../../emulator" } sm-common = { path = "../common" } p3-field = { workspace=true } proofman-common = { workspace = true } proofman-macros = { workspace = true } proofman-util = { workspace = true } -proofman = { workspace = true } pil-std-lib = { workspace = true } log = { workspace = true } @@ -21,4 +22,4 @@ num-bigint = { workspace = true } [features] default = [] -no_lib_link = ["proofman-common/no_lib_link", "proofman/no_lib_link"] \ No newline at end of file +no_lib_link = ["proofman-common/no_lib_link"] \ No newline at end of file diff --git a/state-machines/binary/pil/binary_extension_table.pil b/state-machines/binary/pil/binary_extension_table.pil index 871debe4..6e244258 100644 --- a/state-machines/binary/pil/binary_extension_table.pil +++ b/state-machines/binary/pil/binary_extension_table.pil @@ -1,5 +1,5 @@ require "std_lookup.pil" -require "constants.pil" +require "std_constants.pil" // Operations Table: // Running Total diff --git a/state-machines/binary/pil/binary_table.pil b/state-machines/binary/pil/binary_table.pil index 2e17c36b..78581301 100644 --- a/state-machines/binary/pil/binary_table.pil +++ b/state-machines/binary/pil/binary_table.pil @@ -1,4 +1,4 @@ -require "constants.pil"; +require "std_constants.pil"; // PIL Binary Operations Table used by Binary // Running Total diff --git a/state-machines/binary/src/binary.rs b/state-machines/binary/src/binary.rs index 7dcec2c8..9b624506 100644 --- a/state-machines/binary/src/binary.rs +++ b/state-machines/binary/src/binary.rs @@ -1,157 +1,72 @@ -use std::sync::{ - atomic::{AtomicU32, Ordering}, - Arc, Mutex, -}; +use std::sync::Arc; -use crate::{BinaryBasicSM, BinaryBasicTableSM, BinaryExtensionSM, BinaryExtensionTableSM}; +use crate::{ + BinaryBasicInstance, BinaryBasicSM, BinaryBasicTableInstance, BinaryBasicTableSM, + BinaryExtensionInstance, BinaryExtensionSM, BinaryExtensionTableInstance, + BinaryExtensionTableSM, BinaryPlanner, +}; use p3_field::PrimeField; use pil_std_lib::Std; -use proofman::{WitnessComponent, WitnessManager}; -use rayon::Scope; -use sm_common::{OpResult, Provable}; -use zisk_core::ZiskRequiredOperation; +use sm_common::{ + ComponentProvider, Instance, InstanceExpanderCtx, Metrics, Planner, RegularCounters, +}; +use zisk_core::ZiskOperationType; use zisk_pil::{ BINARY_AIR_IDS, BINARY_EXTENSION_AIR_IDS, BINARY_EXTENSION_TABLE_AIR_IDS, BINARY_TABLE_AIR_IDS, - ZISK_AIRGROUP_ID, }; -const PROVE_CHUNK_SIZE: usize = 1 << 16; - #[allow(dead_code)] pub struct BinarySM { - // Count of registered predecessors - registered_predecessors: AtomicU32, - - // Inputs - inputs_basic: Mutex>, - inputs_extension: Mutex>, - // Secondary State machines - binary_basic_sm: Arc>, + binary_basic_sm: Arc, + binary_basic_table_sm: Arc, binary_extension_sm: Arc>, + binary_extension_table_sm: Arc, } impl BinarySM { - pub fn new(wcm: Arc>, std: Arc>) -> Arc { - let binary_basic_table_sm = - BinaryBasicTableSM::new(wcm.clone(), ZISK_AIRGROUP_ID, BINARY_TABLE_AIR_IDS); - let binary_basic_sm = BinaryBasicSM::new( - wcm.clone(), - binary_basic_table_sm, - ZISK_AIRGROUP_ID, - BINARY_AIR_IDS, - ); + pub fn new(std: Arc>) -> Arc { + let binary_basic_table_sm = BinaryBasicTableSM::new::(); + let binary_basic_sm = BinaryBasicSM::new(binary_basic_table_sm.clone()); - let binary_extension_table_sm = BinaryExtensionTableSM::new( - wcm.clone(), - ZISK_AIRGROUP_ID, - BINARY_EXTENSION_TABLE_AIR_IDS, - ); - let binary_extension_sm = BinaryExtensionSM::new( - wcm.clone(), - std, - binary_extension_table_sm, - ZISK_AIRGROUP_ID, - BINARY_EXTENSION_AIR_IDS, - ); + let binary_extension_table_sm = BinaryExtensionTableSM::new::(); + let binary_extension_sm = BinaryExtensionSM::new(std, binary_extension_table_sm.clone()); let binary_sm = Self { - registered_predecessors: AtomicU32::new(0), - inputs_basic: Mutex::new(Vec::new()), - inputs_extension: Mutex::new(Vec::new()), binary_basic_sm, + binary_basic_table_sm, binary_extension_sm, + binary_extension_table_sm, }; - let binary_sm = Arc::new(binary_sm); - - wcm.register_component(binary_sm.clone(), None, None); - binary_sm.binary_basic_sm.register_predecessor(); - binary_sm.binary_extension_sm.register_predecessor(); - - binary_sm + Arc::new(binary_sm) } +} - pub fn register_predecessor(&self) { - self.registered_predecessors.fetch_add(1, Ordering::SeqCst); +impl ComponentProvider for BinarySM { + fn get_counter(&self) -> Box { + Box::new(RegularCounters::new(vec![ZiskOperationType::Binary, ZiskOperationType::BinaryE])) } - pub fn unregister_predecessor(&self) { - if self.registered_predecessors.fetch_sub(1, Ordering::SeqCst) == 1 { - /* as Provable>::prove( - self, - &[], - true, - scope, - );*/ - //self.threads_controller.wait_for_threads(); - - self.binary_basic_sm.unregister_predecessor(); - self.binary_extension_sm.unregister_predecessor(); - } + fn get_planner(&self) -> Box { + Box::new(BinaryPlanner::::default()) } - pub fn prove_instance( - &self, - operations: Vec, - is_extension: bool, - prover_buffer: &mut [F], - offset: u64, - ) { - if !is_extension { - self.binary_basic_sm.prove_instance(operations, prover_buffer, offset); - } else { - self.binary_extension_sm.prove_instance(operations, prover_buffer, offset); - } - } -} - -impl WitnessComponent for BinarySM {} - -impl Provable for BinarySM { - fn prove(&self, operations: &[ZiskRequiredOperation], drain: bool, scope: &Scope) { - let mut _inputs_basic = Vec::new(); - let mut _inputs_extension = Vec::new(); - - let basic_operations = BinaryBasicSM::::operations(); - let extension_operations = BinaryExtensionSM::::operations(); - - // TODO Split the operations into basic and extended operations in parallel - for operation in operations { - if basic_operations.contains(&operation.opcode) { - _inputs_basic.push(operation.clone()); - } else if extension_operations.contains(&operation.opcode) { - _inputs_extension.push(operation.clone()); - } else { - panic!("BinarySM: Operator {:#04x} not found", operation.opcode); + fn get_instance(&self, iectx: InstanceExpanderCtx) -> Box> { + match iectx.plan.air_id { + id if id == BINARY_AIR_IDS[0] => { + Box::new(BinaryBasicInstance::new(self.binary_basic_sm.clone(), iectx)) } + id if id == BINARY_EXTENSION_AIR_IDS[0] => { + Box::new(BinaryExtensionInstance::new(self.binary_extension_sm.clone(), iectx)) + } + id if id == BINARY_TABLE_AIR_IDS[0] => { + Box::new(BinaryBasicTableInstance::new(self.binary_basic_table_sm.clone(), iectx)) + } + id if id == BINARY_EXTENSION_TABLE_AIR_IDS[0] => Box::new( + BinaryExtensionTableInstance::new(self.binary_extension_table_sm.clone(), iectx), + ), + _ => panic!("BinarySM::get_instance() Unsupported air_id: {:?}", iectx.plan.air_id), } - - let mut inputs_basic = self.inputs_basic.lock().unwrap(); - inputs_basic.extend(_inputs_basic); - - while inputs_basic.len() >= PROVE_CHUNK_SIZE || (drain && !inputs_basic.is_empty()) { - let num_drained_basic = std::cmp::min(PROVE_CHUNK_SIZE, inputs_basic.len()); - let drained_inputs_basic = inputs_basic.drain(..num_drained_basic).collect::>(); - - let binary_basic_sm_cloned = self.binary_basic_sm.clone(); - - binary_basic_sm_cloned.prove(&drained_inputs_basic, false, scope); - } - drop(inputs_basic); - - let mut inputs_extension = self.inputs_extension.lock().unwrap(); - inputs_extension.extend(_inputs_extension); - - while inputs_extension.len() >= PROVE_CHUNK_SIZE || (drain && !inputs_extension.is_empty()) - { - let num_drained_extension = std::cmp::min(PROVE_CHUNK_SIZE, inputs_extension.len()); - let drained_inputs_extension = - inputs_extension.drain(..num_drained_extension).collect::>(); - let binary_extension_sm_cloned = self.binary_extension_sm.clone(); - - binary_extension_sm_cloned.prove(&drained_inputs_extension, false, scope); - } - drop(inputs_extension); } } diff --git a/state-machines/binary/src/binary_basic.rs b/state-machines/binary/src/binary_basic.rs index 765ed11f..c82729a3 100644 --- a/state-machines/binary/src/binary_basic.rs +++ b/state-machines/binary/src/binary_basic.rs @@ -1,32 +1,17 @@ -use std::sync::{ - atomic::{AtomicU32, Ordering}, - Arc, Mutex, -}; +use std::sync::Arc; use log::info; -use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::AirInstance; +use p3_field::PrimeField; use proofman_util::{timer_start_trace, timer_stop_and_log_trace}; -use rayon::Scope; -use sm_common::{create_prover_buffer, OpResult, Provable}; use std::cmp::Ordering as CmpOrdering; use zisk_core::{zisk_ops::ZiskOp, ZiskRequiredOperation}; use zisk_pil::*; use crate::{BinaryBasicTableOp, BinaryBasicTableSM}; -pub struct BinaryBasicSM { - wcm: Arc>, - - // Count of registered predecessors - registered_predecessors: AtomicU32, - - // Inputs - inputs: Mutex>, - +pub struct BinaryBasicSM { // Secondary State machines - binary_basic_table_sm: Arc>, + binary_basic_table_sm: Arc, } #[derive(Debug)] @@ -34,45 +19,11 @@ pub enum BinaryBasicSMErr { InvalidOpcode, } -impl BinaryBasicSM { +impl BinaryBasicSM { const MY_NAME: &'static str = "Binary "; - pub fn new( - wcm: Arc>, - binary_basic_table_sm: Arc>, - airgroup_id: usize, - air_ids: &[usize], - ) -> Arc { - let binary_basic = Self { - wcm: wcm.clone(), - registered_predecessors: AtomicU32::new(0), - inputs: Mutex::new(Vec::new()), - binary_basic_table_sm, - }; - let binary_basic = Arc::new(binary_basic); - - wcm.register_component(binary_basic.clone(), Some(airgroup_id), Some(air_ids)); - - binary_basic.binary_basic_table_sm.register_predecessor(); - - binary_basic - } - - pub fn register_predecessor(&self) { - self.registered_predecessors.fetch_add(1, Ordering::SeqCst); - } - - pub fn unregister_predecessor(&self) { - if self.registered_predecessors.fetch_sub(1, Ordering::SeqCst) == 1 { - /* as Provable>::prove( - self, - &[], - true, - scope, - );*/ - - self.binary_basic_table_sm.unregister_predecessor(); - } + pub fn new(binary_basic_table_sm: Arc) -> Arc { + Arc::new(Self { binary_basic_table_sm }) } pub fn operations() -> Vec { @@ -141,12 +92,12 @@ impl BinaryBasicSM { } #[inline(always)] - pub fn process_slice( + pub fn process_slice( operation: &ZiskRequiredOperation, multiplicity: &mut [u64], - ) -> BinaryRow { + ) -> BinaryTraceRow { // Create an empty trace - let mut row: BinaryRow = Default::default(); + let mut row: BinaryTraceRow = Default::default(); // Execute the opcode let c: u64; @@ -221,7 +172,7 @@ impl BinaryBasicSM { let b_byte = if mode32 && (i >= 4) { 0 } else { b_bytes[i] }; // Store the required in the vector - let row = BinaryBasicTableSM::::calculate_table_row( + let row = BinaryBasicTableSM::calculate_table_row( if mode32 && (i >= 4) { BinaryBasicTableOp::Ext32 } else { @@ -264,7 +215,7 @@ impl BinaryBasicSM { let b_byte = if mode32 && (i >= 4) { 0 } else { b_bytes[i] }; // Store the required in the vector - let row = BinaryBasicTableSM::::calculate_table_row( + let row = BinaryBasicTableSM::calculate_table_row( if mode32 && (i >= 4) { BinaryBasicTableOp::Ext32 } else { @@ -325,7 +276,7 @@ impl BinaryBasicSM { let flags = cin + 8 * plast[i]; // Store the required in the vector - let row = BinaryBasicTableSM::::calculate_table_row( + let row = BinaryBasicTableSM::calculate_table_row( if mode32 && (i >= 4) { BinaryBasicTableOp::Ext32 } else { @@ -377,7 +328,7 @@ impl BinaryBasicSM { let flags = cin + 8 * plast[i]; // Store the required in the vector - let row = BinaryBasicTableSM::::calculate_table_row( + let row = BinaryBasicTableSM::calculate_table_row( if mode32 && (i >= 4) { BinaryBasicTableOp::Ext32 } else { @@ -423,7 +374,7 @@ impl BinaryBasicSM { let flags = cout + 8 * plast[i]; // Store the required in the vector - let row = BinaryBasicTableSM::::calculate_table_row( + let row = BinaryBasicTableSM::calculate_table_row( if mode32 && (i >= 4) { BinaryBasicTableOp::Ext32 } else { @@ -490,7 +441,7 @@ impl BinaryBasicSM { let flags = cout + 2 + 4 * result_is_a; // Store the required in the vector - let row = BinaryBasicTableSM::::calculate_table_row( + let row = BinaryBasicTableSM::calculate_table_row( if mode32 && (i >= 4) { BinaryBasicTableOp::Ext32 } else { @@ -557,7 +508,7 @@ impl BinaryBasicSM { let flags = cout + 2 + 4 * result_is_a; // Store the required in the vector - let row = BinaryBasicTableSM::::calculate_table_row( + let row = BinaryBasicTableSM::calculate_table_row( if mode32 && (i >= 4) { BinaryBasicTableOp::Ext32 } else { @@ -591,7 +542,7 @@ impl BinaryBasicSM { let flags = 0; // Store the required in the vector - let row = BinaryBasicTableSM::::calculate_table_row( + let row = BinaryBasicTableSM::calculate_table_row( binary_basic_table_op, a_bytes[i] as u64, b_bytes[i] as u64, @@ -621,7 +572,7 @@ impl BinaryBasicSM { let flags = 0; // Store the required in the vector - let row = BinaryBasicTableSM::::calculate_table_row( + let row = BinaryBasicTableSM::calculate_table_row( binary_basic_table_op, a_bytes[i] as u64, b_bytes[i] as u64, @@ -651,7 +602,7 @@ impl BinaryBasicSM { let flags = 0; // Store the required in the vector - let row = BinaryBasicTableSM::::calculate_table_row( + let row = BinaryBasicTableSM::calculate_table_row( binary_basic_table_op, a_bytes[i] as u64, b_bytes[i] as u64, @@ -683,54 +634,33 @@ impl BinaryBasicSM { row } - pub fn prove_instance( + pub fn prove_instance( &self, - operations: Vec, - prover_buffer: &mut [F], - offset: u64, - ) { - Self::prove_internal( - &self.wcm, - &self.binary_basic_table_sm, - operations, - prover_buffer, - offset, - ); - } - - fn prove_internal( - wcm: &WitnessManager, - binary_basic_table_sm: &BinaryBasicTableSM, - operations: Vec, - prover_buffer: &mut [F], - offset: u64, + operations: &[ZiskRequiredOperation], + binary_trace: &mut BinaryTrace, ) { timer_start_trace!(BINARY_TRACE); - let pctx = wcm.get_pctx(); - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_AIR_IDS[0]); - let air_binary_table = pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_TABLE_AIR_IDS[0]); - assert!(operations.len() <= air.num_rows()); + let num_rows = BinaryTrace::::NUM_ROWS; + assert!(operations.len() <= num_rows); info!( "{}: ยทยทยท Creating Binary basic instance [{} / {} rows filled {:.2}%]", Self::MY_NAME, operations.len(), - air.num_rows(), - operations.len() as f64 / air.num_rows() as f64 * 100.0 + num_rows, + operations.len() as f64 / num_rows as f64 * 100.0 ); - let mut multiplicity_table = vec![0u64; air_binary_table.num_rows()]; - let mut trace_buffer = - BinaryTrace::::map_buffer(prover_buffer, air.num_rows(), offset as usize).unwrap(); + let mut multiplicity_table = vec![0u64; BinaryTableTrace::::NUM_ROWS]; for (i, operation) in operations.iter().enumerate() { let row = Self::process_slice(operation, &mut multiplicity_table); - trace_buffer[i] = row; + binary_trace[i] = row; } timer_stop_and_log_trace!(BINARY_TRACE); timer_start_trace!(BINARY_PADDING); - let padding_row = BinaryRow:: { + let padding_row = BinaryTraceRow:: { m_op: F::from_canonical_u8(0x20), multiplicity: F::zero(), main_step: F::zero(), /* TODO: remove, since main_step is just for @@ -738,14 +668,14 @@ impl BinaryBasicSM { ..Default::default() }; - for i in operations.len()..air.num_rows() { - trace_buffer[i] = padding_row; + for i in operations.len()..num_rows { + binary_trace[i] = padding_row; } - let padding_size = air.num_rows() - operations.len(); + let padding_size = num_rows - operations.len(); for last in 0..2 { let multiplicity = (7 - 6 * last as u64) * padding_size as u64; - let row = BinaryBasicTableSM::::calculate_table_row( + let row = BinaryBasicTableSM::calculate_table_row( BinaryBasicTableOp::And, 0, 0, @@ -760,59 +690,7 @@ impl BinaryBasicSM { timer_stop_and_log_trace!(BINARY_PADDING); timer_start_trace!(BINARY_TABLE); - binary_basic_table_sm.process_slice(&multiplicity_table); + self.binary_basic_table_sm.process_slice(&multiplicity_table); timer_stop_and_log_trace!(BINARY_TABLE); - - std::thread::spawn(move || { - drop(operations); - drop(multiplicity_table); - }); - } -} - -impl WitnessComponent for BinaryBasicSM {} - -impl Provable for BinaryBasicSM { - fn prove(&self, operations: &[ZiskRequiredOperation], drain: bool, _scope: &Scope) { - if let Ok(mut inputs) = self.inputs.lock() { - inputs.extend_from_slice(operations); - - let pctx = self.wcm.get_pctx(); - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_AIR_IDS[0]); - - while inputs.len() >= air.num_rows() || (drain && !inputs.is_empty()) { - let num_drained = std::cmp::min(air.num_rows(), inputs.len()); - let drained_inputs = inputs.drain(..num_drained).collect::>(); - - let binary_basic_table_sm = self.binary_basic_table_sm.clone(); - let wcm = self.wcm.clone(); - - let sctx = self.wcm.get_sctx().clone(); - - let (mut prover_buffer, offset) = create_prover_buffer( - &wcm.get_ectx(), - &wcm.get_sctx(), - ZISK_AIRGROUP_ID, - BINARY_AIR_IDS[0], - ); - - Self::prove_internal( - &wcm, - &binary_basic_table_sm, - drained_inputs, - &mut prover_buffer, - offset, - ); - - let air_instance = AirInstance::new( - sctx, - ZISK_AIRGROUP_ID, - BINARY_AIR_IDS[0], - None, - prover_buffer, - ); - wcm.get_pctx().air_instance_repo.add_air_instance(air_instance, None); - } - } } } diff --git a/state-machines/binary/src/binary_basic_instance.rs b/state-machines/binary/src/binary_basic_instance.rs new file mode 100644 index 00000000..55715bdc --- /dev/null +++ b/state-machines/binary/src/binary_basic_instance.rs @@ -0,0 +1,61 @@ +use std::sync::Arc; + +use p3_field::PrimeField; + +use proofman_common::{AirInstance, FromTrace, ProofCtx}; +use sm_common::{InputsCollector, Instance, InstanceExpanderCtx, InstanceType}; +use zisk_core::{ZiskRequiredOperation, ZiskRom}; +use zisk_pil::BinaryTrace; +use ziskemu::EmuTrace; + +use crate::BinaryBasicSM; + +pub struct BinaryBasicInstance { + /// Binary basic state machine + binary_basic_sm: Arc, + + /// Instance expander context + iectx: InstanceExpanderCtx, + + /// Binary trace + trace: BinaryTrace, + + /// Inputs + inputs: Vec, +} + +impl BinaryBasicInstance { + pub fn new(binary_basic_sm: Arc, iectx: InstanceExpanderCtx) -> Self { + Self { binary_basic_sm, iectx, inputs: Vec::new(), trace: BinaryTrace::new() } + } +} + +impl Instance for BinaryBasicInstance { + fn collect_inputs( + &mut self, + zisk_rom: &ZiskRom, + min_traces: &[EmuTrace], + ) -> Result<(), Box> { + self.inputs = InputsCollector::collect( + self.iectx.plan.check_point.unwrap(), + self.trace.num_rows(), + zisk_rom, + min_traces, + zisk_core::ZiskOperationType::Binary, + )?; + + Ok(()) + } + + fn compute_witness(&mut self, _pctx: &ProofCtx) -> Option> { + self.binary_basic_sm.prove_instance(&self.inputs, &mut self.trace); + + Some(AirInstance::new_from_trace(FromTrace::new(&mut self.trace))) + } + + fn instance_type(&self) -> InstanceType { + InstanceType::Instance + } +} + +unsafe impl Sync for BinaryBasicInstance {} diff --git a/state-machines/binary/src/binary_basic_table.rs b/state-machines/binary/src/binary_basic_table.rs index 0adeb18e..63b49d2c 100644 --- a/state-machines/binary/src/binary_basic_table.rs +++ b/state-machines/binary/src/binary_basic_table.rs @@ -1,16 +1,8 @@ -use std::sync::{ - atomic::{AtomicU32, Ordering}, - Arc, Mutex, -}; +use std::sync::{Arc, Mutex}; -use log::info; use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::AirInstance; -use rayon::prelude::*; -use sm_common::create_prover_buffer; -use zisk_core::{zisk_ops::ZiskOp, P2_16, P2_17, P2_18, P2_19, P2_8, P2_9}; -use zisk_pil::{BINARY_TABLE_AIR_IDS, ZISK_AIRGROUP_ID}; +use zisk_core::{P2_16, P2_17, P2_18, P2_19, P2_8, P2_9}; +use zisk_pil::BinaryTableTrace; #[derive(Debug, Clone, PartialEq, Copy)] #[repr(u8)] @@ -32,68 +24,14 @@ pub enum BinaryBasicTableOp { Ext32 = 0x23, } -pub struct BinaryBasicTableSM { - wcm: Arc>, - - // Count of registered predecessors - registered_predecessors: AtomicU32, - +pub struct BinaryBasicTableSM { // Row multiplicity table - num_rows: usize, multiplicity: Mutex>, } -#[derive(Debug)] -pub enum BasicTableSMErr { - InvalidOpcode, -} - -impl BinaryBasicTableSM { - const MY_NAME: &'static str = "BinaryT "; - - pub fn new(wcm: Arc>, airgroup_id: usize, air_ids: &[usize]) -> Arc { - let pctx = wcm.get_pctx(); - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_TABLE_AIR_IDS[0]); - - let binary_basic_table = Self { - wcm: wcm.clone(), - registered_predecessors: AtomicU32::new(0), - num_rows: air.num_rows(), - multiplicity: Mutex::new(vec![0; air.num_rows()]), - }; - let binary_basic_table = Arc::new(binary_basic_table); - wcm.register_component(binary_basic_table.clone(), Some(airgroup_id), Some(air_ids)); - - binary_basic_table - } - - pub fn register_predecessor(&self) { - self.registered_predecessors.fetch_add(1, Ordering::SeqCst); - } - - pub fn unregister_predecessor(&self) { - if self.registered_predecessors.fetch_sub(1, Ordering::SeqCst) == 1 { - self.create_air_instance(); - } - } - - pub fn operations() -> Vec { - vec![ - ZiskOp::Add.code(), - ZiskOp::Sub.code(), - ZiskOp::Ltu.code(), - ZiskOp::Lt.code(), - ZiskOp::Leu.code(), - ZiskOp::Le.code(), - ZiskOp::Eq.code(), - ZiskOp::Minu.code(), - ZiskOp::Min.code(), - ZiskOp::Maxu.code(), - ZiskOp::Max.code(), - ZiskOp::And.code(), - ZiskOp::Or.code(), - ZiskOp::Xor.code(), - ] +impl BinaryBasicTableSM { + pub fn new() -> Arc { + Arc::new(Self { multiplicity: Mutex::new(vec![0; BinaryTableTrace::::NUM_ROWS]) }) } pub fn process_slice(&self, input: &[u64]) { @@ -105,6 +43,11 @@ impl BinaryBasicTableSM { } } + pub fn detach_multiplicity(&self) -> Vec { + let mut multiplicity = self.multiplicity.lock().unwrap(); + std::mem::take(&mut *multiplicity) + } + //lookup_proves(BINARY_TABLE_ID, [LAST, OP, A, B, CIN, C, FLAGS], multiplicity); #[allow(clippy::too_many_arguments)] pub fn calculate_table_row( @@ -231,51 +174,4 @@ impl BinaryBasicTableSM { //_ => panic!("BinaryBasicTableSM::offset_opcode() got invalid opcode={:?}", opcode), } } - - pub fn create_air_instance(&self) { - let ectx = self.wcm.get_ectx(); - let mut dctx: std::sync::RwLockWriteGuard<'_, proofman_common::DistributionCtx> = - ectx.dctx.write().unwrap(); - let mut multiplicity = self.multiplicity.lock().unwrap(); - - let (is_myne, instance_global_idx) = - dctx.add_instance(ZISK_AIRGROUP_ID, BINARY_TABLE_AIR_IDS[0], 1); - let owner: usize = dctx.owner(instance_global_idx); - - let mut multiplicity_ = std::mem::take(&mut *multiplicity); - dctx.distribute_multiplicity(&mut multiplicity_, owner); - - if is_myne { - // Create the prover buffer - let (mut prover_buffer, offset) = create_prover_buffer( - &self.wcm.get_ectx(), - &self.wcm.get_sctx(), - ZISK_AIRGROUP_ID, - BINARY_TABLE_AIR_IDS[0], - ); - prover_buffer[offset as usize..offset as usize + self.num_rows] - .par_iter_mut() - .enumerate() - .for_each(|(i, input)| *input = F::from_canonical_u64(multiplicity_[i])); - - info!( - "{}: ยทยทยท Creating Binary basic table instance [{} rows filled 100%]", - Self::MY_NAME, - self.num_rows, - ); - let air_instance = AirInstance::new( - self.wcm.get_sctx(), - ZISK_AIRGROUP_ID, - BINARY_TABLE_AIR_IDS[0], - None, - prover_buffer, - ); - self.wcm - .get_pctx() - .air_instance_repo - .add_air_instance(air_instance, Some(instance_global_idx)); - } - } } - -impl WitnessComponent for BinaryBasicTableSM {} diff --git a/state-machines/binary/src/binary_basic_table_instance.rs b/state-machines/binary/src/binary_basic_table_instance.rs new file mode 100644 index 00000000..21156890 --- /dev/null +++ b/state-machines/binary/src/binary_basic_table_instance.rs @@ -0,0 +1,51 @@ +use std::sync::Arc; + +use p3_field::PrimeField; + +use proofman_common::{AirInstance, FromTrace, ProofCtx}; +use sm_common::{Instance, InstanceExpanderCtx, InstanceType}; +use zisk_pil::BinaryTableTrace; + +use rayon::prelude::*; + +use crate::BinaryBasicTableSM; + +pub struct BinaryBasicTableInstance { + /// Binary basic table state machine + binary_basic_table_sm: Arc, + + /// Instance expander context + iectx: InstanceExpanderCtx, + + /// Binary basic table trace + trace: BinaryTableTrace, +} + +impl BinaryBasicTableInstance { + pub fn new(binary_basic_table_sm: Arc, iectx: InstanceExpanderCtx) -> Self { + Self { binary_basic_table_sm, iectx, trace: BinaryTableTrace::::new() } + } +} + +unsafe impl Sync for BinaryBasicTableInstance {} + +impl Instance for BinaryBasicTableInstance { + fn compute_witness(&mut self, pctx: &ProofCtx) -> Option> { + let mut multiplicity = self.binary_basic_table_sm.detach_multiplicity(); + + pctx.dctx_distribute_multiplicity(&mut multiplicity, self.iectx.global_idx); + + self.trace.buffer[0..BinaryTableTrace::::NUM_ROWS] + .par_iter_mut() + .enumerate() + .for_each(|(i, input)| input.multiplicity = F::from_canonical_u64(multiplicity[i])); + + let instance = AirInstance::new_from_trace(FromTrace::new(&mut self.trace)); + + Some(instance) + } + + fn instance_type(&self) -> InstanceType { + InstanceType::Table + } +} diff --git a/state-machines/binary/src/binary_extension.rs b/state-machines/binary/src/binary_extension.rs index eee0c226..60af9955 100644 --- a/state-machines/binary/src/binary_extension.rs +++ b/state-machines/binary/src/binary_extension.rs @@ -1,21 +1,11 @@ -use std::{ - collections::HashMap, - sync::{ - atomic::{AtomicU32, Ordering}, - Arc, Mutex, - }, -}; +use std::{collections::HashMap, sync::Arc}; use crate::{BinaryExtensionTableOp, BinaryExtensionTableSM}; use log::info; use num_bigint::BigInt; use p3_field::PrimeField; use pil_std_lib::Std; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::AirInstance; use proofman_util::{timer_start_debug, timer_stop_and_log_debug}; -use rayon::Scope; -use sm_common::{create_prover_buffer, OpResult, Provable}; use zisk_core::{zisk_ops::ZiskOp, ZiskRequiredOperation}; use zisk_pil::*; @@ -33,74 +23,27 @@ const LS_5_BITS: u64 = 0x1F; const LS_6_BITS: u64 = 0x3F; pub struct BinaryExtensionSM { - // Witness computation manager - wcm: Arc>, - // STD std: Arc>, - // Count of registered predecessors - registered_predecessors: AtomicU32, - - // Inputs - inputs: Mutex>, - // Secondary State machines - binary_extension_table_sm: Arc>, -} - -#[derive(Debug)] -pub enum BinaryExtensionSMErr { - InvalidOpcode, + binary_extension_table_sm: Arc, } impl BinaryExtensionSM { const MY_NAME: &'static str = "BinaryE "; pub fn new( - wcm: Arc>, std: Arc>, - binary_extension_table_sm: Arc>, - airgroup_id: usize, - air_ids: &[usize], + binary_extension_table_sm: Arc, ) -> Arc { - let binary_extension_sm = Self { - wcm: wcm.clone(), - std: std.clone(), - registered_predecessors: AtomicU32::new(0), - inputs: Mutex::new(Vec::new()), - binary_extension_table_sm, - }; - let binary_extension_sm = Arc::new(binary_extension_sm); - - wcm.register_component(binary_extension_sm.clone(), Some(airgroup_id), Some(air_ids)); + let binary_extension_sm = Arc::new(Self { std: std.clone(), binary_extension_table_sm }); std.register_predecessor(); - binary_extension_sm.binary_extension_table_sm.register_predecessor(); - binary_extension_sm } - pub fn register_predecessor(&self) { - self.registered_predecessors.fetch_add(1, Ordering::SeqCst); - } - - pub fn unregister_predecessor(&self) { - if self.registered_predecessors.fetch_sub(1, Ordering::SeqCst) == 1 { - /* as Provable>::prove( - self, - &[], - true, - scope, - );*/ - - self.binary_extension_table_sm.unregister_predecessor(); - - self.std.unregister_predecessor(self.wcm.get_pctx(), None); - } - } - pub fn operations() -> Vec { vec![ ZiskOp::Sll.code(), @@ -149,7 +92,7 @@ impl BinaryExtensionSM { operation: &ZiskRequiredOperation, multiplicity: &mut [u64], range_check: &mut HashMap, - ) -> BinaryExtensionRow { + ) -> BinaryExtensionTraceRow { // Get the opcode let op = operation.opcode; @@ -158,7 +101,7 @@ impl BinaryExtensionSM { // Create an empty trace let mut row = - BinaryExtensionRow:: { op: F::from_canonical_u8(op), ..Default::default() }; + BinaryExtensionTraceRow:: { op: F::from_canonical_u8(op), ..Default::default() }; // Set if the opcode is a shift operation let op_is_shift = Self::opcode_is_shift(opcode); @@ -344,7 +287,7 @@ impl BinaryExtensionSM { row.multiplicity = F::one(); for (i, a_byte) in a_bytes.iter().enumerate() { - let row = BinaryExtensionTableSM::::calculate_table_row( + let row = BinaryExtensionTableSM::calculate_table_row( binary_extension_table_op, i as u64, *a_byte as u64, @@ -364,68 +307,42 @@ impl BinaryExtensionSM { pub fn prove_instance( &self, - operations: Vec, - prover_buffer: &mut [F], - offset: u64, - ) { - Self::prove_internal( - &self.wcm, - &self.binary_extension_table_sm, - &self.std, - operations, - prover_buffer, - offset, - ); - } - - fn prove_internal( - wcm: &WitnessManager, - binary_extension_table_sm: &BinaryExtensionTableSM, - std: &Std, - operations: Vec, - prover_buffer: &mut [F], - offset: u64, + operations: &[ZiskRequiredOperation], + binary_e_trace: &mut BinaryExtensionTrace, ) { timer_start_debug!(BINARY_EXTENSION_TRACE); - let pctx = wcm.get_pctx(); - - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_EXTENSION_AIR_IDS[0]); - let air_binary_extension_table = - pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_EXTENSION_TABLE_AIR_IDS[0]); - assert!(operations.len() <= air.num_rows()); + let num_rows = BinaryExtensionTrace::::NUM_ROWS; + assert!(operations.len() <= BinaryExtensionTrace::::NUM_ROWS); info!( "{}: ยทยทยท Creating Binary extension instance [{} / {} rows filled {:.2}%]", Self::MY_NAME, operations.len(), - air.num_rows(), - operations.len() as f64 / air.num_rows() as f64 * 100.0 + num_rows, + operations.len() as f64 / num_rows as f64 * 100.0 ); - let mut multiplicity_table = vec![0u64; air_binary_extension_table.num_rows()]; + let mut multiplicity_table = vec![0u64; BinaryExtensionTableTrace::::NUM_ROWS]; let mut range_check: HashMap = HashMap::new(); - let mut trace_buffer = - BinaryExtensionTrace::::map_buffer(prover_buffer, air.num_rows(), offset as usize) - .unwrap(); for (i, operation) in operations.iter().enumerate() { let row = Self::process_slice(operation, &mut multiplicity_table, &mut range_check); - trace_buffer[i] = row; + binary_e_trace[i] = row; } timer_stop_and_log_debug!(BINARY_EXTENSION_TRACE); timer_start_debug!(BINARY_EXTENSION_PADDING); let padding_row = - BinaryExtensionRow:: { op: F::from_canonical_u64(0x25), ..Default::default() }; + BinaryExtensionTraceRow:: { op: F::from_canonical_u64(0x25), ..Default::default() }; - for i in operations.len()..air.num_rows() { - trace_buffer[i] = padding_row; + for i in operations.len()..num_rows { + binary_e_trace[i] = padding_row; } - let padding_size = air.num_rows() - operations.len(); + let padding_size = num_rows - operations.len(); for i in 0..8 { let multiplicity = padding_size as u64; - let row = BinaryExtensionTableSM::::calculate_table_row( + let row = BinaryExtensionTableSM::calculate_table_row( BinaryExtensionTableOp::SignExtendW, i, 0, @@ -436,74 +353,18 @@ impl BinaryExtensionSM { timer_stop_and_log_debug!(BINARY_EXTENSION_PADDING); timer_start_debug!(BINARY_EXTENSION_TABLE); - binary_extension_table_sm.process_slice(&multiplicity_table); + self.binary_extension_table_sm.process_slice(&multiplicity_table); timer_stop_and_log_debug!(BINARY_EXTENSION_TABLE); - let range_id = std.get_range(BigInt::from(0), BigInt::from(0xFFFFFF), None); + let range_id = self.std.get_range(BigInt::from(0), BigInt::from(0xFFFFFF), None); timer_start_debug!(BINARY_EXTENSION_RANGE); for (value, multiplicity) in &range_check { - std.range_check( + self.std.range_check( F::from_canonical_u64(*value), F::from_canonical_u64(*multiplicity), range_id, ); } timer_stop_and_log_debug!(BINARY_EXTENSION_RANGE); - - std::thread::spawn(move || { - drop(operations); - drop(multiplicity_table); - drop(range_check); - }); - } -} - -impl WitnessComponent for BinaryExtensionSM {} - -impl Provable for BinaryExtensionSM { - fn prove(&self, operations: &[ZiskRequiredOperation], drain: bool, _scope: &Scope) { - if let Ok(mut inputs) = self.inputs.lock() { - inputs.extend_from_slice(operations); - - let pctx = self.wcm.get_pctx(); - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_EXTENSION_AIR_IDS[0]); - - while inputs.len() >= air.num_rows() || (drain && !inputs.is_empty()) { - let num_drained = std::cmp::min(air.num_rows(), inputs.len()); - let drained_inputs = inputs.drain(..num_drained).collect::>(); - - let binary_extension_table_sm = self.binary_extension_table_sm.clone(); - let wcm = self.wcm.clone(); - - let std = self.std.clone(); - - let sctx = self.wcm.get_sctx().clone(); - - let (mut prover_buffer, offset) = create_prover_buffer( - &wcm.get_ectx(), - &wcm.get_sctx(), - ZISK_AIRGROUP_ID, - BINARY_EXTENSION_AIR_IDS[0], - ); - - Self::prove_internal( - &wcm, - &binary_extension_table_sm, - &std, - drained_inputs, - &mut prover_buffer, - offset, - ); - - let air_instance = AirInstance::new( - sctx, - ZISK_AIRGROUP_ID, - BINARY_EXTENSION_AIR_IDS[0], - None, - prover_buffer, - ); - wcm.get_pctx().air_instance_repo.add_air_instance(air_instance, None); - } - } } } diff --git a/state-machines/binary/src/binary_extension_instance.rs b/state-machines/binary/src/binary_extension_instance.rs new file mode 100644 index 00000000..2dc34824 --- /dev/null +++ b/state-machines/binary/src/binary_extension_instance.rs @@ -0,0 +1,66 @@ +use std::sync::Arc; + +use p3_field::PrimeField; + +use proofman_common::{AirInstance, FromTrace, ProofCtx}; +use proofman_util::{timer_start_debug, timer_stop_and_log_debug}; +use sm_common::{InputsCollector, Instance, InstanceExpanderCtx, InstanceType}; +use zisk_core::{ZiskRequiredOperation, ZiskRom}; +use zisk_pil::BinaryExtensionTrace; +use ziskemu::EmuTrace; + +use crate::BinaryExtensionSM; + +pub struct BinaryExtensionInstance { + /// Binary extension state machine + binary_extension_sm: Arc>, + + /// Instance expander context + iectx: InstanceExpanderCtx, + + /// Binary extension trace + trace: BinaryExtensionTrace, + + /// Inputs + inputs: Vec, +} + +impl BinaryExtensionInstance { + pub fn new(binary_extension_sm: Arc>, iectx: InstanceExpanderCtx) -> Self { + Self { binary_extension_sm, iectx, inputs: Vec::new(), trace: BinaryExtensionTrace::new() } + } +} + +impl Instance for BinaryExtensionInstance { + fn collect_inputs( + &mut self, + zisk_rom: &ZiskRom, + min_traces: &[EmuTrace], + ) -> Result<(), Box> { + self.inputs = InputsCollector::collect( + self.iectx.plan.check_point.unwrap(), + BinaryExtensionTrace::::NUM_ROWS, + zisk_rom, + min_traces, + zisk_core::ZiskOperationType::BinaryE, + )?; + + Ok(()) + } + + fn compute_witness(&mut self, _pctx: &ProofCtx) -> Option> { + timer_start_debug!(PROVE_BINARY); + self.binary_extension_sm.prove_instance(&self.inputs, &mut self.trace); + timer_stop_and_log_debug!(PROVE_BINARY); + + let instance = AirInstance::new_from_trace(FromTrace::new(&mut self.trace)); + + Some(instance) + } + + fn instance_type(&self) -> InstanceType { + InstanceType::Instance + } +} + +unsafe impl Sync for BinaryExtensionInstance {} diff --git a/state-machines/binary/src/binary_extension_table.rs b/state-machines/binary/src/binary_extension_table.rs index 36c64666..72357144 100644 --- a/state-machines/binary/src/binary_extension_table.rs +++ b/state-machines/binary/src/binary_extension_table.rs @@ -1,16 +1,8 @@ -use std::sync::{ - atomic::{AtomicU32, Ordering}, - Arc, Mutex, -}; +use std::sync::{Arc, Mutex}; -use log::info; use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::AirInstance; -use rayon::prelude::*; -use sm_common::create_prover_buffer; use zisk_core::{zisk_ops::ZiskOp, P2_11, P2_19, P2_8}; -use zisk_pil::{BINARY_EXTENSION_TABLE_AIR_IDS, ZISK_AIRGROUP_ID}; +use zisk_pil::BinaryExtensionTableTrace; #[derive(Debug, Clone, PartialEq, Copy)] #[repr(u8)] @@ -26,14 +18,8 @@ pub enum BinaryExtensionTableOp { SignExtendW = 0x25, } -pub struct BinaryExtensionTableSM { - wcm: Arc>, - - // Count of registered predecessors - registered_predecessors: AtomicU32, - +pub struct BinaryExtensionTableSM { // Row multiplicity table - num_rows: usize, multiplicity: Mutex>, } @@ -42,33 +28,12 @@ pub enum ExtensionTableSMErr { InvalidOpcode, } -impl BinaryExtensionTableSM { - const MY_NAME: &'static str = "BinaryET"; - - pub fn new(wcm: Arc>, airgroup_id: usize, air_ids: &[usize]) -> Arc { - let pctx = wcm.get_pctx(); - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_EXTENSION_TABLE_AIR_IDS[0]); - - let binary_extension_table = Self { - wcm: wcm.clone(), - registered_predecessors: AtomicU32::new(0), - num_rows: air.num_rows(), - multiplicity: Mutex::new(vec![0; air.num_rows()]), - }; - let binary_extension_table = Arc::new(binary_extension_table); - wcm.register_component(binary_extension_table.clone(), Some(airgroup_id), Some(air_ids)); - - binary_extension_table - } - - pub fn register_predecessor(&self) { - self.registered_predecessors.fetch_add(1, Ordering::SeqCst); - } +impl BinaryExtensionTableSM { + pub fn new() -> Arc { + let binary_extension_table = + Self { multiplicity: Mutex::new(vec![0; BinaryExtensionTableTrace::::NUM_ROWS]) }; - pub fn unregister_predecessor(&self) { - if self.registered_predecessors.fetch_sub(1, Ordering::SeqCst) == 1 { - self.create_air_instance(); - } + Arc::new(binary_extension_table) } pub fn operations() -> Vec { @@ -91,6 +56,11 @@ impl BinaryExtensionTableSM { } } + pub fn detach_multiplicity(&self) -> Vec { + let mut multiplicity = self.multiplicity.lock().unwrap(); + std::mem::take(&mut *multiplicity) + } + //lookup_proves(BINARY_EXTENSION_TABLE_ID, [OP, OFFSET, A, B, C0, C1], multiplicity); pub fn calculate_table_row(opcode: BinaryExtensionTableOp, offset: u64, a: u64, b: u64) -> u64 { // Calculate the different row offset contributors, according to the PIL @@ -120,54 +90,4 @@ impl BinaryExtensionTableSM { //_ => panic!("BinaryExtensionTableSM::offset_opcode() got invalid opcode={:?}", opcode), } } - - pub fn create_air_instance(&self) { - let ectx = self.wcm.get_ectx(); - let mut dctx: std::sync::RwLockWriteGuard<'_, proofman_common::DistributionCtx> = - ectx.dctx.write().unwrap(); - - let mut multiplicity = self.multiplicity.lock().unwrap(); - - let (is_myne, instance_global_idx) = - dctx.add_instance(ZISK_AIRGROUP_ID, BINARY_EXTENSION_TABLE_AIR_IDS[0], 1); - let owner = dctx.owner(instance_global_idx); - - let mut multiplicity_ = std::mem::take(&mut *multiplicity); - dctx.distribute_multiplicity(&mut multiplicity_, owner); - - if is_myne { - // Create the prover buffer - let (mut prover_buffer, offset) = create_prover_buffer( - &self.wcm.get_ectx(), - &self.wcm.get_sctx(), - ZISK_AIRGROUP_ID, - BINARY_EXTENSION_TABLE_AIR_IDS[0], - ); - - prover_buffer[offset as usize..offset as usize + self.num_rows] - .par_iter_mut() - .enumerate() - .for_each(|(i, input)| *input = F::from_canonical_u64(multiplicity_[i])); - - info!( - "{}: ยทยทยท Creating Binary extension table instance [{} rows filled 100%]", - Self::MY_NAME, - self.num_rows, - ); - - let air_instance = AirInstance::new( - self.wcm.get_sctx(), - ZISK_AIRGROUP_ID, - BINARY_EXTENSION_TABLE_AIR_IDS[0], - None, - prover_buffer, - ); - self.wcm - .get_pctx() - .air_instance_repo - .add_air_instance(air_instance, Some(instance_global_idx)); - } - } } - -impl WitnessComponent for BinaryExtensionTableSM {} diff --git a/state-machines/binary/src/binary_extension_table_instance.rs b/state-machines/binary/src/binary_extension_table_instance.rs new file mode 100644 index 00000000..bb0dd7bc --- /dev/null +++ b/state-machines/binary/src/binary_extension_table_instance.rs @@ -0,0 +1,54 @@ +use std::sync::Arc; + +use p3_field::PrimeField; + +use proofman_common::{AirInstance, FromTrace, ProofCtx}; +use sm_common::{Instance, InstanceExpanderCtx, InstanceType}; +use zisk_pil::BinaryExtensionTableTrace; + +use rayon::prelude::*; + +use crate::BinaryExtensionTableSM; + +pub struct BinaryExtensionTableInstance { + /// Binary extension table state machine + binary_extension_table_sm: Arc, + + /// Instance expander context + iectx: InstanceExpanderCtx, + + /// Binary extension table trace + trace: BinaryExtensionTableTrace, +} + +impl BinaryExtensionTableInstance { + pub fn new( + binary_extension_table_sm: Arc, + iectx: InstanceExpanderCtx, + ) -> Self { + Self { binary_extension_table_sm, iectx, trace: BinaryExtensionTableTrace::::new() } + } +} + +unsafe impl Sync for BinaryExtensionTableInstance {} + +impl Instance for BinaryExtensionTableInstance { + fn compute_witness(&mut self, pctx: &ProofCtx) -> Option> { + let mut multiplicity = self.binary_extension_table_sm.detach_multiplicity(); + + pctx.dctx_distribute_multiplicity(&mut multiplicity, self.iectx.global_idx); + + self.trace.buffer[0..BinaryExtensionTableTrace::::NUM_ROWS] + .par_iter_mut() + .enumerate() + .for_each(|(i, input)| input.multiplicity = F::from_canonical_u64(multiplicity[i])); + + let instance = AirInstance::new_from_trace(FromTrace::new(&mut self.trace)); + + Some(instance) + } + + fn instance_type(&self) -> InstanceType { + InstanceType::Table + } +} diff --git a/state-machines/binary/src/binary_planner.rs b/state-machines/binary/src/binary_planner.rs new file mode 100644 index 00000000..1a4e4e4e --- /dev/null +++ b/state-machines/binary/src/binary_planner.rs @@ -0,0 +1,74 @@ +use p3_field::PrimeField; +use sm_common::{plan, ChunkId, InstCount, InstanceType, Metrics, Plan, Planner, RegularCounters}; +use zisk_core::ZiskOperationType; +use zisk_pil::{ + BinaryExtensionTrace, BinaryTrace, BINARY_AIR_IDS, BINARY_EXTENSION_AIR_IDS, + BINARY_EXTENSION_TABLE_AIR_IDS, BINARY_TABLE_AIR_IDS, ZISK_AIRGROUP_ID, +}; + +pub struct BinaryPlanner(std::marker::PhantomData); + +impl Default for BinaryPlanner { + fn default() -> Self { + Self(std::marker::PhantomData) + } +} + +impl Planner for BinaryPlanner { + fn plan(&self, counters: Vec<(ChunkId, Box)>) -> Vec { + // Prepare counts for binary + let (count_binary, count_binary_e): (Vec<_>, Vec<_>) = counters + .iter() + .map(|(chunk_id, counter)| { + let binary_counter = counter.as_any().downcast_ref::().unwrap(); + ( + InstCount::new( + *chunk_id, + binary_counter.inst_count(ZiskOperationType::Binary).unwrap(), + ), + InstCount::new( + *chunk_id, + binary_counter.inst_count(ZiskOperationType::BinaryE).unwrap(), + ), + ) + }) + .collect(); + + let binaries = [ + (BINARY_AIR_IDS[0], BinaryTrace::::NUM_ROWS, count_binary), + (BINARY_EXTENSION_AIR_IDS[0], BinaryExtensionTrace::::NUM_ROWS, count_binary_e), + ]; + + let mut plan_result = Vec::new(); + for (air_id, num_rows, counts) in binaries.iter() { + let plan: Vec<_> = plan(counts, *num_rows as u64) + .into_iter() + .map(|checkpoint| { + Plan::new( + ZISK_AIRGROUP_ID, + *air_id, + None, + InstanceType::Instance, + Some(checkpoint), + None, + ) + }) + .collect(); + + plan_result.extend(plan); + } + + for &air_id in &[BINARY_TABLE_AIR_IDS[0], BINARY_EXTENSION_TABLE_AIR_IDS[0]] { + plan_result.push(Plan::new( + ZISK_AIRGROUP_ID, + air_id, + None, + InstanceType::Table, + None, + None, + )); + } + + plan_result + } +} diff --git a/state-machines/binary/src/lib.rs b/state-machines/binary/src/lib.rs index 2443c233..62ceb00a 100644 --- a/state-machines/binary/src/lib.rs +++ b/state-machines/binary/src/lib.rs @@ -1,11 +1,21 @@ mod binary; mod binary_basic; +mod binary_basic_instance; mod binary_basic_table; +mod binary_basic_table_instance; mod binary_extension; +mod binary_extension_instance; mod binary_extension_table; +mod binary_extension_table_instance; +mod binary_planner; pub use binary::*; pub use binary_basic::*; +pub use binary_basic_instance::*; pub use binary_basic_table::*; +pub use binary_basic_table_instance::*; pub use binary_extension::*; +pub use binary_extension_instance::*; pub use binary_extension_table::*; +pub use binary_extension_table_instance::*; +pub use binary_planner::*; diff --git a/state-machines/common/Cargo.toml b/state-machines/common/Cargo.toml index d0b716b8..12174c99 100644 --- a/state-machines/common/Cargo.toml +++ b/state-machines/common/Cargo.toml @@ -6,8 +6,10 @@ edition = "2021" [dependencies] ziskemu = { path = "../../emulator" } zisk-core = { path = "../../core" } +zisk-common = { path = "../../common" } proofman-common = { workspace = true } proofman-util = { workspace = true } +p3-field = { workspace = true } rayon = "1.10.0" \ No newline at end of file diff --git a/state-machines/common/src/component_counter.rs b/state-machines/common/src/component_counter.rs new file mode 100644 index 00000000..27250bdf --- /dev/null +++ b/state-machines/common/src/component_counter.rs @@ -0,0 +1,87 @@ +use std::{ + any::Any, + collections::HashMap, + fmt::Debug, + ops::{Add, AddAssign}, +}; +use zisk_core::{InstContext, ZiskInst, ZiskOperationType}; + +#[derive(Debug)] +pub enum CounterType { + Counter(Counter), + CounterStats(CounterStats), +} + +pub trait Metrics: Send + Sync + Any { + fn measure(&mut self, inst: &ZiskInst, inst_ctx: &InstContext); + + fn add(&mut self, other: &dyn Metrics); + + /// Returns the operation types that this metric is interested in. + /// This is used to filter out metrics that are not interested while executing the ROM. + /// If a Metrics is not interested in any operation types, it should return an empty vector. + /// If a Metrics is interested in all operation types, it should return a vector with a single + /// element `ZiskOperationType::None`. + fn op_type(&self) -> Vec; + + fn as_any(&self) -> &dyn Any; +} + +#[derive(Default, Debug, Clone)] +pub struct Counter { + pub inst_count: u64, +} + +impl Counter { + pub fn update(&mut self, num: u64) { + self.inst_count += num; + } +} + +impl Add for &Counter { + type Output = Counter; + + fn add(self, other: Self) -> Counter { + Counter { inst_count: self.inst_count + other.inst_count } + } +} + +impl AddAssign<&Counter> for Counter { + fn add_assign(&mut self, other: &Counter) { + self.inst_count += other.inst_count; + } +} + +#[derive(Default, Debug, Clone)] +pub struct CounterStats { + pub inst_count: HashMap, +} + +impl CounterStats { + pub fn update(&mut self, pc: u64, num: usize) { + let count = self.inst_count.entry(pc).or_default(); + *count += num as u64; + } +} + +impl Add for &CounterStats { + type Output = CounterStats; + + fn add(self, other: Self) -> CounterStats { + let mut inst_count = self.inst_count.clone(); + for (k, v) in &other.inst_count { + let count = inst_count.entry(*k).or_default(); + *count += v; + } + CounterStats { inst_count } + } +} + +impl AddAssign<&CounterStats> for CounterStats { + fn add_assign(&mut self, other: &CounterStats) { + for (k, v) in &other.inst_count { + let count = self.inst_count.entry(*k).or_default(); + *count += v; + } + } +} diff --git a/state-machines/common/src/component_instance.rs b/state-machines/common/src/component_instance.rs new file mode 100644 index 00000000..1bd2844b --- /dev/null +++ b/state-machines/common/src/component_instance.rs @@ -0,0 +1,26 @@ +use p3_field::PrimeField; +use proofman_common::{AirInstance, ProofCtx}; +use zisk_core::ZiskRom; +use ziskemu::EmuTrace; + +#[derive(PartialEq)] +pub enum InstanceType { + Instance, + Table, +} + +pub trait Instance: Send + Sync { + fn collect_inputs( + &mut self, + zisk_rom: &ZiskRom, + min_traces: &[EmuTrace], + ) -> Result<(), Box> { + let _ = zisk_rom; + let _ = min_traces; + Ok(()) + } + + fn compute_witness(&mut self, pctx: &ProofCtx) -> Option>; + + fn instance_type(&self) -> InstanceType; +} diff --git a/state-machines/common/src/component_planner.rs b/state-machines/common/src/component_planner.rs new file mode 100644 index 00000000..6a0026f8 --- /dev/null +++ b/state-machines/common/src/component_planner.rs @@ -0,0 +1,45 @@ +use std::any::Any; + +use crate::{InstanceType, Metrics}; + +pub type ChunkId = usize; + +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct CheckPoint { + pub chunk_id: ChunkId, + // offset inside the chunk to start the trace. The offset corresponds to the number of + // instructions that the sorveyor has seen. + pub skip: u64, +} + +impl CheckPoint { + pub fn new(chunk_id: ChunkId, offset: u64) -> Self { + CheckPoint { chunk_id, skip: offset } + } +} + +pub struct Plan { + pub airgroup_id: usize, + pub air_id: usize, + pub segment_id: Option, + pub instance_type: InstanceType, + pub check_point: Option, + pub meta: Option>, +} + +impl Plan { + pub fn new( + airgroup_id: usize, + air_id: usize, + segment_id: Option, + instance_type: InstanceType, + checkpoint: Option, + meta: Option>, + ) -> Self { + Plan { airgroup_id, air_id, segment_id, instance_type, check_point: checkpoint, meta } + } +} + +pub trait Planner { + fn plan(&self, counter: Vec<(ChunkId, Box)>) -> Vec; +} diff --git a/state-machines/common/src/component_provider.rs b/state-machines/common/src/component_provider.rs new file mode 100644 index 00000000..b67b87db --- /dev/null +++ b/state-machines/common/src/component_provider.rs @@ -0,0 +1,9 @@ +use p3_field::PrimeField; + +use crate::{Instance, InstanceExpanderCtx, Metrics, Planner}; + +pub trait ComponentProvider: Send + Sync { + fn get_counter(&self) -> Box; + fn get_planner(&self) -> Box; + fn get_instance(&self, iectx: InstanceExpanderCtx) -> Box>; +} diff --git a/state-machines/common/src/counters/dummy_counter.rs b/state-machines/common/src/counters/dummy_counter.rs new file mode 100644 index 00000000..4ea8c0d0 --- /dev/null +++ b/state-machines/common/src/counters/dummy_counter.rs @@ -0,0 +1,21 @@ +use std::any::Any; + +use crate::Metrics; +use zisk_core::{InstContext, ZiskInst, ZiskOperationType}; + +#[derive(Default)] +pub struct DummyCounter {} + +impl Metrics for DummyCounter { + fn measure(&mut self, _: &ZiskInst, _: &InstContext) {} + + fn add(&mut self, _: &dyn Metrics) {} + + fn op_type(&self) -> Vec { + vec![] + } + + fn as_any(&self) -> &dyn Any { + self + } +} diff --git a/state-machines/common/src/counters/mod.rs b/state-machines/common/src/counters/mod.rs new file mode 100644 index 00000000..c5efd65a --- /dev/null +++ b/state-machines/common/src/counters/mod.rs @@ -0,0 +1,7 @@ +mod dummy_counter; +mod regular_counter; +mod regular_counters; + +pub use dummy_counter::*; +pub use regular_counter::*; +pub use regular_counters::*; diff --git a/state-machines/common/src/counters/regular_counter.rs b/state-machines/common/src/counters/regular_counter.rs new file mode 100644 index 00000000..93e0193a --- /dev/null +++ b/state-machines/common/src/counters/regular_counter.rs @@ -0,0 +1,51 @@ +use std::ops::Add; + +use crate::{Counter, Metrics}; +use zisk_core::{InstContext, ZiskInst, ZiskOperationType}; + +pub struct RegularCounter { + op_type: ZiskOperationType, + counter: Counter, +} + +impl RegularCounter { + pub fn new(op_type: ZiskOperationType) -> Self { + Self { op_type, counter: Counter::default() } + } + + pub fn inst_count(&self) -> u64 { + self.counter.inst_count + } +} + +impl Metrics for RegularCounter { + fn measure(&mut self, inst: &ZiskInst, _: &InstContext) { + if inst.op_type == self.op_type { + self.counter.update(1); + } + } + + fn add(&mut self, other: &dyn Metrics) { + let other = other + .as_any() + .downcast_ref::() + .expect("Regular Metrics: Failed to downcast"); + self.counter += &other.counter; + } + + fn op_type(&self) -> Vec { + vec![self.op_type] + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } +} + +impl Add for RegularCounter { + type Output = RegularCounter; + + fn add(self, other: Self) -> RegularCounter { + RegularCounter { op_type: self.op_type, counter: &self.counter + &other.counter } + } +} diff --git a/state-machines/common/src/counters/regular_counters.rs b/state-machines/common/src/counters/regular_counters.rs new file mode 100644 index 00000000..7075f5b8 --- /dev/null +++ b/state-machines/common/src/counters/regular_counters.rs @@ -0,0 +1,63 @@ +use std::ops::Add; + +use crate::{Counter, Metrics}; +use zisk_core::{InstContext, ZiskInst, ZiskOperationType}; + +pub struct RegularCounters { + op_type: Vec, + counter: Vec, +} + +impl RegularCounters { + pub fn new(op_type: Vec) -> Self { + let counter = vec![Counter::default(); op_type.len()]; + Self { op_type, counter } + } + + pub fn inst_count(&self, op_type: ZiskOperationType) -> Option { + if let Some(index) = self.op_type.iter().position(|&_op_type| op_type == _op_type) { + return Some(self.counter[index].inst_count); + } + None + } +} + +impl Metrics for RegularCounters { + fn measure(&mut self, inst: &ZiskInst, _: &InstContext) { + if let Some(index) = self.op_type.iter().position(|&op_type| op_type == inst.op_type) { + self.counter[index].update(1); + } + } + + fn add(&mut self, other: &dyn Metrics) { + let other = other + .as_any() + .downcast_ref::() + .expect("Regular Metrics: Failed to downcast"); + for (counter, other_counter) in self.counter.iter_mut().zip(other.counter.iter()) { + *counter += other_counter; + } + } + + fn op_type(&self) -> Vec { + self.op_type.clone() + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } +} + +impl Add for RegularCounters { + type Output = RegularCounters; + + fn add(self, other: Self) -> RegularCounters { + let counter = self + .counter + .into_iter() + .zip(other.counter) + .map(|(counter, other_counter)| &counter + &other_counter) + .collect(); + RegularCounters { op_type: self.op_type, counter } + } +} diff --git a/state-machines/common/src/instance_expander.rs b/state-machines/common/src/instance_expander.rs new file mode 100644 index 00000000..1a4d663c --- /dev/null +++ b/state-machines/common/src/instance_expander.rs @@ -0,0 +1,14 @@ +use crate::Plan; + +pub struct InstanceExpanderCtx { + pub plan: Plan, + pub global_idx: usize, +} + +impl InstanceExpanderCtx { + pub fn new(global_idx: usize, plan: Plan) -> Self { + Self { plan, global_idx } + } +} + +unsafe impl Send for InstanceExpanderCtx {} diff --git a/state-machines/common/src/instance_observer/inputs_collector.rs b/state-machines/common/src/instance_observer/inputs_collector.rs new file mode 100644 index 00000000..2eb18047 --- /dev/null +++ b/state-machines/common/src/instance_observer/inputs_collector.rs @@ -0,0 +1,62 @@ +use crate::CheckPoint; +use zisk_common::InstObserver; +use zisk_core::{InstContext, ZiskInst, ZiskOperationType, ZiskRequiredOperation}; + +use zisk_core::ZiskRom; +use ziskemu::{EmuTrace, ZiskEmulator}; + +pub struct InputsCollector { + check_point: CheckPoint, + num_rows: usize, + op_type: ZiskOperationType, + + skipping: bool, + skipped: u64, + inputs: Vec, +} + +impl InputsCollector { + pub fn collect( + check_point: CheckPoint, + num_rows: usize, + zisk_rom: &ZiskRom, + min_traces: &[EmuTrace], + op_type: ZiskOperationType, + ) -> Result, Box> { + let mut instance = + Self { check_point, num_rows, skipping: true, skipped: 0, inputs: Vec::new(), op_type }; + + let chunk_id = instance.check_point.chunk_id; + + let observer: &mut dyn InstObserver = &mut instance; + + ZiskEmulator::process_rom_slice_plan(zisk_rom, min_traces, chunk_id, observer); + + Ok(std::mem::take(&mut instance.inputs)) + } +} + +impl InstObserver for InputsCollector { + #[inline(always)] + fn on_instruction(&mut self, zisk_inst: &ZiskInst, inst_ctx: &InstContext) -> bool { + if zisk_inst.op_type != self.op_type { + return false; + } + + if self.skipping { + if self.check_point.skip == 0 || self.skipped == self.check_point.skip { + self.skipping = false; + } else { + self.skipped += 1; + return false; + } + } + + let a = if zisk_inst.m32 { inst_ctx.a & 0xffffffff } else { inst_ctx.a }; + let b = if zisk_inst.m32 { inst_ctx.b & 0xffffffff } else { inst_ctx.b }; + + self.inputs.push(ZiskRequiredOperation { step: inst_ctx.step, opcode: zisk_inst.op, a, b }); + + self.inputs.len() == self.num_rows + } +} diff --git a/state-machines/common/src/instance_observer/mod.rs b/state-machines/common/src/instance_observer/mod.rs new file mode 100644 index 00000000..876c0a8e --- /dev/null +++ b/state-machines/common/src/instance_observer/mod.rs @@ -0,0 +1,3 @@ +mod inputs_collector; + +pub use inputs_collector::*; diff --git a/state-machines/common/src/lib.rs b/state-machines/common/src/lib.rs index bb6f10ee..73782c61 100644 --- a/state-machines/common/src/lib.rs +++ b/state-machines/common/src/lib.rs @@ -1,33 +1,25 @@ +mod component_counter; +mod component_instance; +mod component_planner; +mod component_provider; +mod counters; mod field; +mod instance_expander; +mod instance_observer; mod operations; +mod planner_helpers; mod provable; -mod session; -mod temp; -mod worker; +mod witness_buffer; +pub use component_counter::*; +pub use component_instance::*; +pub use component_planner::*; +pub use component_provider::*; +pub use counters::*; pub use field::*; +pub use instance_expander::*; +pub use instance_observer::*; pub use operations::*; -use proofman_common::{ExecutionCtx, SetupCtx}; -use proofman_util::create_buffer_fast; +pub use planner_helpers::*; pub use provable::*; -pub use session::*; -pub use temp::*; -pub use worker::*; - -pub fn create_prover_buffer( - ectx: &ExecutionCtx, - sctx: &SetupCtx, - airgroup_id: usize, - air_id: usize, -) -> (Vec, u64) { - // Compute buffer size using the BufferAllocator - let (buffer_size, offsets) = ectx - .buffer_allocator - .as_ref() - .get_buffer_info(sctx, airgroup_id, air_id) - .unwrap_or_else(|err| panic!("Error getting buffer info: {}", err)); - - let buffer = create_buffer_fast(buffer_size as usize); - - (buffer, offsets[0]) -} +pub use witness_buffer::*; diff --git a/state-machines/common/src/planner_helpers.rs b/state-machines/common/src/planner_helpers.rs new file mode 100644 index 00000000..f5329e22 --- /dev/null +++ b/state-machines/common/src/planner_helpers.rs @@ -0,0 +1,126 @@ +use crate::CheckPoint; + +#[derive(Debug)] +pub struct InstCount { + pub chunk_id: usize, + pub inst_count: u64, +} + +impl InstCount { + pub fn new(chunk_id: usize, inst_count: u64) -> Self { + InstCount { chunk_id, inst_count } + } +} + +/// Generates a list of checkpoints from instruction counts in multiple chunks. +/// +/// # Arguments +/// - `counts`: A vector of `InstCount` structs, each representing the number of instructions in a +/// chunk. +/// - `size`: The number of instructions at which to place checkpoints. +/// +/// # Returns +/// A vector of `CheckPoint` structs, each representing a checkpoint with its associated chunk ID +/// and offset. +/// +/// # Example +/// ``` +/// use sm_common::{plan, CheckPoint, InstCount}; +/// +/// let counts = vec![InstCount::new(0, 500), InstCount::new(1, 700), InstCount::new(2, 300)]; +/// let size = 300; +/// let checkpoints = plan(&counts, size); +/// assert_eq!( +/// checkpoints, +/// vec![ +/// CheckPoint::new(0, 0), +/// CheckPoint::new(0, 300), +/// CheckPoint::new(1, 100), +/// CheckPoint::new(1, 400), +/// CheckPoint::new(2, 0), +/// ] +/// ); +/// ``` +pub fn plan(counts: &[InstCount], size: u64) -> Vec { + if counts.is_empty() { + return vec![]; + } + + let mut checkpoints = vec![CheckPoint::new(0, 0)]; + + let mut offset = 0i64; + + let size = size as i64; + + for (current_chunk, count) in counts.iter().enumerate() { + let inst_count = count.inst_count as i64; + + // Add checkpoints within the current chunk + while offset + size < inst_count { + offset += size; + checkpoints.push(CheckPoint::new(current_chunk, offset as u64)); + } + + // Carry over remaining instructions to the next chunk + offset -= inst_count; + } + + checkpoints +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_plan_basic() { + let counts = vec![InstCount::new(0, 500), InstCount::new(1, 700), InstCount::new(2, 300)]; + let size = 300; + let checkpoints = plan(&counts, size); + assert_eq!( + checkpoints, + vec![ + CheckPoint::new(0, 0), + CheckPoint::new(0, 300), + CheckPoint::new(1, 100), + CheckPoint::new(1, 400), + CheckPoint::new(2, 0), + ] + ); + } + + #[test] + fn test_plan_single_chunk() { + let counts = vec![InstCount { chunk_id: 0, inst_count: 1000 }]; + let size = 250; + let checkpoints = plan(&counts, size); + assert_eq!( + checkpoints, + vec![ + CheckPoint::new(0, 0), + CheckPoint::new(0, 250), + CheckPoint::new(0, 500), + CheckPoint::new(0, 750), + ] + ); + } + + #[test] + fn test_plan_small_chunks() { + let counts = vec![InstCount::new(0, 100), InstCount::new(1, 150)]; + let size = 200; + let checkpoints = plan(&counts, size); + assert_eq!(checkpoints, vec![CheckPoint::new(0, 0), CheckPoint::new(1, 100),]); + } + + #[test] + fn test_plan_no_remainder() { + let counts = vec![ + InstCount { chunk_id: 0, inst_count: 300 }, + InstCount { chunk_id: 1, inst_count: 300 }, + ]; + let size = 300; + let checkpoints = plan(&counts, size); + assert_eq!(checkpoints, vec![CheckPoint::new(0, 0), CheckPoint::new(1, 0),]); + } +} diff --git a/state-machines/common/src/session.rs b/state-machines/common/src/session.rs deleted file mode 100644 index 5222c451..00000000 --- a/state-machines/common/src/session.rs +++ /dev/null @@ -1,122 +0,0 @@ -use std::{ - collections::HashMap, - sync::{Arc, Mutex}, -}; - -pub trait CalculateProver { - fn calculate(&self, operation: O) -> OR; - - fn prove(&mut self, operations: &[O]); - - fn calculate_prove(&mut self, operation: O) -> OR; -} -pub trait Sessionable { - fn when_closed(&self); - fn terminate(&self); -} - -pub type SessionId = usize; -type ComponentId = usize; - -struct ComponentSessions { - sessions: HashMap, - component: Arc, -} - -impl ComponentSessions { - pub fn new(component: Arc) -> Self { - Self { sessions: HashMap::new(), component } - } -} - -pub struct SessionsInner { - component_sessions: HashMap, - session_map: HashMap, -} - -pub struct Sessions { - inner: Mutex, -} - -impl Default for Sessions { - fn default() -> Self { - Self::new() - } -} - -unsafe impl Send for Sessions {} -unsafe impl Sync for Sessions {} - -impl Sessions { - pub fn new() -> Self { - Self { - inner: Mutex::new(SessionsInner { - component_sessions: HashMap::new(), - session_map: HashMap::new(), - }), - } - } - - fn get_unique_id(arc: &Arc) -> ComponentId { - Arc::as_ptr(arc) as *const () as usize - } - - pub fn open_session(&self, component: Arc) -> SessionId { - let mut inner = self.inner.lock().unwrap(); - - let session_id = inner.session_map.len(); - let component_id = Self::get_unique_id(&component); - - let component_session = inner - .component_sessions - .entry(component_id) - .or_insert_with(|| ComponentSessions::new(component.clone())); - - component_session.sessions.insert(session_id, true); - - inner.session_map.insert(session_id, component_id); - println!("Opened session {}", session_id); - session_id - } - - pub fn close_session(&self, session_id: SessionId) -> Result<(), Box> { - println!("Closing session {}", session_id); - let mut inner = self.inner.lock().unwrap(); - - let component_id = match inner.session_map.get(&session_id) { - Some(&id) => id, - None => return Err(format!("Session {} not found", session_id).into()), - }; - - let component_sessions = match inner.component_sessions.get_mut(&component_id) { - Some(sessions) => sessions, - None => return Err(format!("Component {} not found", component_id).into()), - }; - - if !component_sessions.sessions.contains_key(&session_id) { - return Err(format!("Session {} is not found", session_id).into()); - } - - component_sessions - .sessions - .remove(&session_id) - .ok_or_else(|| format!("Session {} is already closed", session_id))?; - - // Check if `when_closed` needs to be called - let should_call_when_closed = component_sessions.sessions.is_empty(); - - // Optionally clone the component if `when_closed` will be called - let component = - if should_call_when_closed { Some(component_sessions.component.clone()) } else { None }; - - // Drop the lock by explicitly dropping `inner` - drop(inner); - - // Call `when_closed` outside the lock - if let Some(component) = component { - component.when_closed(); - } - - Ok(()) - } -} diff --git a/state-machines/common/src/temp.rs b/state-machines/common/src/temp.rs deleted file mode 100644 index 4545bdb9..00000000 --- a/state-machines/common/src/temp.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::error::Error; - -#[derive(Debug)] -pub struct EmuTrace { - pub a: u64, - pub b: u64, -} - -pub trait Emulator { - fn emulate( - &self, - freq: usize, - callback: impl Fn(Vec), - ) -> Result, Box>; -} - -pub struct MockEmulator {} - -impl Emulator for MockEmulator { - fn emulate( - &self, - freq: usize, - callback: impl Fn(Vec), - ) -> Result, Box> { - let mut inputs = Vec::with_capacity(freq); - - for i in 0..(1 << 6) + 3 { - inputs.push(EmuTrace { a: i, b: i + 1 }); - - if inputs.len() == freq { - callback(std::mem::take(&mut inputs)); - } - } - - if !inputs.is_empty() { - println!("Emulator: Flushing Remaining inputs {:?}", inputs); - callback(inputs); - } - - Ok(vec![1, 2, 3, 4, 5]) - } -} diff --git a/state-machines/common/src/witness_buffer.rs b/state-machines/common/src/witness_buffer.rs new file mode 100644 index 00000000..040c0367 --- /dev/null +++ b/state-machines/common/src/witness_buffer.rs @@ -0,0 +1,12 @@ +use p3_field::PrimeField; + +pub struct WitnessBuffer { + pub buffer: Vec, + pub offset: u64, +} + +impl WitnessBuffer { + pub fn new(buffer: Vec, offset: u64) -> Self { + Self { buffer, offset } + } +} diff --git a/state-machines/common/src/worker.rs b/state-machines/common/src/worker.rs deleted file mode 100644 index bd14abac..00000000 --- a/state-machines/common/src/worker.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::{ - sync::{mpsc::Sender, Mutex}, - thread, -}; - -pub enum WorkerTask { - Prove(Box>), - Finish, -} - -pub struct WorkerHandler { - tx: Sender>, - worker_handle: Mutex>>, -} - -impl WorkerHandler { - pub fn new(tx: Sender>, worker_handle: thread::JoinHandle<()>) -> Self { - Self { tx, worker_handle: Mutex::new(Some(worker_handle)) } - } - - pub fn send(&self, task: WorkerTask) { - if let Err(e) = self.tx.send(task) { - eprintln!("Failed to send a task: {:?}", e); - } - } - - pub fn terminate(&self) { - // Send a shutdown signal to ensure the worker thread notices the shutdown - self.send(WorkerTask::Finish); - - self.worker_handle.lock().unwrap().take().unwrap().join().unwrap(); - } -} diff --git a/state-machines/freq-ops/Cargo.toml b/state-machines/freq-ops/Cargo.toml deleted file mode 100644 index ee6ddfab..00000000 --- a/state-machines/freq-ops/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "sm-freq-ops" -version = "0.1.0" -edition = "2021" - -[dependencies] -zisk-core = { path = "../../core" } -sm-common = { path = "../common" } - -p3-field = { workspace=true } -proofman-common = { workspace = true } -proofman-macros = { workspace = true } -proofman = { workspace = true } - -log = { workspace = true } -rayon = { workspace = true } - -[features] -default = [] -no_lib_link = ["proofman-common/no_lib_link", "proofman/no_lib_link"] \ No newline at end of file diff --git a/state-machines/freq-ops/pil/freq_ops.pil b/state-machines/freq-ops/pil/freq_ops.pil deleted file mode 100644 index e69de29b..00000000 diff --git a/state-machines/freq-ops/src/freq_ops.rs b/state-machines/freq-ops/src/freq_ops.rs deleted file mode 100644 index 56bc4190..00000000 --- a/state-machines/freq-ops/src/freq_ops.rs +++ /dev/null @@ -1,92 +0,0 @@ -use std::sync::{ - atomic::{AtomicU32, Ordering}, - Arc, Mutex, -}; - -use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::{ExecutionCtx, ProofCtx, SetupCtx}; -use rayon::Scope; -use sm_common::{OpResult, Provable}; -use zisk_core::ZiskRequiredOperation; - -const PROVE_CHUNK_SIZE: usize = 1 << 12; - -pub struct FreqOpsSM { - // Count of registered predecessors - registered_predecessors: AtomicU32, - - // Inputs - inputs: Mutex>, -} - -impl FreqOpsSM { - pub fn new(wcm: &mut WitnessManager, airgroup_id: usize, air_ids: &[usize]) -> Arc { - let freqop_sm = - Self { registered_predecessors: AtomicU32::new(0), inputs: Mutex::new(Vec::new()) }; - let freqop_sm = Arc::new(freqop_sm); - - wcm.register_component(freqop_sm.clone(), Some(airgroup_id), Some(air_ids)); - - freqop_sm - } - - pub fn register_predecessor(&self) { - self.registered_predecessors.fetch_add(1, Ordering::SeqCst); - } - - pub fn unregister_predecessor(&self, scope: &Scope) { - if self.registered_predecessors.fetch_sub(1, Ordering::SeqCst) == 1 { - >::prove(self, &[], true, scope); - } - } -} - -impl WitnessComponent for FreqOpsSM { - fn calculate_witness( - &self, - _stage: u32, - _air_instance: Option, - _pctx: Arc>, - _ectx: Arc>, - _sctx: Arc>, - ) { - } -} - -impl Provable for FreqOpsSM { - fn calculate( - &self, - _operation: ZiskRequiredOperation, - ) -> Result> { - unimplemented!() - } - - fn prove(&self, operations: &[ZiskRequiredOperation], drain: bool, scope: &Scope) { - if let Ok(mut inputs) = self.inputs.lock() { - inputs.extend_from_slice(operations); - - while inputs.len() >= PROVE_CHUNK_SIZE || (drain && !inputs.is_empty()) { - let num_drained = std::cmp::min(PROVE_CHUNK_SIZE, inputs.len()); - let _drained_inputs = inputs.drain(..num_drained).collect::>(); - - scope.spawn(move |_| { - // TODO! Implement prove drained_inputs (a chunk of operations) - }); - } - } - } - - fn calculate_prove( - &self, - operation: ZiskRequiredOperation, - drain: bool, - scope: &Scope, - ) -> Result> { - let result = self.calculate(operation.clone()); - - self.prove(&[operation], drain, scope); - - result - } -} diff --git a/state-machines/freq-ops/src/freq_ops_trace.rs b/state-machines/freq-ops/src/freq_ops_trace.rs deleted file mode 100644 index 4ac5308b..00000000 --- a/state-machines/freq-ops/src/freq_ops_trace.rs +++ /dev/null @@ -1,4 +0,0 @@ -use proofman_common as common; -pub use proofman_macros::trace; - -trace!(FreqOpsRow, FreqOpsTrace { fake: F }); diff --git a/state-machines/freq-ops/src/lib.rs b/state-machines/freq-ops/src/lib.rs deleted file mode 100644 index 282919bd..00000000 --- a/state-machines/freq-ops/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod freq_ops; -mod freq_ops_trace; - -pub use freq_ops::*; -pub use freq_ops_trace::*; diff --git a/state-machines/main/Cargo.toml b/state-machines/main/Cargo.toml index abaf42e3..0e585cb7 100644 --- a/state-machines/main/Cargo.toml +++ b/state-machines/main/Cargo.toml @@ -15,11 +15,10 @@ zisk-pil = { path = "../../pil" } proofman-common = { workspace = true } proofman-util = { workspace = true } -proofman = { workspace = true } p3-field = { workspace = true } log = { workspace = true } rayon = { workspace = true } [features] default = [] -no_lib_link = ["proofman-common/no_lib_link", "proofman/no_lib_link"] \ No newline at end of file +no_lib_link = ["proofman-common/no_lib_link"] \ No newline at end of file diff --git a/state-machines/main/pil/main.pil b/state-machines/main/pil/main.pil index 027bee94..6cd1deaf 100644 --- a/state-machines/main/pil/main.pil +++ b/state-machines/main/pil/main.pil @@ -274,6 +274,6 @@ airtemplate Main(int N = 2**21, int RC = 2, int stack_enabled = 0, const int ope lookup_assumes(ROM_BUS_ID, [pc, a_offset_imm0, a_imm1, b_offset_imm0, b_imm1, ind_width, op, store_offset, jmp_offset1, jmp_offset2, rom_flags], sel: 1 - SEGMENT_L1); - direct_update(MAIN_CONTINUATION_ID, cols: [0, 0, 4096, 0, 0], bus_type: PIOP_BUS_SUM, proves: 1); - direct_update(MAIN_CONTINUATION_ID, cols: [0, 1, 0x10000000, 0, 0], bus_type: PIOP_BUS_SUM, proves: 0); -} \ No newline at end of file + direct_global_update(MAIN_CONTINUATION_ID, cols: [0, 0, 4096, 0, 0, 0, 0, 0], bus_type: PIOP_BUS_SUM, proves: 1); + direct_global_update(MAIN_CONTINUATION_ID, cols: [0, 1, 0x10000000, 0, 0, 0, 0, 0], bus_type: PIOP_BUS_SUM, proves: 0); +} diff --git a/state-machines/main/src/instance_extension.rs b/state-machines/main/src/instance_extension.rs deleted file mode 100644 index 42aea872..00000000 --- a/state-machines/main/src/instance_extension.rs +++ /dev/null @@ -1,35 +0,0 @@ -use proofman_common::AirInstance; -use zisk_core::ZiskOperationType; -use ziskemu::EmuTraceStart; - -pub struct InstanceExtensionCtx { - pub prover_buffer: Vec, - pub offset: u64, - pub op_type: ZiskOperationType, - pub emu_trace_start: EmuTraceStart, - pub segment_id: Option, - pub instance_global_idx: usize, - pub air_instance: Option>, -} - -impl InstanceExtensionCtx { - pub fn new( - prover_buffer: Vec, - offset: u64, - op_type: ZiskOperationType, - emu_trace_start: EmuTraceStart, - segment_id: Option, - instance_global_idx: usize, - air_instance: Option>, - ) -> Self { - Self { - prover_buffer, - offset, - op_type, - emu_trace_start, - instance_global_idx, - segment_id, - air_instance, - } - } -} diff --git a/state-machines/main/src/lib.rs b/state-machines/main/src/lib.rs index d4e2d658..500eeac5 100644 --- a/state-machines/main/src/lib.rs +++ b/state-machines/main/src/lib.rs @@ -1,5 +1,3 @@ -mod instance_extension; mod main_sm; -pub use instance_extension::*; pub use main_sm::*; diff --git a/state-machines/main/src/main_sm.rs b/state-machines/main/src/main_sm.rs index 30240f83..44268288 100644 --- a/state-machines/main/src/main_sm.rs +++ b/state-machines/main/src/main_sm.rs @@ -1,23 +1,14 @@ use log::info; use p3_field::PrimeField; +use sm_common::InstanceExpanderCtx; -use crate::InstanceExtensionCtx; -use proofman_util::{timer_start_debug, timer_stop_and_log_debug}; -use sm_binary::BinarySM; use std::sync::Arc; use zisk_core::{zisk_ops::ZiskOp, ZiskRom, ROM_ENTRY}; -use proofman::WitnessManager; -use proofman_common::{AirInstance, ProofCtx}; +use proofman_common::{AirInstance, FromTrace, ProofCtx}; -use proofman::WitnessComponent; -use sm_arith::ArithSM; -use sm_mem::MemSM; -use zisk_pil::{ - MainRow, MainTrace, ARITH_AIR_IDS, BINARY_AIR_IDS, BINARY_EXTENSION_AIR_IDS, MAIN_AIR_IDS, - ZISK_AIRGROUP_ID, -}; -use ziskemu::{Emu, EmuTrace, ZiskEmulator}; +use zisk_pil::{MainAirValues, MainTrace, MainTraceRow}; +use ziskemu::{Emu, EmuTrace}; /// This is a multithreaded implementation of the Zisk MainSM state machine. /// @@ -25,89 +16,62 @@ use ziskemu::{Emu, EmuTrace, ZiskEmulator}; /// processing the inputs generated by the emulator. The MainSM state machine interacts with the /// secondary state machines to process the inputs generated by the emulator. pub struct MainSM { - /// Witness computation manager - wcm: Arc>, - - /// Arithmetic state machine - arith_sm: Arc>, - - /// Binary state machine - binary_sm: Arc>, - - /// Memory state machine - mem_sm: Arc, + _phantom: std::marker::PhantomData, } impl MainSM { const MY_NAME: &'static str = "MainSM "; - /// Constructor for the MainSM state machine - /// Registers the state machine at the WCManager and stores references to the secondary state - /// machines that directly interact with the MainSM - /// Returns an Arc to the MainSM state machine - /// # Arguments - /// * `wcm` - Witness computation manager to register the state machine - /// * `arith_sm` - Arc to the ArithSM state machine - /// * `binary_sm` - Arc to the BinarySM state machine - /// * `mem_sm` - Arc to the MemSM state machine - /// # Returns - /// * Arc to the MainSM state machine - pub fn new( - wcm: Arc>, - arith_sm: Arc>, - binary_sm: Arc>, - mem_sm: Arc, - ) -> Arc { - let main_sm = Arc::new(Self { wcm: wcm.clone(), arith_sm, binary_sm, mem_sm }); - - wcm.register_component(main_sm.clone(), Some(ZISK_AIRGROUP_ID), Some(MAIN_AIR_IDS)); - - // For all the secondary state machines, register the main state machine as a predecessor - main_sm.mem_sm.register_predecessor(); - main_sm.binary_sm.register_predecessor(); - main_sm.arith_sm.register_predecessor(); + pub fn new() -> Arc { + Arc::new(Self { _phantom: std::marker::PhantomData }) + } - main_sm + pub fn get_instance(&self, iectx: InstanceExpanderCtx) -> MainInstance { + MainInstance::new(iectx) } pub fn prove_main( &self, + pctx: Arc>, zisk_rom: &ZiskRom, vec_traces: &[EmuTrace], - iectx: &mut InstanceExtensionCtx, - pctx: &ProofCtx, + main_instance: &mut MainInstance, ) { - let segment_id = iectx.segment_id.unwrap(); - let segment_trace = &vec_traces[segment_id]; + let iectx = &main_instance.iectx; + let current_segment = iectx.plan.segment_id.unwrap(); + let num_rows = MainTrace::::NUM_ROWS; - let offset = iectx.offset; - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, MAIN_AIR_IDS[0]); - let filled = segment_trace.steps.len() + 1; + let filled = vec_traces[current_segment].steps.steps + 1; info!( "{}: ยทยทยท Creating Main segment #{} [{} / {} rows filled {:.2}%]", Self::MY_NAME, - segment_id, + current_segment, filled, - air.num_rows(), - filled as f64 / air.num_rows() as f64 * 100.0 + num_rows, + filled as f64 / num_rows as f64 * 100.0 ); // Set Row 0 of the current segment - let row0 = if segment_id == 0 { - MainRow:: { + let row0 = if current_segment == 0 { + MainTraceRow:: { pc: F::from_canonical_u64(ROM_ENTRY), op: F::from_canonical_u8(ZiskOp::CopyB.code()), a_src_imm: F::one(), b_src_imm: F::one(), - ..MainRow::default() + ..MainTraceRow::default() } } else { - let emu_trace_previous = vec_traces[segment_id - 1].steps.last().unwrap(); + //let emu_trace_previous = vec_traces[segment_id - 1].last_state; let mut emu = - Emu::from_emu_trace_start(zisk_rom, &vec_traces[segment_id - 1].last_state); - let row_previous = emu.step_slice_full_trace(emu_trace_previous); - - MainRow:: { + Emu::from_emu_trace_start(zisk_rom, &vec_traces[current_segment - 1].last_state); + let mut mem_reads_index: usize = + vec_traces[current_segment - 1].last_state.mem_reads_index; + let row_previous = emu.step_slice_full_trace( + &vec_traces[current_segment - 1].steps, + &mut mem_reads_index, + ); + + MainTraceRow:: { set_pc: row_previous.set_pc, jmp_offset1: row_previous.jmp_offset1, jmp_offset2: if row_previous.flag == F::one() { @@ -127,167 +91,55 @@ impl MainSM { pc: row_previous.pc, a_src_imm: F::one(), b_src_imm: F::one(), - ..MainRow::default() + ..MainTraceRow::default() } }; - let mut emu = Emu::from_emu_trace_start(zisk_rom, &segment_trace.start_state); + let mut emu = Emu::from_emu_trace_start(zisk_rom, &vec_traces[current_segment].start_state); - let rng = offset as usize..(offset as usize + MainRow::::ROW_SIZE); - iectx.prover_buffer[rng].copy_from_slice(row0.as_slice()); + main_instance.main_trace.buffer[0] = row0; // Set Rows 1 to N of the current segment (N = maximum number of air rows) - let total_rows = segment_trace.steps.len(); - const SLICE_ROWS: usize = 4096; - let mut partial_trace = MainTrace::::new(SLICE_ROWS); - - let mut last_row = MainRow::::default(); - for slice in (0..(air.num_rows())).step_by(SLICE_ROWS) { - // process the steps of the chunk - let slice_start = std::cmp::min(slice, total_rows); - let slice_end = std::cmp::min(slice + SLICE_ROWS, total_rows); - - for (i, emu_trace_step) in - segment_trace.steps[slice_start..slice_end].iter().enumerate() - { - partial_trace[i] = emu.step_slice_full_trace(emu_trace_step); - } - // if there are steps in the chunk update last row - if slice_end - slice_start > 0 { - last_row = partial_trace[slice_end - slice_start - 1]; - } + let emu_trace_step = &vec_traces[current_segment].steps; + let mut mem_reads_index: usize = 0; + //for (idx, emu_trace) in vec_traces[current_segment].steps.iter().enumerate() { + for idx in 0..vec_traces[current_segment].steps.steps as usize { + let expanded_row = emu.step_slice_full_trace(emu_trace_step, &mut mem_reads_index); - // if there are less steps than the chunk size, fill the rest with the last row - for i in (slice_end - slice_start)..SLICE_ROWS { - partial_trace[i] = last_row; - } - - //copy the chunk to the prover buffer - let partial_buffer = partial_trace.buffer.as_ref().unwrap(); - let buffer_offset_slice = offset as usize + (slice + 1) * MainRow::::ROW_SIZE; - - let rng = buffer_offset_slice..buffer_offset_slice + partial_buffer.len(); - iectx.prover_buffer[rng].copy_from_slice(partial_buffer); + main_instance.main_trace.buffer[idx + 1] = expanded_row; } - let buffer = std::mem::take(&mut iectx.prover_buffer); - let sctx = self.wcm.get_sctx(); - let mut air_instance = AirInstance::new( - sctx.clone(), - ZISK_AIRGROUP_ID, - MAIN_AIR_IDS[0], - Some(segment_id), - buffer, - ); - - let main_last_segment = F::from_bool(segment_id == vec_traces.len() - 1); - let main_segment = F::from_canonical_usize(segment_id); - - air_instance.set_airvalue(&sctx, "Main.main_last_segment", main_last_segment); - air_instance.set_airvalue(&sctx, "Main.main_segment", main_segment); - - iectx.air_instance = Some(air_instance); - } - - pub fn prove_arith( - &self, - zisk_rom: &ZiskRom, - vec_traces: &[EmuTrace], - iectx: &mut InstanceExtensionCtx, - pctx: &ProofCtx, - ) { - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, ARITH_AIR_IDS[0]); - - timer_start_debug!(PROCESS_ARITH); - let inputs = ZiskEmulator::process_slice_required::( - zisk_rom, - vec_traces, - iectx.op_type, - &iectx.emu_trace_start, - air.num_rows(), - ); - timer_stop_and_log_debug!(PROCESS_ARITH); - - timer_start_debug!(PROVE_ARITH); - - self.arith_sm.prove_instance(inputs, &mut iectx.prover_buffer, iectx.offset); - timer_stop_and_log_debug!(PROVE_ARITH); + let filled_rows = vec_traces[current_segment].steps.steps as usize; + let last_row = main_instance.main_trace.buffer[filled_rows]; + // Fill the rest of the buffer with the last row + for i in (filled_rows + 1)..num_rows { + main_instance.main_trace.buffer[i] = last_row; + } - timer_start_debug!(CREATE_AIR_INSTANCE); - let buffer = std::mem::take(&mut iectx.prover_buffer); - iectx.air_instance = Some(AirInstance::new( - self.wcm.get_sctx(), - ZISK_AIRGROUP_ID, - ARITH_AIR_IDS[0], - None, - buffer, - )); - timer_stop_and_log_debug!(CREATE_AIR_INSTANCE); - } + let main_last_segment = F::from_bool(current_segment == vec_traces.len() - 1); + let main_segment = F::from_canonical_usize(current_segment); - pub fn prove_binary( - &self, - zisk_rom: &ZiskRom, - vec_traces: &[EmuTrace], - iectx: &mut InstanceExtensionCtx, - pctx: &ProofCtx, - ) { - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_AIR_IDS[0]); + let mut main_air_values = MainAirValues::::new(); + main_air_values.main_last_segment = main_last_segment; + main_air_values.main_segment = main_segment; - timer_start_debug!(PROCESS_BINARY); - let inputs = ZiskEmulator::process_slice_required::( - zisk_rom, - vec_traces, - iectx.op_type, - &iectx.emu_trace_start, - air.num_rows(), + let air_instance = AirInstance::new_from_trace( + FromTrace::new(&mut main_instance.main_trace).with_air_values(&mut main_air_values), ); - timer_stop_and_log_debug!(PROCESS_BINARY); - - timer_start_debug!(PROVE_BINARY); - self.binary_sm.prove_instance(inputs, false, &mut iectx.prover_buffer, iectx.offset); - timer_stop_and_log_debug!(PROVE_BINARY); - timer_start_debug!(CREATE_AIR_INSTANCE); - let buffer = std::mem::take(&mut iectx.prover_buffer); - iectx.air_instance = Some(AirInstance::new( - self.wcm.get_sctx(), - ZISK_AIRGROUP_ID, - BINARY_AIR_IDS[0], - None, - buffer, - )); - timer_stop_and_log_debug!(CREATE_AIR_INSTANCE); + pctx.air_instance_repo.add_air_instance(air_instance, Some(main_instance.iectx.global_idx)); } +} - pub fn prove_binary_extension( - &self, - zisk_rom: &ZiskRom, - vec_traces: &[EmuTrace], - iectx: &mut InstanceExtensionCtx, - pctx: &ProofCtx, - ) { - let air = pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_EXTENSION_AIR_IDS[0]); - - let inputs = ZiskEmulator::process_slice_required::( - zisk_rom, - vec_traces, - iectx.op_type, - &iectx.emu_trace_start, - air.num_rows(), - ); +pub struct MainInstance { + iectx: InstanceExpanderCtx, + main_trace: MainTrace, +} - self.binary_sm.prove_instance(inputs, true, &mut iectx.prover_buffer, iectx.offset); +impl MainInstance { + pub fn new(iectx: InstanceExpanderCtx) -> Self { + let main_trace = MainTrace::new(); - let buffer = std::mem::take(&mut iectx.prover_buffer); - iectx.air_instance = Some(AirInstance::new( - self.wcm.get_sctx(), - ZISK_AIRGROUP_ID, - BINARY_EXTENSION_AIR_IDS[0], - None, - buffer, - )); + Self { iectx, main_trace } } } - -impl WitnessComponent for MainSM {} diff --git a/state-machines/mem/Cargo.toml b/state-machines/mem/Cargo.toml index 3f8ee914..9c514ee0 100644 --- a/state-machines/mem/Cargo.toml +++ b/state-machines/mem/Cargo.toml @@ -11,10 +11,10 @@ zisk-pil = { path = "../../pil" } p3-field = { workspace=true } proofman-common = { workspace = true } proofman-macros = { workspace = true } -proofman = { workspace = true } +witness = { workspace = true } log = { workspace = true } rayon = { workspace = true } [features] default = [] -no_lib_link = ["proofman-common/no_lib_link", "proofman/no_lib_link"] \ No newline at end of file +no_lib_link = ["proofman-common/no_lib_link"] \ No newline at end of file diff --git a/state-machines/mem/src/lib.rs b/state-machines/mem/src/lib.rs index 67bf225c..c3c0aeb2 100644 --- a/state-machines/mem/src/lib.rs +++ b/state-machines/mem/src/lib.rs @@ -1,9 +1,7 @@ mod mem; mod mem_aligned; -mod mem_traces; mod mem_unaligned; pub use mem::*; pub use mem_aligned::*; -pub use mem_traces::*; pub use mem_unaligned::*; diff --git a/state-machines/mem/src/mem.rs b/state-machines/mem/src/mem.rs index 391bca7b..09ade6ac 100644 --- a/state-machines/mem/src/mem.rs +++ b/state-machines/mem/src/mem.rs @@ -9,8 +9,7 @@ use rayon::Scope; use sm_common::{MemOp, MemUnalignedOp, OpResult, Provable}; use zisk_core::ZiskRequiredMemory; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::{ExecutionCtx, ProofCtx, SetupCtx}; +use witness::{WitnessComponent, WitnessManager}; #[allow(dead_code)] const PROVE_CHUNK_SIZE: usize = 1 << 12; @@ -43,7 +42,7 @@ impl MemSM { }; let mem_sm = Arc::new(mem_sm); - wcm.register_component(mem_sm.clone(), None, None); + wcm.register_component(mem_sm.clone()); // For all the secondary state machines, register the main state machine as a predecessor mem_sm.mem_aligned_sm.register_predecessor(); @@ -66,17 +65,7 @@ impl MemSM { } } -impl WitnessComponent for MemSM { - fn calculate_witness( - &self, - _stage: u32, - _air_instance: Option, - _pctx: Arc>, - _ectx: Arc>, - _sctx: Arc>, - ) { - } -} +impl WitnessComponent for MemSM {} impl Provable for MemSM { fn calculate( diff --git a/state-machines/mem/src/mem_aligned.rs b/state-machines/mem/src/mem_aligned.rs index 47feebfb..09188530 100644 --- a/state-machines/mem/src/mem_aligned.rs +++ b/state-machines/mem/src/mem_aligned.rs @@ -4,11 +4,9 @@ use std::sync::{ }; use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::{ExecutionCtx, ProofCtx, SetupCtx}; use rayon::Scope; use sm_common::{MemOp, OpResult, Provable}; -use zisk_pil::{MEM_AIRGROUP_ID, MEM_ALIGN_AIR_IDS}; +use witness::{WitnessComponent, WitnessManager}; const PROVE_CHUNK_SIZE: usize = 1 << 12; @@ -27,11 +25,7 @@ impl MemAlignedSM { Self { registered_predecessors: AtomicU32::new(0), inputs: Mutex::new(Vec::new()) }; let mem_aligned_sm = Arc::new(mem_aligned_sm); - wcm.register_component( - mem_aligned_sm.clone(), - Some(MEM_AIRGROUP_ID), - Some(MEM_ALIGN_AIR_IDS), - ); + wcm.register_component(mem_aligned_sm.clone()); mem_aligned_sm } @@ -48,7 +42,7 @@ impl MemAlignedSM { fn read( &self, - _addr: u64, /* , _ctx: &mut ProofCtx, _ectx: &ExecutionCtx */ + _addr: u64, /* , _ctx: &mut ProofCtx */ ) -> Result> { Ok((0, true)) } @@ -56,23 +50,13 @@ impl MemAlignedSM { fn write( &self, _addr: u64, - _val: u64, /* , _ctx: &mut ProofCtx, _ectx: &ExecutionCtx */ + _val: u64, /* , _ctx: &mut ProofCtx */ ) -> Result> { Ok((0, true)) } } -impl WitnessComponent for MemAlignedSM { - fn calculate_witness( - &self, - _stage: u32, - _air_instance: Option, - _pctx: Arc>, - _ectx: Arc>, - _sctx: Arc>, - ) { - } -} +impl WitnessComponent for MemAlignedSM {} impl Provable for MemAlignedSM { fn calculate(&self, operation: MemOp) -> Result> { diff --git a/state-machines/mem/src/mem_traces.rs b/state-machines/mem/src/mem_traces.rs deleted file mode 100644 index c80a8c74..00000000 --- a/state-machines/mem/src/mem_traces.rs +++ /dev/null @@ -1,5 +0,0 @@ -use proofman_common as common; -pub use proofman_macros::trace; - -trace!(MemALignedRow, MemALignedTrace { fake: F }); -trace!(MemUnaLignedRow, MemUnaLignedTrace { fake: F}); diff --git a/state-machines/mem/src/mem_unaligned.rs b/state-machines/mem/src/mem_unaligned.rs index 9d47a135..23d65f8c 100644 --- a/state-machines/mem/src/mem_unaligned.rs +++ b/state-machines/mem/src/mem_unaligned.rs @@ -4,11 +4,9 @@ use std::sync::{ }; use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::{ExecutionCtx, ProofCtx, SetupCtx}; use rayon::Scope; use sm_common::{MemUnalignedOp, OpResult, Provable}; -use zisk_pil::{MEM_AIRGROUP_ID, MEM_UNALIGNED_AIR_IDS}; +use witness::{WitnessComponent, WitnessManager}; const PROVE_CHUNK_SIZE: usize = 1 << 12; @@ -27,11 +25,7 @@ impl MemUnalignedSM { Self { registered_predecessors: AtomicU32::new(0), inputs: Mutex::new(Vec::new()) }; let mem_aligned_sm = Arc::new(mem_aligned_sm); - wcm.register_component( - mem_aligned_sm.clone(), - Some(MEM_AIRGROUP_ID), - Some(MEM_UNALIGNED_AIR_IDS), - ); + wcm.register_component(mem_aligned_sm.clone()); mem_aligned_sm } @@ -49,7 +43,7 @@ impl MemUnalignedSM { fn read( &self, _addr: u64, - _width: usize, /* , _ctx: &mut ProofCtx, _ectx: &ExecutionCtx */ + _width: usize, /* , _ctx: &mut ProofCtx */ ) -> Result> { Ok((0, true)) } @@ -58,23 +52,13 @@ impl MemUnalignedSM { &self, _addr: u64, _width: usize, - _val: u64, /* , _ctx: &mut ProofCtx, _ectx: &ExecutionCtx */ + _val: u64, /* , _ctx: &mut ProofCtx */ ) -> Result> { Ok((0, true)) } } -impl WitnessComponent for MemUnalignedSM { - fn calculate_witness( - &self, - _stage: u32, - _air_instance: Option, - _pctx: Arc>, - _ectx: Arc>, - _sctx: Arc>, - ) { - } -} +impl WitnessComponent for MemUnalignedSM {} impl Provable for MemUnalignedSM { fn calculate(&self, operation: MemUnalignedOp) -> Result> { diff --git a/state-machines/quick-ops/pil/quick_ops.pil b/state-machines/quick-ops/pil/quick_ops.pil deleted file mode 100644 index e69de29b..00000000 diff --git a/state-machines/quick-ops/src/lib.rs b/state-machines/quick-ops/src/lib.rs deleted file mode 100644 index dc37315e..00000000 --- a/state-machines/quick-ops/src/lib.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod quick_ops; -mod quick_ops_trace; - -pub use quick_ops::*; -pub use quick_ops_trace::*; diff --git a/state-machines/quick-ops/src/quick_ops.rs b/state-machines/quick-ops/src/quick_ops.rs deleted file mode 100644 index a91b6fd6..00000000 --- a/state-machines/quick-ops/src/quick_ops.rs +++ /dev/null @@ -1,102 +0,0 @@ -use std::sync::{ - atomic::{AtomicU32, Ordering}, - Arc, Mutex, -}; - -use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::{ExecutionCtx, ProofCtx, SetupCtx}; -use rayon::Scope; -use sm_common::{OpResult, Provable}; -use zisk_core::ZiskRequiredOperation; -use zisk_pil::{QUICKOPS_AIRGROUP_ID, QUICKOPS_AIR_IDS}; - -const PROVE_CHUNK_SIZE: usize = 1 << 12; - -pub struct QuickOpsSM { - // Count of registered predecessors - registered_predecessors: AtomicU32, - - // Inputs - inputs: Mutex>, -} - -impl QuickOpsSM { - pub fn new(wcm: Arc>) -> Arc { - let quickop_sm = - Self { registered_predecessors: AtomicU32::new(0), inputs: Mutex::new(Vec::new()) }; - let quickop_sm = Arc::new(quickop_sm); - - wcm.register_component( - quickop_sm.clone(), - Some(QUICKOPS_AIRGROUP_ID), - Some(QUICKOPS_AIR_IDS), - ); - - quickop_sm - } - - pub fn register_predecessor(&self) { - self.registered_predecessors.fetch_add(1, Ordering::SeqCst); - } - - pub fn unregister_predecessor(&self, scope: &Scope) { - if self.registered_predecessors.fetch_sub(1, Ordering::SeqCst) == 1 { - >::prove( - self, - &[], - true, - scope, - ); - } - } -} - -impl WitnessComponent for QuickOpsSM { - fn calculate_witness( - &self, - _stage: u32, - _air_instance: Option, - _pctx: Arc>, - _ectx: Arc>, - _sctx: Arc>, - ) { - } -} - -impl Provable for QuickOpsSM { - fn calculate( - &self, - _operation: ZiskRequiredOperation, - ) -> Result> { - unimplemented!() - } - - fn prove(&self, operations: &[ZiskRequiredOperation], drain: bool, scope: &Scope) { - if let Ok(mut inputs) = self.inputs.lock() { - inputs.extend_from_slice(operations); - - while inputs.len() >= PROVE_CHUNK_SIZE || (drain && !inputs.is_empty()) { - let num_drained = std::cmp::min(PROVE_CHUNK_SIZE, inputs.len()); - let _drained_inputs = inputs.drain(..num_drained).collect::>(); - - scope.spawn(move |_| { - // TODO! Implement prove drained_inputs (a chunk of operations) - }); - } - } - } - - fn calculate_prove( - &self, - operation: ZiskRequiredOperation, - drain: bool, - scope: &Scope, - ) -> Result> { - let result = self.calculate(operation.clone()); - - self.prove(&[operation], drain, scope); - - result - } -} diff --git a/state-machines/quick-ops/src/quick_ops_trace.rs b/state-machines/quick-ops/src/quick_ops_trace.rs deleted file mode 100644 index 61ebfef6..00000000 --- a/state-machines/quick-ops/src/quick_ops_trace.rs +++ /dev/null @@ -1,4 +0,0 @@ -use proofman_common as common; -pub use proofman_macros::trace; - -trace!(QuickOpsRow, QuickOpsTrace { fake: F }); diff --git a/state-machines/rom/Cargo.toml b/state-machines/rom/Cargo.toml index c724d925..6569d5d1 100644 --- a/state-machines/rom/Cargo.toml +++ b/state-machines/rom/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] zisk-core = { path = "../../core" } +zisk-common = { path = "../../common" } sm-common = { path = "../common" } zisk-pil = { path = "../../pil" } ziskemu = { path = "../../emulator" } @@ -13,7 +14,6 @@ p3-field = { workspace=true } proofman-common = { workspace = true } proofman-macros = { workspace = true } proofman-util = { workspace = true } -proofman = { workspace = true } log = { workspace = true } rayon = { workspace = true } @@ -21,4 +21,4 @@ itertools = "0.13.0" [features] default = [] -no_lib_link = ["proofman-common/no_lib_link", "proofman/no_lib_link"] +no_lib_link = ["proofman-common/no_lib_link"] diff --git a/state-machines/rom/pil/rom.pil b/state-machines/rom/pil/rom.pil index 2c2011e0..578333bc 100644 --- a/state-machines/rom/pil/rom.pil +++ b/state-machines/rom/pil/rom.pil @@ -2,19 +2,22 @@ require "std_lookup.pil" const int ROM_BUS_ID = 7890; +public rom_root[4]; + airtemplate Rom(int N = 2**21, int stack_enabled = 0, const int rom_bus_id = ROM_BUS_ID) { + commit stage(0) public(rom_root) rom; - col witness line; - col witness a_offset_imm0; - col witness a_imm1; - col witness b_offset_imm0; - col witness b_imm1; - col witness ind_width; - col witness op; - col witness store_offset; - col witness jmp_offset1; - col witness jmp_offset2; - col witness flags; + col rom line; + col rom a_offset_imm0; + col rom a_imm1; + col rom b_offset_imm0; + col rom b_imm1; + col rom ind_width; + col rom op; + col rom store_offset; + col rom jmp_offset1; + col rom jmp_offset2; + col rom flags; col witness multiplicity; diff --git a/state-machines/rom/src/lib.rs b/state-machines/rom/src/lib.rs index 6c51134e..070f292b 100644 --- a/state-machines/rom/src/lib.rs +++ b/state-machines/rom/src/lib.rs @@ -1,3 +1,9 @@ mod rom; +mod rom_counter; +mod rom_instance; +mod rom_planner; pub use rom::*; +pub use rom_counter::*; +pub use rom_instance::*; +pub use rom_planner::*; diff --git a/state-machines/rom/src/rom.rs b/state-machines/rom/src/rom.rs index 3fc4f9b1..2e808a39 100644 --- a/state-machines/rom/src/rom.rs +++ b/state-machines/rom/src/rom.rs @@ -1,195 +1,83 @@ use std::{path::PathBuf, sync::Arc}; use itertools::Itertools; -use p3_field::Field; -use proofman::{WitnessComponent, WitnessManager}; -use proofman_common::{AirInstance, BufferAllocator, SetupCtx}; -use proofman_util::create_buffer_fast; +use log::info; +use p3_field::PrimeField; +use sm_common::{ComponentProvider, Instance, InstanceExpanderCtx, Metrics, Plan, Planner}; -use zisk_core::{Riscv2zisk, ZiskPcHistogram, ZiskRom, SRC_IMM}; -use zisk_pil::{Pilout, RomRow, RomTrace, MAIN_AIR_IDS, ROM_AIR_IDS, ZISK_AIRGROUP_ID}; -//use ziskemu::ZiskEmulatorErr; -use std::error::Error; +use crate::{RomCounter, RomInstance, RomPlanner}; +use zisk_core::{Riscv2zisk, ZiskRom, SRC_IMM}; +use zisk_pil::{MainTrace, RomRomTrace, RomRomTraceRow, RomTrace, RomTraceRow}; -pub struct RomSM { - wcm: Arc>, +pub struct RomSM { + zisk_rom: Arc, } -impl RomSM { - pub fn new(wcm: Arc>) -> Arc { - let rom_sm = Self { wcm: wcm.clone() }; - let rom_sm = Arc::new(rom_sm); +impl RomSM { + const MY_NAME: &'static str = "RomSM "; - let rom_air_ids = ROM_AIR_IDS; - wcm.register_component(rom_sm.clone(), Some(ZISK_AIRGROUP_ID), Some(rom_air_ids)); - - rom_sm - } - - pub fn prove( - &self, - rom: &ZiskRom, - pc_histogram: ZiskPcHistogram, - ) -> Result<(), Box> { - let buffer_allocator = self.wcm.get_ectx().buffer_allocator.clone(); - let sctx = self.wcm.get_sctx(); - - if pc_histogram.end_pc == 0 { - panic!("RomSM::prove() detected pc_histogram.end_pc == 0"); // TODO: return an error - } - - let main_trace_len = - self.wcm.get_pctx().pilout.get_air(ZISK_AIRGROUP_ID, MAIN_AIR_IDS[0]).num_rows() as u64; - - let (prover_buffer, _, air_id) = - Self::compute_trace_rom(rom, buffer_allocator, &sctx, pc_histogram, main_trace_len)?; - - let air_instance = - AirInstance::new(sctx.clone(), ZISK_AIRGROUP_ID, air_id, None, prover_buffer); - let (is_mine, instance_gid) = - self.wcm.get_ectx().dctx.write().unwrap().add_instance(ZISK_AIRGROUP_ID, air_id, 1); - if is_mine { - self.wcm - .get_pctx() - .air_instance_repo - .add_air_instance(air_instance, Some(instance_gid)); - } - - Ok(()) - } - pub fn compute_trace( - rom_path: PathBuf, - buffer_allocator: Arc>, - sctx: &SetupCtx, - ) -> Result<(Vec, u64, usize), Box> { - // Get the ELF file path as a string - let elf_filename: String = rom_path.to_str().unwrap().into(); - println!("Proving ROM for ELF file={}", elf_filename); - - // Load and parse the ELF file, and transpile it into a ZisK ROM using Riscv2zisk - - // Create an instance of the RISCV -> ZisK program converter - let riscv2zisk = Riscv2zisk::new(elf_filename, String::new(), String::new(), String::new()); - - // Convert program to rom - let rom_result = riscv2zisk.run(); - if rom_result.is_err() { - //return Err(ZiskEmulatorErr::Unknown(zisk_rom.err().unwrap().to_string())); - panic!("RomSM::prover() failed converting elf to rom"); - } - let rom = rom_result.unwrap(); - - let empty_pc_histogram = ZiskPcHistogram::default(); - - Self::compute_trace_rom(&rom, buffer_allocator, sctx, empty_pc_histogram, 0) + pub fn new(zisk_rom: Arc) -> Arc { + Arc::new(Self { zisk_rom }) } - pub fn compute_trace_rom( + pub fn prove_instance( rom: &ZiskRom, - buffer_allocator: Arc>, - sctx: &SetupCtx, - pc_histogram: ZiskPcHistogram, - main_trace_len: u64, - ) -> Result<(Vec, u64, usize), Box> { - let pilout = Pilout::pilout(); - let sizes = ( - pilout.get_air(ZISK_AIRGROUP_ID, ROM_AIR_IDS[0]).num_rows(), - // pilout.get_air(ZISK_AIRGROUP_ID, ROM_M_AIR_IDS[0]).num_rows(), - // pilout.get_air(ZISK_AIRGROUP_ID, ROM_L_AIR_IDS[0]).num_rows(), - ); - - let number_of_instructions = rom.insts.len(); - - Self::create_rom_s( - sizes.0, - rom, - number_of_instructions, - buffer_allocator, - sctx, - pc_histogram, + plan: &Plan, + rom_trace: &mut RomTrace, + mut rom_custom_trace: &mut RomRomTrace, + ) { + let metadata = plan.meta.as_ref().unwrap().downcast_ref::().unwrap(); + + let pc_histogram = &metadata.rom.inst_count; + let main_trace_len = MainTrace::::NUM_ROWS as u64; + + info!( + "{}: ยทยทยท Creating Rom instance [{} / {} rows filled {:.2}%]", + Self::MY_NAME, + pc_histogram.len(), main_trace_len, - ) - // match number_of_instructions { - // n if n <= sizes.0 => Self::create_rom_s( - // sizes.0, - // rom, - // n, - // buffer_allocator, - // sctx, - // pc_histogram, - // main_trace_len, - // ), - // n if n <= sizes.1 => Self::create_rom_m( - // sizes.1, - // rom, - // n, - // buffer_allocator, - // sctx, - // pc_histogram, - // main_trace_len, - // ), - // n if n < sizes.2 => Self::create_rom_l( - // sizes.2, - // rom, - // n, - // buffer_allocator, - // sctx, - // pc_histogram, - // main_trace_len, - // ), - // _ => panic!("RomSM::compute_trace() found rom too big size={}", - // number_of_instructions), } - } - - fn create_rom_s( - rom_s_size: usize, - rom: &zisk_core::ZiskRom, - number_of_instructions: usize, - buffer_allocator: Arc>, - sctx: &SetupCtx, - pc_histogram: ZiskPcHistogram, - main_trace_len: u64, - ) -> Result<(Vec, u64, usize), Box> { - // Set trace size - let trace_size = rom_s_size; - - // Allocate a prover buffer - let (buffer_size, offsets) = buffer_allocator - .get_buffer_info(sctx, ZISK_AIRGROUP_ID, ROM_AIR_IDS[0]) - .unwrap_or_else(|err| panic!("Error getting buffer info: {}", err)); - let mut prover_buffer = create_buffer_fast(buffer_size as usize); - - // Create an empty ROM trace - let mut rom_trace = - RomTrace::::map_buffer(&mut prover_buffer, trace_size, offsets[0] as usize) - .expect("RomSM::compute_trace() failed mapping buffer to ROMSRow"); + pc_histogram.len() as f64 / main_trace_len as f64 * 100.0 + ); // For every instruction in the rom, fill its corresponding ROM trace //for (i, inst_builder) in rom.insts.clone().into_iter().enumerate() { - let keys = rom.insts.keys(); - let sorted_keys = keys.sorted(); - let mut i = 0; - for key in sorted_keys { + for (i, key) in rom.insts.keys().sorted().enumerate() { // Get the Zisk instruction let inst = &rom.insts[key].i; // Calculate the multiplicity, i.e. the number of times this pc is used in this // execution let mut multiplicity: u64; - if pc_histogram.map.is_empty() { + if pc_histogram.is_empty() { multiplicity = 1; // If the histogram is empty, we use 1 for all pc's } else { - let counter = pc_histogram.map.get(&inst.paddr); + let counter = pc_histogram.get(&inst.paddr); if counter.is_some() { multiplicity = *counter.unwrap(); - if inst.paddr == pc_histogram.end_pc { + if inst.paddr == metadata.end_pc { multiplicity += - main_trace_len - 1 - (pc_histogram.steps % (main_trace_len - 1)); + main_trace_len - 1 - (metadata.steps % (main_trace_len - 1)); } } else { continue; // We skip those pc's that are not used in this execution } } + rom_trace[i].multiplicity = F::from_canonical_u64(multiplicity); + } + + // Padd with zeroes + for i in rom.insts.len()..rom_trace.num_rows() { + rom_trace[i] = RomTraceRow::default(); + } + + Self::compute_trace_rom(rom, &mut rom_custom_trace); + } + + pub fn compute_trace_rom(rom: &ZiskRom, rom_custom_trace: &mut RomRomTrace) { + // For every instruction in the rom, fill its corresponding ROM trace + for (i, key) in rom.insts.keys().sorted().enumerate() { + // Get the Zisk instruction + let inst = &rom.insts[key].i; // Convert the i64 offsets to F let jmp_offset1 = if inst.jmp_offset1 >= 0 { @@ -219,246 +107,57 @@ impl RomSM { }; // Fill the rom trace row fields - rom_trace[i].line = F::from_canonical_u64(inst.paddr); // TODO: unify names: pc, paddr, line - rom_trace[i].a_offset_imm0 = a_offset_imm0; - rom_trace[i].a_imm1 = + rom_custom_trace[i].line = F::from_canonical_u64(inst.paddr); // TODO: unify names: pc, paddr, line + rom_custom_trace[i].a_offset_imm0 = a_offset_imm0; + rom_custom_trace[i].a_imm1 = F::from_canonical_u64(if inst.a_src == SRC_IMM { inst.a_use_sp_imm1 } else { 0 }); - rom_trace[i].b_offset_imm0 = b_offset_imm0; - rom_trace[i].b_imm1 = + rom_custom_trace[i].b_offset_imm0 = b_offset_imm0; + rom_custom_trace[i].b_imm1 = F::from_canonical_u64(if inst.b_src == SRC_IMM { inst.b_use_sp_imm1 } else { 0 }); - //rom_trace[i].b_src_ind = - // F::from_canonical_u64(if inst.b_src == SRC_IND { 1 } else { 0 }); - rom_trace[i].ind_width = F::from_canonical_u64(inst.ind_width); - rom_trace[i].op = F::from_canonical_u8(inst.op); - rom_trace[i].store_offset = store_offset; - rom_trace[i].jmp_offset1 = jmp_offset1; - rom_trace[i].jmp_offset2 = jmp_offset2; - rom_trace[i].flags = F::from_canonical_u64(inst.get_flags()); - rom_trace[i].multiplicity = F::from_canonical_u64(multiplicity); - /*println!( - "ROM SM [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}], {}", - inst.paddr, - inst.a_offset_imm0, - if inst.a_src == SRC_IMM { inst.a_use_sp_imm1 } else { 0 }, - inst.b_offset_imm0, - if inst.b_src == SRC_IMM { inst.b_use_sp_imm1 } else { 0 }, - if inst.b_src == SRC_IND { 1 } else { 0 }, - inst.ind_width, - inst.op, - inst.store_offset as u64, - inst.jmp_offset1 as u64, - inst.jmp_offset2 as u64, - inst.get_flags(), - multiplicity, - );*/ - i += 1; + rom_custom_trace[i].ind_width = F::from_canonical_u64(inst.ind_width); + rom_custom_trace[i].op = F::from_canonical_u8(inst.op); + rom_custom_trace[i].store_offset = store_offset; + rom_custom_trace[i].jmp_offset1 = jmp_offset1; + rom_custom_trace[i].jmp_offset2 = jmp_offset2; + rom_custom_trace[i].flags = F::from_canonical_u64(inst.get_flags()); } // Padd with zeroes - for i in number_of_instructions..trace_size { - rom_trace[i] = RomRow::default(); + for i in rom.insts.len()..rom_custom_trace.num_rows() { + rom_custom_trace[i] = RomRomTraceRow::default(); } - - Ok((prover_buffer, offsets[0], ROM_AIR_IDS[0])) } - // fn create_rom_m( - // rom_m_size: usize, - // rom: &zisk_core::ZiskRom, - // number_of_instructions: usize, - // buffer_allocator: Arc, - // sctx: &SetupCtx, - // pc_histogram: ZiskPcHistogram, - // main_trace_len: u64, - // ) -> Result<(Vec, u64, usize), Box> { - // // Set trace size - // let trace_size = rom_m_size; - - // // Allocate a prover buffer - // let (buffer_size, offsets) = buffer_allocator - // .get_buffer_info(sctx, ZISK_AIRGROUP_ID, ROM_M_AIR_IDS[0]) - // .unwrap_or_else(|err| panic!("Error getting buffer info: {}", err)); - // let mut prover_buffer = create_buffer_fast(buffer_size as usize); - - // // Create an empty ROM trace - // let mut rom_trace = - // RomM1Trace::::map_buffer(&mut prover_buffer, trace_size, offsets[0] as usize) - // .expect("RomSM::compute_trace() failed mapping buffer to ROMMRow"); - - // // For every instruction in the rom, fill its corresponding ROM trace - // for (i, inst_builder) in rom.insts.clone().into_iter().enumerate() { - // // Get the Zisk instruction - // let inst = inst_builder.1.i; - - // // Calculate the multiplicity, i.e. the number of times this pc is used in this - // // execution - // let mut multiplicity: u64; - // if pc_histogram.map.is_empty() { - // multiplicity = 1; // If the histogram is empty, we use 1 for all pc's - // } else { - // let counter = pc_histogram.map.get(&inst.paddr); - // if counter.is_some() { - // multiplicity = *counter.unwrap(); - // if inst.paddr == pc_histogram.end_pc { - // multiplicity += main_trace_len - 1 - (pc_histogram.steps % - // main_trace_len); } - // } else { - // continue; // We skip those pc's that are not used in this execution - // } - // } - - // // Convert the i64 offsets to F - // let jmp_offset1 = if inst.jmp_offset1 >= 0 { - // F::from_canonical_u64(inst.jmp_offset1 as u64) - // } else { - // F::neg(F::from_canonical_u64((-inst.jmp_offset1) as u64)) - // }; - // let jmp_offset2 = if inst.jmp_offset2 >= 0 { - // F::from_canonical_u64(inst.jmp_offset2 as u64) - // } else { - // F::neg(F::from_canonical_u64((-inst.jmp_offset2) as u64)) - // }; - // let store_offset = if inst.store_offset >= 0 { - // F::from_canonical_u64(inst.store_offset as u64) - // } else { - // F::neg(F::from_canonical_u64((-inst.store_offset) as u64)) - // }; - // let a_offset_imm0 = if inst.a_offset_imm0 as i64 >= 0 { - // F::from_canonical_u64(inst.a_offset_imm0) - // } else { - // F::neg(F::from_canonical_u64((-(inst.a_offset_imm0 as i64)) as u64)) - // }; - // let b_offset_imm0 = if inst.b_offset_imm0 as i64 >= 0 { - // F::from_canonical_u64(inst.b_offset_imm0) - // } else { - // F::neg(F::from_canonical_u64((-(inst.b_offset_imm0 as i64)) as u64)) - // }; - - // // Fill the rom trace row fields - // rom_trace[i].line = F::from_canonical_u64(inst.paddr); // TODO: unify names: pc, - // paddr, line rom_trace[i].a_offset_imm0 = a_offset_imm0; - // rom_trace[i].a_imm1 = - // F::from_canonical_u64(if inst.a_src == SRC_IMM { inst.a_use_sp_imm1 } else { 0 - // }); rom_trace[i].b_offset_imm0 = b_offset_imm0; - // rom_trace[i].b_imm1 = - // F::from_canonical_u64(if inst.b_src == SRC_IMM { inst.b_use_sp_imm1 } else { 0 - // }); //rom_trace[i].b_src_ind = - // // F::from_canonical_u64(if inst.b_src == SRC_IND { 1 } else { 0 }); - // rom_trace[i].ind_width = F::from_canonical_u64(inst.ind_width); - // rom_trace[i].op = F::from_canonical_u8(inst.op); - // rom_trace[i].store_offset = store_offset; - // rom_trace[i].jmp_offset1 = jmp_offset1; - // rom_trace[i].jmp_offset2 = jmp_offset2; - // rom_trace[i].flags = F::from_canonical_u64(inst.get_flags()); - // rom_trace[i].multiplicity = F::from_canonical_u64(multiplicity); - // } - - // // Padd with zeroes - // for i in number_of_instructions..trace_size { - // rom_trace[i] = RomM1Row::default(); - // } - - // Ok((prover_buffer, offsets[0], ROM_M_AIR_IDS[0])) - // } - - // fn create_rom_l( - // rom_l_size: usize, - // rom: &zisk_core::ZiskRom, - // number_of_instructions: usize, - // buffer_allocator: Arc, - // sctx: &SetupCtx, - // pc_histogram: ZiskPcHistogram, - // main_trace_len: u64, - // ) -> Result<(Vec, u64, usize), Box> { - // // Set trace size - // let trace_size = rom_l_size; - - // // Allocate a prover buffer - // let (buffer_size, offsets) = buffer_allocator - // .get_buffer_info(sctx, ZISK_AIRGROUP_ID, ROM_L_AIR_IDS[0]) - // .unwrap_or_else(|err| panic!("Error getting buffer info: {}", err)); - // let mut prover_buffer = create_buffer_fast(buffer_size as usize); + pub fn compute_custom_trace_rom( + rom_path: PathBuf, + rom_custom_trace: &mut RomRomTrace, + ) { + // Get the ELF file path as a string + let elf_filename: String = rom_path.to_str().unwrap().into(); + println!("Proving ROM for ELF file={}", elf_filename); - // // Create an empty ROM trace - // let mut rom_trace = - // RomL2Trace::::map_buffer(&mut prover_buffer, trace_size, offsets[0] as usize) - // .expect("RomSM::compute_trace() failed mapping buffer to ROMLRow"); + // Load and parse the ELF file, and transpile it into a ZisK ROM using Riscv2zisk - // // For every instruction in the rom, fill its corresponding ROM trace - // for (i, inst_builder) in rom.insts.clone().into_iter().enumerate() { - // // Get the Zisk instruction - // let inst = inst_builder.1.i; + // Create an instance of the RISCV -> ZisK program converter + let riscv2zisk = Riscv2zisk::new(elf_filename, String::new(), String::new(), String::new()); - // // Calculate the multiplicity, i.e. the number of times this pc is used in this - // // execution - // let mut multiplicity: u64; - // if pc_histogram.map.is_empty() { - // multiplicity = 1; // If the histogram is empty, we use 1 for all pc's - // } else { - // let counter = pc_histogram.map.get(&inst.paddr); - // if counter.is_some() { - // multiplicity = *counter.unwrap(); - // if inst.paddr == pc_histogram.end_pc { - // multiplicity += main_trace_len - 1 - (pc_histogram.steps % - // main_trace_len); } - // } else { - // continue; // We skip those pc's that are not used in this execution - // } - // } + // Convert program to rom + let rom = riscv2zisk.run().expect("RomSM::prover() failed converting elf to rom"); - // // Convert the i64 offsets to F - // let jmp_offset1 = if inst.jmp_offset1 >= 0 { - // F::from_canonical_u64(inst.jmp_offset1 as u64) - // } else { - // F::neg(F::from_canonical_u64((-inst.jmp_offset1) as u64)) - // }; - // let jmp_offset2 = if inst.jmp_offset2 >= 0 { - // F::from_canonical_u64(inst.jmp_offset2 as u64) - // } else { - // F::neg(F::from_canonical_u64((-inst.jmp_offset2) as u64)) - // }; - // let store_offset = if inst.store_offset >= 0 { - // F::from_canonical_u64(inst.store_offset as u64) - // } else { - // F::neg(F::from_canonical_u64((-inst.store_offset) as u64)) - // }; - // let a_offset_imm0 = if inst.a_offset_imm0 as i64 >= 0 { - // F::from_canonical_u64(inst.a_offset_imm0) - // } else { - // F::neg(F::from_canonical_u64((-(inst.a_offset_imm0 as i64)) as u64)) - // }; - // let b_offset_imm0 = if inst.b_offset_imm0 as i64 >= 0 { - // F::from_canonical_u64(inst.b_offset_imm0) - // } else { - // F::neg(F::from_canonical_u64((-(inst.b_offset_imm0 as i64)) as u64)) - // }; + Self::compute_trace_rom(&rom, rom_custom_trace); + } +} - // // Fill the rom trace row fields - // rom_trace[i].line = F::from_canonical_u64(inst.paddr); // TODO: unify names: pc, - // paddr, line rom_trace[i].a_offset_imm0 = a_offset_imm0; - // rom_trace[i].a_imm1 = - // F::from_canonical_u64(if inst.a_src == SRC_IMM { inst.a_use_sp_imm1 } else { 0 - // }); rom_trace[i].b_offset_imm0 = b_offset_imm0; - // rom_trace[i].b_imm1 = - // F::from_canonical_u64(if inst.b_src == SRC_IMM { inst.b_use_sp_imm1 } else { 0 - // }); //rom_trace[i].b_src_ind = - // // F::from_canonical_u64(if inst.b_src == SRC_IND { 1 } else { 0 }); - // rom_trace[i].ind_width = F::from_canonical_u64(inst.ind_width); - // rom_trace[i].op = F::from_canonical_u8(inst.op); - // rom_trace[i].store_offset = store_offset; - // rom_trace[i].jmp_offset1 = jmp_offset1; - // rom_trace[i].jmp_offset2 = jmp_offset2; - // rom_trace[i].flags = F::from_canonical_u64(inst.get_flags()); - // rom_trace[i].multiplicity = F::from_canonical_u64(multiplicity); - // } +impl ComponentProvider for RomSM { + fn get_counter(&self) -> Box { + Box::new(RomCounter::default()) + } - // // Padd with zeroes - // for i in number_of_instructions..trace_size { - // rom_trace[i] = RomL2Row::default(); - // } + fn get_planner(&self) -> Box { + Box::new(RomPlanner {}) + } - // Ok((prover_buffer, offsets[0], ROM_L_AIR_IDS[0])) - // } + fn get_instance(&self, iectx: InstanceExpanderCtx) -> Box> { + Box::new(RomInstance::new(self.zisk_rom.clone(), iectx)) + } } - -impl WitnessComponent for RomSM {} diff --git a/state-machines/rom/src/rom_counter.rs b/state-machines/rom/src/rom_counter.rs new file mode 100644 index 00000000..2963e6b0 --- /dev/null +++ b/state-machines/rom/src/rom_counter.rs @@ -0,0 +1,43 @@ +use std::any::Any; + +use sm_common::{CounterStats, Metrics}; +use zisk_core::{InstContext, ZiskInst, ZiskOperationType}; + +#[derive(Default)] +pub struct RomCounter { + pub rom: CounterStats, + pub end_pc: u64, + pub steps: u64, +} + +impl Metrics for RomCounter { + fn measure(&mut self, inst: &ZiskInst, inst_ctx: &InstContext) { + self.rom.update(inst_ctx.pc, 1); + if inst.end { + self.end_pc = inst_ctx.pc; + self.steps = inst_ctx.step + 1; + } + } + + fn add(&mut self, other: &dyn Metrics) { + let other = + other.as_any().downcast_ref::().expect("Rom Metrics: Failed to downcast"); + self.rom += &other.rom; + + if other.end_pc != 0 { + self.end_pc = other.end_pc; + } + + if other.steps != 0 { + self.steps = other.steps; + } + } + + fn op_type(&self) -> Vec { + vec![ZiskOperationType::None] + } + + fn as_any(&self) -> &dyn Any { + self + } +} diff --git a/state-machines/rom/src/rom_instance.rs b/state-machines/rom/src/rom_instance.rs new file mode 100644 index 00000000..60f559fc --- /dev/null +++ b/state-machines/rom/src/rom_instance.rs @@ -0,0 +1,51 @@ +use std::sync::Arc; + +use p3_field::PrimeField; +use proofman_common::{AirInstance, FromTrace, ProofCtx}; +use sm_common::{Instance, InstanceExpanderCtx, InstanceType}; +use zisk_core::ZiskRom; +use zisk_pil::{RomRomTrace, RomTrace}; + +use crate::RomSM; + +pub struct RomInstance { + /// Instance expander context + zisk_rom: Arc, + iectx: InstanceExpanderCtx, + rom_trace: RomTrace, + rom_custom_trace: RomRomTrace, +} + +impl RomInstance { + pub fn new( + zisk_rom: Arc, + iectx: InstanceExpanderCtx, + ) -> Self { + let rom_trace = RomTrace::new(); + let rom_custom_trace = RomRomTrace::new(); + + Self { zisk_rom, iectx, rom_trace, rom_custom_trace } + } +} + +impl Instance for RomInstance { + fn compute_witness(&mut self, _pctx: &ProofCtx) -> Option> { + RomSM::prove_instance( + &self.zisk_rom, + &self.iectx.plan, + &mut self.rom_trace, + &mut self.rom_custom_trace, + ); + + Some(AirInstance::new_from_trace( + FromTrace::new(&mut self.rom_trace) + .with_custom_traces(vec![&mut self.rom_custom_trace]) + )) + } + + fn instance_type(&self) -> InstanceType { + InstanceType::Instance + } +} + +unsafe impl Sync for RomInstance {} diff --git a/state-machines/rom/src/rom_planner.rs b/state-machines/rom/src/rom_planner.rs new file mode 100644 index 00000000..ec215edc --- /dev/null +++ b/state-machines/rom/src/rom_planner.rs @@ -0,0 +1,30 @@ +use sm_common::{ChunkId, InstanceType, Metrics, Plan, Planner}; +use zisk_pil::{ROM_AIR_IDS, ZISK_AIRGROUP_ID}; + +use crate::RomCounter; + +pub struct RomPlanner {} + +impl Planner for RomPlanner { + fn plan(&self, metrics: Vec<(ChunkId, Box)>) -> Vec { + if metrics.is_empty() { + panic!("RomPlanner::plan() No metrics found"); + } + + let mut total = RomCounter::default(); + + for (_, metric) in metrics { + let metric = metric.as_any().downcast_ref::().unwrap(); + total.add(metric); + } + + vec![Plan::new( + ZISK_AIRGROUP_ID, + ROM_AIR_IDS[0], + None, + InstanceType::Instance, + None, + Some(Box::new(total)), + )] + } +} diff --git a/state-machines/quick-ops/Cargo.toml b/state-machines/std/Cargo.toml similarity index 60% rename from state-machines/quick-ops/Cargo.toml rename to state-machines/std/Cargo.toml index c52ae9a2..682147d0 100644 --- a/state-machines/quick-ops/Cargo.toml +++ b/state-machines/std/Cargo.toml @@ -1,20 +1,25 @@ [package] -name = "sm-quick-ops" +name = "sm-std" version = "0.1.0" edition = "2021" [dependencies] zisk-core = { path = "../../core" } +zisk-common = { path = "../../common" } sm-common = { path = "../common" } zisk-pil = { path = "../../pil" } +ziskemu = { path = "../../emulator" } p3-field = { workspace=true } proofman-common = { workspace = true } proofman-macros = { workspace = true } -proofman = { workspace = true } +proofman-util = { workspace = true } +pil-std-lib = { workspace = true } + log = { workspace = true } rayon = { workspace = true } +itertools = "0.13.0" [features] default = [] -no_lib_link = ["proofman-common/no_lib_link", "proofman/no_lib_link"] \ No newline at end of file +no_lib_link = ["proofman-common/no_lib_link"] \ No newline at end of file diff --git a/state-machines/std/src/lib.rs b/state-machines/std/src/lib.rs new file mode 100644 index 00000000..1ba44923 --- /dev/null +++ b/state-machines/std/src/lib.rs @@ -0,0 +1,7 @@ +mod std_instance; +mod std_planner; +mod std_sm; + +pub use std_instance::*; +pub use std_planner::*; +pub use std_sm::*; diff --git a/state-machines/std/src/std_instance.rs b/state-machines/std/src/std_instance.rs new file mode 100644 index 00000000..c5d2c8d1 --- /dev/null +++ b/state-machines/std/src/std_instance.rs @@ -0,0 +1,36 @@ +use std::sync::Arc; + +use p3_field::PrimeField; +use pil_std_lib::{RangeCheckAir, Std}; +use proofman_common::{AirInstance, ProofCtx}; +use sm_common::{Instance, InstanceExpanderCtx, InstanceType}; + +pub struct StdInstance { + std: Arc>, + + /// Instance expander context + iectx: InstanceExpanderCtx, +} + +impl StdInstance { + pub fn new(std: Arc>, iectx: InstanceExpanderCtx) -> Self { + Self { std, iectx } + } +} + +impl Instance for StdInstance { + fn compute_witness(&mut self, _pctx: &ProofCtx) -> Option> { + let plan = &self.iectx.plan; + let rc_type = plan.meta.as_ref().unwrap().downcast_ref::().unwrap(); + + self.std.drain_inputs(rc_type); + + None + } + + fn instance_type(&self) -> InstanceType { + InstanceType::Table + } +} + +unsafe impl Sync for StdInstance {} diff --git a/state-machines/std/src/std_planner.rs b/state-machines/std/src/std_planner.rs new file mode 100644 index 00000000..15d96f9e --- /dev/null +++ b/state-machines/std/src/std_planner.rs @@ -0,0 +1,34 @@ +use std::sync::Arc; + +use p3_field::PrimeField; +use pil_std_lib::Std; +use sm_common::{ChunkId, InstanceType, Metrics, Plan, Planner}; + +pub struct StdPlanner { + std: Arc>, +} + +impl StdPlanner { + pub fn new(std: Arc>) -> Self { + Self { std } + } +} + +impl Planner for StdPlanner { + fn plan(&self, _: Vec<(ChunkId, Box)>) -> Vec { + self.std + .get_ranges() + .into_iter() + .map(|(airgroup_id, air_id, rc_type)| { + Plan::new( + airgroup_id, + air_id, + None, + InstanceType::Table, + None, + Some(Box::new(rc_type)), + ) + }) + .collect() + } +} diff --git a/state-machines/std/src/std_sm.rs b/state-machines/std/src/std_sm.rs new file mode 100644 index 00000000..530f005f --- /dev/null +++ b/state-machines/std/src/std_sm.rs @@ -0,0 +1,31 @@ +use std::sync::Arc; + +use p3_field::PrimeField; +use pil_std_lib::Std; +use sm_common::{ComponentProvider, DummyCounter, Instance, InstanceExpanderCtx, Metrics, Planner}; + +use crate::{StdInstance, StdPlanner}; + +pub struct StdSM { + std: Arc>, +} + +impl StdSM { + pub fn new(std: Arc>) -> Arc { + Arc::new(Self { std: std.clone() }) + } +} + +impl ComponentProvider for StdSM { + fn get_counter(&self) -> Box { + Box::new(DummyCounter::default()) + } + + fn get_planner(&self) -> Box { + Box::new(StdPlanner::new(self.std.clone())) + } + + fn get_instance(&self, iectx: InstanceExpanderCtx) -> Box> { + Box::new(StdInstance::new(self.std.clone(), iectx)) + } +} diff --git a/witness-computation/Cargo.toml b/witness-computation/Cargo.toml index 8540e2a0..c1ccd495 100644 --- a/witness-computation/Cargo.toml +++ b/witness-computation/Cargo.toml @@ -7,13 +7,13 @@ edition = "2021" crate-type = ["dylib"] [dependencies] +executor = { path = "../executor" } +sm-std = { path = "../state-machines/std" } sm-arith = { path = "../state-machines/arith" } sm-binary = { path = "../state-machines/binary" } sm-common = { path = "../state-machines/common" } -sm-freq-ops = { path = "../state-machines/freq-ops" } sm-main = { path = "../state-machines/main" } sm-mem = { path = "../state-machines/mem" } -sm-quick-ops = { path = "../state-machines/quick-ops" } sm-rom = { path = "../state-machines/rom" } zisk-pil = { path = "../pil" } ziskemu = { path = "../emulator" } @@ -22,7 +22,7 @@ zisk-core = { path = "../core" } proofman-common = { workspace = true } proofman-util = { workspace = true } -proofman = { workspace = true } +witness = { workspace = true } p3-field = { workspace=true } pil-std-lib = { workspace = true } log = { workspace = true } @@ -33,4 +33,4 @@ rayon = { workspace = true } [features] default = [] -no_lib_link = ["proofman-common/no_lib_link", "proofman/no_lib_link"] \ No newline at end of file +no_lib_link = ["proofman-common/no_lib_link"] \ No newline at end of file diff --git a/witness-computation/src/executor.rs b/witness-computation/src/executor.rs deleted file mode 100644 index b77f6bfe..00000000 --- a/witness-computation/src/executor.rs +++ /dev/null @@ -1,243 +0,0 @@ -use p3_field::PrimeField; -use pil_std_lib::Std; -use proofman::WitnessManager; -use proofman_common::{ExecutionCtx, ProofCtx, SetupCtx}; -use proofman_util::{timer_start_debug, timer_stop_and_log_debug}; - -use rayon::prelude::*; - -use sm_arith::ArithSM; -use sm_binary::BinarySM; -use sm_common::create_prover_buffer; -use sm_main::{InstanceExtensionCtx, MainSM}; -use sm_mem::MemSM; -use sm_rom::RomSM; -use std::{ - fs, - path::{Path, PathBuf}, - sync::Arc, -}; -use zisk_core::{Riscv2zisk, ZiskOperationType, ZiskRom, ZISK_OPERATION_TYPE_VARIANTS}; -use zisk_pil::{ - ARITH_AIR_IDS, BINARY_AIR_IDS, BINARY_EXTENSION_AIR_IDS, MAIN_AIR_IDS, ZISK_AIRGROUP_ID, -}; -use ziskemu::{EmuOptions, ZiskEmulator}; - -pub struct ZiskExecutor { - /// ZisK ROM, a binary file that contains the ZisK program to be executed - pub zisk_rom: Arc, - - /// Main State Machine - pub main_sm: Arc>, - - /// ROM State Machine - pub rom_sm: Arc>, - - /// Memory State Machine - pub mem_sm: Arc, - - /// Binary State Machine - pub binary_sm: Arc>, - - /// Arithmetic State Machine - pub arith_sm: Arc>, -} - -impl ZiskExecutor { - const NUM_THREADS: usize = 8; - - pub fn new(wcm: Arc>, rom_path: PathBuf) -> Self { - let std = Std::new(wcm.clone()); - - let rom_sm = RomSM::new(wcm.clone()); - let mem_sm = MemSM::new(wcm.clone()); - let binary_sm = BinarySM::new(wcm.clone(), std.clone()); - let arith_sm = ArithSM::new(wcm.clone()); - - // If rom_path has an .elf extension it must be converted to a ZisK ROM - let zisk_rom = if rom_path.extension().unwrap() == "elf" { - // Create an instance of the RISCV -> ZisK program converter - let rv2zk = Riscv2zisk::new( - rom_path.display().to_string(), - String::new(), - String::new(), - String::new(), - ); - - // Convert program to rom - match rv2zk.run() { - Ok(rom) => rom, - Err(e) => { - panic!("Application error: {}", e); - } - } - } else { - // TODO - Remove this when the ZisK ROM is able to be loaded from a file - panic!("ROM file must be an ELF file"); - }; - - let zisk_rom = Arc::new(zisk_rom); - - // TODO - Compute MAX_ACCUMULATED having the num_rows of the Main AIR - // TODO - If there is more than one Main AIR available, the MAX_ACCUMULATED will be the one - // with the highest num_rows. It has to be a power of 2. - - let main_sm = MainSM::new(wcm.clone(), arith_sm.clone(), binary_sm.clone(), mem_sm.clone()); - - Self { zisk_rom, main_sm, rom_sm, mem_sm, binary_sm, arith_sm } - } - - /// Executes the MainSM state machine and processes the inputs in batches when the maximum - /// number of accumulated inputs is reached. The MainSM state machine uses the emulator to - /// execute the a program and using a callback the main state machine receives batches of - /// inputs generated by the emulator. The inputs are processed in batches when the maximum - /// number of accumulated inputs is reached - /// # Arguments - /// * `pctx` - Proof context to interact with the proof system - /// * `ectx` - Execution context to interact with the execution environment - pub fn execute( - &self, - rom_path: &Path, - public_inputs_path: &Path, - pctx: Arc>, - ectx: Arc>, - sctx: Arc>, - ) { - let air_main = pctx.pilout.get_air(ZISK_AIRGROUP_ID, MAIN_AIR_IDS[0]); - - // Prepare the settings for the emulator - let emu_options = EmuOptions { - elf: Some(rom_path.to_path_buf().display().to_string()), - inputs: Some(public_inputs_path.display().to_string()), - trace_steps: Some(air_main.num_rows() as u64 - 1), - ..EmuOptions::default() - }; - - // Call emulate with these options - let public_inputs = { - // Read inputs data from the provided inputs path - let path = PathBuf::from(public_inputs_path.display().to_string()); - fs::read(path).expect("Could not read inputs file") - }; - - // During ROM processing, we gather execution data necessary for creating the AIR instances. - // This data is collected by the emulator and includes the minimal execution trace, - // along with essential state information of the processor. This ensures that the execution - // can be reproduced from specific points in the trace to generate the inputs for each state - // machine. We aim to track the starting point of execution for every N instructions - // across different operation types. Currently, we are only collecting data for - // Binary and BinaryE operations. - let air_arith = pctx.pilout.get_air(ZISK_AIRGROUP_ID, ARITH_AIR_IDS[0]); - let air_binary = pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_AIR_IDS[0]); - let air_binary_e = pctx.pilout.get_air(ZISK_AIRGROUP_ID, BINARY_EXTENSION_AIR_IDS[0]); - - let mut op_sizes = [0u64; ZISK_OPERATION_TYPE_VARIANTS]; - // The starting points for the Main is allocated using None operation - op_sizes[ZiskOperationType::None as usize] = air_main.num_rows() as u64; - op_sizes[ZiskOperationType::Arith as usize] = air_arith.num_rows() as u64; - op_sizes[ZiskOperationType::Binary as usize] = air_binary.num_rows() as u64; - op_sizes[ZiskOperationType::BinaryE as usize] = air_binary_e.num_rows() as u64; - - // ROM State Machine - // ---------------------------------------------- - // Run the ROM to compute the ROM witness - let rom_sm = self.rom_sm.clone(); - let zisk_rom = self.zisk_rom.clone(); - let pc_histogram = - ZiskEmulator::process_rom_pc_histogram(&self.zisk_rom, &public_inputs, &emu_options) - .expect( - "MainSM::execute() failed calling ZiskEmulator::process_rom_pc_histogram()", - ); - let handle_rom = std::thread::spawn(move || rom_sm.prove(&zisk_rom, pc_histogram)); - - // Main, Binary and Arith State Machines - // ---------------------------------------------- - // Run the emulator in parallel n times to collect execution traces - // and record the execution starting points for each AIR instance - timer_start_debug!(PAR_PROCESS_ROM); - let (emu_traces, mut emu_slices) = ZiskEmulator::par_process_rom::( - &self.zisk_rom, - &public_inputs, - &emu_options, - Self::NUM_THREADS, - op_sizes, - ) - .expect("Error during emulator execution"); - timer_stop_and_log_debug!(PAR_PROCESS_ROM); - - emu_slices.points.sort_by(|a, b| a.op_type.partial_cmp(&b.op_type).unwrap()); - - // Join threads to synchronize the execution - handle_rom.join().unwrap().expect("Error during ROM witness computation"); - - // FIXME: Move InstanceExtensionCtx form main SM to another place - let mut instances_extension_ctx: Vec> = - Vec::with_capacity(emu_slices.points.len()); - - let mut dctx = ectx.dctx.write().unwrap(); - let mut main_segnent_id = 0; - for emu_slice in emu_slices.points.iter() { - let (airgroup_id, air_id) = match emu_slice.op_type { - ZiskOperationType::None => (ZISK_AIRGROUP_ID, MAIN_AIR_IDS[0]), - ZiskOperationType::Arith => (ZISK_AIRGROUP_ID, ARITH_AIR_IDS[0]), - ZiskOperationType::Binary => (ZISK_AIRGROUP_ID, BINARY_AIR_IDS[0]), - ZiskOperationType::BinaryE => (ZISK_AIRGROUP_ID, BINARY_EXTENSION_AIR_IDS[0]), - _ => panic!("Invalid operation type"), - }; - let segment_id = match emu_slice.op_type { - ZiskOperationType::None => { - main_segnent_id += 1; - Some(main_segnent_id - 1) - } - _ => None, - }; - - if let (true, global_idx) = dctx.add_instance(airgroup_id, air_id, 1) { - let (buffer, offset) = create_prover_buffer::(&ectx, &sctx, airgroup_id, air_id); - instances_extension_ctx.push(InstanceExtensionCtx::new( - buffer, - offset, - emu_slice.op_type, - emu_slice.emu_trace_start.clone(), - segment_id, - global_idx, - None, - )); - } - } - drop(dctx); - - instances_extension_ctx.par_iter_mut().for_each(|iectx| match iectx.op_type { - ZiskOperationType::None => { - self.main_sm.prove_main(&self.zisk_rom, &emu_traces, iectx, &pctx); - } - ZiskOperationType::Arith => { - self.main_sm.prove_arith(&self.zisk_rom, &emu_traces, iectx, &pctx); - } - ZiskOperationType::Binary => { - self.main_sm.prove_binary(&self.zisk_rom, &emu_traces, iectx, &pctx); - } - ZiskOperationType::BinaryE => { - self.main_sm.prove_binary_extension(&self.zisk_rom, &emu_traces, iectx, &pctx); - } - _ => panic!("Invalid operation type"), - }); - // Drop the emulator traces concurrently - std::thread::spawn(move || { - drop(emu_traces); - }); - - timer_start_debug!(ADD_INSTANCES_TO_THE_REPO); - for iectx in instances_extension_ctx { - if let Some(air_instance) = iectx.air_instance { - pctx.air_instance_repo - .add_air_instance(air_instance, Some(iectx.instance_global_idx)); - } - } - timer_stop_and_log_debug!(ADD_INSTANCES_TO_THE_REPO); - - // self.mem_sm.unregister_predecessor(scope); - self.binary_sm.unregister_predecessor(); - self.arith_sm.unregister_predecessor(); - } -} diff --git a/witness-computation/src/lib.rs b/witness-computation/src/lib.rs index 9a41bb3d..39ef75d6 100644 --- a/witness-computation/src/lib.rs +++ b/witness-computation/src/lib.rs @@ -1,5 +1,3 @@ -mod executor; mod zisk_lib; -pub use executor::*; pub use zisk_lib::*; diff --git a/witness-computation/src/zisk_lib.rs b/witness-computation/src/zisk_lib.rs index 02a78d12..73167678 100644 --- a/witness-computation/src/zisk_lib.rs +++ b/witness-computation/src/zisk_lib.rs @@ -1,119 +1,57 @@ -use proofman_util::{timer_start_info, timer_stop_and_log_info}; -use std::{cell::OnceCell, error::Error, path::PathBuf, sync::Arc}; -use zisk_pil::*; +use executor::ZiskExecutor; +use pil_std_lib::Std; +use sm_arith::ArithSM; +use sm_binary::BinarySM; +use sm_rom::RomSM; +use sm_std::StdSM; +use std::sync::Arc; +use zisk_core::Riscv2zisk; use p3_field::PrimeField; use p3_goldilocks::Goldilocks; -use proofman::{WitnessLibrary, WitnessManager}; -use proofman_common::{ - initialize_logger, ExecutionCtx, ProofCtx, SetupCtx, VerboseMode, WitnessPilout, -}; - -use crate::ZiskExecutor; - -pub struct ZiskWitness { - /// Public inputs path - pub public_inputs_path: PathBuf, - - /// ROM path - pub rom_path: PathBuf, - - /// Witness computation manager - pub wcm: OnceCell>>, - - /// Executor - pub executor: OnceCell>, -} - -impl ZiskWitness { - pub fn new(rom_path: PathBuf, public_inputs_path: PathBuf) -> Result> { - // Check rom_path path exists - if !rom_path.exists() { - return Err(format!("ROM file not found at path: {:?}", rom_path).into()); - } - - // Check public_inputs_path is a folder - if !public_inputs_path.exists() { - return Err( - format!("Public inputs file not found at path: {:?}", public_inputs_path).into() +use witness::{witness_library, WitnessLibrary, WitnessManager}; + +witness_library!(WitnessLib, Goldilocks); + +impl WitnessLibrary for WitnessLib { + fn register_witness(&mut self, wcm: Arc>) { + // If rom_path has an .elf extension it must be converted to a ZisK ROM + let zisk_rom = if wcm.get_rom_path().unwrap().extension().unwrap() == "elf" { + // Create an instance of the RISCV -> ZisK program converter + let rv2zk = Riscv2zisk::new( + wcm.get_rom_path().unwrap().display().to_string(), + String::new(), + String::new(), + String::new(), ); - } - - Ok(ZiskWitness { - public_inputs_path, - rom_path, - wcm: OnceCell::new(), - executor: OnceCell::new(), - }) - } - - fn initialize( - &mut self, - pctx: Arc>, - ectx: Arc>, - sctx: Arc>, - ) { - let wcm = WitnessManager::new(pctx, ectx, sctx); - let wcm = Arc::new(wcm); - - self.wcm.set(wcm.clone()).ok(); - self.executor.set(ZiskExecutor::new(wcm, self.rom_path.clone())).ok(); - } -} - -impl WitnessLibrary for ZiskWitness { - fn start_proof( - &mut self, - pctx: Arc>, - ectx: Arc>, - sctx: Arc>, - ) { - self.initialize(pctx.clone(), ectx.clone(), sctx.clone()); - - self.wcm.get().unwrap().start_proof(pctx, ectx, sctx); - } - - fn end_proof(&mut self) { - self.wcm.get().unwrap().end_proof(); - } - fn execute(&self, pctx: Arc>, ectx: Arc>, sctx: Arc>) { - timer_start_info!(EXECUTE); - self.executor.get().unwrap().execute( - &self.rom_path, - &self.public_inputs_path, - pctx, - ectx, - sctx, - ); - timer_stop_and_log_info!(EXECUTE); - } - fn calculate_witness( - &mut self, - stage: u32, - pctx: Arc>, - ectx: Arc>, - sctx: Arc>, - ) { - self.wcm.get().unwrap().calculate_witness(stage, pctx, ectx, sctx); + // Convert program to rom + match rv2zk.run() { + Ok(rom) => rom, + Err(e) => { + panic!("Application error: {}", e); + } + } + } else { + // TODO - Remove this when the ZisK ROM is able to be loaded from a file + panic!("ROM file must be an ELF file"); + }; + let zisk_rom = Arc::new(zisk_rom); + + // Create the secondary state machines + let std = Std::new(wcm.clone()); + + let std_sm = StdSM::new(std.clone()); + let rom_sm = RomSM::new(zisk_rom.clone()); + let binary_sm = BinarySM::new(std.clone()); + let arith_sm = ArithSM::new(); + + let mut executor = ZiskExecutor::new(wcm.get_public_inputs_path().unwrap(), zisk_rom); + executor.register_sm(std_sm); + executor.register_sm(rom_sm); + executor.register_sm(binary_sm); + executor.register_sm(arith_sm); + + wcm.register_component(Arc::new(executor)); } - - fn pilout(&self) -> WitnessPilout { - Pilout::pilout() - } -} - -#[no_mangle] -pub extern "Rust" fn init_library( - rom_path: Option, - public_inputs_path: Option, - verbose_mode: VerboseMode, -) -> Result>, Box> { - let rom_path = rom_path.clone().ok_or("ROM path is required")?; - let public_inputs = public_inputs_path.ok_or("Public inputs path is required")?; - - initialize_logger(verbose_mode); - - let zisk_witness = ZiskWitness::new(rom_path, public_inputs)?; - Ok(Box::new(zisk_witness)) }