faster memory impl
This commit is contained in:
@@ -1 +1,2 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
|
||||
Generated
+571
@@ -2,6 +2,71 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anes"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.8.2"
|
||||
@@ -11,6 +76,12 @@ dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.0"
|
||||
@@ -20,22 +91,188 @@ dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cast"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"ciborium-ll",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-io"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
|
||||
|
||||
[[package]]
|
||||
name = "ciborium-ll"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
|
||||
dependencies = [
|
||||
"ciborium-io",
|
||||
"half",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "criterion"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
|
||||
dependencies = [
|
||||
"anes",
|
||||
"cast",
|
||||
"ciborium",
|
||||
"clap",
|
||||
"criterion-plot",
|
||||
"is-terminal",
|
||||
"itertools",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"oorandom",
|
||||
"plotters",
|
||||
"rayon",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tinytemplate",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "criterion-plot"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
|
||||
dependencies = [
|
||||
"cast",
|
||||
"itertools",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
||||
|
||||
[[package]]
|
||||
name = "dsa-emu"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"clap",
|
||||
"criterion",
|
||||
"fxhash",
|
||||
"ron",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
@@ -45,12 +282,138 @@ dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "half"
|
||||
version = "2.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crunchy",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.182"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
|
||||
|
||||
[[package]]
|
||||
name = "plotters"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"plotters-backend",
|
||||
"plotters-svg",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "plotters-backend"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
|
||||
|
||||
[[package]]
|
||||
name = "plotters-svg"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
|
||||
dependencies = [
|
||||
"plotters-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
@@ -69,6 +432,55 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
|
||||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
version = "0.12.0"
|
||||
@@ -89,6 +501,15 @@ version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
@@ -119,6 +540,25 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.149"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
@@ -130,6 +570,16 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinytemplate"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeid"
|
||||
version = "1.0.3"
|
||||
@@ -141,3 +591,124 @@ name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.114"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||
|
||||
@@ -3,8 +3,20 @@ name = "dsa-emu"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
name = "dsa"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.5.0", features = ["html_reports"] }
|
||||
|
||||
[dependencies]
|
||||
arc-swap = "1.8.2"
|
||||
clap = { version = "4.5.60", features = ["derive"] }
|
||||
fxhash = "0.2.1"
|
||||
ron = "0.12.0"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
|
||||
[[bench]]
|
||||
name = "bench_mainstore"
|
||||
harness = false
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
use criterion::{
|
||||
BenchmarkGroup, BenchmarkId, Criterion, Throughput, black_box, criterion_group, criterion_main,
|
||||
measurement::WallTime,
|
||||
};
|
||||
use std::time::Duration;
|
||||
|
||||
use dsa::{FastStore, MainStore, RandomAccessMemory};
|
||||
|
||||
// ── reproduce the trait and PhysAddr here, or import from your crate ─────────
|
||||
type PhysAddr = u32;
|
||||
|
||||
// ── address generators ────────────────────────────────────────────────────────
|
||||
|
||||
/// Cycles through a small set of addresses — stays hot in L1/L2.
|
||||
/// Simulates a tight inner loop hitting the same working set repeatedly.
|
||||
fn sequential_addrs(n: usize, max_addr: u32) -> Vec<PhysAddr> {
|
||||
(0..n).map(|i| ((i as u32 * 4) & (max_addr - 1))).collect()
|
||||
}
|
||||
|
||||
/// LCG pseudo-random addresses across the full address space.
|
||||
/// Simulates worst-case cache behaviour.
|
||||
fn random_addrs(n: usize, max_addr: u32) -> Vec<PhysAddr> {
|
||||
let mut addrs = Vec::with_capacity(n);
|
||||
let mut x: u32 = 0xdeadbeef;
|
||||
for _ in 0..n {
|
||||
x = x.wrapping_mul(1664525).wrapping_add(1013904223);
|
||||
addrs.push((x & (max_addr - 1)) & !3);
|
||||
}
|
||||
addrs
|
||||
}
|
||||
|
||||
/// Walks addresses page by page — tests page-boundary crossing behaviour.
|
||||
fn page_stride_addrs(n: usize) -> Vec<PhysAddr> {
|
||||
(0..n).map(|i| (i as u32 * 4096) & 0x00FF_FFFF).collect()
|
||||
}
|
||||
|
||||
// ── generic benchmark functions ───────────────────────────────────────────────
|
||||
|
||||
fn bench_read_byte<M: RandomAccessMemory>(
|
||||
group: &mut BenchmarkGroup<WallTime>,
|
||||
name: &str,
|
||||
mem: &M,
|
||||
addrs: &[PhysAddr],
|
||||
) {
|
||||
group.throughput(Throughput::Elements(addrs.len() as u64));
|
||||
group.bench_function(name, |b| {
|
||||
b.iter(|| {
|
||||
let mut sum: u32 = 0;
|
||||
for &addr in addrs {
|
||||
sum = sum.wrapping_add(mem.read_byte(black_box(addr)) as u32);
|
||||
}
|
||||
black_box(sum)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_write_byte<M: RandomAccessMemory>(
|
||||
group: &mut BenchmarkGroup<WallTime>,
|
||||
name: &str,
|
||||
mem: &mut M,
|
||||
addrs: &[PhysAddr],
|
||||
) {
|
||||
group.throughput(Throughput::Elements(addrs.len() as u64));
|
||||
group.bench_function(name, |b| {
|
||||
b.iter(|| {
|
||||
for (i, &addr) in addrs.iter().enumerate() {
|
||||
mem.write_byte(black_box(addr), black_box(i as u8));
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_read_word<M: RandomAccessMemory>(
|
||||
group: &mut BenchmarkGroup<WallTime>,
|
||||
name: &str,
|
||||
mem: &M,
|
||||
addrs: &[PhysAddr],
|
||||
) {
|
||||
group.throughput(Throughput::Elements(addrs.len() as u64));
|
||||
group.bench_function(name, |b| {
|
||||
b.iter(|| {
|
||||
let mut sum: u32 = 0;
|
||||
for &addr in addrs {
|
||||
sum = sum.wrapping_add(mem.read_word(black_box(addr)));
|
||||
}
|
||||
black_box(sum)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_write_word<M: RandomAccessMemory>(
|
||||
group: &mut BenchmarkGroup<WallTime>,
|
||||
name: &str,
|
||||
mem: &mut M,
|
||||
addrs: &[PhysAddr],
|
||||
) {
|
||||
group.throughput(Throughput::Elements(addrs.len() as u64));
|
||||
group.bench_function(name, |b| {
|
||||
b.iter(|| {
|
||||
for (i, &addr) in addrs.iter().enumerate() {
|
||||
mem.write_word(black_box(addr), black_box(i as u32));
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_read_page<M: RandomAccessMemory>(
|
||||
group: &mut BenchmarkGroup<WallTime>,
|
||||
name: &str,
|
||||
mem: &M,
|
||||
addrs: &[PhysAddr],
|
||||
) {
|
||||
group.throughput(Throughput::Bytes(addrs.len() as u64 * 4096));
|
||||
group.bench_function(name, |b| {
|
||||
b.iter(|| {
|
||||
let mut sum: u8 = 0;
|
||||
for &addr in addrs {
|
||||
let page = mem.read_page(black_box(addr));
|
||||
sum = sum.wrapping_add(page[0]);
|
||||
}
|
||||
black_box(sum)
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn bench_write_page<M: RandomAccessMemory>(
|
||||
group: &mut BenchmarkGroup<WallTime>,
|
||||
name: &str,
|
||||
mem: &mut M,
|
||||
addrs: &[PhysAddr],
|
||||
) {
|
||||
let page_data = [0xABu8; 4096];
|
||||
group.throughput(Throughput::Bytes(addrs.len() as u64 * 4096));
|
||||
group.bench_function(name, |b| {
|
||||
b.iter(|| {
|
||||
for &addr in addrs {
|
||||
mem.write_page(black_box(addr), black_box(&page_data));
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// ── run all access patterns for a given implementation ────────────────────────
|
||||
|
||||
fn bench_implementation<M: RandomAccessMemory>(
|
||||
c: &mut Criterion,
|
||||
impl_name: &str,
|
||||
mut mem: M,
|
||||
max_addr: u32,
|
||||
) {
|
||||
const N: usize = 64;
|
||||
|
||||
let seq_addrs = sequential_addrs(N, max_addr);
|
||||
let rand_addrs = random_addrs(N, max_addr);
|
||||
let page_stride = page_stride_addrs(N);
|
||||
|
||||
// ── read_byte ────────────────────────────────────────────────────────────
|
||||
{
|
||||
let mut g = c.benchmark_group(format!("{}/read_byte", impl_name));
|
||||
g.measurement_time(Duration::from_secs(3));
|
||||
bench_read_byte(&mut g, "sequential", &mem, &seq_addrs);
|
||||
bench_read_byte(&mut g, "random", &mem, &rand_addrs);
|
||||
g.finish();
|
||||
}
|
||||
|
||||
// ── write_byte ───────────────────────────────────────────────────────────
|
||||
{
|
||||
let mut g = c.benchmark_group(format!("{}/write_byte", impl_name));
|
||||
g.measurement_time(Duration::from_secs(3));
|
||||
bench_write_byte(&mut g, "sequential", &mut mem, &seq_addrs);
|
||||
bench_write_byte(&mut g, "random", &mut mem, &rand_addrs);
|
||||
g.finish();
|
||||
}
|
||||
|
||||
// ── read_word ────────────────────────────────────────────────────────────
|
||||
{
|
||||
let mut g = c.benchmark_group(format!("{}/read_word", impl_name));
|
||||
g.measurement_time(Duration::from_secs(3));
|
||||
bench_read_word(&mut g, "sequential", &mem, &seq_addrs);
|
||||
bench_read_word(&mut g, "random", &mem, &rand_addrs);
|
||||
g.finish();
|
||||
}
|
||||
|
||||
// ── write_word ───────────────────────────────────────────────────────────
|
||||
{
|
||||
let mut g = c.benchmark_group(format!("{}/write_word", impl_name));
|
||||
g.measurement_time(Duration::from_secs(3));
|
||||
bench_write_word(&mut g, "sequential", &mut mem, &seq_addrs);
|
||||
bench_write_word(&mut g, "random", &mut mem, &rand_addrs);
|
||||
g.finish();
|
||||
}
|
||||
|
||||
// ── read_page ────────────────────────────────────────────────────────────
|
||||
{
|
||||
let mut g = c.benchmark_group(format!("{}/read_page", impl_name));
|
||||
g.measurement_time(Duration::from_secs(3));
|
||||
bench_read_page(&mut g, "sequential", &mem, &seq_addrs);
|
||||
bench_read_page(&mut g, "random", &mem, &rand_addrs);
|
||||
bench_read_page(&mut g, "page_stride", &mem, &page_stride);
|
||||
g.finish();
|
||||
}
|
||||
|
||||
// ── write_page ───────────────────────────────────────────────────────────
|
||||
{
|
||||
let mut g = c.benchmark_group(format!("{}/write_page", impl_name));
|
||||
g.measurement_time(Duration::from_secs(3));
|
||||
bench_write_page(&mut g, "sequential", &mut mem, &seq_addrs);
|
||||
bench_write_page(&mut g, "random", &mut mem, &rand_addrs);
|
||||
bench_write_page(&mut g, "page_stride", &mut mem, &page_stride);
|
||||
g.finish();
|
||||
}
|
||||
}
|
||||
|
||||
// ── wire up your implementations here ────────────────────────────────────────
|
||||
//
|
||||
// Replace these stubs with your actual types. Each call to bench_implementation
|
||||
// runs the full suite and labels it separately in the HTML report.
|
||||
//
|
||||
// Example:
|
||||
// fn benchmarks(c: &mut Criterion) {
|
||||
// bench_implementation(c, "MainStore", MainStore::new(), 0x00FF_FFFF);
|
||||
// bench_implementation(c, "FxHashMap", HashMapMem::new(), 0x00FF_FFFF);
|
||||
// }
|
||||
//
|
||||
fn benchmarks(c: &mut Criterion) {
|
||||
// TODO: replace with your implementations
|
||||
bench_implementation(c, "MainStore", MainStore::new(), 0x00FF_FFFF);
|
||||
bench_implementation(c, "FastStore", FastStore::new(), 0x00FF_FFFF);
|
||||
|
||||
let _ = c;
|
||||
}
|
||||
|
||||
criterion_group!(benches, benchmarks);
|
||||
criterion_main!(benches);
|
||||
@@ -0,0 +1,41 @@
|
||||
MemoryMap(
|
||||
table_addr: 0x1000,
|
||||
regions: [
|
||||
// 0000-1000 = reserved
|
||||
Region(
|
||||
base: 0x0,
|
||||
size: 0x1000,
|
||||
region_type: Reserved
|
||||
),
|
||||
// 1000-4000 = bootloader
|
||||
Region(
|
||||
base: 0x1000,
|
||||
size: 0x3000,
|
||||
region_type: Bootloader
|
||||
),
|
||||
// 5000-0FFFFFFF = MMIO
|
||||
Region(
|
||||
base: 0x5000,
|
||||
size: 0x0FFF_FFFF,
|
||||
region_type: MMIO
|
||||
),
|
||||
// 10000000-BFFFFFFF = userspace
|
||||
Region(
|
||||
base: 0x1000_0000,
|
||||
size: 0xBFFF_FFFF,
|
||||
region_type: Usable
|
||||
),
|
||||
// C0000000-C0FFFFFF = kernel page tables
|
||||
Region(
|
||||
base: 0xC000_0000,
|
||||
size: 0x100_0000,
|
||||
region_type: KernelTables
|
||||
),
|
||||
// C1000000-FFFFFFFF = kernel
|
||||
Region(
|
||||
base: 0xC100_0000,
|
||||
size: 0x3EFF_FFFF,
|
||||
region_type: Kernel
|
||||
)
|
||||
]
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
#![feature(likely_unlikely)]
|
||||
#![feature(ptr_as_ref_unchecked)]
|
||||
|
||||
mod memory;
|
||||
mod processor;
|
||||
|
||||
pub use {
|
||||
memory::MemoryMap,
|
||||
memory::mainstore::{FastStore, MainStore, RandomAccessMemory},
|
||||
processor::processor::Emulator,
|
||||
processor::state::SharedState,
|
||||
};
|
||||
+34
-5
@@ -1,5 +1,8 @@
|
||||
use arc_swap::ArcSwap;
|
||||
use clap::Parser;
|
||||
use std::{
|
||||
fs,
|
||||
path::PathBuf,
|
||||
sync::{
|
||||
Arc,
|
||||
atomic::{AtomicBool, AtomicU8},
|
||||
@@ -8,13 +11,20 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use crate::processor::{processor::Emulator, state::SharedState};
|
||||
|
||||
mod memory;
|
||||
mod processor;
|
||||
use dsa::{Emulator, FastStore, MainStore, MemoryMap, SharedState};
|
||||
|
||||
fn main() {
|
||||
let mut emulator = Emulator::new();
|
||||
let args = DsaArgs::parse();
|
||||
|
||||
let mut emulator = Emulator::new(FastStore::new());
|
||||
|
||||
let mmap = match args.get_memory_map() {
|
||||
Some(m) => m,
|
||||
None => MemoryMap::default(),
|
||||
};
|
||||
|
||||
emulator.apply_memory_map(mmap);
|
||||
|
||||
let state = emulator.state_handle();
|
||||
let runner = thread::spawn(move || emulator.run());
|
||||
let observer = thread::spawn(|| observe(state));
|
||||
@@ -30,3 +40,22 @@ fn observe(state: Arc<SharedState>) {
|
||||
println!("GP Registers: {:?}", state.gp_registers);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct DsaArgs {
|
||||
/// Memory map to use on boot.
|
||||
/// Overrides default value.
|
||||
#[arg(long = "mmap")]
|
||||
memory_map: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl DsaArgs {
|
||||
pub fn get_memory_map(&self) -> Option<MemoryMap> {
|
||||
self.memory_map.as_ref().and_then(|m| {
|
||||
fs::read_to_string(m)
|
||||
.ok()
|
||||
.and_then(|map| ron::from_str(&map).ok())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+121
-15
@@ -1,9 +1,27 @@
|
||||
use fxhash::FxHashMap;
|
||||
|
||||
use crate::memory::PhysAddr;
|
||||
use std::{
|
||||
alloc::{Layout, alloc_zeroed},
|
||||
hint::likely,
|
||||
};
|
||||
|
||||
type Page = [u8; 4096];
|
||||
|
||||
pub trait RandomAccessMemory {
|
||||
fn read_byte(&self, addr: PhysAddr) -> u8;
|
||||
|
||||
fn write_byte(&mut self, addr: PhysAddr, value: u8);
|
||||
|
||||
fn read_word(&self, addr: PhysAddr) -> u32;
|
||||
|
||||
fn write_word(&mut self, addr: PhysAddr, value: u32);
|
||||
|
||||
fn read_page(&self, addr: PhysAddr) -> &[u8; 4096];
|
||||
|
||||
fn write_page(&mut self, addr: PhysAddr, value: &[u8; 4096]);
|
||||
}
|
||||
|
||||
pub struct MainStore {
|
||||
pages: FxHashMap<PhysAddr, Page>,
|
||||
}
|
||||
@@ -19,42 +37,130 @@ impl MainStore {
|
||||
const fn segment_addr(addr: PhysAddr) -> (PhysAddr, usize) {
|
||||
(addr & !(0xFFF), (addr & 0xFFF) as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_byte(&self, addr: PhysAddr) -> u8 {
|
||||
impl RandomAccessMemory for MainStore {
|
||||
#[inline(always)]
|
||||
fn read_byte(&self, addr: PhysAddr) -> u8 {
|
||||
let (page, offset) = Self::segment_addr(addr);
|
||||
self.pages.get(&page).map(|p| p[offset]).unwrap_or(0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_word(&self, addr: PhysAddr) -> u32 {
|
||||
#[inline(always)]
|
||||
fn read_word(&self, addr: PhysAddr) -> u32 {
|
||||
let (page, offset) = Self::segment_addr(addr);
|
||||
debug_assert_eq!(offset % 4, 0);
|
||||
let page = self.pages.get(&page).unwrap_or(&[0; 4096]);
|
||||
u32::from_be_bytes(page[offset..=offset + 3].try_into().unwrap())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn read_page(&self, addr: PhysAddr) -> &[u8] {
|
||||
#[inline(always)]
|
||||
fn read_page(&self, addr: PhysAddr) -> &[u8; 4096] {
|
||||
debug_assert_eq!(addr % 0x1000, 0);
|
||||
self.pages.get(&addr).unwrap_or(&[0; 4096])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_byte(&mut self, addr: PhysAddr, value: u8) {
|
||||
#[inline(always)]
|
||||
fn write_byte(&mut self, addr: PhysAddr, value: u8) {
|
||||
let (page, offset) = Self::segment_addr(addr);
|
||||
self.pages.entry(page).or_insert_with(|| [0; 4096])[offset] = value;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_word(&mut self, addr: PhysAddr, value: u32) {
|
||||
#[inline(always)]
|
||||
fn write_word(&mut self, addr: PhysAddr, value: u32) {
|
||||
let (page, offset) = Self::segment_addr(addr);
|
||||
debug_assert_eq!(offset % 4, 0);
|
||||
let page = self.pages.entry(page).or_insert_with(|| [0; 4096]);
|
||||
page[offset..=offset + 3].copy_from_slice(&value.to_be_bytes());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn write_page(&mut self, addr: PhysAddr, value: &[u8; 4096]) {
|
||||
let (page, offset) = Self::segment_addr(addr);
|
||||
let page = self.pages.entry(page).or_insert_with(|| [0; 4096]);
|
||||
page[offset..offset + value.len()].copy_from_slice(value);
|
||||
#[inline(always)]
|
||||
fn write_page(&mut self, addr: PhysAddr, value: &[u8; 4096]) {
|
||||
debug_assert_eq!(addr % 0x1000, 0);
|
||||
let page = self.pages.entry(addr).or_insert_with(|| [0; 4096]);
|
||||
page.copy_from_slice(value);
|
||||
}
|
||||
}
|
||||
|
||||
const NUM_PAGES: usize = 2 << 20;
|
||||
|
||||
pub struct FastStore {
|
||||
pages: Box<[*mut Page; NUM_PAGES]>,
|
||||
}
|
||||
|
||||
unsafe impl Send for FastStore {}
|
||||
impl FastStore {
|
||||
pub fn new() -> Self {
|
||||
let pages = vec![0 as *mut Page; 2 << 20]
|
||||
.into_boxed_slice()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
Self { pages }
|
||||
}
|
||||
|
||||
fn alloc(&mut self) -> *mut Page {
|
||||
let layout = Layout::from_size_align(4096, 4096).unwrap();
|
||||
unsafe { alloc_zeroed(layout) as *mut Page }
|
||||
}
|
||||
}
|
||||
|
||||
impl RandomAccessMemory for FastStore {
|
||||
fn read_word(&self, addr: PhysAddr) -> u32 {
|
||||
let page = self.pages[(addr >> 12) as usize];
|
||||
if likely(!page.is_null()) {
|
||||
let offset = (addr & 0xFFF) as usize;
|
||||
return unsafe { (page.add(offset) as *const u32).read() };
|
||||
}
|
||||
|
||||
// Slow path: MMIO, fault, etc — never inlined
|
||||
// Since we're only reading, we can safely return 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn read_byte(&self, addr: PhysAddr) -> u8 {
|
||||
let page = self.pages[(addr >> 12) as usize];
|
||||
if likely(!page.is_null()) {
|
||||
let offset = (addr & 0xFFF) as usize;
|
||||
return unsafe { (page.add(offset) as *const u8).read() };
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn read_page(&self, addr: PhysAddr) -> &[u8; 4096] {
|
||||
let page = self.pages[(addr >> 12) as usize];
|
||||
if likely(!page.is_null()) {
|
||||
let offset = (addr & 0xFFF) as usize;
|
||||
return unsafe { &*(page.add(offset) as *const [u8; 4096]) };
|
||||
}
|
||||
|
||||
return &[0; 4096];
|
||||
}
|
||||
|
||||
fn write_byte(&mut self, addr: PhysAddr, value: u8) {
|
||||
let page = self.pages[(addr >> 12) as usize];
|
||||
|
||||
if likely(!page.is_null()) {
|
||||
let offset = (addr & 0xFFF) as usize;
|
||||
unsafe { (page.add(offset) as *mut u8).write(value) };
|
||||
}
|
||||
}
|
||||
|
||||
fn write_word(&mut self, addr: PhysAddr, value: u32) {
|
||||
let page = self.pages[(addr >> 12) as usize];
|
||||
|
||||
if likely(!page.is_null()) {
|
||||
let offset = (addr & 0xFFF) as usize;
|
||||
unsafe { (page.add(offset) as *mut u32).write(value) };
|
||||
}
|
||||
}
|
||||
|
||||
fn write_page(&mut self, addr: PhysAddr, value: &[u8; 4096]) {
|
||||
let page = self.pages[(addr >> 12) as usize];
|
||||
|
||||
if likely(!page.is_null()) {
|
||||
let offset = (addr & 0xFFF) as usize;
|
||||
unsafe { (page.add(offset) as *mut [u8; 4096]).write(*value) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::memory::mmu::MMU;
|
||||
use crate::{
|
||||
memory::{mainstore::RandomAccessMemory, mmu::MMU},
|
||||
processor::processor::Emulator,
|
||||
};
|
||||
|
||||
mod cache;
|
||||
pub mod mainstore;
|
||||
@@ -15,7 +18,7 @@ pub enum FaultInfo {
|
||||
}
|
||||
|
||||
#[repr(u32)]
|
||||
#[derive(Serialize, Deserialize, Clone, Copy)]
|
||||
#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
|
||||
enum RegionType {
|
||||
Reserved,
|
||||
Bootloader,
|
||||
@@ -25,14 +28,18 @@ enum RegionType {
|
||||
MMIO,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Copy)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy)]
|
||||
pub struct Region {
|
||||
base: PhysAddr,
|
||||
size: usize,
|
||||
size: u32,
|
||||
region_type: RegionType,
|
||||
|
||||
// flags for the emulator
|
||||
#[serde(default)]
|
||||
identity_map_on_boot: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct MemoryMap {
|
||||
table_addr: PhysAddr,
|
||||
pub regions: Vec<Region>,
|
||||
@@ -48,9 +55,27 @@ impl MemoryMap {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply(&self, cpu: &mut Emulator<impl RandomAccessMemory>) {
|
||||
for reg in &self.regions {
|
||||
if reg.identity_map_on_boot {
|
||||
Self::identity_map(cpu.mmu_mut(), reg);
|
||||
}
|
||||
}
|
||||
|
||||
let mem = cpu.memory_mut();
|
||||
let mut offset = self.table_addr;
|
||||
for region in &self.regions {
|
||||
println!("Wrote entry: {region:?} to page table");
|
||||
mem.write_word(offset, region.base);
|
||||
mem.write_word(offset + 4, region.size);
|
||||
mem.write_word(offset + 8, region.region_type as u32);
|
||||
offset += 12;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn identity_map(mmu: &mut MMU, region: &Region) {
|
||||
let first_page = region.base >> 12;
|
||||
let page_count = (region.size >> 12) as u32;
|
||||
let page_count = (region.size >> 12);
|
||||
|
||||
for page in (first_page..first_page + page_count).map(|p| p << 12) {
|
||||
mmu.create_mapping(page, page);
|
||||
@@ -60,6 +85,6 @@ impl MemoryMap {
|
||||
|
||||
impl Default for MemoryMap {
|
||||
fn default() -> Self {
|
||||
ron::from_str(include_str!("../../config/dsa.mmap.ron")).unwrap()
|
||||
ron::from_str(include_str!("../config/dsa.mmap.default.ron")).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,38 @@
|
||||
use std::{sync::Arc, thread, time::Duration};
|
||||
|
||||
use crate::{
|
||||
memory::{FaultInfo, MemoryMap, mainstore::MainStore, mmu::MMU},
|
||||
memory::{
|
||||
FaultInfo, MemoryMap,
|
||||
mainstore::{MainStore, RandomAccessMemory},
|
||||
mmu::MMU,
|
||||
},
|
||||
processor::{
|
||||
interrupts::Interrupt,
|
||||
state::{ProcessorSnapshot, SharedState},
|
||||
},
|
||||
};
|
||||
|
||||
pub struct Emulator {
|
||||
pub struct Emulator<Mem: RandomAccessMemory> {
|
||||
internal_state: ProcessorSnapshot,
|
||||
shared_state: Arc<SharedState>,
|
||||
|
||||
// memory
|
||||
mmu: MMU,
|
||||
mainstore: MainStore,
|
||||
mainstore: Mem,
|
||||
|
||||
// optionals - not necessarily set on boot.
|
||||
memory_map: Option<MemoryMap>,
|
||||
}
|
||||
|
||||
impl Emulator {
|
||||
pub fn new() -> Self {
|
||||
unsafe impl<Mem: RandomAccessMemory> Send for Emulator<Mem> {}
|
||||
impl<Mem: RandomAccessMemory> Emulator<Mem> {
|
||||
pub fn new(mem: Mem) -> Self {
|
||||
Self {
|
||||
internal_state: ProcessorSnapshot::default(),
|
||||
shared_state: Arc::new(SharedState::new()),
|
||||
mmu: MMU::new(),
|
||||
mainstore: MainStore::new(),
|
||||
mainstore: mem,
|
||||
memory_map: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +40,20 @@ impl Emulator {
|
||||
self.shared_state.clone()
|
||||
}
|
||||
|
||||
pub fn mmu_mut(&mut self) -> &mut MMU {
|
||||
&mut self.mmu
|
||||
}
|
||||
|
||||
pub fn memory_mut(&mut self) -> &mut impl RandomAccessMemory {
|
||||
&mut self.mainstore
|
||||
}
|
||||
|
||||
pub fn apply_memory_map(&mut self, map: MemoryMap) -> &mut Self {
|
||||
map.apply(self);
|
||||
self.memory_map = Some(map);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
let mut clock = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user