From 9d2befc29b80e1f74b0160919207e94e7ad437d1 Mon Sep 17 00:00:00 2001 From: saji Date: Sun, 28 Apr 2024 22:44:18 -0500 Subject: [PATCH] added rust tool --- compiler/.gitignore | 1 + compiler/Cargo.lock | 836 +++++++++++++++++++ compiler/Cargo.toml | 23 + compiler/src/lib.rs | 2 + compiler/src/main.rs | 52 ++ compiler/src/pcf.rs | 67 ++ compiler/src/yosys_parser.rs | 511 ++++++++++++ compiler/testcases/json/synth_olmc_test.json | 514 ++++++++++++ compiler/tests/yosys_parser_test.rs | 26 + 9 files changed, 2032 insertions(+) create mode 100644 compiler/.gitignore create mode 100644 compiler/Cargo.lock create mode 100644 compiler/Cargo.toml create mode 100644 compiler/src/lib.rs create mode 100644 compiler/src/main.rs create mode 100644 compiler/src/pcf.rs create mode 100644 compiler/src/yosys_parser.rs create mode 100644 compiler/testcases/json/synth_olmc_test.json create mode 100644 compiler/tests/yosys_parser_test.rs diff --git a/compiler/.gitignore b/compiler/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/compiler/.gitignore @@ -0,0 +1 @@ +/target diff --git a/compiler/Cargo.lock b/compiler/Cargo.lock new file mode 100644 index 0000000..e754530 --- /dev/null +++ b/compiler/Cargo.lock @@ -0,0 +1,836 @@ +# 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 = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstream" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim 0.8.0", + "textwrap", + "unicode-width", + "vec_map", +] + +[[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 0.11.1", +] + +[[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 = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "either" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "galette" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bacf731bf0e2b11cef74a9454c3e073e737e1423c0b94958da9131dd40a09f5" +dependencies = [ + "clap 2.34.0", + "itertools", + "thiserror", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", + "serde", +] + +[[package]] +name = "itertools" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[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 = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.6", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[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.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "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.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "ver2gal" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap 4.5.4", + "galette", + "log", + "regex", + "serde", + "serde_json", + "serde_with", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets", +] + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml new file mode 100644 index 0000000..494af97 --- /dev/null +++ b/compiler/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "ver2gal" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.81" +clap = { version = "4.5.4", features = ["derive"] } +galette = "0.3.0" +log = "0.4.21" +regex = "1.10.4" +serde = { version = "1.0.197", features = ["derive"] } +serde_json = "1.0.115" +serde_with = { version = "3.7.0", features = ["json"] } + + +[lib] +name = "ver2gal" + +[[bin]] +name = "ver2gal" diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs new file mode 100644 index 0000000..de7eb9a --- /dev/null +++ b/compiler/src/lib.rs @@ -0,0 +1,2 @@ +pub mod yosys_parser; +pub mod pcf; diff --git a/compiler/src/main.rs b/compiler/src/main.rs new file mode 100644 index 0000000..d75f627 --- /dev/null +++ b/compiler/src/main.rs @@ -0,0 +1,52 @@ +pub mod pcf; +pub mod yosys_parser; + +use clap::{Parser, Subcommand, Args}; +use crate::yosys_parser::{YosysDoc, Graph}; +use anyhow::{bail, Result}; +use serde_json::from_slice; +use std::path::PathBuf; +use std::fs; + +#[derive(Parser)] +struct Cli { + #[command(subcommand)] + command: Commands, +} + +#[derive(Subcommand)] +enum Commands { + /// Validate a yosys netlist JSON file. + Validate(ValidateArgs), +} + +#[derive(Args)] +struct ValidateArgs { + #[arg(required = true, value_hint = clap::ValueHint::DirPath)] + file: PathBuf, +} + + +fn validate(v: ValidateArgs) -> Result<()>{ + let f = fs::read(v.file)?; + + let data: YosysDoc = from_slice(f.as_slice())?; + + let g = Graph::from(data); + let res = g.validate().map_err(|x| x.to_string()); + if let Err(e) = res { + bail!(e); + } + println!("Validation Complete!"); + println!("Stats:"); + println!("Nodes: {}", g.nodelist.len()); + println!("Edges: {}", g.adjlist.len()); + Ok(()) +} + +fn main() -> Result<()>{ + let args = Cli::parse(); + match args.command { + Commands::Validate(v) => validate(v), + } +} diff --git a/compiler/src/pcf.rs b/compiler/src/pcf.rs new file mode 100644 index 0000000..a85fde0 --- /dev/null +++ b/compiler/src/pcf.rs @@ -0,0 +1,67 @@ +use regex::Regex; +use std::collections::HashMap; + +pub struct PcfFile { + map: HashMap, +} + +pub fn parse_pcf(input: &str) -> PcfFile { + let mut pcf = HashMap::new(); + let re = Regex::new(r"(?m)^set_io (\S+) (\d+)$").unwrap(); + // we run a captures on it. + for (_, [name, pin]) in re.captures_iter(input).map(|c| c.extract()) { + if pcf.contains_key(name) { + panic!("name collision in pcf file"); + } + let num: u32 = str::parse(pin).unwrap(); + pcf.insert(name.to_string(), num); + } + PcfFile { map: pcf } +} + +impl PcfFile { + pub fn pin(&self, name: &str) -> Option { + self.map.get(name).cloned() + } + pub fn pinvec(&self, name: &str, index: usize) -> Option { + // construct a name of the form [] + let realname = format!("{name}[{index}]"); + self.map.get(&realname).cloned() + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_basic() { + let test_str = "set_io pinName 1"; + let name_expected = "pinName"; + let pin_expected = 1; + let f = parse_pcf(test_str); + assert_eq!(f.pin(name_expected), Some(pin_expected)); + assert_eq!(f.pin("invalid"), None); + } + + #[test] + fn test_pins() { + let test = " +set_io scalar 1 +set_io vec[0] 2 +set_io vec[1] 3"; + let f = parse_pcf(test); + assert_eq!(f.pin("scalar"), Some(1)); + assert_eq!(f.pinvec("vec", 0), Some(2)); + assert_eq!(f.pinvec("vec", 1), Some(3)); + assert_eq!(f.pinvec("vec", 2), None); + } + + #[test] + #[should_panic] + fn test_name_collision() { + let test = " +set_io scalar 1 +set_io scalar 2"; + parse_pcf(test); + } +} diff --git a/compiler/src/yosys_parser.rs b/compiler/src/yosys_parser.rs new file mode 100644 index 0000000..78c7f26 --- /dev/null +++ b/compiler/src/yosys_parser.rs @@ -0,0 +1,511 @@ +use crate::pcf::PcfFile; +use galette::gal::Pin; +use log::error; +use log::info; +use serde::{de::Error, Deserialize, Deserializer, Serialize}; +use serde_with::{serde_as, BoolFromInt}; +use std::collections::hash_map::Iter; +use std::collections::HashMap; +use std::str; + +#[derive(Debug, Serialize, Clone, Deserialize, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub enum Net { + #[serde(rename = "x")] + NotConnected, + #[serde(rename = "1")] + LiteralOne, + #[serde(rename = "0")] + LiteralZero, + #[serde(untagged)] + N(u32), +} + +/// The GAL_INPUT marks an external ipnut +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct GalInput { + pub connections: HashMap>, +} + +// Custom deserializer for the strange string of binary +// for some reason the json outputs 00000000000111 for some numbers. +// this converts them back into binary. +fn from_binstr<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + u32::from_str_radix(s.as_str(), 2).map_err(D::Error::custom) +} +fn bool_from_binstr<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + let val = u32::from_str_radix(s.as_str(), 2).map_err(D::Error::custom)?; + Ok(val == 1) +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "UPPERCASE")] +pub struct GalSopParameters { + #[serde(deserialize_with = "from_binstr")] + pub depth: u32, + pub table: String, + #[serde(deserialize_with = "from_binstr")] + pub width: u32, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct GalSop { + pub connections: HashMap>, + pub parameters: GalSopParameters, +} + +#[serde_as] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "UPPERCASE")] +pub struct GALOLMCParameters { + #[serde(deserialize_with = "bool_from_binstr")] + inverted: bool, + #[serde(deserialize_with = "bool_from_binstr")] + registered: bool, +} + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub struct GalOLMC { + pub parameters: GALOLMCParameters, + pub connections: HashMap>, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +#[serde(tag = "type")] +pub enum YosysCell { + #[serde(rename = "GAL_SOP", alias = "GAL_1SOP")] + Sop(GalSop), + #[serde(rename = "GAL_INPUT")] + Input(GalInput), + #[serde(rename = "GAL_OLMC")] + OLMC(GalOLMC), +} + +#[serde_as] +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct ModPort { + pub bits: Vec, + #[serde(default)] + #[serde_as(as = "BoolFromInt")] + pub upto: bool, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(rename_all = "lowercase", tag = "direction")] +pub enum Port { + Input(ModPort), + Output(ModPort), + InOut(ModPort), +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Module { + pub ports: HashMap, + pub cells: HashMap, +} +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct YosysDoc { + pub creator: String, + pub modules: HashMap, +} + +impl GalSop { + // extract the logic table using the parameters. + // pub fn parse_table(self) -> Vec> { + // // get the list of inputs which is a Vec + // let table = self.parameters.table.as_bytes(); + // + // // split into products + // let product_count = self.parameters.depth; + // let product_size = self.parameters.width; + // // we need to have enough elements. + // assert!(table.len() == (product_count * product_size * 2) as usize); + // + // let chunksize = product_size * 2; + // + // table + // .chunks(chunksize as usize) + // .map(|prod| { + // let mut term = Vec::new(); + // for i in 0..product_size { + // let i = i as usize; + // let pin_num = self.connections.inputs.get(i).unwrap(); // this should never panic. + // let pin = table_seg_to_pin(pin_num, &prod[2 * i..2 * i + 1]); + // if let Some(p) = pin { + // term.push(p); + // } + // } + // // now that we've accumulated all of the products, add it to the products list. + // term + // }) + // .collect() + // } +} + +// table_seg_to_pin reads the small chunk for a specific input to a +// sop and creates a gal pin for it. +fn table_seg_to_pin(num: &Net, seg: &[u8]) -> Option { + let Net::N(p) = num else { + todo!("specials"); + }; + let pin_num: usize = *p as usize; + // convert to string for dumb reasons. + match str::from_utf8(seg).unwrap() { + "01" => Some(Pin { + pin: pin_num, + neg: true, + }), // negated + "10" => Some(Pin { + pin: pin_num, + neg: false, + }), // normal + _ => None, + } +} + +/* constraint mapping pipeline + * w + * take yosys document -> look at top-level module ports + * use constraints pcf file to map. This creates a HashMap for mapping nets to pins. + * only do this for *ports*, not cells. now we have a net->pin map, where we know that there's + * hits. + */ + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)] +pub enum PortDirection { + Input, + Output, + Inout, +} +/// NamedPort is our internal representation of a port. +#[derive(Debug, Clone, PartialEq, PartialOrd)] +pub struct NamedPort { + name: String, + net: Net, + direction: PortDirection, +} + +use std::cmp::Ordering; +impl NamedPort { + fn new(name: &str, net: &Net, dir: &PortDirection) -> Self { + NamedPort { + name: name.to_owned(), + net: net.clone(), + direction: dir.clone(), + } + } + + /// Takes a module port, and splits into N NamedPorts, where the name + /// is converted to match the pcf format [index] if there is more than + /// one bit in the port + fn new_split(base_name: &str, port: ModPort, dir: PortDirection) -> Vec { + match port.bits.len().cmp(&1) { + Ordering::Greater => port + .bits + .iter() + .enumerate() + .map(|(idx, n)| NamedPort::new(&format!("{base_name}[{idx}]"), n, &dir)) + .collect(), + Ordering::Equal => { + vec![NamedPort::new(base_name, &port.bits[0], &dir)] + } + _ => panic!("no bits on this port!"), + } + } + /// Retrieves the port mapping for this port, given a PCF file. + pub fn lookup(&self, pcf: &PcfFile) -> u32 { + //NOTE: since NamedPort is exactly (1) pin, we always use the pin case. + // When constructing, if we have a port with multiple bits, we split it (see `new_split`) + pcf.pin(&self.name).expect("missing constraint") + } +} + +#[derive(Debug, Clone)] +pub struct NetAdjPair { + net: Net, + idx1: usize, + port1: String, + port2: String, + idx2: usize, +} + +impl PartialEq for NetAdjPair { + // equality is non-directional, so we have to manually override. + // + fn eq(&self, other: &Self) -> bool { + if self.net != other.net { + return false; + } + // we know the nets are the same + if self.port1 == other.port1 + && self.port2 == other.port2 + && self.idx1 == other.idx1 + && self.idx2 == other.idx2 + { + return true; + } + // the same, but the direction is backwards. for our intents this is fine. + if self.port1 == other.port1 + && self.port2 == other.port1 + && self.idx1 == other.idx2 + && self.idx2 == other.idx1 + { + return true; + } + false + } +} + +impl Eq for NetAdjPair {} + +impl NetAdjPair { + fn uses_net(&self, net: &Net) -> bool { + net == &self.net + } + fn uses_nodeport(&self, idx: usize, port: &str) -> bool { + self.idx1 == idx && self.port1 == port || self.idx2 == idx && self.port2 == port + } +} + +/// A Node is an entry in our graph. A node has inputs and outputs. +#[derive(Debug, PartialEq, Clone)] +pub enum Node { + Input(GalInput), + Sop(GalSop), + Olmc(GalOLMC), +} + +impl Node { + /* These functions are a little odd. We invert the input/output bits. CHIP inputs, are viewed + * as outputs internally, likewise we view the outputs of the chip as inputs (to be driven + * internally. So get_outputs returns values on input_cells, since those are driven already. + * Likewise we reverse this for get_inputs, since the chip's outputs are our inputs. + */ + // fn get_outputs(&self) -> Vec { + // match self { + // Self::Input(i) => i.connections.output.to_vec(), + // Self::Sop(s) => s.connections.output.to_vec(), + // Self::Olmc(o) => o.connections.get("Y").expect("Y outpu").to_vec(), + // } + // } + // fn get_inputs(&self) -> Vec { + // match self { + // Self::Input(gi) => gi.connections.input.to_vec(), + // Self::Sop(gs) => gs.connections.inputs.to_vec(), + // Self::Olmc(go) => go.connections.input.to_vec(), + // } + // } + fn get_ports(&self) -> Iter<'_, String, Vec> { + match self { + Self::Olmc(ol) => ol.connections.iter(), + Self::Input(i) => i.connections.iter(), + Self::Sop(s) => s.connections.iter(), + } + } + fn port_for_net(&self, net: &Net) -> Option { + for (port, nets) in self.get_ports() { + if nets.contains(net) { + return Some(port.to_string()); + } + } + None + } + fn get_nets(&self) -> Vec { + self.get_ports() + .flat_map(|(_, nets)| nets.clone()) + .collect() + } +} + +#[derive(Default, Debug)] +pub struct Graph { + pub nodelist: Vec, + pub adjlist: Vec, + pub ports: Vec, +} + +// For each node, for each port, for each net +// find all other nodes that have this net. + +impl Graph { + /// re-generate the adjacency set for this graph. + pub fn generate_adjacency(&mut self) { + self.adjlist.clear(); + for (idx1, node1) in self.nodelist.iter().enumerate() { + for net in node1.get_nets() { + if !matches!(net, Net::N(_)) { + info!("skipping global nets"); + continue; + } + let connected_nodes: Vec<_> = self + .nodelist + .iter() + .enumerate() + .filter(|&(idx2, node2)| { + if idx1 == idx2 { + return false; + } + node2.get_nets().contains(&net) + }) + .collect(); + + for (idx2, node2) in connected_nodes { + // get the port for node1 + let node1_port = node1.port_for_net(&net).expect("how"); + let node2_port = node2.port_for_net(&net).expect("how"); + let adj = NetAdjPair { + net: net.clone(), + idx1, + idx2, + port1: node1_port, + port2: node2_port, + }; + if !self.adjlist.contains(&adj) { + // if this fails, it means that the opposing pair is already present. + self.adjlist.push(adj); + } + } + } + } + } + /// Find all nodes that are attached to this net in any way. + /// Note that this is an expensive operation since it can't currently use the adjlist. + pub fn find_nodes(&self, net: &Net) -> Vec { + let mut res = Vec::new(); + for (idx, node) in self.nodelist.iter().enumerate() { + if node.get_nets().contains(net) { + res.push(idx); + } + } + res + } + /// find the port that uses the current net, if any + fn find_port(&self, net: &Net) -> Option<&NamedPort> { + self.ports.iter().find(|p| p.net == *net) + } + + /// Validate that the graph has valid invariants. + /// This function does not guarantee a mapping, but it does mean that the output produced + /// by the yosys script is what we expected. Mainly a tool for debugging the Yosys outputs. + pub fn validate(&self) -> Result<(), &str> { + info!("Checking OLMC blocks"); + let all_olmc = self.nodelist.iter().filter_map(|node| match node { + Node::Olmc(o) => Some(o), + _ => None, + }); + + let olmc_clock = all_olmc.filter_map(|o| o.connections.get("C")); + let test = olmc_clock.clone().all(|v| v.len() == 1); + if !test { + return Err("OLMC has more than one clock input!"); + } + // assert that all olmc C nets are either not connected or to a net + let test = olmc_clock + .clone() + .flatten() + .all(|net| matches!(net, Net::NotConnected) || matches!(net, Net::N(_))); + if !test { + return Err("invalid clock pin"); + } + // for the ones connected to a net, extract the net nubmer and Vec it. + let olmc_clocked: Vec = olmc_clock + .clone() + .flatten() + .filter_map(|net| match net { + Net::N(x) => Some(*x), + _ => None, + }) + .collect(); + let test = olmc_clocked.windows(2).all(|w| w[0] == w[1]); + if !test { + return Err("clock pin is not shared amongst all OLMCs"); + } + + Ok(()) + } +} + +const TECHMAP_NAMES: [&str; 5] = ["DFF_P", "GAL_INPUT", "GAL_SOP", "GAL_OLMC", "GAL_1SOP"]; + +impl From for Graph { + fn from(value: YosysDoc) -> Self { + let mut g = Graph::default(); + for (mod_name, module) in value.modules { + info!("Processing module {}", mod_name); + if TECHMAP_NAMES.contains(&mod_name.as_str()) { + info!("Skipping module as it is a techmap module"); + continue; + } + for (cell_name, cell) in module.cells { + info!("Processing cell {}", cell_name); + let newcell = match cell { + YosysCell::Input(d) => Node::Input(d), + YosysCell::Sop(s) => Node::Sop(s), + YosysCell::OLMC(n) => Node::Olmc(n), + }; + g.nodelist.push(newcell); + } + for (port_name, port) in module.ports { + info!("Processing port {}", port_name); + let new_ports: Vec = match port { + Port::Output(o) => NamedPort::new_split(&port_name, o, PortDirection::Output), + Port::Input(i) => NamedPort::new_split(&port_name, i, PortDirection::Input), + Port::InOut(io) => NamedPort::new_split(&port_name, io, PortDirection::Inout), + }; + g.ports.extend(new_ports); + } + } + g.generate_adjacency(); + g + } +} + +/* + * This graph is too general as it stands. we cannot map individual input pins + * like we can with our output pins. Also, i have no way of finding a specific + * node in the graph. + */ + +#[cfg(test)] +mod tests { + use super::*; + use anyhow::Result; + use serde_json::from_str; + + #[test] + fn test_netspecial_n() -> Result<()> { + let netstring = "23"; + let data: Net = from_str(netstring)?; + assert_eq!(data, Net::N(23)); + Ok(()) + } + #[test] + fn test_netspecial_x() -> Result<()> { + let netstring = "\"x\""; + let data: Net = from_str(netstring)?; + assert_eq!(data, Net::NotConnected); + Ok(()) + } + #[test] + fn test_netspecial_zero() -> Result<()> { + let netstring = "[\"0\"]"; + let data: Vec = from_str(netstring)?; + assert_eq!(data[0], Net::LiteralZero); + Ok(()) + } + #[test] + fn test_netspecial_one() -> Result<()> { + let netstring = "\"1\""; + let data: Net = from_str(netstring)?; + assert_eq!(data, Net::LiteralOne); + Ok(()) + } +} diff --git a/compiler/testcases/json/synth_olmc_test.json b/compiler/testcases/json/synth_olmc_test.json new file mode 100644 index 0000000..2c9e398 --- /dev/null +++ b/compiler/testcases/json/synth_olmc_test.json @@ -0,0 +1,514 @@ +{ + "creator": "Yosys 0.38 (git sha1 543faed9c, gcc 13.2.1 -march=x86-64 -mtune=generic -O2 -fno-plt -fexceptions -fstack-clash-protection -fcf-protection -ffile-prefix-map=/build/yosys/src=/usr/src/debug/yosys -fPIC -Os)", + "modules": { + "DFF_P": { + "attributes": { + "blackbox": "00000000000000000000000000000001" + }, + "ports": { + "C": { + "direction": "input", + "bits": [ 2 ] + }, + "D": { + "direction": "input", + "bits": [ 3 ] + }, + "Q": { + "direction": "output", + "bits": [ 4 ] + } + }, + "cells": { + }, + "netnames": { + "C": { + "hide_name": 0, + "bits": [ 2 ], + "attributes": { + } + }, + "D": { + "hide_name": 0, + "bits": [ 3 ], + "attributes": { + } + }, + "Q": { + "hide_name": 0, + "bits": [ 4 ], + "attributes": { + } + } + } + }, + "GAL_1SOP": { + "attributes": { + "dynports": "00000000000000000000000000000001", + "blackbox": "00000000000000000000000000000001", + "cells_not_processed": "00000000000000000000000000000001", + "src": "cells_sim.v:25.1-47.10" + }, + "parameter_default_values": { + "DEPTH": "00000000000000000000000000000000", + "TABLE": "00000000000000000000000000000000", + "WIDTH": "00000000000000000000000000000000" + }, + "ports": { + "A": { + "direction": "input", + "offset": -1, + "upto": 1, + "bits": [ 2, 3 ] + }, + "Y": { + "direction": "output", + "bits": [ 4 ] + } + }, + "cells": { + }, + "netnames": { + "A": { + "hide_name": 0, + "bits": [ 2, 3 ], + "offset": -1, + "upto": 1, + "attributes": { + "src": "cells_sim.v:30.20-30.21" + } + }, + "Y": { + "hide_name": 0, + "bits": [ 4 ], + "attributes": { + "src": "cells_sim.v:31.13-31.14" + } + } + } + }, + "GAL_INPUT": { + "attributes": { + "blackbox": "00000000000000000000000000000001", + "cells_not_processed": "00000000000000000000000000000001", + "src": "cells_sim.v:49.1-54.10" + }, + "ports": { + "A": { + "direction": "input", + "bits": [ 2 ] + }, + "Y": { + "direction": "output", + "bits": [ 3 ] + } + }, + "cells": { + }, + "netnames": { + "A": { + "hide_name": 0, + "bits": [ 2 ], + "attributes": { + "src": "cells_sim.v:50.8-50.9" + } + }, + "Y": { + "hide_name": 0, + "bits": [ 3 ], + "attributes": { + "src": "cells_sim.v:51.9-51.10" + } + } + } + }, + "GAL_OLMC": { + "attributes": { + "blackbox": "00000000000000000000000000000001", + "cells_not_processed": "00000000000000000000000000000001", + "src": "cells_sim.v:56.1-78.10" + }, + "parameter_default_values": { + "INVERTED": "00000000000000000000000000000000", + "REGISTERED": "00000000000000000000000000000000" + }, + "ports": { + "C": { + "direction": "input", + "bits": [ 2 ] + }, + "E": { + "direction": "input", + "bits": [ 3 ] + }, + "A": { + "direction": "input", + "bits": [ 4 ] + }, + "Y": { + "direction": "inout", + "bits": [ 5 ] + } + }, + "cells": { + }, + "netnames": { + "A": { + "hide_name": 0, + "bits": [ 4 ], + "attributes": { + "src": "cells_sim.v:60.14-60.15" + } + }, + "C": { + "hide_name": 0, + "bits": [ 2 ], + "attributes": { + "src": "cells_sim.v:60.8-60.9" + } + }, + "E": { + "hide_name": 0, + "bits": [ 3 ], + "attributes": { + "src": "cells_sim.v:60.11-60.12" + } + }, + "Y": { + "hide_name": 0, + "bits": [ 5 ], + "attributes": { + "src": "cells_sim.v:61.8-61.9" + } + } + } + }, + "GAL_SOP": { + "attributes": { + "dynports": "00000000000000000000000000000001", + "blackbox": "00000000000000000000000000000001", + "cells_not_processed": "00000000000000000000000000000001", + "src": "cells_sim.v:1.1-23.10" + }, + "parameter_default_values": { + "DEPTH": "00000000000000000000000000000000", + "TABLE": "00000000000000000000000000000000", + "WIDTH": "00000000000000000000000000000000" + }, + "ports": { + "A": { + "direction": "input", + "offset": -1, + "upto": 1, + "bits": [ 2, 3 ] + }, + "Y": { + "direction": "output", + "bits": [ 4 ] + } + }, + "cells": { + }, + "netnames": { + "A": { + "hide_name": 0, + "bits": [ 2, 3 ], + "offset": -1, + "upto": 1, + "attributes": { + "src": "cells_sim.v:6.20-6.21" + } + }, + "Y": { + "hide_name": 0, + "bits": [ 4 ], + "attributes": { + "src": "cells_sim.v:7.13-7.14" + } + } + } + }, + "olmc_test": { + "attributes": { + "top": "00000000000000000000000000000001", + "src": "testcases/olmc_test.v:1.1-15.10" + }, + "ports": { + "clk": { + "direction": "input", + "bits": [ 2 ] + }, + "A": { + "direction": "input", + "bits": [ 3 ] + }, + "B": { + "direction": "input", + "bits": [ 4 ] + }, + "AND": { + "direction": "output", + "bits": [ 5 ] + }, + "NAND": { + "direction": "output", + "bits": [ 6 ] + }, + "REG_AND": { + "direction": "output", + "bits": [ 7 ] + }, + "REG_NAND": { + "direction": "output", + "bits": [ 8 ] + } + }, + "cells": { + "$abc$98$auto$blifparse.cc:519:parse_blif$100": { + "hide_name": 1, + "type": "GAL_OLMC", + "parameters": { + "INVERTED": "1", + "REGISTERED": "0" + }, + "attributes": { + "module_not_derived": "00000000000000000000000000000001", + "src": "techmaps/pla.v:37.6-40.5|techmaps/trivial_sop.v:12.11-12.43|techmaps/olmc_comb.v:28.5-33.4" + }, + "port_directions": { + "A": "input", + "C": "input", + "E": "input", + "Y": "inout" + }, + "connections": { + "A": [ 9 ], + "C": [ "x" ], + "E": [ "1" ], + "Y": [ 6 ] + } + }, + "$abc$98$auto$blifparse.cc:519:parse_blif$99": { + "hide_name": 1, + "type": "GAL_SOP", + "parameters": { + "DEPTH": "00000000000000000000000000000001", + "TABLE": "1010", + "WIDTH": "00000000000000000000000000000010" + }, + "attributes": { + "module_not_derived": "00000000000000000000000000000001", + "src": "techmaps/pla.v:37.6-40.5|techmaps/trivial_sop.v:20.6-23.5" + }, + "port_directions": { + "A": "input", + "Y": "output" + }, + "connections": { + "A": [ 10, 11 ], + "Y": [ 9 ] + } + }, + "$auto$ff.cc:266:slice$93": { + "hide_name": 1, + "type": "GAL_OLMC", + "parameters": { + "INVERTED": "0", + "REGISTERED": "1" + }, + "attributes": { + "module_not_derived": "00000000000000000000000000000001", + "src": "testcases/olmc_test.v:10.1-13.4|techmaps/olmc_seq.v:10.5-15.4" + }, + "port_directions": { + "A": "input", + "C": "input", + "E": "input", + "Y": "inout" + }, + "connections": { + "A": [ 9 ], + "C": [ 12 ], + "E": [ "1" ], + "Y": [ 7 ] + } + }, + "$auto$ff.cc:266:slice$94": { + "hide_name": 1, + "type": "GAL_OLMC", + "parameters": { + "INVERTED": "0", + "REGISTERED": "1" + }, + "attributes": { + "module_not_derived": "00000000000000000000000000000001", + "src": "testcases/olmc_test.v:10.1-13.4|techmaps/olmc_seq.v:10.5-15.4" + }, + "port_directions": { + "A": "input", + "C": "input", + "E": "input", + "Y": "inout" + }, + "connections": { + "A": [ 6 ], + "C": [ 12 ], + "E": [ "1" ], + "Y": [ 8 ] + } + }, + "$iopadmap$olmc_test.A": { + "hide_name": 1, + "type": "GAL_INPUT", + "parameters": { + }, + "attributes": { + "keep": "00000000000000000000000000000001" + }, + "port_directions": { + "A": "input", + "Y": "output" + }, + "connections": { + "A": [ 3 ], + "Y": [ 11 ] + } + }, + "$iopadmap$olmc_test.AND": { + "hide_name": 1, + "type": "GAL_OLMC", + "parameters": { + "INVERTED": "0", + "REGISTERED": "0" + }, + "attributes": { + "keep": "00000000000000000000000000000001", + "module_not_derived": "00000000000000000000000000000001", + "src": "techmaps/olmc_comb.v:10.5-15.4" + }, + "port_directions": { + "A": "input", + "C": "input", + "E": "input", + "Y": "inout" + }, + "connections": { + "A": [ 9 ], + "C": [ "x" ], + "E": [ "1" ], + "Y": [ 5 ] + } + }, + "$iopadmap$olmc_test.B": { + "hide_name": 1, + "type": "GAL_INPUT", + "parameters": { + }, + "attributes": { + "keep": "00000000000000000000000000000001" + }, + "port_directions": { + "A": "input", + "Y": "output" + }, + "connections": { + "A": [ 4 ], + "Y": [ 10 ] + } + }, + "$iopadmap$olmc_test.clk": { + "hide_name": 1, + "type": "GAL_INPUT", + "parameters": { + }, + "attributes": { + "keep": "00000000000000000000000000000001" + }, + "port_directions": { + "A": "input", + "Y": "output" + }, + "connections": { + "A": [ 2 ], + "Y": [ 12 ] + } + } + }, + "netnames": { + "$abc$98$iopadmap$A": { + "hide_name": 1, + "bits": [ 11 ], + "attributes": { + } + }, + "$abc$98$iopadmap$B": { + "hide_name": 1, + "bits": [ 10 ], + "attributes": { + } + }, + "$iopadmap$AND": { + "hide_name": 1, + "bits": [ 9 ], + "attributes": { + } + }, + "$iopadmap$clk": { + "hide_name": 1, + "bits": [ 12 ], + "attributes": { + } + }, + "A": { + "hide_name": 0, + "bits": [ 3 ], + "attributes": { + "src": "testcases/olmc_test.v:3.12-3.13" + } + }, + "AND": { + "hide_name": 0, + "bits": [ 5 ], + "attributes": { + "src": "testcases/olmc_test.v:4.8-4.11" + } + }, + "B": { + "hide_name": 0, + "bits": [ 4 ], + "attributes": { + "src": "testcases/olmc_test.v:3.15-3.16" + } + }, + "NAND": { + "hide_name": 0, + "bits": [ 6 ], + "attributes": { + "src": "testcases/olmc_test.v:4.13-4.17" + } + }, + "REG_AND": { + "hide_name": 0, + "bits": [ 7 ], + "attributes": { + "src": "testcases/olmc_test.v:5.12-5.19" + } + }, + "REG_NAND": { + "hide_name": 0, + "bits": [ 8 ], + "attributes": { + "src": "testcases/olmc_test.v:5.21-5.29" + } + }, + "clk": { + "hide_name": 0, + "bits": [ 2 ], + "attributes": { + "src": "testcases/olmc_test.v:3.7-3.10" + } + } + } + } + } +} diff --git a/compiler/tests/yosys_parser_test.rs b/compiler/tests/yosys_parser_test.rs new file mode 100644 index 0000000..c8805c8 --- /dev/null +++ b/compiler/tests/yosys_parser_test.rs @@ -0,0 +1,26 @@ +use ver2gal::yosys_parser::*; +use std::error::Error; +use std::fs; +use serde_json::from_slice; + +#[test] +fn test_load() -> Result<(), Box> { + let f = fs::read("testcases/json/synth_olmc_test.json")?; + + let data: YosysDoc = from_slice(f.as_slice())?; + println!("{:?}", data); + + Ok(()) +} + +#[test] +fn test_graph() -> Result<(), Box> { + let f = fs::read("testcases/json/synth_olmc_test.json")?; + + let data: YosysDoc = from_slice(f.as_slice())?; + + let g = Graph::from(data); + println!("{:?}", g); + g.validate()?; + Ok(()) +}