diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 54f370fcb5920bb7db473bea9baf8e7369887d1c..0000000000000000000000000000000000000000 --- a/Cargo.lock +++ /dev/null @@ -1,1053 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "anstream" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" - -[[package]] -name = "anstyle-parse" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" -dependencies = [ - "anstyle", - "windows-sys", -] - -[[package]] -name = "anyhow" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" - -[[package]] -name = "atomic-polyfill" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" -dependencies = [ - "critical-section", -] - -[[package]] -name = "autocfg" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" - -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" -dependencies = [ - "serde", -] - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cactus" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbc26382d871df4b7442e3df10a9402bf3cf5e55cbd66f12be38861425f0564" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfgrammar" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "163348850b1cd34fa99ef1592b5d598ea7e6752f18aff2125b67537e887edb36" -dependencies = [ - "indexmap", - "lazy_static", - "num-traits", - "regex", - "serde", - "vob", -] - -[[package]] -name = "clap" -version = "4.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" - -[[package]] -name = "cobs" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" - -[[package]] -name = "colorchoice" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" - -[[package]] -name = "critical-section" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "embedded-io" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "filetime" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "windows-sys", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hash32" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - -[[package]] -name = "heapless" -version = "0.7.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" -dependencies = [ - "atomic-polyfill", - "hash32", - "rustc_version", - "serde", - "spin", - "stable_deref_trait", -] - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "hercules_cg" -version = "0.1.0" -dependencies = [ - "bitvec", - "hercules_ir", - "hercules_rt", -] - -[[package]] -name = "hercules_cpu_beta" -version = "0.1.0" -dependencies = [ - "clap", - "hercules_cg", - "hercules_ir", - "hercules_opt", - "rand", -] - -[[package]] -name = "hercules_dot" -version = "0.1.0" -dependencies = [ - "clap", - "hercules_ir", - "hercules_opt", - "rand", -] - -[[package]] -name = "hercules_driver" -version = "0.1.0" -dependencies = [ - "clap", - "hercules_ir", - "hercules_opt", - "ron", -] - -[[package]] -name = "hercules_ir" -version = "0.1.0" -dependencies = [ - "bitvec", - "nom", - "ordered-float", - "rand", - "serde", -] - -[[package]] -name = "hercules_matmul" -version = "0.1.0" -dependencies = [ - "clap", - "hercules_rt", - "rand", -] - -[[package]] -name = "hercules_opt" -version = "0.1.0" -dependencies = [ - "bitvec", - "hercules_cg", - "hercules_ir", - "ordered-float", - "postcard", - "serde", - "take_mut", -] - -[[package]] -name = "hercules_rt" -version = "0.1.0" -dependencies = [ - "hercules_ir", - "libc", - "postcard", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" - -[[package]] -name = "itoa" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" - -[[package]] -name = "juno_frontend" -version = "0.1.0" -dependencies = [ - "cfgrammar", - "clap", - "hercules_ir", - "hercules_opt", - "lrlex", - "lrpar", - "num-rational", - "num-traits", - "ordered-float", - "phf", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.154" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" - -[[package]] -name = "lock_api" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "lrlex" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ff18e1bd3ed77d7bc2800a0f8b0e922a3c7ba525505be8bab9cf45dfc4984b" -dependencies = [ - "cfgrammar", - "getopts", - "lazy_static", - "lrpar", - "num-traits", - "quote", - "regex", - "regex-syntax", - "serde", - "vergen", -] - -[[package]] -name = "lrpar" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efea5a41b9988b5ae41ea9b2375a52cfa0e483f0210357209caa8d361a24a368" -dependencies = [ - "bincode", - "cactus", - "cfgrammar", - "filetime", - "indexmap", - "lazy_static", - "lrtable", - "num-traits", - "packedvec", - "regex", - "serde", - "static_assertions", - "vergen", - "vob", -] - -[[package]] -name = "lrtable" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff5668c3bfd279ed24d5b0d24568c48dc993f9beabd51f74d1865a78c1d206ab" -dependencies = [ - "cfgrammar", - "fnv", - "num-traits", - "serde", - "sparsevec", - "vob", -] - -[[package]] -name = "memchr" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num-bigint" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-conv" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - -[[package]] -name = "ordered-float" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" -dependencies = [ - "num-traits", -] - -[[package]] -name = "packedvec" -version = "1.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde3c690ec20e4a2b4fb46f0289a451181eb50011a1e2acc8d85e2fde9062a45" -dependencies = [ - "num-traits", - "serde", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "postcard" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" -dependencies = [ - "cobs", - "embedded-io", - "heapless", - "serde", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro2" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "regex" -version = "1.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" - -[[package]] -name = "ron" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" -dependencies = [ - "base64", - "bitflags 2.5.0", - "serde", - "serde_derive", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustversion" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092474d1a01ea8278f69e6a358998405fae5b8b963ddaeb2b0b04a128bf1dfb0" - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "semver" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" - -[[package]] -name = "serde" -version = "1.0.200" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.200" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "sparsevec" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35df5d2e580b29f3f7ec5b4ed49b0ab3acf7f3624122b3e823cafb9630f293b8" -dependencies = [ - "num-traits", - "packedvec", - "serde", - "vob", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -dependencies = [ - "lock_api", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "syn" -version = "2.0.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "take_mut" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "time" -version = "0.3.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" -dependencies = [ - "deranged", - "itoa", - "libc", - "num-conv", - "num_threads", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-width" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "vergen" -version = "8.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" -dependencies = [ - "anyhow", - "rustversion", - "time", -] - -[[package]] -name = "vob" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c058f4c41e71a043c67744cb76dcc1ae63ece328c1732a72489ccccc2dec23e6" -dependencies = [ - "num-traits", - "rustc_version", - "serde", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] diff --git a/Cargo.toml b/Cargo.toml index bded2dcf120dba7de5f17d68616ee3ae6afb1dbc..ba6ffb28f3a8dacd63344252d110323885ba12e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,12 +5,14 @@ members = [ "hercules_ir", "hercules_opt", "hercules_rt", + "hercules_rt_proc", "hercules_tools/hercules_driver", "hercules_tools/hercules_dot", "hercules_tools/hercules_cpu_beta", - "juno_frontend", + "juno_frontend", - "hercules_samples/matmul" + "hercules_samples/matmul", + "hercules_samples/task_parallel" ] diff --git a/hercules_cg/Cargo.toml b/hercules_cg/Cargo.toml index b54796695ad4cae63be080daef70b5ee2fb33204..9464153078b92bc8a9ee6f4c5535c4e435395b2a 100644 --- a/hercules_cg/Cargo.toml +++ b/hercules_cg/Cargo.toml @@ -6,4 +6,3 @@ authors = ["Russel Arbore <rarbore2@illinois.edu>"] [dependencies] bitvec = "*" hercules_ir = { path = "../hercules_ir" } -hercules_rt = { path = "../hercules_rt" } diff --git a/hercules_cg/src/common.rs b/hercules_cg/src/common.rs index 9bc91b57a2815ca6b8800d72518e1c41ffc83e1b..f3d5a89d05e9fda42ed09ecc43b092b819f7a9a6 100644 --- a/hercules_cg/src/common.rs +++ b/hercules_cg/src/common.rs @@ -1,10 +1,8 @@ extern crate hercules_ir; -extern crate hercules_rt; use std::collections::HashMap; use self::hercules_ir::*; -use self::hercules_rt::manifest::*; /* * Pretty much all of the codegen functions need to take in some large subset of @@ -188,10 +186,10 @@ impl<'a> FunctionContext<'a> { pub(crate) fn partition_control_successors( &self, partition_id: PartitionID, - ) -> Vec<PartitionID> { + ) -> Vec<(PartitionID, NodeID)> { let partition = &self.partitions_inverted_map[partition_id.idx()]; - let mut partitions: Vec<PartitionID> = partition + partition .iter() // Only consider nodes in other partitions that are successors of // control nodes. These are necessarily other control nodes. @@ -205,14 +203,11 @@ impl<'a> FunctionContext<'a> { .into_iter() .map(|id| self.plan.partitions[id.idx()]) .filter(|id| *id != partition_id) + .map(move |part_id| (part_id, *id)) }) // We want a flat list of all such partitions. .flatten() - .collect(); - - // We only want one copy of the ID per partition. - partitions.dedup(); - partitions + .collect() } /* @@ -376,6 +371,12 @@ impl<'a> PartitionContext<'a> { manifest.outputs.push(PartitionOutput::ControlIndicator); } + // Store the successor partitions. + manifest.successor_partitions = control_successors + .into_iter() + .map(|(part_id, control_id)| (control_id.idx() as u32, part_id.idx() as u32)) + .collect(); + PartitionContext { function, partition_id, @@ -438,7 +439,7 @@ pub(crate) fn generate_type_strings(module: &Module) -> Vec<String> { // since a type may reference a type ID ahead of it in the vector. Instead, // iterate types in a bottom up order with respect to the type intern DAGs. let mut llvm_types = vec!["".to_string(); module.types.len()]; - for id in module.types_bottom_up() { + for id in types_bottom_up(&module.types) { llvm_types[id.idx()] = generate_type_string(&module.types[id.idx()], &llvm_types); } @@ -497,7 +498,7 @@ pub(crate) fn generate_constant_strings(module: &Module) -> Vec<String> { // Render constants into LLVM IR. This is done in a very similar manner as // types. let mut llvm_constants = vec!["".to_string(); module.constants.len()]; - for id in module.constants_bottom_up() { + for id in constants_bottom_up(&module.constants) { llvm_constants[id.idx()] = generate_constant_string( id, &module.constants[id.idx()], diff --git a/hercules_cg/src/cpu.rs b/hercules_cg/src/cpu.rs index 4f4726a7ef022d877faf892483b4df4cc4b79421..134e56a8eeb33441b7ac89e17180c5b06aab7560 100644 --- a/hercules_cg/src/cpu.rs +++ b/hercules_cg/src/cpu.rs @@ -1,6 +1,5 @@ extern crate bitvec; extern crate hercules_ir; -extern crate hercules_rt; use std::collections::HashMap; use std::collections::VecDeque; @@ -12,7 +11,6 @@ use std::fmt::Write; use self::bitvec::prelude::*; use self::hercules_ir::*; -use self::hercules_rt::manifest::*; use crate::*; diff --git a/hercules_cg/src/lib.rs b/hercules_cg/src/lib.rs index 280910dd3f800822c4502dcf431d4e45698500c3..c33fd857ca71b4c82135d7ce933ea441d3ece4f4 100644 --- a/hercules_cg/src/lib.rs +++ b/hercules_cg/src/lib.rs @@ -2,10 +2,8 @@ pub mod common; pub mod cpu; -pub mod cpu_beta; pub mod top; pub use crate::common::*; pub use crate::cpu::*; -pub use crate::cpu_beta::*; pub use crate::top::*; diff --git a/hercules_cg/src/top.rs b/hercules_cg/src/top.rs index b992344db2f469b107c4be29a37f59e3f396a603..626c425772d9d1ec7e37e5ce00471b476c940dd5 100644 --- a/hercules_cg/src/top.rs +++ b/hercules_cg/src/top.rs @@ -1,11 +1,9 @@ extern crate hercules_ir; -extern crate hercules_rt; use std::collections::HashMap; use std::fmt::Write; use self::hercules_ir::*; -use self::hercules_rt::manifest::*; use crate::*; @@ -109,6 +107,17 @@ impl<'a> FunctionContext<'a> { }) .collect(); + // Collect all the node IDs that are values returned by this function. + let returned_values = self + .function + .nodes + .iter() + .filter_map(|node| node.try_return().map(|(_, data)| data.idx() as u32)) + .collect::<Vec<u32>>(); + + // Get the partition ID of the start node. + let top_partition = self.plan.partitions[0].idx() as u32; + // Generate code for each individual partition. This generates a single // LLVM function per partition. These functions will be called in async // tasks by the Hercules runtime. @@ -125,11 +134,14 @@ impl<'a> FunctionContext<'a> { Ok(FunctionManifest { name: self.function.name.clone(), param_types: self.function.param_types.clone(), + return_type: self.function.return_type, typing: self.typing.clone(), num_dynamic_constant_parameters: self.function.num_dynamic_constants, partitions: manifests, // TODO: populate dynamic constant rules. dynamic_constant_rules: vec![], + top_partition, + returned_values, }) } } diff --git a/hercules_ir/src/ir.rs b/hercules_ir/src/ir.rs index 075d10c13e6d44ba6a9c015755b981d4c9e37703..3a315aedcad165d83a3237a86b1c26afd7a31fdc 100644 --- a/hercules_ir/src/ir.rs +++ b/hercules_ir/src/ir.rs @@ -372,133 +372,131 @@ impl Module { } /* - * Create an iterator that traverses all the types in the module bottom up. - * This uses a coroutine to make iteratively traversing the type DAGs - * easier. + * Unfortunately, determining if a constant is an array requires both + * knowledge of constants and types, due to zero initializer constants. */ - pub fn types_bottom_up(&self) -> impl Iterator<Item = TypeID> + '_ { - let types = &self.types; - let mut visited = bitvec![u8, Lsb0; 0; self.types.len()]; - let mut stack = (0..self.types.len()) - .map(TypeID::new) - .collect::<Vec<TypeID>>(); - let coroutine = #[coroutine] move || { - // Since this is a coroutine, handle recursion manually. - while let Some(id) = stack.pop() { - if visited[id.idx()] { - continue; - } - match &types[id.idx()] { - Type::Product(children) | Type::Summation(children) => { - // We have to yield the children of this node before - // this node itself. We keep track of which nodes have - // yielded using visited. - let can_yield = children.iter().all(|x| visited[x.idx()]); - if can_yield { - visited.set(id.idx(), true); - yield id; - } else { - // Push ourselves, then children, so that children - // get popped first. - stack.push(id); - for id in children.iter() { - stack.push(*id); - } - } - } - Type::Array(child, _) => { - // Same idea as product / summation, but there's only - // one child. - let can_yield = visited[child.idx()]; - if can_yield { - visited.set(id.idx(), true); - yield id; - } else { - stack.push(id); - stack.push(*child); + pub fn is_array_constant(&self, cons_id: ConstantID) -> bool { + if let Constant::Zero(ty_id) = self.constants[cons_id.idx()] { + self.types[ty_id.idx()].is_array() + } else { + self.constants[cons_id.idx()].is_strictly_array() + } + } +} + +/* + * Create an iterator that traverses all the types in the module bottom up. + * This uses a coroutine to make iteratively traversing the type DAGs + * easier. + */ +pub fn types_bottom_up(types: &Vec<Type>) -> impl Iterator<Item = TypeID> + '_ { + let mut visited = bitvec![u8, Lsb0; 0; types.len()]; + let mut stack = (0..types.len()).map(TypeID::new).collect::<Vec<TypeID>>(); + let coroutine = #[coroutine] + move || { + // Since this is a coroutine, handle recursion manually. + while let Some(id) = stack.pop() { + if visited[id.idx()] { + continue; + } + match &types[id.idx()] { + Type::Product(children) | Type::Summation(children) => { + // We have to yield the children of this node before + // this node itself. We keep track of which nodes have + // yielded using visited. + let can_yield = children.iter().all(|x| visited[x.idx()]); + if can_yield { + visited.set(id.idx(), true); + yield id; + } else { + // Push ourselves, then children, so that children + // get popped first. + stack.push(id); + for id in children.iter() { + stack.push(*id); } } - _ => { + } + Type::Array(child, _) => { + // Same idea as product / summation, but there's only + // one child. + let can_yield = visited[child.idx()]; + if can_yield { visited.set(id.idx(), true); yield id; + } else { + stack.push(id); + stack.push(*child); } } + _ => { + visited.set(id.idx(), true); + yield id; + } } - }; - CoroutineIterator { - coroutine: Box::new(coroutine), } + }; + CoroutineIterator { + coroutine: Box::new(coroutine), } +} - /* - * Create an iterator that traverses all the constants in the module bottom up. - * This uses a coroutine to make iteratively traversing the constant DAGs - * easier. - */ - pub fn constants_bottom_up(&self) -> impl Iterator<Item = ConstantID> + '_ { - let constants = &self.constants; - let mut visited = bitvec![u8, Lsb0; 0; self.constants.len()]; - let mut stack = (0..self.constants.len()) - .map(ConstantID::new) - .collect::<Vec<ConstantID>>(); - let coroutine = #[coroutine] move || { - // Since this is a coroutine, handle recursion manually. - while let Some(id) = stack.pop() { - if visited[id.idx()] { - continue; - } - match &constants[id.idx()] { - Constant::Product(_, children) | Constant::Array(_, children) => { - // We have to yield the children of this node before - // this node itself. We keep track of which nodes have - // yielded using visited. - let can_yield = children.iter().all(|x| visited[x.idx()]); - if can_yield { - visited.set(id.idx(), true); - yield id; - } else { - // Push ourselves, then children, so that children - // get popped first. - stack.push(id); - for id in children.iter() { - stack.push(*id); - } - } - } - Constant::Summation(_, _, child) => { - // Same idea as product / summation, but there's only - // one child. - let can_yield = visited[child.idx()]; - if can_yield { - visited.set(id.idx(), true); - yield id; - } else { - stack.push(id); - stack.push(*child); +/* + * Create an iterator that traverses all the constants in the module bottom up. + * This uses a coroutine to make iteratively traversing the constant DAGs + * easier. + */ +pub fn constants_bottom_up(constants: &Vec<Constant>) -> impl Iterator<Item = ConstantID> + '_ { + let mut visited = bitvec![u8, Lsb0; 0; constants.len()]; + let mut stack = (0..constants.len()) + .map(ConstantID::new) + .collect::<Vec<ConstantID>>(); + let coroutine = #[coroutine] + move || { + // Since this is a coroutine, handle recursion manually. + while let Some(id) = stack.pop() { + if visited[id.idx()] { + continue; + } + match &constants[id.idx()] { + Constant::Product(_, children) | Constant::Array(_, children) => { + // We have to yield the children of this node before + // this node itself. We keep track of which nodes have + // yielded using visited. + let can_yield = children.iter().all(|x| visited[x.idx()]); + if can_yield { + visited.set(id.idx(), true); + yield id; + } else { + // Push ourselves, then children, so that children + // get popped first. + stack.push(id); + for id in children.iter() { + stack.push(*id); } } - _ => { + } + Constant::Summation(_, _, child) => { + // Same idea as product / summation, but there's only + // one child. + let can_yield = visited[child.idx()]; + if can_yield { visited.set(id.idx(), true); yield id; + } else { + stack.push(id); + stack.push(*child); } } + _ => { + visited.set(id.idx(), true); + yield id; + } } - }; - CoroutineIterator { - coroutine: Box::new(coroutine), - } - } - - /* - * Unfortunately, determining if a constant is an array requires both - * knowledge of constants and types, due to zero initializer constants. - */ - pub fn is_array_constant(&self, cons_id: ConstantID) -> bool { - if let Constant::Zero(ty_id) = self.constants[cons_id.idx()] { - self.types[ty_id.idx()].is_array() - } else { - self.constants[cons_id.idx()].is_strictly_array() } + }; + CoroutineIterator { + coroutine: Box::new(coroutine), } } @@ -899,6 +897,14 @@ impl Node { } } + pub fn try_return(&self) -> Option<(NodeID, NodeID)> { + if let Node::Return { control, data } = self { + Some((*control, *data)) + } else { + None + } + } + pub fn try_constant(&self) -> Option<ConstantID> { if let Node::Constant { id } = self { Some(*id) diff --git a/hercules_ir/src/lib.rs b/hercules_ir/src/lib.rs index 44252678b2fb7a0cc58a393341eb189e86870910..c2fe35b704a08bc9bb4a32ffe778a082c96eb4f6 100644 --- a/hercules_ir/src/lib.rs +++ b/hercules_ir/src/lib.rs @@ -9,6 +9,7 @@ pub mod dot; pub mod gcm; pub mod ir; pub mod loops; +pub mod manifest; pub mod parse; pub mod schedule; pub mod subgraph; @@ -24,6 +25,7 @@ pub use crate::dot::*; pub use crate::gcm::*; pub use crate::ir::*; pub use crate::loops::*; +pub use crate::manifest::*; pub use crate::parse::*; pub use crate::schedule::*; pub use crate::subgraph::*; diff --git a/hercules_ir/src/manifest.rs b/hercules_ir/src/manifest.rs new file mode 100644 index 0000000000000000000000000000000000000000..74dc2ce49ad46afc48784865b24844add758bea8 --- /dev/null +++ b/hercules_ir/src/manifest.rs @@ -0,0 +1,195 @@ +extern crate serde; + +use self::serde::Deserialize; +use self::serde::Serialize; + +use crate::*; + +/* + * Every .hbin file contains a manifest which describes the Hercules functions + * contained in the module. This information is used by the runtime to execute + * the functions properly, the chief concern being how to stitch together the + * execution of each partition. + */ +#[derive(Debug, Serialize, Deserialize, Hash)] +pub struct ModuleManifest { + // A module contains a manifest per individual function. + pub functions: Vec<FunctionManifest>, + // All of the types used in the module. + pub types: Vec<Type>, + // The only constants that aren't baked into the generated code are array + // constants. These are explicitly stored in and loaded from the manifest. + // Arrays are composed of the underlying array bytes. We don't need to store + // the dimensions of arrays at this point, since the runtime doesn't + // manipulate or otherwise need the dimensions of constant arrays. + pub array_constants: Vec<Vec<u8>>, +} + +#[derive(Debug, Serialize, Deserialize, Hash)] +pub struct FunctionManifest { + pub name: String, + // Types of the function parameters. + pub param_types: Vec<TypeID>, + // Type of the return value. + pub return_type: TypeID, + // Types of all of the nodes in this function. Used for figuring out the + // type of partition data inputs and outputs. + pub typing: Vec<TypeID>, + // Number of dynamic constant parameters that need to provided. + pub num_dynamic_constant_parameters: u32, + // Manifests for constituent partitions. + pub partitions: Vec<PartitionManifest>, + // When using dynamic constants, certain constraints are generated. For + // example, if one uses division in dynamic constant math, the resulting + // dynamic constant must be an integer, so the numerator dynamic constant + // must be divisible by the denominator dynamic constant. These are stored + // per function, since different functions have different contraints on + // their dynamic constant parameters. + pub dynamic_constant_rules: Vec<DynamicConstantRule>, + // The partition containing the start node might not be partition 0. + pub top_partition: u32, + // Keep track of which node values are returned from the overall function. + // Integer is the node ID. + pub returned_values: Vec<u32>, +} + +/* + * Rules for validity of provided dynamic constants. Integers refer to dynamic + * constant parameters of a function. + */ +#[derive(Debug, Serialize, Deserialize, Hash, PartialEq, Eq)] +pub enum DynamicConstantRule { + // Generated from subtraction. + LessThan(u32, u32), + // Generated from division. + Divides(u32, u32), +} + +#[derive(Debug, Serialize, Deserialize, Hash, PartialEq, Eq)] +pub enum PartitionInput { + // Data input from another partition within this function. Integer is the + // node ID used from the other partition. + DataInput(u32), + // An argument from the function parameters. Integer is the parameter index. + FunctionArgument(u32), + // An array constant used in this function. Integer is the array constant + // number. + ArrayConstant(u32), + // A dynamic constant parameter of this function. Integer is the dynamic + // constant parameter number. + DynamicConstant(u32), +} + +#[derive(Debug, Serialize, Deserialize, Hash, PartialEq, Eq)] +pub enum PartitionOutput { + // Data output used by another partition within this function, or to be + // returned from this function. Integer is the node ID used in the other + // partition or by a return node. + DataOutput(u32), + // Value indicating control flow that the runtime should take. + ControlIndicator, +} + +#[derive(Debug, Serialize, Deserialize, Default, Hash)] +pub struct PartitionManifest { + // Top node for this partition, as an integer. + pub top_node: u32, + pub inputs: Vec<PartitionInput>, + pub outputs: Vec<PartitionOutput>, + + // Store the partitions that come after this partition. The first element of + // the pair is the control returning node in the current partition that + // corresponds to a particular successor, and the second element of the pair + // is the partition index of the corresponding successor partition. + pub successor_partitions: Vec<(u32, u32)>, +} + +/* + * Get the data inputs of partitions in a function. + */ +pub fn function_partition_inputs(manifest: &FunctionManifest) -> Vec<u32> { + let mut all_data_inputs = manifest + .partitions + .iter() + .map(|manifest| { + manifest.inputs.iter().filter_map(|input| { + if let PartitionInput::DataInput(idx) = input { + Some(*idx) + } else { + None + } + }) + }) + .flatten() + .collect::<Vec<u32>>(); + all_data_inputs.sort(); + all_data_inputs.dedup(); + all_data_inputs +} + +/* + * Get the data outputs of partitions in a function. + */ +pub fn function_partition_outputs(manifest: &FunctionManifest) -> Vec<u32> { + let mut all_data_outputs = manifest + .partitions + .iter() + .map(|manifest| { + manifest.outputs.iter().filter_map(|output| { + if let PartitionOutput::DataOutput(idx) = output { + Some(*idx) + } else { + None + } + }) + }) + .flatten() + .collect::<Vec<u32>>(); + all_data_outputs.sort(); + all_data_outputs.dedup(); + all_data_outputs +} + +/* + * Verify a manifest is valid. + */ +pub fn verify_manifest(manifest: &ModuleManifest) -> Result<(), String> { + manifest + .functions + .iter() + .map(|manifest| { + // First, check that all partitiion data inputs get used, and that + // all partition data outputs are produced. + let all_data_inputs = function_partition_inputs(manifest); + let all_data_outputs = function_partition_outputs(manifest); + + // Data outputs include values returned from the overall function. + // These are obviously not used by another partition, but that's + // fine. Remove them here explicitly. + let all_data_outputs = all_data_outputs.into_iter().filter(|idx| !manifest.returned_values.contains(idx)).collect::<Vec<u32>>(); + if all_data_inputs != all_data_outputs { + return Err(format!("PANIC: Partitions in manifest contain inconsistent data inputs and data outputs of partitions.\nHere are the data input IDs:\n{:?}\nHere are the data output IDs:\n{:?}\n", all_data_inputs, all_data_outputs)); + } + + // Next, check that partitions contain multiple successors if and + // only if a control indicator is present in their outputs. + // TODO: this will fail to verify a partition with a return node and + // a single successor partition, which technically is allowed. Deal + // with this later. + manifest.partitions.iter().map(|manifest| { + let multiple_successors = manifest.successor_partitions.len() > 1; + let control_indicator = manifest.outputs.contains(&PartitionOutput::ControlIndicator); + if !multiple_successors && control_indicator { + Err("PANIC: Partition in manifest doesn't have multiple successor partitions, but has a control indicator output.".to_string()) + } else if multiple_successors && !control_indicator { + Err("PANIC: Partition in manifest has multiple successor partitions, but not a control indicator output.".to_string()) + } else { + Ok(()) + } + }).collect::<Result<Vec<()>, String>>()?; + + Ok(()) + }) + .collect::<Result<Vec<()>, String>>() + .map(|_| ()) +} diff --git a/hercules_rt/Cargo.toml b/hercules_rt/Cargo.toml index 3df92d6a5b4c3ca1c7d0c2c3147ab61d69f8f78b..76c940b71979ee5bb7ab1d01abb77e3f7f3a0460 100644 --- a/hercules_rt/Cargo.toml +++ b/hercules_rt/Cargo.toml @@ -2,9 +2,10 @@ name = "hercules_rt" version = "0.1.0" authors = ["Russel Arbore <rarbore2@illinois.edu>"] +edition = "2021" [dependencies] libc = "*" postcard = { version = "*", features = ["alloc"] } serde = { version = "*", features = ["derive"] } -hercules_ir = { path = "../hercules_ir" } +hercules_rt_proc = { path = "../hercules_rt_proc" } diff --git a/hercules_rt/src/lib.rs b/hercules_rt/src/lib.rs index 2d19454d8307538cec592d162882015857529b2a..c8a9c729ac1d10af3c5ddc01c10adc3889cfb223 100644 --- a/hercules_rt/src/lib.rs +++ b/hercules_rt/src/lib.rs @@ -1,21 +1,23 @@ -extern crate postcard; - -use std::fs::File; -use std::io::prelude::*; -use std::path::Path; +extern crate hercules_rt_proc; pub(crate) mod elf; -pub mod manifest; pub(crate) use crate::elf::*; -pub(crate) use crate::manifest::*; +pub use hercules_rt_proc::use_hbin; #[derive(Debug)] pub struct Module { - manifest: ModuleManifest, elf: Elf, } impl Module { + /* + * Parse ELF object from ELF bytes buffer. + */ + pub fn new(buffer: &[u8]) -> Self { + let elf = unsafe { parse_elf(buffer) }; + Module { elf } + } + /* * Get the function pointer corresponding to a function name. Panic if not * found. @@ -31,31 +33,3 @@ impl Module { ) } } - -pub fn load_binary(path: &Path) -> Module { - let mut f = File::open(path).unwrap(); - let mut buffer = vec![]; - f.read_to_end(&mut buffer).unwrap(); - let manifest_and_elf_bytes: (ModuleManifest, Vec<u8>) = postcard::from_bytes(&buffer).unwrap(); - let elf = unsafe { parse_elf(&manifest_and_elf_bytes.1) }; - Module { - manifest: manifest_and_elf_bytes.0, - elf, - } -} - -/* - * An ugly, unchecked macro for looking up Hercules functions in a module. Curse - * Rust for not supporting variadic generics and type pattern matching :shrug:. - * TODO: Generate per-lookup struct type for checking that the provided types - * are correct. - */ -#[macro_export] -macro_rules! lookup_function { - ($module:expr, $function:expr, $($param_ty:ty),*, => $ret_ty:ty) => { - { - let fn_ptr: fn($($param_ty),*) -> $ret_ty = unsafe { std::mem::transmute($module.get_function_ptr($function)) }; - fn_ptr - } - }; -} diff --git a/hercules_rt/src/manifest.rs b/hercules_rt/src/manifest.rs deleted file mode 100644 index c184e8b19b7d78c95bf41fa91824dfe0248ce39e..0000000000000000000000000000000000000000 --- a/hercules_rt/src/manifest.rs +++ /dev/null @@ -1,97 +0,0 @@ -extern crate hercules_ir; -extern crate serde; - -use self::serde::Deserialize; -use self::serde::Serialize; - -use self::hercules_ir::ir::*; - -/* - * Every .hbin file contains a manifest which describes the Hercules functions - * contained in the module. This information is used by the runtime to execute - * the functions properly, the chief concern being how to stitch together the - * execution of each partition. - */ -#[derive(Debug, Serialize, Deserialize)] -pub struct ModuleManifest { - // A module contains a manifest per individual function. - pub functions: Vec<FunctionManifest>, - // All of the types used in the module. - pub types: Vec<Type>, - // The only constants that aren't baked into the generated code are array - // constants. These are explicitly stored in and loaded from the manifest. - // Arrays are composed of the underlying array bytes. We don't need to store - // the dimensions of arrays at this point, since the runtime doesn't - // manipulate or otherwise need the dimensions of constant arrays. - pub array_constants: Vec<Vec<u8>>, -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct FunctionManifest { - pub name: String, - // Types of the function parameters. - pub param_types: Vec<TypeID>, - // Types of all of the nodes in this function. Used for figuring out the - // type of partition data inputs and outputs. - pub typing: Vec<TypeID>, - // Number of dynamic constant parameters that need to provided. - pub num_dynamic_constant_parameters: u32, - // Manifests for constituent partitions. - pub partitions: Vec<PartitionManifest>, - // When using dynamic constants, certain constraints are generated. For - // example, using a dynamic constant in a fork means that it must be non- - // zero, since fork-join nests are guaranteed to execute at least one - // iteration. Also, if one uses division in dynamic constant math, the - // resulting dynamic constant must be an integer, so the numerator dynamic - // constant must be divisible by the denominator dynamic constant. These are - // stored per function, since different functions have different contraints - // on their dynamic constant parameters. - pub dynamic_constant_rules: Vec<DynamicConstantRule>, -} - -/* - * Rules for validity of provided dynamic constants. Integers refer to dynamic - * constant parameters of a function. - */ -#[derive(Debug, Serialize, Deserialize)] -pub enum DynamicConstantRule { - // Generated from forks. - NonZero(u32), - // Generated from subtraction. - LessThan(u32, u32), - // Generated from division. - Divides(u32, u32), -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum PartitionInput { - // Data input from another partition within this function. Integer is the - // node ID used from the other partition. - DataInput(u32), - // An argument from the function parameters. Integer is the parameter index. - FunctionArgument(u32), - // An array constant used in this function. Integer is the array constant - // number. - ArrayConstant(u32), - // A dynamic constant parameter of this function. Integer is the dynamic - // constant parameter number. - DynamicConstant(u32), -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum PartitionOutput { - // Data output used by another partition within this function, or to be - // returned from this function. Integer is the node ID used in the other - // partition or by a return node. - DataOutput(u32), - // Value indicating control flow that the runtime should take. - ControlIndicator, -} - -#[derive(Debug, Serialize, Deserialize, Default)] -pub struct PartitionManifest { - // Top node for this partition, as an integer. - pub top_node: u32, - pub inputs: Vec<PartitionInput>, - pub outputs: Vec<PartitionOutput>, -} diff --git a/hercules_rt_proc/Cargo.toml b/hercules_rt_proc/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..eafa8a446884dc52f6f0afe208b03104396f28de --- /dev/null +++ b/hercules_rt_proc/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "hercules_rt_proc" +version = "0.1.0" +authors = ["Russel Arbore <rarbore2@illinois.edu>"] +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +postcard = { version = "*", features = ["alloc"] } +serde = { version = "*", features = ["derive"] } +hercules_ir = { path = "../hercules_ir" } +anyhow = "*" \ No newline at end of file diff --git a/hercules_rt_proc/src/lib.rs b/hercules_rt_proc/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..b335a0135daac4b0e6c329c6ce1d30ec078b8484 --- /dev/null +++ b/hercules_rt_proc/src/lib.rs @@ -0,0 +1,315 @@ +#![feature(iter_intersperse)] + +extern crate anyhow; +extern crate hercules_ir; +extern crate postcard; +extern crate proc_macro; + +use std::ffi::OsStr; +use std::fmt::Write; +use std::fs::File; +use std::hash::{DefaultHasher, Hash, Hasher}; +use std::io::prelude::*; +use std::path::Path; + +use proc_macro::*; + +use self::hercules_ir::*; + +/* + * Parse manifest from header of .hbin file. + */ +fn manifest_and_module_bytes(buffer: &[u8]) -> (ModuleManifest, Vec<u8>) { + postcard::from_bytes(buffer).unwrap() +} + +/* + * Convert Hercules types to the Rust types generated in the interface. + */ +fn generate_type_string(ty: &Type, rust_types: &Vec<String>) -> String { + match ty { + Type::Control(_) => "NOT_A_REAL_TYPE".to_string(), + Type::Boolean => "bool".to_string(), + Type::Integer8 => "i8".to_string(), + Type::Integer16 => "i16".to_string(), + Type::Integer32 => "i32".to_string(), + Type::Integer64 => "i64".to_string(), + Type::UnsignedInteger8 => "u8".to_string(), + Type::UnsignedInteger16 => "u16".to_string(), + Type::UnsignedInteger32 => "u32".to_string(), + Type::UnsignedInteger64 => "u64".to_string(), + Type::Float32 => "f32".to_string(), + Type::Float64 => "f64".to_string(), + Type::Product(fields) => { + fields + .iter() + .map(|field_id| &rust_types[field_id.idx()] as &str) + .fold("(".to_string(), |acc, field| acc + field + ",") + + ")" + } + Type::Summation(_) => todo!(), + Type::Array(elem, _) => format!("::std::boxed::Box<[{}]>", &rust_types[elem.idx()]), + } +} + +/* + * Generate async Rust code orchestrating partition execution. + */ +fn codegen(manifest: &ModuleManifest, elf: &[u8]) -> Result<String, anyhow::Error> { + // Verify the manifest. + verify_manifest(manifest).map_err(anyhow::Error::msg)?; + + // Convert Hercules IR types to Rust types. + let mut rust_types = vec!["".to_string(); manifest.types.len()]; + for id in types_bottom_up(&manifest.types) { + rust_types[id.idx()] = generate_type_string(&manifest.types[id.idx()], &rust_types); + } + + // Write to a String containing all of the Rust code. + let mut rust_code = "".to_string(); + + // Emit the ELF bytes as a static byte string constant. + write!( + rust_code, + "const __HERCULES_ELF_OBJ: &[u8] = {};", + Literal::byte_string(elf) + )?; + + // Emit the async functions. + for function in &manifest.functions { + // Emit the function signature. + write!(rust_code, "async fn {}(", function.name)?; + let param_tys = function.param_types.iter().map(|id| &rust_types[id.idx()]); + for (idx, param) in param_tys.enumerate() { + write!(rust_code, "param_{}: {},", idx, param)?; + } + for dyn_cons_idx in 0..function.num_dynamic_constant_parameters { + write!(rust_code, "dyn_cons_{}: u64,", dyn_cons_idx)?; + } + write!( + rust_code, + ") -> {} {{", + rust_types[function.return_type.idx()] + )?; + + // Check that the ELF got embedded properly. + write!( + rust_code, + "use std::hash::{{DefaultHasher, Hash, Hasher}};debug_assert_eq!({{let mut s = DefaultHasher::new(); __HERCULES_ELF_OBJ.hash(&mut s); s.finish()}}, {});", + { + let mut s = DefaultHasher::new(); + elf.hash(&mut s); + s.finish() + } + )?; + + // Load the ELF object, and cast the appropriate pointers. + write!( + rust_code, + r#"let module = ::hercules_rt::Module::new(__HERCULES_ELF_OBJ);"# + )?; + for (idx, partition) in function.partitions.iter().enumerate() { + // Determine the signature for the partition function. + let u64_ty_id = TypeID::new( + manifest + .types + .iter() + .position(|ty| *ty == Type::UnsignedInteger64) + .unwrap(), + ); + let input_types = partition.inputs.iter().map(|input| match input { + PartitionInput::DataInput(node_idx) => function.typing[*node_idx as usize], + PartitionInput::FunctionArgument(param_idx) => { + function.param_types[*param_idx as usize] + } + PartitionInput::ArrayConstant(_) => todo!(), + PartitionInput::DynamicConstant(_) => u64_ty_id, + }); + let output_type = Type::Product( + partition + .outputs + .iter() + .map(|input| match input { + PartitionOutput::DataOutput(node_idx) => { + function.typing[*node_idx as usize] + } + PartitionOutput::ControlIndicator => u64_ty_id, + }) + .collect(), + ); + + // Get the pointer for the partition function, and cast it to the + // correct function pointer type. + write!( + rust_code, + r#"let fn_ptr_part_{}: extern "C" fn({}) -> {} = unsafe {{ ::core::mem::transmute(module.get_function_ptr("{}_part_{}")) }};"#, + idx, + input_types + .map(|id| &rust_types[id.idx()] as &str) + .intersperse(", ") + .fold("".to_string(), |acc, field| acc + field), + // Generate the output product type on the fly. This type is not + // necessarily present in the typing of the original IR, before + // code generation. + generate_type_string(&output_type, &rust_types), + function.name, + idx + )?; + } + + // Declare all of the input / output intermediate variables. We declare + // them as Options since we want to catch use before definition bugs. We + // get the list of variables from partition outputs specifically, since + // this also includes returned values. + let all_partition_outputs = function_partition_outputs(function); + for node in all_partition_outputs { + write!( + rust_code, + "let mut node_{}: Option<{}> = None;", + node, + &rust_types[function.typing[node as usize].idx()] + )?; + } + + // The core executor is a Rust loop. We literally run a "control token" + // as described in the original sea of nodes paper through the + // partitions to drive execution. + write!( + rust_code, + "let mut control_token: u32 = {};loop {{", + function.top_partition + )?; + + // Match on the control token position to determine which partition to + // execute. + write!(rust_code, "match control_token {{")?; + for (idx, partition) in function.partitions.iter().enumerate() { + // The control token stores the current partition index. + write!(rust_code, "{} => {{", idx)?; + + // Calculate the inputs. + for (input_idx, input) in partition.inputs.iter().enumerate() { + write!( + rust_code, + "let input_{} = {};", + input_idx, + match input { + PartitionInput::DataInput(idx) => format!( + "node_{}.expect(\"PANIC: Encountered use before def in runtime.\")", + idx + ), + PartitionInput::FunctionArgument(idx) => format!("param_{}", idx), + PartitionInput::ArrayConstant(_) => todo!(), + PartitionInput::DynamicConstant(idx) => format!("dyn_cons_{}", idx), + } + )?; + } + + // Make the call. + write!(rust_code, "let output = fn_ptr_part_{}(", idx)?; + for input_idx in 0..partition.inputs.len() { + write!(rust_code, "input_{},", input_idx)?; + } + write!(rust_code, ");")?; + + // Assign the outputs. + for (output_idx, output) in partition.outputs.iter().enumerate() { + write!( + rust_code, + "{} = Some(output.{});", + match output { + PartitionOutput::DataOutput(idx) => format!("node_{}", idx), + PartitionOutput::ControlIndicator => "todo!()".to_string(), + }, + output_idx + )?; + } + + // If there are no control successors, return from the function. If + // there is one control successor, unconditionally set the control + // token to that successor's index. If there are multiple control + // successors, set the control token to the control indicator output + // of the partition function. + // TODO: handle functions with multiple returned values. + // TODO: handle partitions with a return node and a single successor + // partition. + if partition.successor_partitions.len() == 0 { + assert_eq!(function.returned_values.len(), 1); + write!( + rust_code, + "return node_{}.expect(\"PANIC: Encountered use before def in runtime.\");", + function.returned_values[0] + )?; + } else if partition.successor_partitions.len() == 1 { + write!( + rust_code, + "control_token = {};", + partition.successor_partitions[0].1 + )?; + } else { + todo!(); + } + + // Close the branch. + write!(rust_code, "}}")?; + } + + // Close the match, and handle invalid control token values. + write!( + rust_code, + "_ => panic!(\"PANIC: Invalid control token value.\"),}}" + )?; + + // Close the loop. + write!(rust_code, "}}")?; + + // Close the function. + write!(rust_code, "}}")?; + } + + eprintln!("{}", rust_code); + + Ok(rust_code) +} + +/* + * Load a Hercules compiled module from a .hbin file. + */ +#[proc_macro] +pub fn use_hbin(path: TokenStream) -> TokenStream { + use TokenTree::Literal; + + // Get the path as a Rust path object, and make sure it's a .hbin file. + let mut tokens_iter = path.into_iter(); + let token = tokens_iter + .next() + .expect("Please provide a path to a .hbin file to the use_hbin! macro."); + assert!(tokens_iter.next().is_none(), "Too many tokens provided to the use_hbin! macro. Please provide only a path to a .hbin file."); + let literal = if let Literal(literal) = token { + literal + } else { + panic!("Please provide a string literal containing the path to a .hbin file to the use_hbin! macro."); + }; + let literal_string = literal.to_string(); + let path = Path::new(&literal_string[1..(literal_string.len() - 1)]); + assert_eq!( + path.extension(), + Some(OsStr::new("hbin")), + "Please provide only .hbin files to the use_hbin! macro." + ); + assert_eq!( + path.try_exists().ok(), + Some(true), + "Please provide a valid path to a .hbin file to the use_hbin! macro." + ); + + // Load manifest from path. + let mut f = File::open(path).unwrap(); + let mut buffer = vec![]; + f.read_to_end(&mut buffer).unwrap(); + let (manifest, elf) = manifest_and_module_bytes(&buffer); + eprintln!("{:?}", manifest); + + // Generate Rust code. + codegen(&manifest, &elf).unwrap().parse().unwrap() +} diff --git a/hercules_samples/matmul/src/main.rs b/hercules_samples/matmul/src/main.rs index 36177bead6c195f375036baf103311b657f9da6a..f281b97ec103d1e2a864983388795ff108bb1f15 100644 --- a/hercules_samples/matmul/src/main.rs +++ b/hercules_samples/matmul/src/main.rs @@ -1,36 +1,12 @@ extern crate clap; +extern crate hercules_rt; -use std::path::Path; +hercules_rt::use_hbin!("matmul.hbin"); fn main() { - let module = hercules_rt::load_binary(Path::new("matmul.hbin")); - - println!("{:?}", module); - - let matmul = hercules_rt::lookup_function!( - module, - "matmul_part_1", - *const f32, - *const f32, - *mut f32, - u64, - u64, - u64, - => *const f32 - ); - - let a = [[1.0f32, 2.0f32], [3.0f32, 4.0f32]]; - let b = [[5.0f32, 6.0f32], [7.0f32, 8.0f32]]; - let mut c = [[0.0f32, 0.0f32], [0.0f32, 0.0f32]]; - unsafe { - matmul( - std::mem::transmute(a.as_ptr()), - std::mem::transmute(b.as_ptr()), - std::mem::transmute(c.as_mut_ptr()), - 2, - 2, - 2, - ) - }; - println!("{} {}\n{} {}", c[0][0], c[0][1], c[1][0], c[1][1]); + //let a = [[1.0f32, 2.0f32], [3.0f32, 4.0f32]]; + //let b = [[5.0f32, 6.0f32], [7.0f32, 8.0f32]]; + //let mut c = [[0.0f32, 0.0f32], [0.0f32, 0.0f32]]; + //matmul(&a, &b, &mut c, 2, 2, 2); + //println!("{} {}\n{} {}", c[0][0], c[0][1], c[1][0], c[1][1]); } diff --git a/hercules_samples/task_parallel/Cargo.toml b/hercules_samples/task_parallel/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..03c402c6626426c892aba0b9c32c8ab73a19fc53 --- /dev/null +++ b/hercules_samples/task_parallel/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "hercules_task_parallel" +version = "0.1.0" +authors = ["Russel Arbore <rarbore2@illinois.edu>"] +edition = "2021" + +[dependencies] +clap = { version = "*", features = ["derive"] } +hercules_rt = { path = "../../hercules_rt" } +rand = "*" +async-std = "*" diff --git a/hercules_samples/task_parallel/src/main.rs b/hercules_samples/task_parallel/src/main.rs new file mode 100644 index 0000000000000000000000000000000000000000..01480279fa5b9f94e42f6d3b274dad82baeb393d --- /dev/null +++ b/hercules_samples/task_parallel/src/main.rs @@ -0,0 +1,11 @@ +extern crate async_std; +extern crate clap; +extern crate hercules_rt; + +hercules_rt::use_hbin!("task_parallel.hbin"); + +fn main() { + async_std::task::block_on(async { + println!("{}", task_parallel(16).await); + }); +} diff --git a/hercules_samples/task_parallel.hir b/hercules_samples/task_parallel/task_parallel.hir similarity index 100% rename from hercules_samples/task_parallel.hir rename to hercules_samples/task_parallel/task_parallel.hir