forked from libre-chip/cpu
Compare commits
10 commits
5e1238b5c7
...
6d40eaadb3
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d40eaadb3 | |||
| 305d7b0ae6 | |||
| 781dbc6bcb | |||
| 5faf0899a8 | |||
| 8c02483b65 | |||
| e4a7d9f59c | |||
| 3b5104c8fa | |||
| 2de4a67360 | |||
| d5a7d9dd9e | |||
| 59da0aec06 |
14 changed files with 299378 additions and 17935 deletions
483
Cargo.lock
generated
483
Cargo.lock
generated
|
|
@ -2,6 +2,21 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.18"
|
||||
|
|
@ -81,12 +96,36 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "bindgen"
|
||||
version = "0.71.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cexpr",
|
||||
"clang-sys",
|
||||
"itertools",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"rustc-hash",
|
||||
"shlex",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
|
|
@ -130,20 +169,47 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.1.28"
|
||||
name = "bytes"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1"
|
||||
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cexpr"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clang-sys"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
|
||||
dependencies = [
|
||||
"glob",
|
||||
"libc",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.20"
|
||||
|
|
@ -209,9 +275,17 @@ checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
|
|||
name = "cpu"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base16ct 1.0.0",
|
||||
"fayalite",
|
||||
"hex-literal",
|
||||
"parse_powerisa_pdf",
|
||||
"regex",
|
||||
"roxmltree",
|
||||
"serde",
|
||||
"sha2",
|
||||
"simple-mermaid",
|
||||
"ureq",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -223,6 +297,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
|
|
@ -278,12 +361,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
|||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.9"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -342,7 +425,7 @@ name = "fayalite-proc-macros-impl"
|
|||
version = "0.3.0"
|
||||
source = "git+https://git.libre-chip.org/libre-chip/fayalite.git?branch=master#c97b44d9d646a4aa64fcc046538fc2354bb708ee"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"base16ct 0.2.0",
|
||||
"num-bigint",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
|
|
@ -367,12 +450,28 @@ dependencies = [
|
|||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.5"
|
||||
|
|
@ -395,6 +494,17 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.4"
|
||||
|
|
@ -408,10 +518,10 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
name = "glob"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
|
|
@ -424,12 +534,24 @@ dependencies = [
|
|||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hex-literal"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1"
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.9"
|
||||
|
|
@ -439,6 +561,22 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "http"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"itoa",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httparse"
|
||||
version = "1.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||
|
||||
[[package]]
|
||||
name = "indenter"
|
||||
version = "0.3.3"
|
||||
|
|
@ -447,13 +585,14 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.5.0"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
|
||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.5",
|
||||
"hashbrown 0.16.1",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -462,6 +601,15 @@ version = "1.70.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
|
|
@ -476,7 +624,7 @@ checksum = "58715c67c327da7f1558708348d68c207fd54900c4ae0529e29305d04d795b8c"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"derive_destructure2",
|
||||
"getrandom",
|
||||
"getrandom 0.3.4",
|
||||
"libc",
|
||||
"scopeguard",
|
||||
"windows-sys 0.61.2",
|
||||
|
|
@ -484,9 +632,25 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.159"
|
||||
version = "0.2.180"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
|
||||
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
|
|
@ -494,12 +658,57 @@ version = "0.4.14"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mupdf-sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13e9a0d4e844ab50315d43312f3d62f72c77205b07c8ee21cbd4b52bdc2a9910"
|
||||
dependencies = [
|
||||
"bindgen",
|
||||
"cc",
|
||||
"pkg-config",
|
||||
"regex",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
|
|
@ -545,6 +754,23 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse_powerisa_pdf"
|
||||
version = "0.1.0"
|
||||
source = "git+https://git.libre-chip.org/libre-chip/parse_powerisa_pdf.git?branch=master#38a1fb328bd44f26389c28fbf66716154f4113dc"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"libm",
|
||||
"mupdf-sys",
|
||||
"quick-xml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.8.3"
|
||||
|
|
@ -557,6 +783,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.22"
|
||||
|
|
@ -576,6 +808,15 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.38.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
|
|
@ -616,6 +857,64 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.16",
|
||||
"libc",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "roxmltree"
|
||||
version = "0.21.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1964b10c76125c36f8afe190065a4bf9a87bf324842c05701330bba9f1cacbb"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.37"
|
||||
|
|
@ -629,6 +928,41 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b"
|
||||
dependencies = [
|
||||
"log",
|
||||
"once_cell",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282"
|
||||
dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.18"
|
||||
|
|
@ -643,18 +977,28 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.210"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.210"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -676,9 +1020,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
version = "0.10.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
|
|
@ -691,6 +1035,12 @@ version = "1.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
|
||||
|
||||
[[package]]
|
||||
name = "simple-mermaid"
|
||||
version = "0.2.0"
|
||||
|
|
@ -703,6 +1053,12 @@ version = "0.11.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.96"
|
||||
|
|
@ -765,6 +1121,47 @@ version = "1.0.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "ureq"
|
||||
version = "3.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"flate2",
|
||||
"log",
|
||||
"percent-encoding",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"ureq-proto",
|
||||
"utf-8",
|
||||
"webpki-roots",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ureq-proto"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d81f9efa9df032be5934a46a068815a10a042b494b6a58cb0a1a97bb5467ed6f"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"http",
|
||||
"httparse",
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
|
|
@ -783,6 +1180,12 @@ version = "0.9.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.1+wasi-0.2.4"
|
||||
|
|
@ -792,6 +1195,15 @@ dependencies = [
|
|||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "6.0.3"
|
||||
|
|
@ -800,6 +1212,7 @@ checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f"
|
|||
dependencies = [
|
||||
"either",
|
||||
"home",
|
||||
"regex",
|
||||
"rustix",
|
||||
"winsafe",
|
||||
]
|
||||
|
|
@ -921,3 +1334,29 @@ checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
|
|||
dependencies = [
|
||||
"tap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||
|
|
|
|||
|
|
@ -14,9 +14,16 @@ categories = []
|
|||
rust-version = "1.89.0"
|
||||
|
||||
[workspace.dependencies]
|
||||
base16ct = "1.0.0"
|
||||
fayalite = { git = "https://git.libre-chip.org/libre-chip/fayalite.git", version = "0.3.0", branch = "master" }
|
||||
hex-literal = "1.1.0"
|
||||
parse_powerisa_pdf = { git = "https://git.libre-chip.org/libre-chip/parse_powerisa_pdf.git", version = "0.1.0", branch = "master" }
|
||||
roxmltree = "0.21.1"
|
||||
serde = { version = "1.0.202", features = ["derive"] }
|
||||
sha2 = "0.10.9"
|
||||
simple-mermaid = "0.2.0"
|
||||
ureq = "3.1.4"
|
||||
which = { version = "6.0.3", features = ["regex"] }
|
||||
|
||||
[profile.dev]
|
||||
opt-level = 1
|
||||
|
|
|
|||
|
|
@ -16,5 +16,20 @@ version.workspace = true
|
|||
|
||||
[dependencies]
|
||||
fayalite.workspace = true
|
||||
roxmltree.workspace = true
|
||||
serde.workspace = true
|
||||
simple-mermaid.workspace = true
|
||||
|
||||
[build-dependencies]
|
||||
base16ct.workspace = true
|
||||
hex-literal.workspace = true
|
||||
parse_powerisa_pdf.workspace = true
|
||||
sha2.workspace = true
|
||||
ureq.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
base16ct.workspace = true
|
||||
hex-literal.workspace = true
|
||||
regex = "1.12.2"
|
||||
sha2.workspace = true
|
||||
which.workspace = true
|
||||
|
|
|
|||
96
crates/cpu/build.rs
Normal file
96
crates/cpu/build.rs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
|
||||
use parse_powerisa_pdf::parse_powerisa_pdf_and_generate_xml;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::{
|
||||
error::Error,
|
||||
io::{ErrorKind, Read},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
const EXPECTED_FILE_SIZE: u64 = 6425593;
|
||||
const EXPECTED_FILE_HASH: &[u8; 32] =
|
||||
&hex_literal::hex!("56372d23ece7e9e2c1b381a639443982a3e16e38109df1c141d655b779b61fdb");
|
||||
|
||||
fn verify_powerisa_file(file: impl std::io::Read) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
let mut buf = Vec::with_capacity(usize::try_from(EXPECTED_FILE_SIZE)? + 1);
|
||||
file.take(EXPECTED_FILE_SIZE + 1).read_to_end(&mut buf)?;
|
||||
if buf.len() > EXPECTED_FILE_SIZE as usize {
|
||||
Err(format!("file is bigger than the expected length {EXPECTED_FILE_SIZE}").into())
|
||||
} else if buf.len() < EXPECTED_FILE_SIZE as usize {
|
||||
Err(format!(
|
||||
"file is smaller than the expected length {EXPECTED_FILE_SIZE}: actual length {}",
|
||||
buf.len()
|
||||
)
|
||||
.into())
|
||||
} else {
|
||||
let hash = Sha256::digest(&buf);
|
||||
let hash = &*hash;
|
||||
if hash != EXPECTED_FILE_HASH {
|
||||
Err(format!(
|
||||
"file's SHA256 hash doesn't match the expected hash: expected: {:x} got: {:x}",
|
||||
base16ct::HexDisplay(EXPECTED_FILE_HASH),
|
||||
base16ct::HexDisplay(hash)
|
||||
)
|
||||
.into())
|
||||
} else {
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_powerisa_pdf(path: impl AsRef<Path>) -> Result<bool, Box<dyn Error>> {
|
||||
let path = path.as_ref();
|
||||
let metadata = match std::fs::metadata(path) {
|
||||
Err(e) if e.kind() == ErrorKind::NotFound => return Ok(false),
|
||||
v => v?,
|
||||
};
|
||||
if !metadata.is_file() {
|
||||
return Ok(false);
|
||||
}
|
||||
let file = std::fs::File::open(path)?;
|
||||
verify_powerisa_file(file)?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn out_dir() -> String {
|
||||
std::env::var("OUT_DIR").expect("OUT_DIR env var is not set or invalid")
|
||||
}
|
||||
|
||||
fn get_powerisa_pdf_name_and_dir<'a>(
|
||||
out_dir: &'a str,
|
||||
) -> Result<(&'static str, &'a Path), Box<dyn Error>> {
|
||||
const FILE_NAME: &str = "OPF_PowerISA_v3.1C.pdf";
|
||||
let out_dir = Path::new(out_dir);
|
||||
if is_powerisa_pdf(FILE_NAME)? {
|
||||
println!("cargo::rerun-if-changed={FILE_NAME}");
|
||||
return Ok((FILE_NAME, Path::new(".")));
|
||||
}
|
||||
let full_path = out_dir.join(FILE_NAME);
|
||||
let full_path = full_path
|
||||
.into_os_string()
|
||||
.into_string()
|
||||
.expect("should be valid UTF-8");
|
||||
if is_powerisa_pdf(&full_path)? {
|
||||
println!("cargo::rerun-if-changed={full_path}");
|
||||
return Ok((FILE_NAME, out_dir));
|
||||
}
|
||||
const URL: &str = "https://libre-chip.org/OPF_PowerISA_v3.1C.pdf";
|
||||
println!("cargo::warning={FILE_NAME} not found locally, downloading from {URL}");
|
||||
let buf = verify_powerisa_file(ureq::get(URL).call()?.into_body().into_reader())?;
|
||||
std::fs::write(&full_path, buf)?;
|
||||
println!("cargo::rerun-if-changed={full_path}");
|
||||
Ok((FILE_NAME, out_dir))
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
let out_dir = out_dir();
|
||||
let (pdf_name, pdf_dir) = get_powerisa_pdf_name_and_dir(&out_dir)?;
|
||||
let old_dir = std::env::current_dir()?;
|
||||
std::env::set_current_dir(pdf_dir)?;
|
||||
let xml = parse_powerisa_pdf_and_generate_xml(pdf_name, None, false)?;
|
||||
std::env::set_current_dir(old_dir)?;
|
||||
std::fs::write(Path::new(&out_dir).join("powerisa-instructions.xml"), xml)?;
|
||||
Ok(())
|
||||
}
|
||||
4
crates/cpu/src/decoder.rs
Normal file
4
crates/cpu/src/decoder.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
|
||||
pub mod simple_power_isa;
|
||||
405
crates/cpu/src/decoder/simple_power_isa.rs
Normal file
405
crates/cpu/src/decoder/simple_power_isa.rs
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
|
||||
use crate::{
|
||||
config::CpuConfig, instruction::MOp, powerisa_instructions_xml::Instructions,
|
||||
util::array_vec::ArrayVec,
|
||||
};
|
||||
use fayalite::prelude::*;
|
||||
|
||||
#[hdl_module]
|
||||
pub fn decode_one_32bit_insn() {
|
||||
#[hdl]
|
||||
let output: ArrayVec<MOp, ConstUsize<2>> = m.output();
|
||||
#[hdl]
|
||||
let input: UInt<32> = m.input();
|
||||
for insn in Instructions::get().instructions() {
|
||||
for header in insn.header() {
|
||||
for mnemonic_line in header.mnemonics().lines() {
|
||||
let Some(mnemonic) = mnemonic_line.split_whitespace().next() else {
|
||||
continue;
|
||||
};
|
||||
match mnemonic {
|
||||
"b" | "ba" | "bl" | "bla" => {
|
||||
// TODO
|
||||
}
|
||||
"bc" | "bca" | "bcl" | "bcla" => {
|
||||
// TODO
|
||||
}
|
||||
"bclr" | "bclrl" => {
|
||||
// TODO
|
||||
}
|
||||
"bcctr" | "bcctrl" => {
|
||||
// TODO
|
||||
}
|
||||
"bctar" | "bctarl" => {
|
||||
// TODO
|
||||
}
|
||||
"crand" | "crnand" | "cror" | "crxor" | "crnor" | "creqv" | "crandc"
|
||||
| "crorc" => {
|
||||
// TODO
|
||||
}
|
||||
"mcrf" => {
|
||||
// TODO
|
||||
}
|
||||
"sc" | "scv" => {
|
||||
// TODO
|
||||
}
|
||||
"lbz" | "plbz" | "lbzx" | "lbzu" | "lbzux" | "lhz" | "plhz" | "lhzx"
|
||||
| "lhzu" | "lhzux" | "lha" | "plha" | "lhax" | "lhau" | "lhaux" | "lwz"
|
||||
| "plwz" | "lwzx" | "lwzu" | "lwzux" | "lwa" | "plwa" | "lwax" | "lwaux"
|
||||
| "ld" | "pld" | "ldx" | "ldu" | "ldux" => {
|
||||
// TODO
|
||||
}
|
||||
"stb" | "pstb" | "stbx" | "stbu" | "stbux" | "sth" | "psth" | "sthx"
|
||||
| "sthu" | "sthux" | "stw" | "pstw" | "stwx" | "stwu" | "stwux" | "std"
|
||||
| "pstd" | "stdx" | "stdu" | "stdux" => {
|
||||
// TODO
|
||||
}
|
||||
"lq" | "plq" | "stq" | "pstq" => {
|
||||
// TODO
|
||||
}
|
||||
"lhbrx" | "sthbrx" | "lwbrx" | "stwbrx" | "ldbrx" | "stdbrx" => {
|
||||
// TODO
|
||||
}
|
||||
"lmw" | "stmw" => {
|
||||
// load/store multi-word are intentionally not implemented
|
||||
}
|
||||
"lswi" | "lswx" | "stswi" | "stswx" => {
|
||||
// load/store string are intentionally not implemented
|
||||
}
|
||||
"addi" | "paddi" => {
|
||||
// TODO
|
||||
}
|
||||
"addis" => {
|
||||
// TODO
|
||||
}
|
||||
"addpcis" => {
|
||||
// TODO
|
||||
}
|
||||
"add" | "add." | "addo" | "addo." => {
|
||||
// TODO
|
||||
}
|
||||
"addic" | "addic." => {
|
||||
// TODO
|
||||
}
|
||||
"subf" | "subf." | "subfo" | "subfo." => {
|
||||
// TODO
|
||||
}
|
||||
"subfic" => {
|
||||
// TODO
|
||||
}
|
||||
"addc" | "addc." | "addco" | "addco." => {
|
||||
// TODO
|
||||
}
|
||||
"subfc" | "subfc." | "subfco" | "subfco." => {
|
||||
// TODO
|
||||
}
|
||||
"adde" | "adde." | "addeo" | "addeo." => {
|
||||
// TODO
|
||||
}
|
||||
"subfe" | "subfe." | "subfeo" | "subfeo." => {
|
||||
// TODO
|
||||
}
|
||||
"addme" | "addme." | "addmeo" | "addmeo." => {
|
||||
// TODO
|
||||
}
|
||||
"addze" | "addze." | "addzeo" | "addzeo." => {
|
||||
// TODO
|
||||
}
|
||||
"subfme" | "subfme." | "subfmeo" | "subfmeo." => {
|
||||
// TODO
|
||||
}
|
||||
"subfze" | "subfze." | "subfzeo" | "subfzeo." => {
|
||||
// TODO
|
||||
}
|
||||
"addex" => {
|
||||
// TODO
|
||||
}
|
||||
"neg" | "neg." | "nego" | "nego." => {
|
||||
// TODO
|
||||
}
|
||||
"mulli" | "mullw" | "mullw." | "mullwo" | "mullwo." | "mulhw" | "mulhw."
|
||||
| "mulhwu" | "mulhwu." => {
|
||||
// TODO
|
||||
}
|
||||
"divw" | "divw." | "divwo" | "divwo." | "divwu" | "divwu." | "divwuo"
|
||||
| "divwuo." | "divwe" | "divwe." | "divweo" | "divweo." | "divweu"
|
||||
| "divweu." | "divweuo" | "divweuo." | "modsw" | "moduw" => {
|
||||
// TODO
|
||||
}
|
||||
"darn" => {
|
||||
// TODO
|
||||
}
|
||||
"mulld" | "mulld." | "mulldo" | "mulldo." | "mulhd" | "mulhd." | "mulhdu"
|
||||
| "mulhdu." | "maddhd" | "maddhdu" | "maddld" => {
|
||||
// TODO
|
||||
}
|
||||
"divd" | "divd." | "divdo" | "divdo." | "divdu" | "divdu." | "divduo"
|
||||
| "divduo." | "divde" | "divde." | "divdeo" | "divdeo." | "divdeu"
|
||||
| "divdeu." | "divdeuo" | "divdeuo." | "modsd" | "modud" => {
|
||||
// TODO
|
||||
}
|
||||
"cmpi" | "cmp" | "cmpli" | "cmpl" => {
|
||||
// TODO
|
||||
}
|
||||
"cmprb" | "cmpeqb" => {
|
||||
// TODO
|
||||
}
|
||||
"twi" | "tw" | "tdi" | "td" => {
|
||||
// TODO
|
||||
}
|
||||
"isel" => {
|
||||
// TODO
|
||||
}
|
||||
"andi." | "andis." | "ori" | "oris" | "xori" | "xoris" | "and" | "and."
|
||||
| "xor" | "xor." | "nand" | "nand." | "or" | "or." | "orc" | "orc." | "nor"
|
||||
| "nor." | "eqv" | "eqv." | "andc" | "andc." => {
|
||||
// TODO
|
||||
}
|
||||
"extsb" | "extsb." | "extsh" | "extsh." => {
|
||||
// TODO
|
||||
}
|
||||
"cmpb" => {
|
||||
// TODO
|
||||
}
|
||||
"cntlzw" | "cntlzw." | "cnttzw" | "cnttzw." | "popcntb" | "popcntw"
|
||||
| "prtyw" | "popcntd" | "prtyd" | "cntlzd" | "cntlzd." | "cnttzd"
|
||||
| "cnttzd." | "cntlzdm" | "cnttzdm" | "bpermd" | "cfuged" | "pextd"
|
||||
| "pdepd" => {
|
||||
// TODO
|
||||
}
|
||||
"extsw" | "extsw." => {
|
||||
// TODO
|
||||
}
|
||||
"rlwinm" | "rlwinm." | "rlwnm" | "rlwnm." | "rlwimi" | "rlwimi." | "rldicl"
|
||||
| "rldicl." | "rldicr" | "rldicr." | "rldic" | "rldic." | "rldcl"
|
||||
| "rldcl." | "rldcr" | "rldcr." | "rldimi" | "rldimi." => {
|
||||
// TODO
|
||||
}
|
||||
"slw" | "slw." | "srw" | "srw." | "srawi" | "srawi." | "sraw" | "sraw."
|
||||
| "sld" | "sld." | "sradi" | "sradi." | "srd" | "srd." | "srad" | "srad." => {
|
||||
// TODO
|
||||
}
|
||||
"extswsli" | "extswsli." => {
|
||||
// TODO
|
||||
}
|
||||
"cdtbcd" | "cbcdtd" | "addg6s" => {
|
||||
// TODO
|
||||
}
|
||||
"brh" | "brw" | "brd" => {
|
||||
// TODO
|
||||
}
|
||||
"hashst" | "hashchk" | "hashstp" | "hashchkp" => {
|
||||
// hash check/store are intentionally not implemented
|
||||
}
|
||||
"mfvsrd" | "mfvsrld" | "mfvsrwz" | "mtvsrd" | "mtvsrwa" | "mtvsrwz"
|
||||
| "mtvsrdd" | "mtvsrws" => {
|
||||
// TODO(FP) -- mostly intentionally not implemented
|
||||
}
|
||||
"mtspr" | "mfspr" | "mftb" | "mtmsr" | "mtmsrd" | "mfmsr" => {
|
||||
// TODO
|
||||
}
|
||||
"mcrxrx" | "mtocrf" | "mtcrf" | "mfocrf" | "mfcr" | "setb" | "setbc"
|
||||
| "setbcr" | "setnbc" | "setnbcr" => {
|
||||
// TODO
|
||||
}
|
||||
"pnop" => {
|
||||
// TODO: not implemented
|
||||
}
|
||||
"lfs" | "plfs" | "lfsx" | "lfsu" | "lfsux" | "lfd" | "plfd" | "lfdx"
|
||||
| "lfdu" | "lfdux" | "lfiwax" | "lfiwzx" | "stfs" | "pstfs" | "stfsx"
|
||||
| "stfsu" | "stfsux" | "stfd" | "pstfd" | "stfdx" | "stfdu" | "stfdux"
|
||||
| "stfiwx" | "lfdp" | "lfdpx" | "stfdp" | "stfdpx" | "fmr" | "fmr."
|
||||
| "fneg" | "fneg." | "fabs" | "fabs." | "fnabs" | "fnabs." | "fcpsgn"
|
||||
| "fcpsgn." | "fmrgew" | "fmrgow" | "fadd" | "fadd." | "fadds" | "fadds."
|
||||
| "fsub" | "fsub." | "fsubs" | "fsubs." | "fmul" | "fmul." | "fmuls"
|
||||
| "fmuls." | "fdiv" | "fdiv." | "fdivs" | "fdivs." | "fsqrt" | "fsqrt."
|
||||
| "fsqrts" | "fsqrts." | "fre" | "fre." | "fres" | "fres." | "frsqrte"
|
||||
| "frsqrte." | "frsqrtes" | "frsqrtes." | "ftdiv" | "ftsqrt" | "fmadd"
|
||||
| "fmadd." | "fmadds" | "fmadds." | "fmsub" | "fmsub." | "fmsubs"
|
||||
| "fmsubs." | "fnmadd" | "fnmadd." | "fnmadds" | "fnmadds." | "fnmsub"
|
||||
| "fnmsub." | "fnmsubs" | "fnmsubs." | "frsp" | "frsp." | "fctid"
|
||||
| "fctid." | "fctidz" | "fctidz." | "fctidu" | "fctidu." | "fctiduz"
|
||||
| "fctiduz." | "fctiw" | "fctiw." | "fctiwz" | "fctiwz." | "fctiwu"
|
||||
| "fctiwu." | "fctiwuz" | "fctiwuz." | "fcfid" | "fcfid." | "fcfidu"
|
||||
| "fcfidu." | "fcfids" | "fcfids." | "fcfidus" | "fcfidus." | "frin"
|
||||
| "frin." | "friz" | "friz." | "frip" | "frip." | "frim" | "frim."
|
||||
| "fcmpu" | "fcmpo" | "fsel" | "fsel." | "mffs" | "mffs." | "mffsce"
|
||||
| "mffscdrn" | "mffscdrni" | "mffscrn" | "mffscrni" | "mffsl" | "mcrfs"
|
||||
| "mtfsfi" | "mtfsfi." | "mtfsf" | "mtfsf." | "mtfsb0" | "mtfsb0."
|
||||
| "mtfsb1" | "mtfsb1." => {
|
||||
// TODO(FP)
|
||||
}
|
||||
"dadd" | "dadd." | "daddq" | "daddq." | "dsub" | "dsub." | "dsubq"
|
||||
| "dsubq." | "dmul" | "dmul." | "dmulq" | "dmulq." | "ddiv" | "ddiv."
|
||||
| "ddivq" | "ddivq." | "dcmpu" | "dcmpuq" | "dcmpo" | "dcmpoq" | "dtstdc"
|
||||
| "dtstdcq" | "dtstdg" | "dtstdgq" | "dtstex" | "dtstexq" | "dtstsf"
|
||||
| "dtstsfq" | "dtstsfi" | "dtstsfiq" | "dquai" | "dquai." | "dquaiq"
|
||||
| "dquaiq." | "dqua" | "dqua." | "dquaq" | "dquaq." | "drrnd" | "drrnd."
|
||||
| "drrndq" | "drrndq." | "drintx" | "drintx." | "drintxq" | "drintxq."
|
||||
| "drintn" | "drintn." | "drintnq" | "drintnq." | "dctdp" | "dctdp."
|
||||
| "dctqpq" | "dctqpq." | "drsp" | "drsp." | "drdpq" | "drdpq." | "dcffix"
|
||||
| "dcffix." | "dcffixq" | "dcffixq." | "dcffixqq" | "dctfix" | "dctfix."
|
||||
| "dctfixq" | "dctfixq." | "dctfixqq" | "ddedpd" | "ddedpd." | "ddedpdq"
|
||||
| "ddedpdq." | "denbcd" | "denbcd." | "denbcdq" | "denbcdq." | "dxex"
|
||||
| "dxex." | "dxexq" | "dxexq." | "diex" | "diex." | "diexq" | "diexq."
|
||||
| "dscli" | "dscli." | "dscliq" | "dscliq." | "dscri" | "dscri." | "dscriq"
|
||||
| "dscriq." => {
|
||||
// decimal FP is intentionally not implemented
|
||||
}
|
||||
"lvebx" | "lvehx" | "lvewx" | "lvx" | "lvxl" | "stvebx" | "stvehx"
|
||||
| "stvewx" | "stvx" | "stvxl" | "lvsl" | "lvsr" | "vpkpx" | "vpkuhum"
|
||||
| "vpkuwum" | "vpkudum" | "vupkhsb" | "vupklsb" | "vupkhsh" | "vupklsh"
|
||||
| "vupkhsw" | "vupklsw" | "vupkhpx" | "vupklpx" | "vmrghb" | "vmrglb"
|
||||
| "vmrghh" | "vmrglh" | "vmrghw" | "vmrglw" | "vmrgew" | "vmrgow"
|
||||
| "vspltb" | "vsplth" | "vspltw" | "vspltisb" | "vspltish" | "vspltisw"
|
||||
| "vperm" | "vpermr" | "vsel" | "vsldbi" | "vsldoi" | "vsrdbi" | "vsl"
|
||||
| "vsr" | "vslo" | "vsro" | "vslv" | "vsrv" | "vextractub" | "vextractuh"
|
||||
| "vextractuw" | "vextractd" | "vextublx" | "vextubrx" | "vextuhlx"
|
||||
| "vextuhrx" | "vextuwlx" | "vextuwrx" | "vextdubvlx" | "vextdubvrx"
|
||||
| "vextduhvlx" | "vextduhvrx" | "vextduwvlx" | "vextduwvrx" | "vextddvlx"
|
||||
| "vextddvrx" | "vinsertb" | "vinserth" | "vinsertw" | "vinsertd"
|
||||
| "vinsblx" | "vinsbrx" | "vinshlx" | "vinshrx" | "vinswlx" | "vinswrx"
|
||||
| "vinsdlx" | "vinsdrx" | "vinsw" | "vinsd" | "vinsbvlx" | "vinsbvrx"
|
||||
| "vinshvlx" | "vinshvrx" | "vinswvlx" | "vinswvrx" | "vaddcuw" | "vaddubm"
|
||||
| "vadduhm" | "vadduwm" | "vaddudm" | "vadduqm" | "vaddeuqm" | "vaddcuq"
|
||||
| "vaddecuq" | "vsubcuw" | "vsubsbs" | "vsububm" | "vsubuhm" | "vsubuwm"
|
||||
| "vsubudm" | "vsububs" | "vsubuhs" | "vsubuws" | "vsubuqm" | "vsubeuqm"
|
||||
| "vsubcuq" | "vsubecuq" | "vmulesb" | "vmulosb" | "vmuleub" | "vmuloub"
|
||||
| "vmulesh" | "vmulosh" | "vmuleuh" | "vmulouh" | "vmulesw" | "vmulosw"
|
||||
| "vmuleuw" | "vmulouw" | "vmuleud" | "vmuloud" | "vmulesd" | "vmulosd"
|
||||
| "vmuluwm" | "vmulhsw" | "vmulhuw" | "vmulhsd" | "vmulhud" | "vmulld"
|
||||
| "vmladduhm" | "vmsumubm" | "vmsummbm" | "vmsumshm" | "vmsumuhm"
|
||||
| "vmsumudm" | "vmsumcud" | "vdivsw" | "vdivuw" | "vdivesw" | "vdiveuw"
|
||||
| "vdivsd" | "vdivud" | "vdivesd" | "vdiveud" | "vdivsq" | "vdivuq"
|
||||
| "vdivesq" | "vdiveuq" | "vmodsw" | "vmoduw" | "vmodsd" | "vmodud"
|
||||
| "vmodsq" | "vmoduq" | "vnegw" | "vnegd" | "vextsb2w" | "vextsh2w"
|
||||
| "vextsb2d" | "vextsh2d" | "vextsw2d" | "vextsd2q" | "vavgsb" | "vavgub"
|
||||
| "vavgsh" | "vavguh" | "vavgsw" | "vavguw" | "vabsdub" | "vabsduh"
|
||||
| "vabsduw" | "vmaxsb" | "vmaxub" | "vmaxsh" | "vmaxuh" | "vmaxsw"
|
||||
| "vmaxuw" | "vmaxsd" | "vmaxud" | "vminsb" | "vminub" | "vminsh"
|
||||
| "vminuh" | "vminsw" | "vminuw" | "vminsd" | "vminud" | "vcmpequb"
|
||||
| "vcmpequb." | "vcmpequh" | "vcmpequh." | "vcmpequw" | "vcmpequw."
|
||||
| "vcmpequd" | "vcmpequd." | "vcmpequq" | "vcmpequq." | "vcmpgtsb"
|
||||
| "vcmpgtsb." | "vcmpgtub" | "vcmpgtub." | "vcmpgtsh" | "vcmpgtsh."
|
||||
| "vcmpgtuh" | "vcmpgtuh." | "vcmpgtsw" | "vcmpgtsw." | "vcmpgtuw"
|
||||
| "vcmpgtuw." | "vcmpgtsd" | "vcmpgtsd." | "vcmpgtud" | "vcmpgtud."
|
||||
| "vcmpgtsq" | "vcmpgtsq." | "vcmpgtuq" | "vcmpgtuq." | "vcmpneb"
|
||||
| "vcmpneb." | "vcmpnezb" | "vcmpnezb." | "vcmpneh" | "vcmpneh."
|
||||
| "vcmpnezh" | "vcmpnezh." | "vcmpnew" | "vcmpnew." | "vcmpnezw"
|
||||
| "vcmpnezw." | "vcmpsq" | "vcmpuq" | "vand" | "vandc" | "veqv" | "vnand"
|
||||
| "vor" | "vorc" | "vnor" | "vxor" | "vrlb" | "vrlh" | "vrlw" | "vrld"
|
||||
| "vrlq" | "vrlwnm" | "vrldnm" | "vrlqnm" | "vrlwmi" | "vrldmi" | "vrlqmi"
|
||||
| "vslb" | "vslh" | "vslw" | "vsld" | "vslq" | "vsrb" | "vsrh" | "vsrw"
|
||||
| "vsrd" | "vsrq" | "vsrab" | "vsrah" | "vsraw" | "vsrad" | "vsraq"
|
||||
| "vaddfp" | "vsubfp" | "vmaddfp" | "vnmsubfp" | "vmaxfp" | "vminfp"
|
||||
| "vcfsx" | "vcfux" | "vrfim" | "vrfin" | "vrfip" | "vrfiz" | "vcmpeqfp"
|
||||
| "vcmpeqfp." | "vcmpgefp" | "vcmpgefp." | "vcmpgtfp" | "vcmpgtfp."
|
||||
| "vexptefp" | "vrefp" | "vrsqrtefp" | "vcipher" | "vcipherlast"
|
||||
| "vncipher" | "vncipherlast" | "vsbox" | "vpmsumb" | "vpmsumh" | "vpmsumw"
|
||||
| "vpmsumd" | "vpermxor" | "vgnb" | "vclzb" | "vclzh" | "vclzw" | "vclzd"
|
||||
| "vclzdm" | "vctzb" | "vctzh" | "vctzw" | "vctzd" | "vctzdm" | "vclzlsbb"
|
||||
| "vctzlsbb" | "vpdepd" | "vpextd" | "vcfuged" | "vpopcntb" | "vpopcnth"
|
||||
| "vpopcntw" | "vpopcntd" | "vprtybw" | "vprtybd" | "vprtybq" | "vbpermd"
|
||||
| "vbpermq" | "mtvsrbm" | "mtvsrhm" | "mtvsrwm" | "mtvsrdm" | "mtvsrqm"
|
||||
| "mtvsrbmi" | "vexpandbm" | "vexpandhm" | "vexpandwm" | "vexpanddm"
|
||||
| "vexpandqm" | "vcntmbb" | "vcntmbh" | "vcntmbw" | "vcntmbd"
|
||||
| "vextractbm" | "vextracthm" | "vextractwm" | "vextractdm" | "vextractqm"
|
||||
| "vstribr" | "vstribr." | "vstribl" | "vstribl." | "vstrihr" | "vstrihr."
|
||||
| "vstrihl" | "vstrihl." | "vclrlb" | "vclrrb" | "bcdadd." | "bcdsub."
|
||||
| "bcdcfz." | "vmul10uq" | "vmul10cuq" | "vmul10euq" | "vmul10ecuq"
|
||||
| "bcdcpsgn." | "bcdsetsgn." | "mtvscr" | "mfvscr" => {
|
||||
// VMX is intentionally not implemented
|
||||
}
|
||||
// note this list only contains the instructions that are in
|
||||
// powerisa-instructions.xml, this is not the complete list of VSX instructions
|
||||
"lxsdx" | "lxsibzx" | "lxsihzx" | "lxsiwax" | "lxsiwzx" | "lxsspx"
|
||||
| "stxsdx" | "stxsibx" | "stxsihx" | "stxsiwx" | "stxsspx" | "lxvb16x"
|
||||
| "lxvh8x" | "lxvx" | "lxvdsx" | "lxvwsx" | "lxvrbx" | "lxvrdx" | "lxvrhx"
|
||||
| "lxvrwx" | "lxvll" | "stxvb16x" | "stxvd2x" | "stxvh8x" | "stxvw4x"
|
||||
| "stxvx" | "stxvrbx" | "stxvrdx" | "stxvrhx" | "stxvrwx" | "stxvll"
|
||||
| "lxvp" | "plxvp" | "xsabsdp" | "xsabsqp" | "xscpsgndp" | "xscpsgnqp"
|
||||
| "xsnabsdp" | "xsnabsqp" | "xsnegdp" | "xsnegqp" | "xvabsdp" | "xvabssp"
|
||||
| "xvcpsgndp" | "xvcpsgnsp" | "xvnabsdp" | "xvnabssp" | "xvnegdp"
|
||||
| "xvnegsp" | "xsaddqp" | "xsaddqpo" | "xsaddsp" | "xsdivsp" | "xsmulqp"
|
||||
| "xsmulqpo" | "xsmulsp" | "xssubdp" | "xssubqp" | "xssubqpo" | "xssubsp"
|
||||
| "xsmaddadp" | "xsmaddmdp" | "xsmaddasp" | "xsmaddmsp" | "xsmaddqp"
|
||||
| "xsmaddqpo" | "xsmsubasp" | "xsmsubmsp" | "xsmsubqp" | "xsmsubqpo"
|
||||
| "xsnmaddadp" | "xsnmaddmdp" | "xsnmaddasp" | "xsnmaddmsp" | "xsnmaddqp"
|
||||
| "xsnmaddqpo" | "xsnmsubasp" | "xsnmsubmsp" | "xsnmsubqp" | "xsnmsubqpo"
|
||||
| "xstsqrtdp" | "xvmaddadp" | "xvmaddmdp" | "xvmaddasp" | "xvmaddmsp"
|
||||
| "xvmsubadp" | "xvmsubmdp" | "xvmsubasp" | "xvmsubmsp" | "xvnmaddadp"
|
||||
| "xvnmaddmdp" | "xvnmaddasp" | "xvnmaddmsp" | "xvnmsubadp" | "xvnmsubmdp"
|
||||
| "xvnmsubasp" | "xvnmsubmsp" | "xvtsqrtdp" | "xvtsqrtsp" | "xsmincqp"
|
||||
| "xscvdpspn" | "xscvdpqp" | "xscvspdpn" | "xvcvbf16spn" | "xvcvspdp"
|
||||
| "xvrdpim" | "xvrdpip" | "xvrspim" | "xvrspip" | "xscvqpsqz" | "xscvqpuqz"
|
||||
| "xscvqpuwz" | "xscvsdqp" | "xscvudqp" | "xscvsqqp" | "xscvuqqp"
|
||||
| "xscvsxddp" | "xscvuxddp" | "xscvsxdsp" | "xscvuxdsp" | "xvcvsxddp"
|
||||
| "xvcvuxddp" | "xvcvsxwdp" | "xvcvuxwdp" | "xvcvsxdsp" | "xvcvuxdsp"
|
||||
| "xvcvsxwsp" | "xvcvuxwsp" | "xsxexpdp" | "xsxexpqp" | "xsxsigdp"
|
||||
| "xsxsigqp" | "xviexpdp" | "xviexpsp" | "xvxexpdp" | "xvxexpsp"
|
||||
| "xvxsigdp" | "xvxsigsp" | "xxmfacc" | "xxmtacc" | "xxsetaccz"
|
||||
| "xvi16ger2" | "pmxvi16ger2" | "xvi16ger2s" | "pmxvi16ger2s" | "xvi4ger8"
|
||||
| "pmxvi4ger8" | "xvi8ger4" | "pmxvi8ger4" | "pmxvbf16ger2np"
|
||||
| "pmxvf16ger2np" | "pmxvf32gernp" | "xxland" | "xxlandc" | "xxleqv"
|
||||
| "xxlnand" | "xxlnor" | "xxlor" | "xxlorc" | "xxlxor" | "xxsel" | "xxeval"
|
||||
| "xxblendvb" | "xxblendvd" | "xxblendvh" | "xxblendvw" | "xxbrh" | "xxbrq"
|
||||
| "xxbrw" | "xxextractuw" | "xxinsertw" | "xxmrghw" | "xxmrglw"
|
||||
| "xxsplti32dx" | "xxspltib" | "xxspltidp" | "xxspltiw" | "xxspltw"
|
||||
| "xxperm" | "xxpermr" | "xxsldwi" | "xxgenpcvdm" | "xxgenpcvwm" | "lxvkq"
|
||||
| "xvtlsbb" => {
|
||||
// VSX is intentionally not implemented
|
||||
}
|
||||
"icbi" | "icbt" | "dcbz" | "dcbst" | "dcbf" | "isync" | "sync" => {
|
||||
// TODO
|
||||
}
|
||||
"copy" | "paste." | "cpabort" => {
|
||||
// copy/paste is intentionally not implemented
|
||||
}
|
||||
"lwat" | "ldat" | "stwat" | "stdat" => {
|
||||
// TODO
|
||||
}
|
||||
"lbarx" | "lharx" | "lwarx" | "stbcx." | "sthcx." | "stwcx." | "ldarx"
|
||||
| "stdcx." | "stqcx." => {
|
||||
// TODO
|
||||
}
|
||||
"wait" => {
|
||||
// TODO
|
||||
}
|
||||
"clrbhrb" | "mfbhrbe" => {
|
||||
// TODO branch history
|
||||
}
|
||||
"rfscv" | "rfid" | "hrfid" | "urfid" => {
|
||||
// TODO
|
||||
}
|
||||
"stop" => {
|
||||
// TODO
|
||||
}
|
||||
"lbzcix" | "lhzcix" | "lwzcix" | "ldcix" => {
|
||||
// TODO
|
||||
}
|
||||
"stbcix" | "sthcix" | "stwcix" | "stdcix" => {
|
||||
// TODO
|
||||
}
|
||||
"slbie" | "slbieg" | "slbia" | "slbiag" | "slbmfev" | "slbmfee" | "slbfee."
|
||||
| "slbsync" | "tlbsync" => {
|
||||
// TODO
|
||||
}
|
||||
"msgsndu" | "msgclru" | "msgsnd" | "msgclr" | "msgsndp" | "msgclrp"
|
||||
| "msgsync" => {
|
||||
// TODO
|
||||
}
|
||||
_ => panic!("unhandled mnemonic: {mnemonic:?}"),
|
||||
}
|
||||
}
|
||||
// TODO: decode instruction fields
|
||||
}
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[hdl_module]
|
||||
pub fn simple_power_isa_decoder(config: PhantomConst<CpuConfig>) {
|
||||
todo!()
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ use fayalite::{
|
|||
expr::{HdlPartialEqImpl, ops::ArrayLiteral},
|
||||
intern::Interned,
|
||||
prelude::*,
|
||||
ty::StaticType,
|
||||
};
|
||||
use std::{borrow::Cow, fmt, marker::PhantomData, ops::Range};
|
||||
|
||||
|
|
@ -947,6 +948,43 @@ pub struct MOpDestReg {
|
|||
pub flag_regs: Array<HdlOption<()>, { range_u32_len(&MOpRegNum::FLAG_REG_NUMS) }>,
|
||||
}
|
||||
|
||||
impl MOpDestReg {
|
||||
#[hdl]
|
||||
#[track_caller]
|
||||
pub fn new_sim(normal_regs: &[u32], flag_regs: &[u32]) -> SimValue<Self> {
|
||||
let zero_reg = MOpRegNum::const_zero().to_sim_value();
|
||||
let mut normal_regs_sim = std::array::from_fn(|_| zero_reg.clone());
|
||||
for (i, reg) in normal_regs.iter().copied().enumerate() {
|
||||
let Some(normal_reg_sim) = normal_regs_sim.get_mut(i) else {
|
||||
panic!("too many normal regs");
|
||||
};
|
||||
if reg >= 1 << MOpRegNum::WIDTH {
|
||||
panic!("normal reg number out of range");
|
||||
}
|
||||
*normal_reg_sim.value = reg.cast_to_static::<UInt<_>>();
|
||||
}
|
||||
let mut flag_regs_sim = std::array::from_fn(|_| {
|
||||
#[hdl(sim)]
|
||||
HdlNone()
|
||||
});
|
||||
for &flag_reg in flag_regs {
|
||||
let Some(index) = { MOpRegNum::FLAG_REG_NUMS }.position(|v| flag_reg == v) else {
|
||||
panic!(
|
||||
"flag reg number {flag_reg} is out of range, supported range is: {:?}",
|
||||
MOpRegNum::FLAG_REG_NUMS
|
||||
);
|
||||
};
|
||||
flag_regs_sim[index] = #[hdl(sim)]
|
||||
HdlSome(());
|
||||
}
|
||||
#[hdl(sim)]
|
||||
Self {
|
||||
normal_regs: normal_regs_sim,
|
||||
flag_regs: flag_regs_sim,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
|
||||
pub enum RenameTableName {
|
||||
/// the large rename table for normal registers (has less read/write ports)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
pub mod config;
|
||||
pub mod decoder;
|
||||
pub mod instruction;
|
||||
pub mod next_pc;
|
||||
pub mod powerisa_instructions_xml;
|
||||
pub mod reg_alloc;
|
||||
pub mod register;
|
||||
pub mod unit;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
2719
crates/cpu/src/powerisa_instructions_xml.rs
Normal file
2719
crates/cpu/src/powerisa_instructions_xml.rs
Normal file
File diff suppressed because it is too large
Load diff
0
crates/cpu/tests/expected/decode_one_32bit_insn.vcd
Normal file
0
crates/cpu/tests/expected/decode_one_32bit_insn.vcd
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -326,7 +326,9 @@ impl MockInsn {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
struct MockMachineState {
|
||||
reset_at_exit: bool,
|
||||
call_stack: Vec<u64>,
|
||||
orig_input: &'static [u8],
|
||||
input: &'static [u8],
|
||||
output: Vec<u8>,
|
||||
regs: MockRegs,
|
||||
|
|
@ -340,16 +342,36 @@ const RESET_PC: u64 = 0;
|
|||
const EXIT_PC: u64 = u64::from_be_bytes(*b"ExitExit");
|
||||
|
||||
impl MockMachineState {
|
||||
fn new(insns: MockInsns, input: impl AsRef<[u8]>) -> Self {
|
||||
fn new(insns: MockInsns, input: impl AsRef<[u8]>, reset_at_exit: bool) -> Self {
|
||||
let input = Interned::into_inner(input.as_ref().intern());
|
||||
Self {
|
||||
reset_at_exit,
|
||||
call_stack: Vec::with_capacity(16),
|
||||
input: Interned::into_inner(input.as_ref().intern()),
|
||||
orig_input: input,
|
||||
input,
|
||||
output: Vec::with_capacity(16),
|
||||
regs: MockRegs::new(),
|
||||
pc: RESET_PC,
|
||||
insns,
|
||||
}
|
||||
}
|
||||
fn reset(&mut self) {
|
||||
let Self {
|
||||
reset_at_exit: _,
|
||||
call_stack,
|
||||
orig_input,
|
||||
input,
|
||||
output,
|
||||
regs,
|
||||
pc,
|
||||
insns: _,
|
||||
} = self;
|
||||
call_stack.clear();
|
||||
*input = *orig_input;
|
||||
output.clear();
|
||||
*regs = MockRegs::new();
|
||||
*pc = RESET_PC;
|
||||
}
|
||||
fn run_one(&mut self, trace: bool) -> RetireSeqEntry {
|
||||
let orig_pc = self.pc;
|
||||
let insn = self
|
||||
|
|
@ -420,7 +442,18 @@ impl MockMachineState {
|
|||
next_pc = target;
|
||||
}
|
||||
MockInsn::Ret => next_pc = self.call_stack.pop().unwrap_or(DEMO_ILLEGAL_INSN_TRAP),
|
||||
MockInsn::ExitSysCall => next_pc = EXIT_PC,
|
||||
MockInsn::ExitSysCall => {
|
||||
if self.reset_at_exit {
|
||||
self.reset();
|
||||
return RetireSeqEntry {
|
||||
pc: orig_pc,
|
||||
cond_br_taken: None,
|
||||
insn,
|
||||
};
|
||||
} else {
|
||||
next_pc = EXIT_PC;
|
||||
}
|
||||
}
|
||||
MockInsn::Illegal => next_pc = DEMO_ILLEGAL_INSN_TRAP,
|
||||
}
|
||||
self.pc = next_pc;
|
||||
|
|
@ -721,7 +754,7 @@ fn test_program_expr_parser() {
|
|||
#[track_caller]
|
||||
fn test(expected_output: &str, expected_exit_code: u64, input: &str) {
|
||||
println!("starting new test case: input={input:?}\n\n");
|
||||
let mut state = MockMachineState::new(mock_program_expr_parser(), input);
|
||||
let mut state = MockMachineState::new(mock_program_expr_parser(), input, false);
|
||||
let exit_code = state.run_until_exit(10000, true).unwrap();
|
||||
println!("output: {:?}", str::from_utf8(&state.output));
|
||||
println!("exit code: {exit_code}");
|
||||
|
|
@ -771,7 +804,7 @@ impl FetchPipeQueueEntry {
|
|||
.rotate_left(32)
|
||||
.wrapping_mul(0x92B38C197608A6B) // random prime
|
||||
.rotate_right(60);
|
||||
(random % 8) as u8
|
||||
if random % 32 == 0 { 30 } else { 3 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -799,6 +832,12 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
|||
async |mut sim| {
|
||||
sim.write(from_fetch.fetch.ready, false).await;
|
||||
sim.write(from_fetch.cancel.ready, false).await;
|
||||
sim.write(
|
||||
from_fetch.next_fetch_block_ids,
|
||||
#[hdl(sim)]
|
||||
(from_fetch.next_fetch_block_ids.ty()).HdlNone(),
|
||||
)
|
||||
.await;
|
||||
sim.write(
|
||||
to_post_decode.inner.data,
|
||||
to_post_decode.ty().inner.data.HdlNone(),
|
||||
|
|
@ -840,12 +879,21 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
|||
let mut next_id = 0u32;
|
||||
loop {
|
||||
let mut sim_queue = queue_debug.ty().new_sim(FetchPipeQueueEntry.default_sim());
|
||||
let mut next_fetch_block_ids =
|
||||
from_fetch.next_fetch_block_ids.ty().HdlSome.new_sim(0u8);
|
||||
for entry in &queue {
|
||||
ArrayVec::try_push_sim(&mut sim_queue, entry)
|
||||
.ok()
|
||||
.expect("queue is known to be small enough");
|
||||
let _ = ArrayVec::try_push_sim(&mut next_fetch_block_ids, &entry.fetch_block_id);
|
||||
}
|
||||
sim.write(queue_debug, sim_queue).await;
|
||||
sim.write(
|
||||
from_fetch.next_fetch_block_ids,
|
||||
#[hdl(sim)]
|
||||
(from_fetch.next_fetch_block_ids.ty()).HdlSome(next_fetch_block_ids),
|
||||
)
|
||||
.await;
|
||||
if let Some(front) = queue.front().filter(|v| v.cycles_left.as_int() == 0) {
|
||||
#[hdl(sim)]
|
||||
let FetchPipeQueueEntry {
|
||||
|
|
@ -874,6 +922,7 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
|||
fetch_block_id,
|
||||
id: next_id.cast_to_static::<UInt<_>>(),
|
||||
pc,
|
||||
predicted_next_pc: 0u64,
|
||||
size_in_bytes: insn.byte_len().cast_to_static::<UInt<_>>(),
|
||||
kind: insn.wip_decoded_insn_kind(),
|
||||
};
|
||||
|
|
@ -890,6 +939,7 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
|||
fetch_block_id,
|
||||
id: next_id.cast_to_static::<UInt<_>>(),
|
||||
pc: start_pc,
|
||||
predicted_next_pc: 0u64,
|
||||
size_in_bytes: 0u8.cast_to_static::<UInt<_>>(),
|
||||
kind: WipDecodedInsnKind.Interrupt(DEMO_ILLEGAL_INSN_TRAP),
|
||||
},
|
||||
|
|
@ -917,10 +967,27 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
|||
.await;
|
||||
sim.write(from_fetch.cancel.ready, true).await;
|
||||
sim.wait_for_clock_edge(cd.clk).await;
|
||||
println!(
|
||||
"Dump mock fetch decode pipe queue: {:#?}",
|
||||
Vec::from_iter(queue.iter().map(|v| {
|
||||
DebugAsDisplay(format!(
|
||||
"fid={:#x} pc={:#x}",
|
||||
v.fetch_block_id.as_int(),
|
||||
v.start_pc.as_int(),
|
||||
))
|
||||
}))
|
||||
);
|
||||
if sim.read_past_bool(to_post_decode.inner.ready, cd.clk).await {
|
||||
#[hdl(sim)]
|
||||
if let HdlSome(_) = sim.read_past(to_post_decode.inner.data, cd.clk).await {
|
||||
queue.pop_front();
|
||||
let Some(v) = queue.pop_front() else {
|
||||
unreachable!();
|
||||
};
|
||||
println!(
|
||||
"mock fetch decode pipe queue pop: fid={:#x} pc={:#x}",
|
||||
v.fetch_block_id.as_int(),
|
||||
v.start_pc.as_int(),
|
||||
);
|
||||
}
|
||||
}
|
||||
for entry in &mut queue {
|
||||
|
|
@ -935,7 +1002,14 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
|||
{
|
||||
// cancel in-progress fetches from newest to oldest
|
||||
for _ in 0..*in_progress_fetches_to_cancel {
|
||||
let _ = queue.pop_back();
|
||||
let Some(v) = queue.pop_back() else {
|
||||
unreachable!();
|
||||
};
|
||||
println!(
|
||||
"mock fetch decode pipe queue cancel unpush: fid={:#x} pc={:#x}",
|
||||
v.fetch_block_id.as_int(),
|
||||
v.start_pc.as_int(),
|
||||
);
|
||||
}
|
||||
}
|
||||
if !sim.read_past_bool(from_fetch.fetch.ready, cd.clk).await {
|
||||
|
|
@ -949,6 +1023,11 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
|
|||
start_pc,
|
||||
fetch_block_id,
|
||||
} = &inner;
|
||||
println!(
|
||||
"mock fetch decode pipe queue push: fid={:#x} pc={:#x}",
|
||||
fetch_block_id.as_int(),
|
||||
start_pc.as_int(),
|
||||
);
|
||||
queue.push_back(
|
||||
#[hdl(sim)]
|
||||
FetchPipeQueueEntry {
|
||||
|
|
@ -979,7 +1058,8 @@ impl ExecuteRetirePipeQueueEntry {
|
|||
WipDecodedInsn {
|
||||
fetch_block_id: 0u8,
|
||||
id: 0_hdl_u12,
|
||||
pc: 0xEEEE_EEEE_EEEE_EEEEu64,
|
||||
pc: 0u64,
|
||||
predicted_next_pc: 0u64,
|
||||
size_in_bytes: 0_hdl_u4,
|
||||
kind: WipDecodedInsnKind.NonBranch(),
|
||||
},
|
||||
|
|
@ -996,7 +1076,13 @@ impl ExecuteRetirePipeQueueEntry {
|
|||
.rotate_left(32)
|
||||
.wrapping_mul(0x73161B54984B1C21) // random prime
|
||||
.rotate_right(60);
|
||||
(random % 16) as u8
|
||||
const DELAYS: &[u8; 0x20] = &[
|
||||
0, 0, 0, 0, 0, 0, 0, 0, //
|
||||
1, 1, 1, 1, 1, 1, 1, 1, //
|
||||
2, 2, 2, 2, 2, 2, 2, 2, //
|
||||
3, 3, 3, 3, 4, 5, 6, 50, // 50 for simulating a cache miss or something
|
||||
];
|
||||
DELAYS[(random & 0x1F) as usize]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1052,6 +1138,7 @@ impl MockExecuteState {
|
|||
fetch_block_id: &insn.fetch_block_id,
|
||||
id: &insn.id,
|
||||
pc,
|
||||
predicted_next_pc: &insn.predicted_next_pc,
|
||||
size_in_bytes: mock_insn.byte_len().cast_to_static::<UInt<4>>(),
|
||||
kind: mock_insn.wip_decoded_insn_kind(),
|
||||
};
|
||||
|
|
@ -1060,16 +1147,14 @@ impl MockExecuteState {
|
|||
"insn doesn't match expected:\ninsn: {insn:?}\nexpected insn: {expected_insn:?}"
|
||||
));
|
||||
}
|
||||
if let Some(next_insn) = self.queue.front() {
|
||||
if next_pc != next_insn.insn.pc.as_int() {
|
||||
self.canceling = true;
|
||||
if !passive {
|
||||
println!(
|
||||
"MockExecuteState: starting canceling {} instruction(s): next_pc={next_pc:#x}, mis-predicted next_pc={next_insn_pc}",
|
||||
self.queue.len(),
|
||||
next_insn_pc = next_insn.insn.pc
|
||||
);
|
||||
}
|
||||
if next_pc != insn.predicted_next_pc.as_int() {
|
||||
self.canceling = true;
|
||||
if !passive {
|
||||
println!(
|
||||
"MockExecuteState: starting canceling {} instruction(s): next_pc={next_pc:#x}, mis-predicted next_pc={}",
|
||||
self.queue.len(),
|
||||
insn.predicted_next_pc
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(
|
||||
|
|
@ -1130,6 +1215,10 @@ impl MockExecuteState {
|
|||
if !self.used_ids.insert(insn.id.clone()) {
|
||||
panic!("next_pc gave a duplicate insn id: {insn:?}");
|
||||
}
|
||||
println!(
|
||||
"MockExecutionState::start fid={} id={} pc={}",
|
||||
insn.fetch_block_id, insn.id, insn.pc
|
||||
);
|
||||
self.queue.push_back(
|
||||
#[hdl(sim)]
|
||||
ExecuteRetirePipeQueueEntry {
|
||||
|
|
@ -1187,14 +1276,15 @@ fn mock_execute_retire_pipe(
|
|||
cd,
|
||||
async |mut sim| {
|
||||
sim.write(from_post_decode.ready, 0usize).await;
|
||||
sim.write(from_post_decode.cancel.ready, false).await;
|
||||
sim.write(
|
||||
retire_output.inner.data,
|
||||
retire_output.ty().inner.data.HdlNone(),
|
||||
)
|
||||
.await;
|
||||
sim.write(
|
||||
retire_output.next_insn_ids,
|
||||
retire_output.next_insn_ids.ty().HdlNone(),
|
||||
retire_output.next_insns,
|
||||
retire_output.next_insns.ty().HdlNone(),
|
||||
)
|
||||
.await;
|
||||
sim.write(
|
||||
|
|
@ -1237,7 +1327,7 @@ fn mock_execute_retire_pipe(
|
|||
let config = from_post_decode.config.ty();
|
||||
let mut state = MockExecuteState::new(
|
||||
config,
|
||||
RetireSeq::new(MockMachineState::new(mock_insns, mock_input)),
|
||||
RetireSeq::new(MockMachineState::new(mock_insns, mock_input, true)),
|
||||
);
|
||||
let empty_retire_insn = #[hdl(sim)]
|
||||
RetireToNextPcInterfacePerInsn::<_> {
|
||||
|
|
@ -1255,22 +1345,32 @@ fn mock_execute_retire_pipe(
|
|||
let mut sim_queue = queue_debug
|
||||
.ty()
|
||||
.new_sim(ExecuteRetirePipeQueueEntry.default_sim());
|
||||
let mut next_insn_ids = retire_output.next_insn_ids.ty().HdlSome.new_sim(0_hdl_u12);
|
||||
let mut next_insns = retire_output.next_insns.ty().HdlSome.new_sim(
|
||||
#[hdl(sim)]
|
||||
WipDecodedInsn {
|
||||
fetch_block_id: 0u8,
|
||||
id: 0_hdl_u12,
|
||||
pc: 0u64,
|
||||
predicted_next_pc: 0u64,
|
||||
size_in_bytes: 0_hdl_u4,
|
||||
kind: WipDecodedInsnKind.NonBranch(),
|
||||
},
|
||||
);
|
||||
for entry in &state.queue {
|
||||
ArrayVec::try_push_sim(&mut sim_queue, entry)
|
||||
.ok()
|
||||
.expect("queue is known to be small enough");
|
||||
let _ = ArrayVec::try_push_sim(&mut next_insn_ids, &entry.insn.id);
|
||||
let _ = ArrayVec::try_push_sim(&mut next_insns, &entry.insn);
|
||||
}
|
||||
sim.write(queue_debug, sim_queue).await;
|
||||
sim.write(
|
||||
retire_output.next_insn_ids,
|
||||
retire_output.next_insns,
|
||||
if state.canceling {
|
||||
#[hdl(sim)]
|
||||
(retire_output.next_insn_ids.ty()).HdlNone()
|
||||
(retire_output.next_insns.ty()).HdlNone()
|
||||
} else {
|
||||
#[hdl(sim)]
|
||||
(retire_output.next_insn_ids.ty()).HdlSome(next_insn_ids)
|
||||
(retire_output.next_insns.ty()).HdlSome(next_insns)
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
|
@ -1310,6 +1410,8 @@ fn mock_execute_retire_pipe(
|
|||
},
|
||||
)
|
||||
.await;
|
||||
sim.write(from_post_decode.cancel.ready, state.canceling)
|
||||
.await;
|
||||
sim.wait_for_clock_edge(cd.clk).await;
|
||||
println!(
|
||||
"Dump mock execute retire pipe queue: {:#?}",
|
||||
|
|
@ -1322,8 +1424,17 @@ fn mock_execute_retire_pipe(
|
|||
))
|
||||
}))
|
||||
);
|
||||
if state.canceling {
|
||||
state.finish_cancel();
|
||||
#[hdl(sim)]
|
||||
if let HdlSome(v) = sim.read_past(from_post_decode.cancel.data, cd.clk).await {
|
||||
#[hdl(sim)]
|
||||
let () = v;
|
||||
if sim
|
||||
.read_past_bool(from_post_decode.cancel.ready, cd.clk)
|
||||
.await
|
||||
{
|
||||
assert!(state.canceling);
|
||||
state.finish_cancel();
|
||||
}
|
||||
}
|
||||
if sim.read_past_bool(retire_output.inner.ready, cd.clk).await {
|
||||
for _ in 0..**ArrayVec::len_sim(&retiring) {
|
||||
|
|
@ -1339,7 +1450,7 @@ fn mock_execute_retire_pipe(
|
|||
&mut new_insns,
|
||||
*sim.read_past(from_post_decode.ready, cd.clk).await,
|
||||
);
|
||||
for insn in dbg!(ArrayVec::elements_sim_ref(&new_insns)) {
|
||||
for insn in ArrayVec::elements_sim_ref(&new_insns) {
|
||||
state.start(insn, delay_sequence_index);
|
||||
}
|
||||
}
|
||||
|
|
@ -1430,9 +1541,9 @@ fn test_next_pc() {
|
|||
};
|
||||
sim.write_clock(sim.io().cd.clk, false);
|
||||
sim.write_reset(sim.io().cd.rst, true);
|
||||
for _cycle in 0..500 {
|
||||
for cycle in 0..2000 {
|
||||
sim.advance_time(SimDuration::from_nanos(500));
|
||||
println!("clock tick");
|
||||
println!("clock tick: {cycle}");
|
||||
sim.write_clock(sim.io().cd.clk, true);
|
||||
sim.advance_time(SimDuration::from_nanos(500));
|
||||
sim.write_clock(sim.io().cd.clk, false);
|
||||
|
|
|
|||
190
crates/cpu/tests/simple_power_isa_decoder.rs
Normal file
190
crates/cpu/tests/simple_power_isa_decoder.rs
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
|
||||
use cpu::{
|
||||
decoder::simple_power_isa::decode_one_32bit_insn,
|
||||
instruction::{AddSubMOp, MOp, MOpDestReg, MOpRegNum, OutputIntegerMode},
|
||||
util::array_vec::ArrayVec,
|
||||
};
|
||||
use fayalite::{prelude::*, sim::vcd::VcdWriterDecls, util::RcWriter};
|
||||
use std::{
|
||||
fmt::{self, Write as _},
|
||||
io::Write,
|
||||
process::Command,
|
||||
};
|
||||
|
||||
struct TestCase {
|
||||
mnemonic: &'static str,
|
||||
input: u32,
|
||||
output: SimValue<ArrayVec<MOp, ConstUsize<2>>>,
|
||||
loc: &'static std::panic::Location<'static>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for TestCase {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self {
|
||||
mnemonic,
|
||||
input,
|
||||
output,
|
||||
loc,
|
||||
} = self;
|
||||
f.debug_struct("TestCase")
|
||||
.field("mnemonic", mnemonic)
|
||||
.field("input", &format_args!("0x{input:08x}"))
|
||||
.field("output", &ArrayVec::elements_sim_ref(output))
|
||||
.field("loc", &format_args!("{loc}"))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
fn test_cases() -> Vec<TestCase> {
|
||||
let mut retval = Vec::new();
|
||||
#[track_caller]
|
||||
fn insn_single(
|
||||
mnemonic: &'static str,
|
||||
input: u32,
|
||||
output: impl ToSimValue<Type = MOp>,
|
||||
) -> TestCase {
|
||||
let zero_mop = UInt::new_dyn(MOp.canonical().bit_width())
|
||||
.zero()
|
||||
.cast_bits_to(MOp);
|
||||
let mut single_storage = ArrayVec::new_sim(ArrayVec[MOp][ConstUsize], &zero_mop);
|
||||
ArrayVec::try_push_sim(&mut single_storage, zero_mop).expect("known to have space");
|
||||
ArrayVec::elements_sim_mut(&mut single_storage)[0] = output.to_sim_value();
|
||||
TestCase {
|
||||
mnemonic,
|
||||
input,
|
||||
output: single_storage.clone(),
|
||||
loc: std::panic::Location::caller(),
|
||||
}
|
||||
}
|
||||
retval.push(insn_single(
|
||||
"addi 3, 4, 0x1234",
|
||||
0x38641234,
|
||||
AddSubMOp::add_sub_i(
|
||||
MOpDestReg::new_sim(&[3], &[]),
|
||||
[
|
||||
(MOpRegNum::POWER_ISA_GPR_REG_NUMS.start + 4).cast_to_static::<UInt<_>>(),
|
||||
MOpRegNum::CONST_ZERO_REG_NUM.cast_to_static::<UInt<_>>(),
|
||||
],
|
||||
0x1234.cast_to_static::<SInt<_>>(),
|
||||
#[hdl(sim)]
|
||||
OutputIntegerMode::Full64(),
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
),
|
||||
));
|
||||
retval
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_test_cases_assembly() -> std::io::Result<()> {
|
||||
let llvm_mc_regex = regex::Regex::new(r"llvm-mc(-\d+)?$").expect("known to be a valid regex");
|
||||
let llvm_mc = which::which_re(llvm_mc_regex)
|
||||
.expect("can't find llvm-mc or llvm-mc-<num> in path")
|
||||
.next()
|
||||
.expect("can't find llvm-mc or llvm-mc-<num> in path");
|
||||
let test_cases = test_cases();
|
||||
let mut assembly = String::new();
|
||||
for TestCase {
|
||||
mnemonic,
|
||||
input: _,
|
||||
output: _,
|
||||
loc: _,
|
||||
} in &test_cases
|
||||
{
|
||||
writeln!(assembly, "{mnemonic}").unwrap();
|
||||
}
|
||||
let (reader, mut writer) = std::io::pipe()?;
|
||||
let thread = std::thread::spawn(move || writer.write_all(assembly.as_bytes()));
|
||||
let std::process::Output {
|
||||
status,
|
||||
stdout,
|
||||
stderr,
|
||||
} = Command::new(&llvm_mc)
|
||||
.arg("--triple=powerpc64le-linux-gnu")
|
||||
.arg("--assemble")
|
||||
.arg("--filetype=asm")
|
||||
.arg("--show-encoding")
|
||||
.arg("-")
|
||||
.stdin(reader)
|
||||
.output()?;
|
||||
let _ = thread.join();
|
||||
let stderr = String::from_utf8_lossy(&stderr);
|
||||
eprint!("{stderr}");
|
||||
if !status.success() {
|
||||
panic!("{} failed: {status}", llvm_mc.display());
|
||||
}
|
||||
let stdout = String::from_utf8_lossy(&stdout);
|
||||
print!("{stdout}");
|
||||
let mut lines = stdout.lines();
|
||||
let text_line = lines.next();
|
||||
assert_eq!(text_line, Some("\t.text"));
|
||||
for test_case in test_cases {
|
||||
let Some(line) = lines.next() else {
|
||||
panic!("output missing line for: {test_case:?}");
|
||||
};
|
||||
let Some((_, comment)) = line.split_once('#') else {
|
||||
panic!("output line missing comment. test_case={test_case:?}\nline:\n{line}");
|
||||
};
|
||||
let [b0, b1, b2, b3] = test_case.input.to_le_bytes();
|
||||
let expected_comment = format!(" encoding: [0x{b0:02x},0x{b1:02x},0x{b2:02x},0x{b3:02x}]");
|
||||
assert_eq!(
|
||||
comment, expected_comment,
|
||||
"test_case={test_case:?}\nline:\n{line}"
|
||||
);
|
||||
}
|
||||
for line in lines {
|
||||
assert!(line.trim().is_empty(), "bad trailing output line: {line:?}");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
#[test]
|
||||
fn test_decode_one_32bit_insn() {
|
||||
let _n = SourceLocation::normalize_files_for_tests();
|
||||
let m = decode_one_32bit_insn();
|
||||
let mut sim = Simulation::new(m);
|
||||
let writer = RcWriter::default();
|
||||
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
|
||||
struct DumpVcdOnDrop {
|
||||
writer: Option<RcWriter>,
|
||||
}
|
||||
impl Drop for DumpVcdOnDrop {
|
||||
fn drop(&mut self) {
|
||||
if let Some(mut writer) = self.writer.take() {
|
||||
let vcd = String::from_utf8(writer.take()).unwrap();
|
||||
println!("####### VCD:\n{vcd}\n#######");
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut writer = DumpVcdOnDrop {
|
||||
writer: Some(writer),
|
||||
};
|
||||
for test_case in test_cases() {
|
||||
sim.write(sim.io().input, test_case.input);
|
||||
sim.advance_time(SimDuration::from_micros(1));
|
||||
let output = sim.read(sim.io().output);
|
||||
let expected = format!("{:?}", ArrayVec::elements_sim_ref(&test_case.output));
|
||||
let output = format!("{:?}", ArrayVec::elements_sim_ref(&output));
|
||||
assert!(
|
||||
expected == output,
|
||||
"test_case={test_case:?}\noutput={output}"
|
||||
);
|
||||
}
|
||||
let vcd = String::from_utf8(writer.writer.take().unwrap().take()).unwrap();
|
||||
println!("####### VCD:\n{vcd}\n#######");
|
||||
if vcd != include_str!("expected/decode_one_32bit_insn.vcd") {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
#[test]
|
||||
fn test_simple_power_isa_decoder() {
|
||||
// TODO
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue