mirror of
https://github.com/annoyatron255/yosys4gal.git
synced 2024-12-22 18:52:23 +00:00
added rust tool
This commit is contained in:
parent
87efbe693d
commit
9d2befc29b
1
compiler/.gitignore
vendored
Normal file
1
compiler/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
836
compiler/Cargo.lock
generated
Normal file
836
compiler/Cargo.lock
generated
Normal file
|
@ -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"
|
23
compiler/Cargo.toml
Normal file
23
compiler/Cargo.toml
Normal file
|
@ -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"
|
2
compiler/src/lib.rs
Normal file
2
compiler/src/lib.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod yosys_parser;
|
||||||
|
pub mod pcf;
|
52
compiler/src/main.rs
Normal file
52
compiler/src/main.rs
Normal file
|
@ -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),
|
||||||
|
}
|
||||||
|
}
|
67
compiler/src/pcf.rs
Normal file
67
compiler/src/pcf.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
use regex::Regex;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub struct PcfFile {
|
||||||
|
map: HashMap<String, u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<u32> {
|
||||||
|
self.map.get(name).cloned()
|
||||||
|
}
|
||||||
|
pub fn pinvec(&self, name: &str, index: usize) -> Option<u32> {
|
||||||
|
// construct a name of the form <name>[<index>]
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
511
compiler/src/yosys_parser.rs
Normal file
511
compiler/src/yosys_parser.rs
Normal file
|
@ -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<String, Vec<Net>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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<u32, D::Error>
|
||||||
|
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<bool, D::Error>
|
||||||
|
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<String, Vec<Net>>,
|
||||||
|
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<String, Vec<Net>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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<Net>,
|
||||||
|
#[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<String, Port>,
|
||||||
|
pub cells: HashMap<String, YosysCell>,
|
||||||
|
}
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
pub struct YosysDoc {
|
||||||
|
pub creator: String,
|
||||||
|
pub modules: HashMap<String, Module>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GalSop {
|
||||||
|
// extract the logic table using the parameters.
|
||||||
|
// pub fn parse_table(self) -> Vec<Vec<Pin>> {
|
||||||
|
// // get the list of inputs which is a Vec<u32>
|
||||||
|
// 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<Pin> {
|
||||||
|
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<Net, u32> 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 <name>[index] if there is more than
|
||||||
|
/// one bit in the port
|
||||||
|
fn new_split(base_name: &str, port: ModPort, dir: PortDirection) -> Vec<NamedPort> {
|
||||||
|
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<Net> {
|
||||||
|
// 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<Net> {
|
||||||
|
// 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<Net>> {
|
||||||
|
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<String> {
|
||||||
|
for (port, nets) in self.get_ports() {
|
||||||
|
if nets.contains(net) {
|
||||||
|
return Some(port.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
fn get_nets(&self) -> Vec<Net> {
|
||||||
|
self.get_ports()
|
||||||
|
.flat_map(|(_, nets)| nets.clone())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
pub struct Graph {
|
||||||
|
pub nodelist: Vec<Node>,
|
||||||
|
pub adjlist: Vec<NetAdjPair>,
|
||||||
|
pub ports: Vec<NamedPort>,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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<usize> {
|
||||||
|
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<u32> = 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<YosysDoc> 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<NamedPort> = 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<Net> = 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(())
|
||||||
|
}
|
||||||
|
}
|
514
compiler/testcases/json/synth_olmc_test.json
Normal file
514
compiler/testcases/json/synth_olmc_test.json
Normal file
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
compiler/tests/yosys_parser_test.rs
Normal file
26
compiler/tests/yosys_parser_test.rs
Normal file
|
@ -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<dyn Error>> {
|
||||||
|
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<dyn Error>> {
|
||||||
|
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(())
|
||||||
|
}
|
Loading…
Reference in a new issue