A => .gitignore +1 -0
A => Cargo.lock +679 -0
@@ 1,679 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "anstream"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "4.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c8d502cbaec4595d2e7d5f61e318f05417bd2b66fdc3809498f0d3fdf0bea27"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+ "once_cell",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5891c7bc0edb3e1c2204fc5e94009affabeb1821c9e5fdc3959536c5c0bb984d"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9fd1a5729c4548118d7d70ff234a44868d00489a4b6597b0b020918a0e91a1a"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "dirs"
+version = "4.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
+[[package]]
+name = "dunce"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"
+
+[[package]]
+name = "either"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+
+[[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 = "getrandom"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
+
+[[package]]
+name = "gtkwave_tcl_generator"
+version = "0.1.0"
+dependencies = [
+ "clap",
+ "glob",
+ "parking_lot",
+ "string-builder",
+ "vhdl_lang",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
+
+[[package]]
+name = "indexmap"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "itertools"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.147"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
+
+[[package]]
+name = "lock_api"
+version = "0.4.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "memchr"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76fc44e2588d5b436dbc3c6cf62aef290f90dab6235744a93dfe1cc18f451e2c"
+
+[[package]]
+name = "memoffset"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+
+[[package]]
+name = "pad"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall 0.3.5",
+ "smallvec",
+ "windows-targets",
+]
+
+[[package]]
+name = "pinned_vec"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "268ad82d92622fb0a049ff14b01089b0f1bcd5c507fab44724394d328417348a"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rayon"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall 0.2.16",
+ "thiserror",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "serde"
+version = "1.0.188"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.188"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_spanned"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
+
+[[package]]
+name = "string-builder"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bd10a070fb1f2796a288abec42695db4682a82b6f12ffacd60fb8d5ad3a4a12"
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "syn"
+version = "2.0.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.47"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.47"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "toml"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.19.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "vhdl_lang"
+version = "0.65.0"
+source = "git+https://github.com/Rutherther/rust_hdl.git#aacf15291c3e112609d3f59bce0c4fb45ac9d637"
+dependencies = [
+ "clap",
+ "dirs",
+ "dunce",
+ "fnv",
+ "glob",
+ "itertools",
+ "pad",
+ "parking_lot",
+ "pinned_vec",
+ "rayon",
+ "toml",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[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-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+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.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "winnow"
+version = "0.5.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"
+dependencies = [
+ "memchr",
+]
A => Cargo.toml +13 -0
@@ 1,13 @@
+[package]
+name = "gtkwave_tcl_generator"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+clap = { version = "4.4.1", features = ["derive"] }
+glob = "0.3.1"
+parking_lot = "0.12.1"
+string-builder = "0.2.0"
+vhdl_lang = {git = "https://github.com/Rutherther/rust_hdl.git", version = "0.65.0"}
A => src/display_elements.rs +150 -0
@@ 1,150 @@
+use std::{slice::Iter, fmt::Display};
+
+#[derive(Eq, PartialEq, Clone)]
+pub enum DisplayElement {
+ Signal(Signal),
+ Empty(Vec<DisplayOption>)
+}
+
+#[derive(Eq, PartialEq, Clone, Copy)]
+pub enum DisplayOption {
+ Color(DisplayColor),
+ Format(DisplayFormat),
+ Omit
+}
+
+#[derive(Eq, PartialEq, Clone)]
+pub struct Signal {
+ name: String,
+ options: Vec<DisplayOption>
+}
+
+impl From<&str> for Signal {
+ fn from(value: &str) -> Self {
+ Self {
+ name: value.to_owned(),
+ options: vec![]
+ }
+ }
+}
+
+#[derive(Eq, PartialEq, Clone)]
+pub struct Entity {
+ name: String,
+ architecture: Option<Architecture>,
+}
+
+#[derive(Eq, PartialEq, Clone)]
+pub struct Architecture {
+ name: String,
+ entity_name: String,
+ signals: Vec<Signal>
+}
+
+#[derive(Eq, PartialEq, Copy, Clone)]
+pub enum DisplayColor {
+ Normal,
+ Red,
+ Orange,
+ Yellow,
+ Green,
+ Blue,
+ Indigo,
+ Violet,
+ Cycle,
+}
+
+impl Display for DisplayColor {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", match self {
+ DisplayColor::Normal => "Normal",
+ DisplayColor::Red => "Red",
+ DisplayColor::Orange => "Orange",
+ DisplayColor::Yellow => "Yellow",
+ DisplayColor::Green => "Green",
+ DisplayColor::Blue => "Blue",
+ DisplayColor::Indigo => "Indigo",
+ DisplayColor::Violet => "Violet",
+ DisplayColor::Cycle => "Cycle",
+ })
+ }
+}
+
+#[derive(Eq, PartialEq, Copy, Clone)]
+pub enum DisplayFormat {
+ Hex,
+ Decimal,
+ SignedDecimal,
+ Binary,
+}
+
+impl Display for DisplayFormat {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}", match self {
+ DisplayFormat::Hex => "Hex",
+ DisplayFormat::Decimal => "Decimal",
+ DisplayFormat::SignedDecimal => "SignedDecimal",
+ DisplayFormat::Binary => "Binary",
+ })
+ }
+}
+
+impl Signal {
+ pub fn new(name: String, options: Vec<DisplayOption>) -> Self {
+ Self {
+ name,
+ options
+ }
+ }
+
+ pub fn name(&self) -> &str {
+ &self.name
+ }
+
+ pub fn options(&self) -> Iter<'_, DisplayOption> {
+ self.options.iter()
+ }
+}
+
+impl Entity {
+ pub fn new(name: String) -> Self {
+ Self {
+ name,
+ architecture: None
+ }
+ }
+
+ pub fn name(&self) -> &str {
+ &self.name
+ }
+
+ pub fn add_architecture(&mut self, architecture: Architecture) {
+ self.architecture = Some(architecture);
+ }
+
+ pub fn architecture(&self) -> Option<&Architecture> {
+ self.architecture.as_ref()
+ }
+}
+
+impl Architecture {
+ pub fn new(name: String, entity_name: String, signals: Vec<Signal>) -> Self {
+ Self {
+ name,
+ entity_name,
+ signals,
+ }
+ }
+
+ pub fn signals(&self) -> Iter<'_, Signal> {
+ self.signals.iter()
+ }
+
+ pub fn name(&self) -> &str {
+ &self.name
+ }
+
+ pub fn entity_name(&self) -> &str {
+ &self.entity_name
+ }
+}
A => src/file_parser.rs +254 -0
@@ 1,254 @@
+use vhdl_lang::{Source, syntax::{tokens::{TokenStream, Tokenizer, Kind, Comment}, Symbols}, Diagnostic, data::{Contents, ContentReader}};
+
+use crate::display_elements::{DisplayColor, Entity, Architecture, Signal, DisplayOption, DisplayFormat};
+
+#[derive(PartialEq, Eq, Clone)]
+struct Context {
+ color: Option<DisplayColor>,
+ omit: bool
+}
+
+pub struct FileParser<'a> {
+ diagnostics: Vec<Diagnostic>,
+ stream: TokenStream<'a>,
+
+ entities: Vec<Entity>,
+ current_entity: usize
+}
+
+#[derive(Debug)]
+pub enum ParseError {
+ EntityNotPresent,
+ ArchitectureNotFound,
+ ParsingError(Diagnostic),
+ EndOfFile,
+}
+
+impl From<Diagnostic> for ParseError {
+ fn from(value: Diagnostic) -> Self {
+ Self::ParsingError(value)
+ }
+}
+
+impl From<&Context> for Vec<DisplayOption> {
+ fn from(value: &Context) -> Self {
+ let mut options = vec![];
+
+ if value.omit {
+ options.push(DisplayOption::Omit);
+ }
+
+ if let Some(color) = value.color {
+ options.push(DisplayOption::Color(color));
+ }
+
+ options
+ }
+}
+
+impl<'a> FileParser<'a> {
+ pub fn new(source: &'a Source, contents: &'a Contents, symbols: &'a Symbols) -> Self {
+ let mut diagnostics = vec![];
+ let tokenizer = Tokenizer::new(symbols, source, ContentReader::new(contents));
+ let stream = TokenStream::new(tokenizer, &mut diagnostics);
+
+ Self {
+ diagnostics,
+ stream,
+ entities: vec![],
+ current_entity: 0,
+ }
+ }
+
+ pub fn find_next_entity(&mut self) -> Result<Entity, ParseError> {
+ if self.current_entity < self.entities.len() {
+ self.current_entity += 1;
+ return Ok(self.entities[self.current_entity - 1].clone());
+ }
+
+ if self.stream.skip_until(|k| k == Kind::Entity || k == Kind::Architecture).is_err() {
+ return Err(ParseError::EndOfFile);
+ }
+
+ if self.stream.peek_kind().unwrap() == Kind::Entity {
+ let entity = Self::parse_entity(&mut self.stream)?;
+ self.entities.push(entity.clone());
+ self.current_entity += 1;
+
+ Ok(entity)
+ } else {
+ let architecture = Self::parse_architecture(&mut self.stream)?;
+
+ if let Some(entity) = self.entities.iter_mut().find(|e| e.name() == architecture.entity_name()) {
+ entity.add_architecture(architecture);
+ }
+
+ self.find_next_entity()
+ }
+ }
+
+ pub fn parse_entity_architecture(&mut self, mut entity: Entity) -> Result<Entity, ParseError> {
+ let Some(found_entity) = self.entities.iter_mut().find(|e| e.name() == entity.name()) else {
+ return Err(ParseError::EntityNotPresent);
+ };
+
+ if entity.architecture().is_some() {
+ return Ok(entity);
+ }
+
+ if found_entity.architecture().is_some() {
+ return Ok(found_entity.clone());
+ }
+
+ if self.stream.skip_until(|k| k == Kind::Entity || k == Kind::Architecture).is_err() {
+ return Err(ParseError::EndOfFile);
+ }
+
+ if self.stream.peek_kind().unwrap() == Kind::Entity {
+ let entity = Self::parse_entity(&mut self.stream)?;
+ self.entities.push(entity.clone());
+ return self.parse_entity_architecture(entity)
+ }
+
+ let architecture = Self::parse_architecture(&mut self.stream)?;
+ if architecture.entity_name() == entity.name() {
+ entity.add_architecture(architecture.clone());
+ found_entity.add_architecture(architecture);
+
+ return Ok(entity);
+ }
+
+ if let Some(matched_entity) = self.entities.iter_mut().find(|e| e.name() == architecture.entity_name()) {
+ matched_entity.add_architecture(architecture);
+ }
+
+ self.parse_entity_architecture(entity)
+ }
+
+ fn parse_architecture(stream: &mut TokenStream) -> Result<Architecture, ParseError> {
+ stream.expect_kind(Kind::Architecture)?;
+
+ let architecture_name = Self::parse_identifier(stream)?;
+
+ stream.expect_kind(Kind::Of)?;
+
+ let entity_name = Self::parse_identifier(stream)?;
+
+ stream.expect_kind(Kind::Is)?;
+
+ let mut context = Context { color: None, omit: false };
+ let mut signals = vec![];
+
+ while !stream.next_kind_is(Kind::Begin) {
+ let token = stream.peek().ok_or(ParseError::EndOfFile)?;
+
+ if let Some(comments) = &token.comments {
+ for comment in &comments.leading {
+ Self::update_context(&mut context, comment);
+ }
+ }
+
+ match token.kind {
+ Kind::Signal => signals.append(Self::parse_signals(stream, &context)?.as_mut()),
+ Kind::Begin => break,
+ _ => stream.skip(),
+ }
+ }
+
+ let architecture = Architecture::new(architecture_name, entity_name, signals);
+
+ Ok(architecture)
+ }
+
+ fn parse_signals(stream: &mut TokenStream, context: &Context) -> Result<Vec<Signal>, ParseError> {
+ stream.expect_kind(Kind::Signal)?;
+
+ let mut signal_names = vec![];
+ signal_names.push(Self::parse_identifier(stream)?);
+
+ while stream.peek_kind().ok_or(ParseError::EndOfFile)? != Kind::Colon {
+ stream.skip();
+ signal_names.push(Self::parse_identifier(stream)?);
+ }
+
+ stream.skip();
+
+ let signal_type = Self::parse_identifier(stream)?;
+
+ stream.skip_until(|k| k == Kind::SemiColon)?;
+ let semicolon_token = stream.peek().ok_or(ParseError::EndOfFile)?;
+
+ let options: Vec<DisplayOption> = if let Some(comments) = &semicolon_token.comments {
+ if let Some(trailing) = &comments.trailing {
+ let mut context = context.clone();
+ Self::update_context(&mut context, trailing);
+ (&context).into()
+ } else {
+ context.into()
+ }
+ } else {
+ context.into()
+ };
+
+ let mut signals = vec![];
+ for signal_name in signal_names {
+ let mut options = options.clone();
+ if signal_type.starts_with("std_logic_vector") {
+ options.push(DisplayOption::Format(DisplayFormat::Binary));
+ }
+
+ signals.push(Signal::new(signal_name, options));
+ }
+
+ Ok(signals)
+ }
+
+ fn parse_entity(stream: &mut TokenStream) -> Result<Entity, ParseError> {
+ stream.expect_kind(Kind::Entity)?;
+
+ let name = Self::parse_identifier(stream)?;
+ Ok(Entity::new(name))
+ }
+
+ fn parse_identifier(stream: &mut TokenStream) -> Result<String, ParseError> {
+ let token = stream.peek_expect()?;
+ let identifier = token.to_identifier_value()?;
+
+ stream.skip();
+
+ Ok(identifier.item.name_utf8())
+ }
+
+ fn update_context(context: &mut Context, comment: &Comment) {
+ let commands = comment.value.split(['\n', ','].as_ref());
+
+ for command in commands {
+ match command.trim() {
+ "omit" => context.omit = true,
+ "reset" => {
+ context.color = None;
+ context.omit = false;
+ },
+ _ if command.trim().starts_with("color ") => {
+ let color = command["color ".len()..].trim();
+
+ let color = match color {
+ "normal" => DisplayColor::Normal,
+ "red" => DisplayColor::Red,
+ "orange" => DisplayColor::Orange,
+ "yellow" => DisplayColor::Yellow,
+ "green" => DisplayColor::Green,
+ "blue" => DisplayColor::Blue,
+ "Indigo" => DisplayColor::Indigo,
+ "Violet" => DisplayColor::Violet,
+ "Cycle" => DisplayColor::Cycle,
+ _ => DisplayColor::Normal,
+ };
+
+ context.color = Some(color);
+ },
+ _ => ()
+ }
+ }
+ }
+}
A => src/main.rs +89 -0
@@ 1,89 @@
+pub mod file_parser;
+pub mod display_elements;
+pub mod tcl_generator;
+
+use std::{path::PathBuf, fs::File, io::Write};
+
+use clap::{arg, Parser};
+use file_parser::FileParser;
+use glob::glob;
+use tcl_generator::TclGenerator;
+use vhdl_lang::{syntax::Symbols, Source};
+
+use crate::display_elements::{Signal, DisplayOption, DisplayColor};
+
+#[derive(Parser)]
+#[command(author, version, about, long_about = None)]
+struct Cli {
+ #[arg(short = 'f', long = "folder")]
+ folder: PathBuf,
+ #[arg(short = 't', long = "testbench")]
+ testbench: String,
+ #[arg(short = 'o', long = "output")]
+ output: PathBuf,
+}
+
+fn main() {
+ let cli = Cli::parse();
+ let find_wildcard = cli.folder.to_str().unwrap().to_owned() + "/**/*.vhd";
+ println!("Going to look into {find_wildcard}");
+
+ let matching_files = glob(&find_wildcard).unwrap();
+
+ let symbols = Symbols::default();
+
+ let mut found = false;
+ for file_result in matching_files {
+ let file = file_result.unwrap();
+
+ let source = Source::from_latin1_file(file.as_path()).unwrap();
+ let contents = source.contents();
+ let mut parser = FileParser::new(&source, &contents, &symbols);
+
+ match parser.find_next_entity() {
+ Ok(entity) => {
+ if entity.name() != &cli.testbench[..] {
+ continue;
+ }
+ found = true;
+
+ println!("Found the testbench.");
+
+ let entity = parser.parse_entity_architecture(entity).unwrap();
+ let architecture = entity.architecture().unwrap();
+
+ let mut generator = TclGenerator::new("top.".to_owned() + &cli.testbench + ".");
+ generator.add_signal(&Signal::new("clk".to_owned(), vec![DisplayOption::Color(DisplayColor::Indigo)]))
+ .add_signal(&Signal::new("rst".to_owned(), vec![DisplayOption::Color(DisplayColor::Indigo)]))
+ .add_empty()
+ .zoom_out();
+
+ for signal in architecture.signals() {
+ if signal.name() == "clk" || signal.name() == "rst" {
+ continue;
+ }
+
+ generator.add_signal(signal);
+ }
+
+ let generated = generator.generate();
+
+ let mut file = File::create(&cli.output).unwrap();
+ file.write_all(generated.as_bytes()).unwrap();
+
+ break;
+ },
+ Err(err) => {
+ println!("{:?}", err);
+ }
+ }
+
+ if found {
+ break;
+ }
+ }
+
+ if !found {
+ println!("Could not find the entity.")
+ }
+}
A => src/tcl_generator.rs +93 -0
@@ 1,93 @@
+use string_builder::Builder;
+
+use crate::display_elements::{DisplayColor, DisplayFormat, Signal, DisplayOption};
+
+
+pub struct TclGenerator {
+ signals: Vec<(String, Option<DisplayColor>, Option<DisplayFormat>)>,
+ zoom_out: bool,
+ signal_prefix: String,
+}
+
+impl TclGenerator {
+ pub fn new(signal_prefix: String) -> Self {
+ Self {
+ signals: vec![],
+ zoom_out: false,
+ signal_prefix,
+ }
+ }
+
+ pub fn add_signal(&mut self, signal: &Signal) -> &mut Self {
+ let mut color = None;
+ let mut format = None;
+
+ for option in signal.options() {
+ match option {
+ DisplayOption::Omit => return self,
+ DisplayOption::Color(c) => {
+ color = Some(c.clone());
+ },
+ DisplayOption::Format(f) => {
+ format = Some(f.clone());
+ }
+ }
+ }
+
+ self.signals.push((signal.name().to_owned(), color, format));
+ self
+ }
+
+ pub fn add_empty(&mut self) -> &mut Self {
+ self.signals.push(("".to_owned(), None, None));
+ self
+ }
+
+ pub fn zoom_out(&mut self) -> &mut Self {
+ self.zoom_out = true;
+ self
+ }
+
+ pub fn generate(self) -> String {
+ let mut builder = Builder::new(300);
+
+ builder.append("gtkwave::nop\n");
+ builder.append("gtkwave::/Edit/Set_Trace_Max_Hier 2\n");
+ builder.append("gtkwave::/View/Show_Filled_High_Values 1\n");
+ builder.append("gtkwave::/View/Show_Wave_Highlight 1\n");
+ builder.append("gtkwave::/View/Show_Mouseover 1\n");
+ builder.append("gtkwave::/View/Left_Justified_Signals 1\n");
+
+ for signal in self.signals {
+ if signal.0 == "" {
+ builder.append("gtkwave::/Edit/Insert_Blank\n");
+ } else {
+ builder.append("gtkwave::addSignalsFromList \"");
+ builder.append(&self.signal_prefix[..]);
+ builder.append(&signal.0[..]);
+ builder.append("\"\n");
+
+ builder.append("gtkwave::highlightSignalsFromList \"");
+ builder.append(&self.signal_prefix[..]);
+ builder.append(&signal.0[..]);
+ builder.append("\"\n");
+
+ if let Some(color) = signal.1 {
+ builder.append(format!("gtkwave::/Edit/Color_Format/{color}\n"));
+ }
+
+ if let Some(format) = signal.2 {
+ builder.append(format!("gtkwave::/Edit/Data_Format/{format}\n"));
+ }
+
+ builder.append("gtkwave::/Edit/UnHighlight_All\n");
+ }
+ }
+
+ if self.zoom_out {
+ builder.append("gtkwave::/Time/Zoom/Zoom_Best_Fit\n");
+ }
+
+ builder.string().unwrap()
+ }
+}